def GenBareBonesA64(): sec_null = elfhelper.Section.MakeSectionNull() sec_text = elfhelper.Section.MakeSectionText(1) sec_text.data = bytes(ALL_A64) sec_text.sh_size = len(sec_text.data) sec_shstrtab = elfhelper.Section.MakeSectionStrTab(".shstrtab") sec_shstrtab.data = elfhelper.MakeSecStrTabContents( [sec_null, sec_text, sec_shstrtab]) sec_shstrtab.sh_size = len(sec_shstrtab.data) seg_exe = elfhelper.Segment.MakeExeSegment(65536) seg_exe.sections.append(sec_null) seg_exe.sections.append(sec_text) seg_pseudo = elfhelper.Segment.MakePseudoSegment() seg_pseudo.sections.append(sec_shstrtab) exe = elfhelper.Executable.MakeExecutableA64( 0x400000, [sec_null, sec_text, sec_shstrtab], [seg_exe, seg_pseudo]) exe.update_vaddrs_and_offset() print(f"PATCH ENTRY: {sec_text.sh_addr:x}") exe.ehdr.e_entry = sec_text.sh_addr print(f"PATCH INSTRUCTIONS: {sec_text.sh_addr:x}") # simplifying assumption - we stay on the same page so adrp # does not need patching only the add instruction following it msg_adr = sec_text.sh_addr + 9 * 4 add_ins = 0x91035021 & 0xff0003ff | ((msg_adr & 0xfff) << 10) sec_text.data = (ALL_A64[:8] + add_ins.to_bytes(4, "little") + ALL_A64[12:]) return exe
def GenBareBonesA32(): sec_null = elfhelper.Section.MakeSectionNull() sec_text = elfhelper.Section.MakeSectionText(1) sec_text.data = bytes(ALL_A32) sec_text.sh_size = len(sec_text.data) sec_shstrtab = elfhelper.Section.MakeSectionStrTab(".shstrtab") sec_shstrtab.data = elfhelper.MakeSecStrTabContents([sec_null, sec_text, sec_shstrtab]) sec_shstrtab.sh_size = len(sec_shstrtab.data) seg_exe = elfhelper.Segment.MakeExeSegment(65536) seg_exe.sections.append(sec_null) seg_exe.sections.append(sec_text) seg_pseudo = elfhelper.Segment.MakePseudoSegment() seg_pseudo.sections.append(sec_shstrtab) exe = elfhelper.Executable.MakeExecutableA32( 0x20000, [sec_null, sec_text, sec_shstrtab], [seg_exe, seg_pseudo]) exe.update_vaddrs_and_offset() print(f"PATCH ENTRY: {sec_text.sh_addr:x}") exe.ehdr.e_entry = sec_text.sh_addr return exe
def GenBareBonesX64() -> elfhelper.Executable: sec_null = elfhelper.Section.MakeSectionNull() sec_rodata = elfhelper.Section.MakeSectionRodata(1) sec_rodata.data = RODATA_X64 sec_rodata.sh_size = len(sec_rodata.data) sec_text = elfhelper.Section.MakeSectionText(1) sec_text.data = bytes(TEXT_X64) sec_text.sh_size = len(sec_text.data) sec_shstrtab = elfhelper.Section.MakeSectionStrTab(".shstrtab") sec_shstrtab.data = elfhelper.MakeSecStrTabContents( [sec_null, sec_rodata, sec_text, sec_shstrtab]) sec_shstrtab.sh_size = len(sec_shstrtab.data) seg_ro = elfhelper.Segment.MakeROSegment(4096) seg_exe = elfhelper.Segment.MakeExeSegment(4096) seg_pseudo = elfhelper.Segment.MakePseudoSegment() seg_ro.sections.append(sec_null) seg_ro.sections.append(sec_rodata) seg_exe.sections.append(sec_text) seg_pseudo.sections.append(sec_shstrtab) exe = elfhelper.Executable.MakeExecutableX64( 0x400000, [sec_null, sec_rodata, sec_text, sec_shstrtab], [seg_ro, seg_exe, seg_pseudo]) exe.update_vaddrs_and_offset() print(f"PATCH ENTRY: {sec_text.sh_addr:x}") exe.ehdr.e_entry = sec_text.sh_addr print(f"PATCH MSG: {sec_rodata.sh_addr:x}") # string address is at offset 14 sec_text.data = (bytes(TEXT_X64[:17]) + sec_rodata.sh_addr.to_bytes(4, "little") + bytes(TEXT_X64[21:])) return exe
def Assemble(unit: elf_unit.Unit, create_sym_tab: bool) -> elf.Executable: sections = [] segments = [] seg_exe = elf.Segment.MakeExeSegment(65536) segments.append(seg_exe) sec_null = elf.Section.MakeSectionNull() sections.append(sec_null) seg_exe.sections.append(sec_null) # sec_text = unit.sec_text assert len(sec_text.data) > 0 sections.append(sec_text) seg_exe.sections.append(sec_text) sec_rodata = unit.sec_rodata if len(sec_rodata.data) > 0: seg_ro = elf.Segment.MakeROSegment(65536) segments.append(seg_ro) # sections.append(sec_rodata) seg_ro.sections.append(sec_rodata) if len(unit.sec_data.data) + len(unit.sec_bss.data) > 0: seg_rw = elf.Segment.MakeRWSegment(65536) segments.append(seg_rw) sec_data = unit.sec_data if len(sec_data.data) > 0: sections.append(sec_data) seg_rw.sections.append(sec_data) sec_bss = unit.sec_bss if len(sec_bss.data) > 0: sections.append(sec_bss) seg_rw.sections.append(sec_bss) seg_pseudo = elf.Segment.MakePseudoSegment() segments.append(seg_pseudo) # if create_sym_tab: # we do not create the content here since we cannot really do this until # the section addresses are finalized which = elf_enum.EI_CLASS.X_64 sec_symtab = elf.Section.MakeSectionSymTab(".symtab", which, len(sections) + 1) sections.append(sec_symtab) sec_symtab.SetData( bytearray(len(unit.symbols) * elf.Symbol.SIZE[which])) seg_pseudo.sections.append(sec_symtab) # TODO: this is not quite right sec_symtab.sh_info = len(unit.symbols) sym_names = bytearray() sym_names += b"\0" for sym in unit.symbols: if sym.name: sym.st_name = len(sym_names) sym_names += (bytes(sym.name, "utf-8") + b"\0") else: sym.st_name = 0 sec_symstrtab = elf.Section.MakeSectionStrTab(".strtab") sections.append(sec_symstrtab) sec_symstrtab.SetData(sym_names) seg_pseudo.sections.append(sec_symstrtab) sec_shstrtab = elf.Section.MakeSectionStrTab(".shstrtab") sections.append(sec_shstrtab) sec_shstrtab.SetData(elf.MakeSecStrTabContents(sections)) seg_pseudo.sections.append(sec_shstrtab) exe = elf.Executable.MakeExecutableA64(0x400000, sections, segments) exe.update_vaddrs_and_offset() if False: for sym in unit.symbols: print("@@@SYMS", sym) for rel in unit.relocations: print("@@@REL", rel) for sym in unit.symbols: if sym.section: assert sym.section.sh_addr > 0 assert sym.st_value != elf.TO_BE_FILLED_IN_LATER sym.st_value += sym.section.sh_addr sym.st_shndx = sym.section.index for rel in unit.relocations: _ApplyRelocation(rel) if create_sym_tab: # we only put dummiess in the symtable above - do it for real now sec_symtab.data = bytearray() for sym in unit.symbols: sec_symtab.AddData(sym.pack(which)) sym_entry = unit.global_symbol_map["_start"] assert sym_entry and not sym_entry.is_undefined() entry_addr = sym_entry.st_value print(f"PATCH ENTRY: {entry_addr:x}") exe.ehdr.e_entry = entry_addr return exe