def extract_and_parse_die(off): if off in DIEs: print("Using cached {}".format(DIEs[off]), file=sys.stderr) return txts = dwarfutils.extract_dies_by_offset(args.dwarffile.name, off) txt = txts[0] print(txt, file=sys.stderr) assert dwarfutils.extract_offset(txt) == off handlers = { "TAG_array_type": parse_array_type, "TAG_base_type": parse_base_type, "TAG_compile_unit": parse_compile_unit_type, "TAG_const_type": parse_const_type, "TAG_enumeration_type": parse_enumeration_type, "TAG_member": parse_member_type, "TAG_pointer_type": parse_pointer_type, "TAG_structure_type": parse_structure_type, "TAG_subroutine_type": parse_subroutine_type, "TAG_typedef": parse_typedef, "TAG_union_type": parse_union_type, "TAG_variable": parse_variable_type, "TAG_volatile_type": parse_volatile_type, } tag = dwarfutils.extract_tag(txt) try: return handlers[tag](txt) except KeyError: raise NotImplementedError
def parse_struct(parent_off): txts = dwarfutils.extract_dies_by_offset(args.dwarffile.name, parent_off, children=True) level = 0 for txt in txts[1:]: if "TAG_member" in txt: if level > 0: # ignore continue parse_member_type(txt) DIEs[parent_off].members.append(dwarfutils.extract_offset(txt)) elif "NULL" in txt: level -= 1 if level < 0: return elif "TAG_union_type" in txt: if not "AT_declaration" in txt: level += 1 if level == 0: parse_union_type(txt) elif "TAG_structure_type" in txt: if not "AT_declaration" in txt: level += 1 if level == 0: parse_structure_type(txt) else: raise NotImplementedError else: assert len(txts) == 1 or "AT_declaration" in txts[0]
def find_compile_unit(off): txts = dwarfutils.extract_dies_by_offset(args.dwarffile.name, off, parents=True) assert "TAG_compile_unit" in txts[0] cu_off = dwarfutils.extract_offset(txts[0]) return cu_off
def parse_typedef(txt): off = dwarfutils.extract_offset(txt) name = dwarfutils.extract_name(txt) if "__builtin_va_list" in name: name = name.upper() type_off, type_name = dwarfutils.extract_type(txt) extract_and_parse_die(type_off) DIEs[off] = DIETypedef(name=name, ttype=(type_off, type_name))
def parse_enumeration_type(txt): off = dwarfutils.extract_offset(txt) try: name = dwarfutils.extract_name(txt) except AttributeError: name = None DIEs[off] = DIEEnumeration(name=name, members=list()) parse_enumeration(off)
def parse_const_type(txt): off = dwarfutils.extract_offset(txt) try: type_off, type_name = dwarfutils.extract_type(txt) except AttributeError: type_off, type_name = None, None else: extract_and_parse_die(type_off) DIEs[off] = DIEConst(ttype=(type_off, type_name))
def parse_union_type(txt): off = dwarfutils.extract_offset(txt) try: name = dwarfutils.extract_name(txt) except AttributeError: name = None byte_size = dwarfutils.extract_byte_size(txt) DIEs[off] = DIEUnion(name=name, byte_size=byte_size, members=list()) parse_union(off)
def parse_subroutine_type(txt): off = dwarfutils.extract_offset(txt) try: type_off, type_name = dwarfutils.extract_type(txt) except AttributeError: type_off, type_name = None, "void" else: extract_and_parse_die(type_off) DIEs[off] = DIESubroutine(ttype=(type_off, type_name), members=list()) parse_subroutine(off)
def parse_structure_type(txt): off = dwarfutils.extract_offset(txt) try: name = dwarfutils.extract_name(txt) except AttributeError: name = None try: byte_size = dwarfutils.extract_byte_size(txt) except AttributeError: assert "AT_declaration" in txt byte_size = -1 DIEs[off] = DIEStructure(name=name, byte_size=byte_size, members=list()) parse_struct(off)
def parse_subroutine(parent_off): txts = dwarfutils.extract_dies_by_offset(args.dwarffile.name, parent_off, children=True) assert dwarfutils.extract_tag(txts[0]) == "TAG_subroutine_type" for txt in txts[1:]: if "TAG_formal_parameter" in txt: off = dwarfutils.extract_offset(txt) type_off, type_name = dwarfutils.extract_type(txt) extract_and_parse_die(type_off) DIEs[off] = DIEFormalParameter(ttype=(type_off, type_name)) DIEs[parent_off].members.append(off) elif "TAG_unspecified_parameters" in txt: pass elif "NULL" in txt: return else: raise NotImplementedError
def parse_enumeration(parent_off): txts = dwarfutils.extract_dies_by_offset(args.dwarffile.name, parent_off, children=True) assert dwarfutils.extract_tag(txts[0]) == "TAG_enumeration_type" for txt in txts[1:]: if "TAG_enumerator" in txt: off = dwarfutils.extract_offset(txt) DIEs[off] = DIEEnumerator( name=dwarfutils.extract_name(txt), const_value=dwarfutils.extract_const_value(txt)) DIEs[parent_off].members.append(off) elif "NULL" in txt: return else: raise NotImplementedError else: assert "AT_declaration" in txts[0]
def parse_member_type(txt): off = dwarfutils.extract_offset(txt) try: name = dwarfutils.extract_name(txt) except AttributeError: name = None type_off, type_name = dwarfutils.extract_type(txt) extract_and_parse_die(type_off) try: location = dwarfutils.extract_location(txt) except AttributeError: try: location = dwarfutils.extract_bit_location(txt) except AttributeError: location = -1 try: bit_size = dwarfutils.extract_bit_size(txt) except AttributeError: bit_size = -1 DIEs[off] = DIEMember(name=name, ttype=(type_off, type_name), location=location, bit_size=bit_size)
def parse_variable_type(txt): off = dwarfutils.extract_offset(txt) name = dwarfutils.extract_name(txt) type_off, type_name = dwarfutils.extract_type(txt) extract_and_parse_die(type_off) DIEs[off] = DIEVariable(name=name, ttype=(type_off, type_name))
def parse_compile_unit_type(txt): off = dwarfutils.extract_offset(txt) DIEs[off] = DIECompileUnit(name=dwarfutils.extract_name(txt))
def parse_base_type(txt): off = dwarfutils.extract_offset(txt) DIEs[off] = DIEBase(name=dwarfutils.extract_name(txt), byte_size=dwarfutils.extract_byte_size(txt))
def parse_array_type(txt): off = dwarfutils.extract_offset(txt) type_off, type_name = dwarfutils.extract_type(txt) extract_and_parse_die(type_off) DIEs[off] = DIEArray(ttype=(type_off, type_name), size=_extract_array_count(off))
def parse_volatile_type(txt): off = dwarfutils.extract_offset(txt) type_off, type_name = dwarfutils.extract_type(txt) extract_and_parse_die(type_off) DIEs[off] = DIEVolatile(ttype=(type_off, type_name))