class Test(object):
            class nested(object):
                ulong_valid = False

                @classmethod
                def check_ulong(cls, gdbtype):
                    cls.ulong_valid = True

            type_cbs = TypeCallbacks([('unsigned long', nested.check_ulong)])
示例#2
0
def xfs_for_each_ail_log_item_typed(mp: gdb.Value) -> Iterable[gdb.Value]:
    """
    Iterates over the XFS Active Item Log and returns each item, resolved
    to the specific type.

    Args:
        mp: The XFS mount to iterate.  The value must be of
            type ``struct xfs_mount``.

    Yields:
        :obj:`gdb.Value`:

        Depending on type, the value will be any of the following types:

        - ``struct xfs_buf_log_item_type``
        - ``struct xfs_inode_log_item_type``
        - ``struct xfs_efi_log_item_type``
        - ``struct xfs_efd_log_item_type``
        - ``struct xfs_dq_logitem``
        - ``int`` (for UNLINK item)

    Raises:
        :obj:`gdb.NotAvailableError`: The target value was not available.
    """
    for item in types.xfs_for_each_ail_log_item(mp):
        yield types.xfs_log_item_typed(item)


type_cbs = TypeCallbacks([('struct xfs_ail', XFS.detect_ail_version)])
示例#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)])
示例#4
0
    def __compound_head_uses_low_bit(self) -> int:
        return int(self.gdb_obj['compound_head']) - 1

    def __compound_head(self) -> int:
        return self._compound_head()

    def compound_head(self) -> 'Page':
        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':
示例#5
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)])
示例#6
0
        for field in enum_type.fields():
            if field.enumval < nr_items:
                names[field.enumval] = field.name

        return (nr_items, names)

    @classmethod
    def get_stat_names(cls) -> List[str]:
        return cls.vm_stat_names

    @classmethod
    def get_event_names(cls) -> List[str]:
        return cls.vm_event_names

    @classmethod
    def get_events(cls) -> List[int]:
        nr = cls.nr_event_items
        events = [0] * nr

        for cpu in for_each_online_cpu():
            states = get_percpu_var(cls.symbols.vm_event_states, cpu)
            for item in range(0, nr):
                events[item] += int(states["event"][item])

        return events


type_cbs = TypeCallbacks([('enum zone_stat_item', VmStat.check_enum_type),
                          ('enum vm_event_item', VmStat.check_enum_type)])
示例#7
0
    def setup_thread_info(self, thread: gdb.InferiorThread) -> None:
        task = thread.info.task_struct
        thread_info = task['stack'].cast(types.thread_info_p_type)
        thread.info.set_thread_info(thread_info)

    @classmethod
    # pylint: disable=unused-argument
    def setup_inactive_task_frame_handler(cls, inactive: gdb.Type) -> None:
        cls.set_fetch_registers(_FRC_inactive_task_frame)

    @classmethod
    # pylint: disable=unused-argument
    def setup_thread_return_handler(cls, inactive: gdb.Type) -> None:
        cls.set_fetch_registers(_FRC_thread_return)

    @classmethod
    def get_stack_pointer(cls, thread_struct: gdb.Value) -> int:
        return int(thread_struct['sp'])


type_cbs = TypeCallbacks([
    ('struct inactive_task_frame',
     x86_64Architecture.setup_inactive_task_frame_handler)
])
msymbol_cbs = MinimalSymbolCallbacks([
    ('thread_return', x86_64Architecture.setup_thread_return_handler)
])

register_arch(x86_64Architecture)
示例#8
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)])
示例#9
0
            gdbtype: The ``struct device`` type.
        """
        if struct_has_member(gdbtype, 'knode_class'):
            cls._class_is_private = False

    @classmethod
    def class_is_private(cls) -> bool:
        """
        Returns whether the class device uses ``struct device_private``

        Meant to be used only be crash.types.classdev.
        """
        return cls._class_is_private


type_cbs = TypeCallbacks([('struct device',
                           ClassdevState.setup_iterator_type)])

def for_each_class_device(class_struct: gdb.Value,
                          subtype: gdb.Value = None) -> Iterable[gdb.Value]:
    """
    Iterate over the list of class devices

    Args:
        class_struct: The class of devices to iterate
        subtype: A ``struct device_type *`` to use to filter the results.
            The value must be of type ``struct device_type *`` and will
            be used to compare against the ``type`` field of each
            ``struct device``.

    Yields:
        :obj:`gdb.Value`: A device on the class's device list.  The value is
示例#10
0
        if not name in globals():
            globals()[name] = 0


# Check struct request and define functions based on its current form in this
# kernel
def _check_struct_request(request_s: gdb.Type) -> None:
    global _rq_in_flight
    if struct_has_member(request_s, 'rq_state'):

        def _rq_in_flight(request: gdb.Value) -> bool:
            return (request['rq_state'] !=
                    types.enum_mq_rq_state_type['MQ_RQ_IDLE'])
    elif struct_has_member(request_s, 'atomic_flags'):

        def _rq_in_flight(request: gdb.Value) -> bool:
            return (request['atomic_flags'] & (1 << int(
                types.enum_rq_atomic_flags_type['REQ_ATOM_STARTED'].enumval))
                    != 0)
    else:

        def _rq_in_flight(request: gdb.Value) -> bool:
            return request['cmd_flags'] & REQ_STARTED != 0  # type: ignore


symbol_cbs = SymbolCallbacks([('disk_type', _check_types),
                              ('part_type', _check_types)])
type_cbs = TypeCallbacks([('struct device_type', _check_types),
                          ('enum req_flag_bits', _export_req_flags),
                          ('struct request', _check_struct_request)])