Esempio n. 1
0
def container_of(val: gdb.Value, gdbtype: gdb.Type, member: str) -> gdb.Value:
    """
    Returns an object that contains the specified object at the given
    offset.

    Args:
        val (gdb.Value): The value to be converted.  It can refer to an
            allocated structure or a pointer.
        gdbtype (gdb.Type): The type of the object that will be generated
        member (str):
            The name of the member in the target struct that contains `val`.

    Returns:
        gdb.Value<gdbtype>: The converted object, of the type specified by
            the caller.
    Raises:
        TypeError: val is not a gdb.Value
    """
    if not isinstance(val, gdb.Value):
        raise ArgumentTypeError('val', val, gdb.Value)
    if not isinstance(gdbtype, gdb.Type):
        raise ArgumentTypeError('gdbtype', gdbtype, gdb.Type)
    charp = types.char_p_type
    if val.type.code != gdb.TYPE_CODE_PTR:
        val = val.address
    offset = offsetof(gdbtype, member)
    return (val.cast(charp) - offset).cast(gdbtype.pointer()).dereference()
Esempio n. 2
0
    def setup_page_type(cls, gdbtype: gdb.Type) -> None:
        # TODO: should check config, but that failed to work on ppc64, hardcode
        # 64k for now
        if crash.current_target().arch.name() == "powerpc:common64":
            cls.PAGE_SHIFT = 16
            # also a config
            cls.directmap_base = 0xc000000000000000

            cls.sparsemem = True
            cls.sparsemem_vmemmap = False
            cls.sparsemem_extreme = False
            cls.SECTION_SIZE_BITS = 24

        cls.PAGE_SIZE = 1 << cls.PAGE_SHIFT
        cls.PAGE_MASK = ~(cls.PAGE_SIZE - 1)

        cls.slab_cache_name = find_member_variant(gdbtype,
                                                  ['slab_cache', 'lru'])
        cls.slab_page_name = find_member_variant(gdbtype, ['slab_page', 'lru'])
        cls.compound_head_name = find_member_variant(
            gdbtype, ['compound_head', 'first_page'])
        if not hasattr(cls, 'vmemmap'):
            cls.vmemmap = gdb.Value(cls.vmemmap_base).cast(gdbtype.pointer())

        if struct_has_member(gdbtype, 'page_type'):
            cls._is_buddy = cls.__is_buddy_page_type
        else:
            cls._is_buddy = cls.__is_buddy_mapcount

        cls.setup_page_type_done = True
        if cls.setup_pageflags_done and not cls.setup_pageflags_finish_done:
            cls.setup_pageflags_finish()
Esempio n. 3
0
def all_type_tags(gdb_type: gdb.Type, names=None, ops=None, seen=None) -> set:
    name_list = list(names or []) if isinstance(names, set) else names or []
    seen = seen or set([])
    ops = ops or []
    prev_type = None

    while prev_type != gdb_type:
        prev_type = gdb_type
        gdb_type = gdb_type.unqualified()
        if str(gdb_type) in seen:
            break
        seen.add(str(gdb_type))
        if gdb_type.tag is not None:
            print(" .. : <tag=%s>" % str(gdb_type.tag))
            name_list.append(gdb_type.tag)
        if gdb_type.name is not None:
            print(" .. : <name=%s>" % str(gdb_type.name))
            name_list.append(gdb_type.name)

        if gdb_type.code in \
           (gdb.TYPE_CODE_PTR, gdb.TYPE_CODE_REF, gdb.TYPE_CODE_RVALUE_REF,
            gdb.TYPE_CODE_ARRAY):
            print(" .. [%s].target() -> %s" %
                  (str(gdb_type), str(gdb_type.target())))
            gdb_type = gdb_type.target()
            ops.append(gdb.Value.referenced_value)

        elif gdb_type.code in \
          (gdb.TYPE_CODE_UNION, gdb.TYPE_CODE_STRUCT):
            next_base = next = None
            for field in gdb_type.fields():
                if field.type in (prev_type, gdb_type, None if
                                  prev_type is None else prev_type.pointer(),
                                  gdb_type.pointer()):
                    continue
                if field.is_base_class:
                    print(
                      f"   [%s].{field.name} ***BASE_CLASS*** {str(field.type)}"\
                        % (str(field.parent_type)))
                all_type_tags(
                    field.type,
                    names=name_list,
                    ops=(ops + [(lambda v: v.cast(field.parent_type)[field])]),
                    seen=seen)

        elif gdb_type.code == gdb.TYPE_CODE_TYPEDEF:
            print(" [%s] typedef -> %s" %
                  (str(gdb_type), str(gdb_type.strip_typedefs())))
            ops.append(lambda v: v.cast(v.type.strip_typedefs()))
            gdb_type = gdb_type.strip_typedefs()
    return (set(name_list), ops)
Esempio n. 4
0
def get_minsymbol_pointer(symname: str, gdbtype: gdb.Type) -> gdb.Value:
    """
    Looks up a minsymbol by name and returns a typed pointer to it.

    Args:
        symname (str): The name of minsymbol to lookup.
        gdbtype (gdb.Type): The type of the minsymbol.

    Returns:
        gdb.Value: The pointer of given type to the minsymbol.
    Raises:
        MissingSymbolError: The minsymbol cannot be located
    """
    sym = gdb.lookup_minimal_symbol(symname)
    if not sym:
        raise MissingSymbolError(f"Cannot locate minsymbol {symname}")
    addr = sym.value().address
    return addr.cast(gdbtype.pointer())
Esempio n. 5
0
def get_typed_pointer(val: AddressSpecifier, gdbtype: gdb.Type) -> gdb.Value:
    """
    Returns a pointer to the requested type at the given address

    If the val is passed as a gdb.Value, it will be casted to
    the expected type.  If it is not a pointer, the address of the
    value will be used instead.

    Args:
        val (gdb.Value, str, or int): The address for which to provide
            a casted pointer
        gdbtype (gdb.Type): The type of the pointer to return

    Returns:
        gdb.Value: The casted pointer of the requested type

    Raises:
        TypeError: string value for val does not describe a hex address or
            the type cannot be converted to an address
    """
    if gdbtype.code != gdb.TYPE_CODE_PTR:
        gdbtype = gdbtype.pointer()
    if isinstance(val, gdb.Value):
        if val.type.code != gdb.TYPE_CODE_PTR:
            val = val.address
    elif isinstance(val, str):
        try:
            val = int(val, 16)
        except TypeError as e:
            raise TypeError(
                "string must describe hex address: {}".format(e)) from None
    else:
        val = int(val)

    if isinstance(val, int):
        ret = gdb.Value(val).cast(gdbtype)
    elif isinstance(val, gdb.Value):
        ret = val.cast(gdbtype)
    else:
        raise TypeError(f"val is unexpected type {type(val)}")

    return ret
Esempio n. 6
0
 def callback(self, value: gdb.Type) -> None:
     if self.pointer:
         value = value.pointer()
     self.value = value