Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100755 188 lines (170 sloc) 4.953 kB
8fbb79f @comex bad crap
authored
1 """
2 Executable and Linkable Format (ELF)
3 Note: This version is modified from construct's to support more section types, 64-bit, big endian?
4 """
5 from construct import *
6 from int24 import *
7 import elfconst
8
9 big_endian = False
10 sixtyfour_bit = False
11
12 if big_endian:
13 UInt64 = UBInt64
14 UInt32 = UBInt32
15 UInt16 = UBInt16
16 SInt64 = SBInt64
17 SInt32 = SBInt32
18 SInt16 = SBInt16
19 UInt24 = UBInt24
20 EndianStruct = Struct
21 else:
22 UInt64 = ULInt64
23 UInt32 = ULInt32
24 UInt16 = ULInt16
25 SInt64 = SLInt64
26 SInt32 = SLInt32
27 SInt16 = SLInt16
28 UInt24 = ULInt24
29 EndianStruct = lambda name, *rest: Struct(name, *(rest[::-1]))
30
31 UIntX = [UInt32, UInt64][sixtyfour_bit]
32 SIntX = [SInt32, SInt64][sixtyfour_bit]
33
34 elf_r_info = Embedded(EndianStruct("info",
35 (UInt32 if sixtyfour_bit else UInt24)("sym"),
36 Enum((UInt32 if sixtyfour_bit else ULInt8)("type"), **elfconst.r_386)
37 ))
38
39 if sixtyfour_bit:
40 elf_sym = Struct("symbol",
41 UInt64("name"),
42 ULInt8("info"),
43 ULInt8("other"),
44 UInt16("section_index"),
45 Padding(4),
46 UInt64("value"),
47 UInt64("size"),
48 )
49 else:
50 elf_sym = Struct("symbol",
51 UInt32("name"),
52 UInt32("value"),
53 UInt32("size"),
54 ULInt8("info"),
55 ULInt8("other"),
56 UInt16("section_index"),
57 )
58
59
60 elf_rel = Struct("rel",
61 UIntX("offset"),
62 elf_r_info,
63 )
64
65 elf_rela = Struct("rela",
66 UIntX("offset"),
67 elf_r_info,
68 SIntX("addend"),
69 )
70
71 elf_program_header = Struct("program_header",
72 Enum(UInt32("type"), **elfconst.pt),
73 UInt32("flags") if sixtyfour_bit else Pass,
74 UIntX("offset"),
75 UIntX("vaddr"),
76 UIntX("paddr"),
77 UIntX("file_size"),
78 UIntX("mem_size"),
79 Pass if sixtyfour_bit else UInt32("flags"),
80 UIntX("align"),
81 )
82
83 elf_section_header = Struct("section_header",
84 UInt32("name_offset"),
85 Pointer(lambda ctx: ctx._.strtab_data_offset + ctx.name_offset,
86 CString("name")
87 ),
88 Enum(UInt32("type"), **elfconst.sht),
89 UIntX("flags"),
90 UIntX("addr"),
91 UIntX("offset"),
92 UIntX("size"),
93 UInt32("link"),
94 UInt32("info"),
95 UIntX("align"),
96 UIntX("entry_size"),
97 Pointer(lambda ctx: ctx.offset,
98 Switch("data", lambda ctx: ctx.type, {
99 "NULL": Pass,
100 "PROGBIS": OnDemand(HexDumpAdapter(Field("data", lambda ctx: ctx.size))),
101 "SYMTAB": Array(lambda ctx: ctx.size / elf_sym.sizeof(), elf_sym),
102 "STRTAB": Pass,
103 "RELA": Array(lambda ctx: ctx.size / elf_rela.sizeof(), elf_rela),
104 "DYNAMIC": Pass,
105 "NOTE": Pass,
106 "NOBITS": Pass,
107 "REL": Array(lambda ctx: ctx.size / elf_rel.sizeof(), elf_rel),
108 "SHLIB": Pass,
109 "DYNSYM": Pass,
110 "INIT_ARRAY": Pass,
111 "FINI_ARRAY": Pass,
112 "PREINIT_ARARY": Pass,
113 }, default=Pass)
114 )
115 )
116
117 elf_file = Struct("elf_file",
118 Struct("identifier",
119 Const(Bytes("magic", 4), "\x7fELF"),
120 Enum(Byte("file_class"),
121 NONE = 0,
122 CLASS32 = 1,
123 CLASS64 = 2,
124 ),
125 Enum(Byte("encoding"),
126 NONE = 0,
127 LSB = 1,
128 MSB = 2,
129 ),
130 Byte("version"),
131 Padding(9),
132 ),
133 Enum(UInt16("type"),
134 NONE = 0,
135 RELOCATABLE = 1,
136 EXECUTABLE = 2,
137 SHARED = 3,
138 CORE = 4,
139 ),
140 Enum(UInt16("machine"), **elfconst.em),
141 UInt32("version"),
142 UIntX("entry"),
143 UIntX("ph_offset"),
144 UIntX("sh_offset"),
145 UInt32("flags"),
146 UInt16("header_size"),
147 UInt16("ph_entry_size"),
148 UInt16("ph_count"),
149 UInt16("sh_entry_size"),
150 UInt16("sh_count"),
151 UInt16("strtab_section_index"),
152
153 # calculate the string table data offset (pointer arithmetics)
154 # ugh... anyway, we need it in order to read the section names, later on
155 Pointer(lambda ctx:
156 ctx.sh_offset + ctx.strtab_section_index * ctx.sh_entry_size + (24 if sixtyfour_bit else 16),
157 UInt32("strtab_data_offset"),
158 ),
159
160 # program header table
161 Rename("program_table",
162 Pointer(lambda ctx: ctx.ph_offset,
163 Array(lambda ctx: ctx.ph_count,
164 elf_program_header
165 )
166 )
167 ),
168
169 # section table
170 Rename("sections",
171 Pointer(lambda ctx: ctx.sh_offset,
172 Array(lambda ctx: ctx.sh_count,
173 elf_section_header
174 )
175 )
176 ),
177 )
178
179
180 if __name__ == "__main__":
181 import sys
182 from construct_try import construct_try
183 obj = construct_try(lambda: elf_file.parse_stream(open(sys.argv[1], "rb")))
184 print obj
185 #[s.data.value for s in obj.sections if s.data is not None]
186 #print obj
187
Something went wrong with that request. Please try again.