Exemplo n.º 1
0
            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
Exemplo n.º 2
0
        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
    """
Exemplo n.º 3
0
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)])
Exemplo n.º 4
0
    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)])
Exemplo n.º 5
0
        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)
Exemplo n.º 6
0
            '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
Exemplo n.º 7
0
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)
])
Exemplo n.º 8
0
    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

Exemplo n.º 9
0
    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)])
Exemplo n.º 10
0
    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