summaryrefslogtreecommitdiff
path: root/external/construct/formats/executable/elf32.py
diff options
context:
space:
mode:
Diffstat (limited to 'external/construct/formats/executable/elf32.py')
-rw-r--r--external/construct/formats/executable/elf32.py154
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)
+
+
+