def compile_dwarf(dies, little_endian=True, bits=64): if isinstance(dies, DwarfDie): dies = (dies, ) assert all(isinstance(die, DwarfDie) for die in dies) cu_die = DwarfDie(DW_TAG.compile_unit, [ DwarfAttrib(DW_AT.comp_dir, DW_FORM.string, '/usr/src'), DwarfAttrib(DW_AT.stmt_list, DW_FORM.sec_offset, 0), ], dies) return create_elf_file(ET.EXEC, [ ElfSection( name='.debug_abbrev', sh_type=SHT.PROGBITS, data=_compile_debug_abbrev(cu_die), ), ElfSection( name='.debug_info', sh_type=SHT.PROGBITS, data=_compile_debug_info(cu_die, little_endian, bits), ), ElfSection( name='.debug_line', sh_type=SHT.PROGBITS, data=_compile_debug_line(cu_die, little_endian), ), ElfSection( name='.debug_str', sh_type=SHT.PROGBITS, data=b'\0', ), ], little_endian=little_endian, bits=bits)
def dwarf_sections( dies, little_endian=True, bits=64, *, lang=None, use_dw_form_indirect=False ): if isinstance(dies, DwarfDie): dies = (dies,) assert all(isinstance(die, DwarfDie) for die in dies) if dies and dies[0].tag in UNIT_HEADER_TYPES: unit_dies = dies else: unit_dies = (DwarfDie(DW_TAG.compile_unit, (), dies),) assert all(die.tag in UNIT_HEADER_TYPES for die in unit_dies) unit_attribs = [DwarfAttrib(DW_AT.stmt_list, DW_FORM.sec_offset, 0)] if lang is not None: unit_attribs.append(DwarfAttrib(DW_AT.language, DW_FORM.data1, lang)) cu_attribs = unit_attribs + [ DwarfAttrib(DW_AT.comp_dir, DW_FORM.string, "/usr/src") ] unit_dies = [ DwarfDie( die.tag, list(die.attribs) + (cu_attribs if die.tag == DW_TAG.compile_unit else unit_attribs), die.children, ) for die in unit_dies ] debug_info, debug_types = _compile_debug_info( unit_dies, little_endian, bits, use_dw_form_indirect ) sections = [ ElfSection( name=".debug_abbrev", sh_type=SHT.PROGBITS, data=_compile_debug_abbrev(unit_dies, use_dw_form_indirect), ), ElfSection(name=".debug_info", sh_type=SHT.PROGBITS, data=debug_info), ElfSection( name=".debug_line", sh_type=SHT.PROGBITS, data=_compile_debug_line(unit_dies, little_endian), ), ElfSection(name=".debug_str", sh_type=SHT.PROGBITS, data=b"\0"), ] if debug_types: sections.append( ElfSection(name=".debug_types", sh_type=SHT.PROGBITS, data=debug_types) ) return sections
def compile_dwarf(dies, little_endian=True, bits=64, *, lang=None): if isinstance(dies, DwarfDie): dies = (dies, ) assert all(isinstance(die, DwarfDie) for die in dies) cu_attribs = [ DwarfAttrib(DW_AT.comp_dir, DW_FORM.string, "/usr/src"), DwarfAttrib(DW_AT.stmt_list, DW_FORM.sec_offset, 0), ] if lang is not None: cu_attribs.append(DwarfAttrib(DW_AT.language, DW_FORM.data1, lang)) cu_die = DwarfDie(DW_TAG.compile_unit, cu_attribs, dies) return create_elf_file( ET.EXEC, [ ElfSection( p_type=PT.LOAD, vaddr=0xFFFF0000, data=b"", ), ElfSection( name=".debug_abbrev", sh_type=SHT.PROGBITS, data=_compile_debug_abbrev(cu_die), ), ElfSection( name=".debug_info", sh_type=SHT.PROGBITS, data=_compile_debug_info(cu_die, little_endian, bits), ), ElfSection( name=".debug_line", sh_type=SHT.PROGBITS, data=_compile_debug_line(cu_die, little_endian), ), ElfSection( name=".debug_str", sh_type=SHT.PROGBITS, data=b"\0", ), ], little_endian=little_endian, bits=bits, )
def test_simple(self): data = b"hello, world" prog = Program() with tempfile.NamedTemporaryFile() as f: f.write( create_elf_file( ET.CORE, [ElfSection(p_type=PT.LOAD, vaddr=0xFFFF0000, data=data)])) f.flush() prog.set_core_dump(f.name) self.assertEqual(prog.read(0xFFFF0000, len(data)), data) self.assertRaises(FaultError, prog.read, 0x0, len(data), physical=True)
def test_zero_fill(self): data = b'hello, world' prog = Program() with tempfile.NamedTemporaryFile() as f: f.write( create_elf_file(ET.CORE, [ ElfSection( p_type=PT.LOAD, vaddr=0xffff0000, data=data, memsz=len(data) + 4, ), ])) f.flush() prog.set_core_dump(f.name) self.assertEqual(prog.read(0xffff0000, len(data) + 4), data + bytes(4))
def test_physical(self): data = b'hello, world' prog = Program() with tempfile.NamedTemporaryFile() as f: f.write( create_elf_file(ET.CORE, [ ElfSection( p_type=PT.LOAD, vaddr=0xffff0000, paddr=0xa0, data=data, ), ])) f.flush() prog.set_core_dump(f.name) self.assertEqual(prog.read(0xffff0000, len(data)), data) self.assertEqual(prog.read(0xa0, len(data), physical=True), data)
def create_elf_symbol_file(symbols): # We need some DWARF data so that libdwfl will load the file. sections = dwarf_sections(()) # Create a section for the symbols to reference and the corresponding # segment for address lookups. min_address = min(symbol.value for symbol in symbols) max_address = max(symbol.value + symbol.size for symbol in symbols) sections.append( ElfSection( name=".foo", sh_type=SHT.NOBITS, p_type=PT.LOAD, vaddr=min_address, memsz=max_address - min_address, )) symbols = [ symbol._replace(shindex=len(sections) if symbol.shindex is None else symbol.shindex) for symbol in symbols ] return create_elf_file(ET.EXEC, sections, symbols)
def test_unsaved(self): data = b"hello, world" prog = Program() with tempfile.NamedTemporaryFile() as f: f.write( create_elf_file( ET.CORE, [ ElfSection( p_type=PT.LOAD, vaddr=0xFFFF0000, data=data, memsz=len(data) + 4, ), ], ) ) f.flush() prog.set_core_dump(f.name) with self.assertRaisesRegex(FaultError, "memory not saved in core dump") as cm: prog.read(0xFFFF0000, len(data) + 4) self.assertEqual(cm.exception.address, 0xFFFF000C)