if not jiffies_sym: return False jiffies = int(jiffies_sym.value()) cls._adjust_jiffies = False cls.set_jiffies(jiffies) return True def _adjusted_jiffies(self) -> int: if self._adjust_jiffies: return self.jiffies - (int(0x100000000) - 300 * self.hz) return self.jiffies symbol_cbs = SymbolCallbacks([('jiffies', CrashKernelCache.setup_jiffies), ('jiffies_64', CrashKernelCache.setup_jiffies)]) utsname = CrashUtsnameCache() config = CrashConfigCache() kernel = CrashKernelCache(config) def config_enabled(key: str) -> bool: """ Determine if a config option is enabled. Args: key (str): The config option without the CONFIG_ prefix. Returns: bool: True if the config exists and is enabled as =y or =m
if nr_cpus <= 0: raise ValueError("nr_cpus must be > 0") vals = dict() var = self._resolve_percpu_var(var) for cpu in range(0, nr_cpus): vals[cpu] = self._get_percpu_var(var, cpu) return vals msym_cbs = MinimalSymbolCallbacks([ ('__per_cpu_start', PerCPUState.setup_per_cpu_size), ('__per_cpu_end', PerCPUState.setup_per_cpu_size) ]) symbol_cbs = SymbolCallbacks([('__per_cpu_offset', PerCPUState.setup_nr_cpus), ('modules', PerCPUState.setup_module_ranges)]) _state = PerCPUState() def is_percpu_var(var: SymbolOrValue) -> bool: """ Returns whether the provided value or symbol falls within any of the percpu ranges Args: var: The symbol or value to query Returns: :obj:`bool`: Whether the value belongs to any percpu range """
def kmem_cache_from_name(name: str) -> KmemCache: try: return kmem_caches[name] except KeyError: raise KmemCacheNotFound(f"No kmem cache found for {name}.") def kmem_cache_get_all() -> ValuesView[KmemCache]: return kmem_caches.values() def slab_from_obj_addr(addr: int) -> Union[Slab, None]: page = page_from_addr(addr).compound_head() if not page.is_slab(): return None return Slab.from_page(page) type_cbs = TypeCallbacks([ ('struct page', Slab.check_page_type), ('struct slab', Slab.check_slab_type), ('kmem_bufctl_t', Slab.check_bufctl_type), ('freelist_idx_t', Slab.check_bufctl_type), ('struct kmem_cache', KmemCache.check_kmem_cache_type), ('struct alien_cache', KmemCache.setup_alien_cache_type) ]) symbol_cbs = SymbolCallbacks([('slab_caches', setup_slab_caches), ('cache_chain', setup_slab_caches)])
try: mnt = mnt['mnt'].address except gdb.error: pass name = "" # Gone are the days where finding the root was as simple as # dentry == dentry->d_parent while dentry != root['dentry'] or mnt != root['mnt']: # pylint: disable=consider-using-in if dentry == mnt['mnt_root'] or dentry == dentry['d_parent']: if mount != mount['mnt_parent']: dentry = mount['mnt_mountpoint'] mount = mount['mnt_parent'] try: mnt = mount['mnt'].address except gdb.error: mnt = mount continue break name = "/" + dentry['d_name']['name'].string() + name dentry = dentry['d_parent'] if not name: name = '/' return name type_cbs = TypeCallbacks([('struct vfsmount', _check_mount_type)]) symbols_cbs = SymbolCallbacks([('init_task', Mount.check_task_interface)])
if not self.is_tail(): return self return self.__class__.from_page_addr(self.__compound_head()) type_cbs = TypeCallbacks([('struct page', Page.setup_page_type), ('enum pageflags', Page.setup_pageflags), ('enum zone_type', Page.setup_zone_type), ('struct mem_section', Page.setup_mem_section)]) msymbol_cbs = MinimalSymbolCallbacks([('kernel_config_data', Page.setup_nodes_width)]) # TODO: this should better be generalized to some callback for # "config is available" without refering to the symbol name here symbol_cbs = SymbolCallbacks([('vmemmap_base', Page.setup_vmemmap_base), ('page_offset_base', Page.setup_directmap_base)]) def pfn_to_page(pfn: int) -> 'Page': return Page(Page.pfn_to_page(pfn), pfn) def page_from_addr(addr: int) -> 'Page': pfn = (addr - Page.directmap_base) // Page.PAGE_SIZE return pfn_to_page(pfn) def page_from_gdb_obj(gdb_obj: gdb.Value) -> 'Page': pfn = (int(gdb_obj.address) - Page.vmemmap_base) // types.page_type.sizeof return Page(gdb_obj, pfn)
'TASK_UNINTERRUPTIBLE', 'EXIT_ZOMBIE', 'TASK_STOPPED', ] missing = [] for bit in required: if not cls.has_flag(bit): missing.append(bit) if missing: raise RuntimeError("Missing required task states: {}" .format(",".join(missing))) symbol_cbs = SymbolCallbacks([('task_state_array', TaskStateFlags.task_state_flags_callback)]) TF = TaskStateFlags class LinuxTask: """ A wrapper class for ``struct task_struct``. There will be typically one of these allocated for every task discovered in the debugging environment. Args: task_struct: The task to wrap. The value must be of type ``struct task_struct``. Attributes: task_struct (:obj:`gdb.Value`): The task being wrapped. The value
def for_each_possible_cpu() -> Iterable[int]: """ Yield CPU numbers of all possible CPUs Yields: :obj:`int`: Number of a possible CPU location """ for cpu in TypesCPUClass.cpus_possible: yield cpu def highest_possible_cpu_nr() -> int: """ Return The highest possible CPU number Returns: :obj:`int`: The highest possible CPU number """ if not TypesCPUClass.cpus_possible: raise DelayedAttributeError('cpus_possible') return TypesCPUClass.cpus_possible[-1] symbol_cbs = SymbolCallbacks([ ('cpu_online_mask', TypesCPUClass.setup_online_mask), ('__cpu_online_mask', TypesCPUClass.setup_online_mask), ('cpu_possible_mask', TypesCPUClass.setup_possible_mask), ('__cpu_possible_mask', TypesCPUClass.setup_possible_mask) ])
def for_each_online_nid(self) -> Iterable[int]: """ Iterate over each online NUMA Node ID Yields: :obj:`int`: The next NUMA Node ID """ if not self.nids_online: raise DelayedAttributeError('node_states') for nid in self.nids_online: yield nid symbol_cbs = SymbolCallbacks([('node_states', NodeStates.setup_node_states)]) _state = NodeStates() def for_each_nid() -> Iterable[int]: """ Iterate over each NUMA Node ID Yields: :obj:`int`: The next NUMA Node ID """ for nid in _state.for_each_nid(): yield nid
Args: inode: The ``struct inode`` for which to return the associated block device. The value must be of type ``struct inode``. Returns: :obj:`gdb.Value`: The ``struct block_device`` associated with the provided ``struct inode``. The value is of type ``struct inode``. """ if is_bdev_inode(inode): return inode_to_block_device(inode) return inode['i_sb']['s_bdev'].dereference() # pylint: disable=unused-argument def _check_types(result: gdb.Symbol) -> None: try: if symvals.part_type.type.unqualified() != types.device_type_type: raise TypeError("part_type expected to be {} not {}".format( symvals.device_type_type, types.part_type.type)) if symvals.disk_type.type.unqualified() != types.device_type_type: raise TypeError("disk_type expected to be {} not {}".format( symvals.device_type_type, types.disk_type.type)) except DelayedAttributeError: pass symbol_cbs = SymbolCallbacks([('disk_type', _check_types), ('part_type', _check_types)]) type_cbs = TypeCallbacks([('struct device_type', _check_types)])
return Page.mfn2pfn(mfn) def m2p(maddr): if not Page.xen_m2p_needed: return maddr mfn = maddr >> Page.PAGE_SHIFT pfn = mfn2pfn(mfn) return pfn << Page.PAGE_SHIFT # TODO: this should better be generalized to some callback for # "config is available" without refering to the symbol name here symbol_cbs = SymbolCallbacks([('vmemmap_base', Page.setup_vmemmap_base), ('page_offset_base', Page.setup_directmap_base), ('gfpflag_names', _setup_flag_names), ('pageflag_names', _setup_flag_names), ('xen_domain_type', Page.setup_xen_m2p)]) def page_addr(struct_page_addr: int) -> int: pfn = (struct_page_addr - Page.vmemmap_base) // types.page_type.sizeof return Page.directmap_base + (pfn * Page.PAGE_SIZE) def pfn_to_page(pfn: int) -> 'Page': return Page(Page.pfn_to_page(pfn), pfn) def page_from_addr(addr: int) -> 'Page': pfn = (addr - Page.directmap_base) // Page.PAGE_SIZE