diff options
Diffstat (limited to 'external/construct/formats/executable/elf32.py')
-rw-r--r-- | external/construct/formats/executable/elf32.py | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/external/construct/formats/executable/elf32.py b/external/construct/formats/executable/elf32.py new file mode 100644 index 0000000..246ae32 --- /dev/null +++ b/external/construct/formats/executable/elf32.py @@ -0,0 +1,154 @@ +""" +Executable and Linkable Format (ELF), 32 bit, big or little endian +Used on *nix systems as a replacement of the older a.out format + +Big-endian support kindly submitted by Craig McQueen (mcqueen-c#edsrd1!yzk!co!jp) +""" +from construct import * +import six + + +def elf32_body(ElfInt16, ElfInt32): + elf32_program_header = Struct("program_header", + Enum(ElfInt32("type"), + NULL = 0, + LOAD = 1, + DYNAMIC = 2, + INTERP = 3, + NOTE = 4, + SHLIB = 5, + PHDR = 6, + _default_ = Pass, + ), + ElfInt32("offset"), + ElfInt32("vaddr"), + ElfInt32("paddr"), + ElfInt32("file_size"), + ElfInt32("mem_size"), + ElfInt32("flags"), + ElfInt32("align"), + ) + + elf32_section_header = Struct("section_header", + ElfInt32("name_offset"), + Pointer(lambda ctx: ctx._.strtab_data_offset + ctx.name_offset, + CString("name") + ), + Enum(ElfInt32("type"), + NULL = 0, + PROGBITS = 1, + SYMTAB = 2, + STRTAB = 3, + RELA = 4, + HASH = 5, + DYNAMIC = 6, + NOTE = 7, + NOBITS = 8, + REL = 9, + SHLIB = 10, + DYNSYM = 11, + _default_ = Pass, + ), + ElfInt32("flags"), + ElfInt32("addr"), + ElfInt32("offset"), + ElfInt32("size"), + ElfInt32("link"), + ElfInt32("info"), + ElfInt32("align"), + ElfInt32("entry_size"), + OnDemandPointer(lambda ctx: ctx.offset, + HexDumpAdapter(Field("data", lambda ctx: ctx.size)) + ), + ) + + return Struct("body", + Enum(ElfInt16("type"), + NONE = 0, + RELOCATABLE = 1, + EXECUTABLE = 2, + SHARED = 3, + CORE = 4, + ), + Enum(ElfInt16("machine"), + NONE = 0, + M32 = 1, + SPARC = 2, + I386 = 3, + Motorolla68K = 4, + Motorolla88K = 5, + Intel860 = 7, + MIPS = 8, + _default_ = Pass + ), + ElfInt32("version"), + ElfInt32("entry"), + ElfInt32("ph_offset"), + ElfInt32("sh_offset"), + ElfInt32("flags"), + ElfInt16("header_size"), + ElfInt16("ph_entry_size"), + ElfInt16("ph_count"), + ElfInt16("sh_entry_size"), + ElfInt16("sh_count"), + ElfInt16("strtab_section_index"), + + # calculate the string table data offset (pointer arithmetics) + # ugh... anyway, we need it in order to read the section names, later on + Pointer(lambda ctx: + ctx.sh_offset + ctx.strtab_section_index * ctx.sh_entry_size + 16, + ElfInt32("strtab_data_offset"), + ), + + # program header table + Rename("program_table", + Pointer(lambda ctx: ctx.ph_offset, + Array(lambda ctx: ctx.ph_count, + elf32_program_header + ) + ) + ), + + # section table + Rename("sections", + Pointer(lambda ctx: ctx.sh_offset, + Array(lambda ctx: ctx.sh_count, + elf32_section_header + ) + ) + ), + ) + +elf32_body_little_endian = elf32_body(ULInt16, ULInt32) +elf32_body_big_endian = elf32_body(UBInt16, UBInt32) + +elf32_file = Struct("elf32_file", + Struct("identifier", + Magic(six.b("\x7fELF")), + Enum(Byte("file_class"), + NONE = 0, + CLASS32 = 1, + CLASS64 = 2, + ), + Enum(Byte("encoding"), + NONE = 0, + LSB = 1, + MSB = 2, + ), + Byte("version"), + Padding(9), + ), + Embedded(IfThenElse("body", lambda ctx: ctx.identifier.encoding == "LSB", + elf32_body_little_endian, + elf32_body_big_endian, + )), +) + + +if __name__ == "__main__": + obj = elf32_file.parse_stream(open("../../../tests/_ctypes_test.so", "rb")) + #[s.data.value for s in obj.sections] + print(obj) + + + |