def print_stats(obj: drgn.Object) -> None: names = [ memb.name for memb in sdb.get_type('struct arc_stats').members ] for name in names: print("{:32} = {}".format(name, int(obj.member_(name).value.ui64)))
def enum_lookup(enum_type_name: str, value: int) -> str: """return a string which is the short name of the enum value (truncating off the common prefix) """ fields = sdb.get_type(enum_type_name).type.enumerators enum_string: str = fields[value].name prefix = os.path.commonprefix([f[0] for f in fields]) return enum_string[prefix.rfind("_") + 1:]
def from_range_tree(self, rt: drgn.Object) -> Iterable[drgn.Object]: enum_dict = dict(sdb.get_type('enum range_seg_type').enumerators) range_seg_type_to_type = { enum_dict['RANGE_SEG32']: 'range_seg32_t*', enum_dict['RANGE_SEG64']: 'range_seg64_t*', enum_dict['RANGE_SEG_GAP']: 'range_seg_gap_t*', } seg_type_name = range_seg_type_to_type[int(rt.rt_type)] yield from sdb.execute_pipeline([rt.rt_root.address_of_()], [Btree(), Cast(seg_type_name)])
def get_valid_type_by_name(cmd: sdb.Command, tname: str) -> drgn.Type: """ Given a type name in string form (`tname`) without any C keyword prefixes (e.g. 'struct', 'enum', 'class', 'union'), return the corresponding drgn.Type object. This function is used primarily by commands that accept a type name as an argument and exist only to save keystrokes for the user. """ if tname in ['struct', 'enum', 'union', 'class']: # # Note: We have to do this because currently in drgn # prog.type('struct') returns a different error than # prog.type('bogus'). The former returns a SyntaxError # "null identifier" while the latter returns LookupError # "could not find typedef bogus". The former is not # user-friendly and thus we just avoid that situation # by instructing the user to skip such keywords. # raise sdb.CommandError( cmd.name, f"skip keyword '{tname}' or quote your type \"{tname} <typename>\"") try: type_ = sdb.get_type(tname) if type_.kind == drgn.TypeKind.TYPEDEF and type_.type_name( ) == sdb.type_canonical_name(type_): # # In some C codebases there are typedefs like this: # # typedef union GCObject GCObject; // taken from LUA repo # # The point of the above is to avoid typing the word # 'union' every time we declare a variable of that type. # For the purposes of SDB, passing around a drng.Type # describing the typedef above isn't particularly # useful. Using such an object with the `ptype` command # (one of the consumers of this function) would yield # the following: # # sdb> ptype GCObject # typedef union GCObject GCObject # # Resolving the typedef's explicitly in those cases # is more useful and this is why this if-clause exists. # # sdb> ptype GCObject # union GCObject { # GCheader gch; # union TString ts; # ... # } # return sdb.type_canonicalize(type_) return type_ except LookupError: # # We couldn't find a type with that name. Check if # it is a structure, an enum, or a union. # pass for prefix in ["struct ", "enum ", "union "]: try: return sdb.get_type(f"{prefix}{tname}") except LookupError: pass raise sdb.CommandError( cmd.name, f"couldn't find typedef, struct, enum, nor union named '{tname}'")
def get_valid_type_by_name(cmd: sdb.Command, tname: str) -> drgn.Type: """ Given a type name in string form (`tname`) without any C keyword prefixes (e.g. 'struct', 'enum', 'class', 'union'), return the corresponding drgn.Type object. If `tname` starts with a C keyword we just return the type as is. This function is used primarily by commands that accept a type name as an argument and exist only to save keystrokes for the user. """ TYPE_KEYWORDS = ['struct', 'enum', 'union', 'class'] tokens = tname.split() if len(tokens) > 2: # # drgn fails in all kinds of ways when we pass it an # invalid type that consists of more than 2 text tokens. # raise sdb.CommandError(cmd.name, f"input '{tname}' is not a valid type name") if len(tokens) == 2: if tokens[0] not in TYPE_KEYWORDS or tokens[1] in TYPE_KEYWORDS: # # For the same reason mentioned in the above comment # we also ensure that someone may not invalid two-token # input that has the following errors: # 1] Doesn't start with a type keyword - e.g "bogus type" # 2] Has a type keyword as its type name (also see # comment below) - e.g. struct struct # raise sdb.CommandError( cmd.name, f"input '{tname}' is not a valid type name") try: return sdb.get_type(tname) except LookupError as err: raise sdb.CommandError(cmd.name, f"couldn't find type '{tname}'") from err except SyntaxError as err: raise sdb.CommandError( cmd.name, f"input '{tname}' is not a valid type name") from err if tname in TYPE_KEYWORDS: # # Note: We have to do this because currently in drgn # prog.type('struct') returns a different error than # prog.type('bogus'). The former returns a SyntaxError # "null identifier" while the latter returns LookupError # "could not find typedef bogus". The former is not # user-friendly and thus we just avoid that situation # by instructing the user to skip such keywords. # raise sdb.CommandError( cmd.name, f"skip keyword '{tname}' or quote your type \"{tname} <typename>\"" ) try: type_ = sdb.get_type(tname) if type_.kind == drgn.TypeKind.TYPEDEF and type_.type_name( ) == sdb.type_canonical_name(type_): # # In some C codebases there are typedefs like this: # # typedef union GCObject GCObject; // taken from LUA repo # # The point of the above is to avoid typing the word # 'union' every time we declare a variable of that type. # For the purposes of SDB, passing around a drng.Type # describing the typedef above isn't particularly # useful. Using such an object with the `ptype` command # (one of the consumers of this function) would yield # the following: # # sdb> ptype GCObject # typedef union GCObject GCObject # # Resolving the typedef's explicitly in those cases # is more useful and this is why this if-clause exists. # # sdb> ptype GCObject # union GCObject { # GCheader gch; # union TString ts; # ... # } # return sdb.type_canonicalize(type_) return type_ except LookupError: # # We couldn't find a type with that name. Check if # it is a structure, an enum, or a union. # pass except SyntaxError as err: raise sdb.CommandError( cmd.name, f"input '{tname}' is not a valid type name") from err for prefix in TYPE_KEYWORDS: try: return sdb.get_type(f"{prefix} {tname}") except LookupError: pass raise sdb.CommandError( cmd.name, f"couldn't find typedef, struct, enum, nor union named '{tname}'")