Exemplo n.º 1
0
def _extract_type(type_: gdb.Type) -> Type:
    """
    Extract a gdb.Type
    """
    fields = [extract_field(f) for f in type_.fields()]
    template_arguments = []
    try:
        i = 0
        while True:
            arg = type_.template_argument(i)
            if isinstance(arg, gdb.Value):
                arg = _extract_value(arg)
            elif isinstance(arg, gdb.Type):
                arg = _extract_type(arg)
            else:
                raise ValueError("Template argument is not a gdb.Value or gdb.Type?")
            template_arguments.append(arg)
            i += 1
    except gdb.error:
        pass

    return Type(type_code=type_.code,
                name=type_.name,
                size=type_.sizeof,
                tag=type_.tag,
                fields=fields,
                template_arguments=template_arguments
               )
Exemplo n.º 2
0
    def get_basic_type(type: gdb.Type):
        """  """

        if type.code == gdb.TYPE_CODE_REF:
            # Dereference type
            type = type.target()

        # Get unqualified type, strip typedefs
        type = type.unqualified().strip_typedefs()

        return type.tag
Exemplo n.º 3
0
    def _format_struct(self,
                       type: gdb.Type,
                       force_name: str = None) -> Tuple[str, str]:
        if utils.get_type_name_or_tag(type) is not None and force_name is None:
            # Named types are not expanded since they are declared before this type
            return self.get_type_name(utils.get_type_name_or_tag(type)), ""
        else:
            if force_name is not None:
                # Named types are always written as structs since they need to be subclassable
                out = "struct"
            else:
                if type.code == gdb.TYPE_CODE_UNION:
                    out = "union"
                else:
                    out = "struct"

            if force_name is not None:
                out += " " + force_name

            out += " {\n"
            for f in type.fields():
                pre, post = self._format_type(f.type)
                out += "\n".join("  " + x for x in pre.splitlines())

                out += (" " +
                        f.name if f.name is not None else "") + post + ";\n"
            out += "}"

            return out, ""
Exemplo n.º 4
0
    def _process_type(self, parent_type: TypeWrapper, t: gdb.Type,
                      agg: TypeAggregator, process_fields: bool):
        t = t.strip_typedefs()

        if t.code == gdb.TYPE_CODE_PTR or t.code == gdb.TYPE_CODE_REF:
            basic = utils.get_basic_type(t)

            if basic.code == gdb.TYPE_CODE_FUNC:
                self._process_type(parent_type, basic.target(), agg, False)
                self._process_type_fields(parent_type, basic, agg)
            else:
                basic = utils.get_struct_type(t)
                if basic is not None:
                    agg.add_work_item(basic)
            return

        t = utils.get_struct_type(t)

        if t is None:
            # Not a struct type
            return

        if process_fields or utils.get_type_name_or_tag(t) is None:
            # Unnamed types are not added to the type graph
            self._process_type_fields(parent_type, t, agg)
        else:
            field_wrapper = agg.add_work_item(t)
            agg.add_type_reference(field_wrapper, parent_type)
Exemplo n.º 5
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()
Exemplo n.º 6
0
def _is_ast(type_: gdb.Type) -> bool:
    if type_.code == gdb.TYPE_CODE_PTR:
        target = type_.target()
        return target.name == "ast_t" or _is_ast(target)
    elif type_.code == gdb.TYPE_CODE_TYPEDEF:
        return type_.name == "ast_ptr_t"
    return False
Exemplo n.º 7
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()
Exemplo n.º 8
0
def _export_req_flags(req_flag_bits: gdb.Type) -> None:
    for (name, field) in req_flag_bits.items():
        globals()[name[2:]] = 1 << field.enumval

    # Define to 0 flags that don't exist.
    for name in ['REQ_PREFLUSH', 'REQ_FLUSH']:
        if not name in globals():
            globals()[name] = 0
Exemplo n.º 9
0
def make_template_arguments_iterator(type: gdb.Type):
    """  """

    try:
        idx = 0
        while True:
            yield type.template_argument(idx)
            idx += 1
    except RuntimeError:
        pass
Exemplo n.º 10
0
    def setup_pageflags(cls, gdbtype: gdb.Type) -> None:
        for field in gdbtype.fields():
            cls.pageflags[field.name] = field.enumval

        cls.setup_pageflags_done = True
        if cls.setup_page_type_done and not cls.setup_pageflags_finish_done:
            cls.setup_pageflags_finish()

        cls.PG_slab = 1 << cls.pageflags['PG_slab']
        cls.PG_lru = 1 << cls.pageflags['PG_lru']
Exemplo n.º 11
0
    def __populate_names(cls, enum_type: gdb.Type,
                         items_name: str) -> Tuple[int, List[str]]:
        nr_items = enum_type[items_name].enumval

        names = ["__UNKNOWN__"] * nr_items

        for field in enum_type.fields():
            if field.enumval < nr_items:
                names[field.enumval] = field.name

        return (nr_items, names)
Exemplo n.º 12
0
    def _format_type(self,
                     type: gdb.Type,
                     force_name: str = None) -> Tuple[str, str]:
        if type.code == gdb.TYPE_CODE_PTR:
            target_pre, target_post = self._format_type(type.target())
            return target_pre + "*", target_post
        elif type.code == gdb.TYPE_CODE_ARRAY:
            base = type.target()
            size = int(type.sizeof / base.sizeof)

            target_pre, target_post = self._format_type(type.target())

            return target_pre, target_post + "[" + str(size) + "]"
        elif type.code == gdb.TYPE_CODE_STRUCT or type.code == gdb.TYPE_CODE_UNION:
            return self._format_struct(type, force_name)
        elif type.code == gdb.TYPE_CODE_TYPEDEF:
            return self._format_type(type.target(), force_name)
        elif type.code == gdb.TYPE_CODE_FUNC:
            pre = "".join(self._format_type(type.target())) + "("
            arglist = type.fields()
            arglist_str = ", ".join("".join(self._format_type(x.type))
                                    for x in arglist)
            return pre, ")(" + arglist_str + ")"
        else:
            return str(type), ""
Exemplo n.º 13
0
def get_basic_type(type_: gdb.Type) -> gdb.Type:
    """Return the "basic" type of a type.

    Arguments:
        type_: The type to reduce to its basic type.

    Returns:
        type_ with const/volatile is stripped away,
        and typedefs/references converted to the underlying type.
    """

    while (type_.code == gdb.TYPE_CODE_REF
           or type_.code == gdb.TYPE_CODE_RVALUE_REF
           or type_.code == gdb.TYPE_CODE_TYPEDEF
           or type_.code == gdb.TYPE_CODE_PTR):
        if (type_.code == gdb.TYPE_CODE_REF
                or type_.code == gdb.TYPE_CODE_RVALUE_REF
                or type_.code == gdb.TYPE_CODE_PTR):
            type_ = type_.target()
        else:
            type_ = type_.strip_typedefs()
    return type_.unqualified()
Exemplo n.º 14
0
def get_struct_type(t: gdb.Type) -> Optional[gdb.Type]:
    """Return the "basic" type of a type.

    Arguments:
        type_: The type to reduce to its basic type.

    Returns:
        type_ with const/volatile is stripped away,
        and typedefs/references converted to the underlying type.
    """
    t = t.strip_typedefs()
    while True:
        if t.code == gdb.TYPE_CODE_PTR or t.code == gdb.TYPE_CODE_REF or t.code == gdb.TYPE_CODE_RVALUE_REF:
            t = t.target()
        elif t.code == gdb.TYPE_CODE_ARRAY:
            t = t.target()
        elif t.code == gdb.TYPE_CODE_TYPEDEF:
            t = t.target()
        else:
            break

    if t.code != gdb.TYPE_CODE_STRUCT and t.code != gdb.TYPE_CODE_UNION:
        return None
    else:
        return t

    while (type_.code == gdb.TYPE_CODE_REF
           or type_.code == gdb.TYPE_CODE_RVALUE_REF
           or type_.code == gdb.TYPE_CODE_TYPEDEF
           or type_.code == gdb.TYPE_CODE_PTR):
        if (type_.code == gdb.TYPE_CODE_REF
                or type_.code == gdb.TYPE_CODE_RVALUE_REF
                or type_.code == gdb.TYPE_CODE_PTR):
            type_ = type_.target()
        else:
            type_ = type_.strip_typedefs()
    return type_.unqualified()
Exemplo n.º 15
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)
Exemplo n.º 16
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())
Exemplo n.º 17
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
Exemplo n.º 18
0
    def setup_pageflags(cls, gdbtype: gdb.Type) -> None:
        for field in gdbtype.fields():
            cls.pageflags[field.name] = field.enumval

        cls.setup_pageflags_done = True
        if cls.setup_page_type_done and not cls.setup_pageflags_finish_done:
            cls.setup_pageflags_finish()

        cls.PG_slab = 1 << cls.pageflags['PG_slab']
        cls.PG_lru = 1 << cls.pageflags['PG_lru']
        cls.PG_head = 1 << cls.pageflags['PG_head']
        cls.PG_swapbacked = 1 << cls.pageflags['PG_swapbacked']

        flags_check = 0
        for flagname in _PAGE_FLAGS_CHECK_AT_FREE:
            flags_check |= 1 << cls.pageflags[flagname]

        cls.PAGE_FLAGS_CHECK_AT_FREE = flags_check
        cls.NR_PAGEFLAGS = cls.pageflags["__NR_PAGEFLAGS"]
        cls.PAGE_FLAGS_CHECK_AT_PREP = (1 << cls.NR_PAGEFLAGS) - 1
Exemplo n.º 19
0
def offsetof_type(gdbtype: gdb.Type,
                  member_name: str,
                  error: bool = True) -> Union[Tuple[int, gdb.Type], None]:
    """
    Returns the offset and type of a named member of a structure

    Args:
        gdbtype (gdb.Type): The type that contains the specified member,
            must be a struct or union
        member_name (str): The member of the member to resolve
        error (bool, optional, default=True): Whether to consider lookup
            failures an error

    Returns:
        Tuple of:
            int: The offset of the resolved member
            gdb.Type: The type of the resolved member

    Raises:
        ArgumentTypeError: gdbtype is not of type gdb.Type
        InvalidComponentError: member_name is not valid for the type
    """
    if not isinstance(gdbtype, gdb.Type):
        raise ArgumentTypeError('gdbtype', gdbtype, gdb.Type)

    # We'll be friendly and accept pointers as the initial type
    if gdbtype.code == gdb.TYPE_CODE_PTR:
        gdbtype = gdbtype.target()

    if gdbtype.code != gdb.TYPE_CODE_STRUCT and \
       gdbtype.code != gdb.TYPE_CODE_UNION:
        raise NotStructOrUnionError('gdbtype', gdbtype)

    try:
        return __offsetof(gdbtype, member_name, error)
    except _InvalidComponentBaseError as e:
        if error:
            raise InvalidComponentError(gdbtype, member_name, str(e)) from e
        return None
Exemplo n.º 20
0
    def _process_type_fields(self, parent_type: TypeWrapper, t: gdb.Type,
                             agg: TypeAggregator):
        for f in t.fields():
            field_t: gdb.Type = f.type

            self._process_type(parent_type, field_t, agg, f.name is None)
Exemplo n.º 21
0
 def can_handle(gdb_type: gdb.Type) -> bool:
     return str(gdb_type).startswith("std::vector") and str(
         gdb_type.template_argument(0)) == "bool"
Exemplo n.º 22
0
 def setup_page_ext_flags(cls, gdbtype: gdb.Type) -> None:
     for field in gdbtype.fields():
         cls.page_ext_flags[field.name] = field.enumval
Exemplo n.º 23
0
 def callback(self, value: gdb.Type) -> None:
     if self.pointer:
         value = value.pointer()
     self.value = value