blob: b3e16e5015c6485743c6306a775ac15996965f50 [file] [log] [blame]
Michael J. Spencerdfd30182010-07-27 06:46:15 +00001#===-- coff-dump.py - COFF object file dump utility-------------------------===#
2#
3# The LLVM Compiler Infrastructure
4#
5# This file is distributed under the University of Illinois Open Source
6# License. See LICENSE.TXT for details.
7#
8#===------------------------------------------------------------------------===#
9
10#
11# COFF File Definition
12#
13
14def string_table_entry (offset):
15 return ('ptr', '+ + PointerToSymbolTable * NumberOfSymbols 18 %s' % offset, ('scalar', 'cstr', '%s'))
16
17def secname(value):
18 if value[0] == '/':
19 return string_table_entry (value [1:].rstrip('\0'))
20 else:
21 return '%s'
22
23def symname(value):
24 parts = struct.unpack("<2L", value)
25 if parts [0] == 0:
26 return string_table_entry (parts [1])
27 else:
28 return '%s'
29
30file = ('struct', [
31 ('MachineType', ('enum', '<H', '0x%X', {
32 0x0: 'IMAGE_FILE_MACHINE_UNKNOWN',
33 0x1d3: 'IMAGE_FILE_MACHINE_AM33',
34 0x866: 'IMAGE_FILE_MACHINE_AMD64',
35 0x1c0: 'IMAGE_FILE_MACHINE_ARM',
36 0xebc: 'IMAGE_FILE_MACHINE_EBC',
37 0x14c: 'IMAGE_FILE_MACHINE_I386',
38 0x200: 'IMAGE_FILE_MACHINE_IA64',
39 0x904: 'IMAGE_FILE_MACHINE_M32R',
40 0x266: 'IMAGE_FILE_MACHINE_MIPS16',
41 0x366: 'IMAGE_FILE_MACHINE_MIPSFPU',
42 0x466: 'IMAGE_FILE_MACHINE_MIPSFPU16',
43 0x1f0: 'IMAGE_FILE_MACHINE_POWERPC',
44 0x1f1: 'IMAGE_FILE_MACHINE_POWERPCFP',
45 0x166: 'IMAGE_FILE_MACHINE_R4000',
46 0x1a2: 'IMAGE_FILE_MACHINE_SH3',
47 0x1a3: 'IMAGE_FILE_MACHINE_SH3DSP',
48 0x1a6: 'IMAGE_FILE_MACHINE_SH4',
49 0x1a8: 'IMAGE_FILE_MACHINE_SH5',
50 0x1c2: 'IMAGE_FILE_MACHINE_THUMB',
51 0x169: 'IMAGE_FILE_MACHINE_WCEMIPSV2',
52 })),
53 ('NumberOfSections', ('scalar', '<H', '%d')),
54 ('TimeDateStamp', ('scalar', '<L', '%d')),
55 ('PointerToSymbolTable', ('scalar', '<L', '0x%0X')),
56 ('NumberOfSymbols', ('scalar', '<L', '%d')),
57 ('SizeOfOptionalHeader', ('scalar', '<H', '%d')),
58 ('Characteristics', ('flags', '<H', '0x%x', [
59 (0x0001, 'IMAGE_FILE_RELOCS_STRIPPED', ),
60 (0x0002, 'IMAGE_FILE_EXECUTABLE_IMAGE', ),
61 (0x0004, 'IMAGE_FILE_LINE_NUMS_STRIPPED', ),
62 (0x0008, 'IMAGE_FILE_LOCAL_SYMS_STRIPPED', ),
63 (0x0010, 'IMAGE_FILE_AGGRESSIVE_WS_TRIM', ),
64 (0x0020, 'IMAGE_FILE_LARGE_ADDRESS_AWARE', ),
65 (0x0080, 'IMAGE_FILE_BYTES_REVERSED_LO', ),
66 (0x0100, 'IMAGE_FILE_32BIT_MACHINE', ),
67 (0x0200, 'IMAGE_FILE_DEBUG_STRIPPED', ),
68 (0x0400, 'IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP', ),
69 (0x0800, 'IMAGE_FILE_NET_RUN_FROM_SWAP', ),
70 (0x1000, 'IMAGE_FILE_SYSTEM', ),
71 (0x2000, 'IMAGE_FILE_DLL', ),
72 (0x4000, 'IMAGE_FILE_UP_SYSTEM_ONLY', ),
73 (0x8000, 'IMAGE_FILE_BYTES_REVERSED_HI', ),
74 ])),
75 ('Sections', ('array', 'NumberOfSections', ('struct', [
76 ('Name', ('scalar', '<8s', secname)),
77 ('VirtualSize', ('scalar', '<L', '%d' )),
78 ('VirtualAddress', ('scalar', '<L', '%d' )),
79 ('SizeOfRawData', ('scalar', '<L', '%d' )),
80 ('PointerToRawData', ('scalar', '<L', '0x%X' )),
81 ('PointerToRelocations', ('scalar', '<L', '0x%X' )),
82 ('PointerToLineNumbers', ('scalar', '<L', '0x%X' )),
83 ('NumberOfRelocations', ('scalar', '<H', '%d' )),
84 ('NumberOfLineNumbers', ('scalar', '<H', '%d' )),
85 ('Charateristics', ('flags', '<L', '0x%X', [
86 (0x00000008, 'IMAGE_SCN_TYPE_NO_PAD'),
87 (0x00000020, 'IMAGE_SCN_CNT_CODE'),
88 (0x00000040, 'IMAGE_SCN_CNT_INITIALIZED_DATA'),
89 (0x00000080, 'IMAGE_SCN_CNT_UNINITIALIZED_DATA'),
90 (0x00000100, 'IMAGE_SCN_LNK_OTHER'),
91 (0x00000200, 'IMAGE_SCN_LNK_INFO'),
92 (0x00000800, 'IMAGE_SCN_LNK_REMOVE'),
93 (0x00001000, 'IMAGE_SCN_LNK_COMDAT'),
94 (0x00008000, 'IMAGE_SCN_GPREL'),
95 (0x00020000, 'IMAGE_SCN_MEM_PURGEABLE'),
96 (0x00020000, 'IMAGE_SCN_MEM_16BIT'),
97 (0x00040000, 'IMAGE_SCN_MEM_LOCKED'),
98 (0x00080000, 'IMAGE_SCN_MEM_PRELOAD'),
99 (0x00F00000, 'IMAGE_SCN_ALIGN', {
100 0x00100000: 'IMAGE_SCN_ALIGN_1BYTES',
101 0x00200000: 'IMAGE_SCN_ALIGN_2BYTES',
102 0x00300000: 'IMAGE_SCN_ALIGN_4BYTES',
103 0x00400000: 'IMAGE_SCN_ALIGN_8BYTES',
104 0x00500000: 'IMAGE_SCN_ALIGN_16BYTES',
105 0x00600000: 'IMAGE_SCN_ALIGN_32BYTES',
106 0x00700000: 'IMAGE_SCN_ALIGN_64BYTES',
107 0x00800000: 'IMAGE_SCN_ALIGN_128BYTES',
108 0x00900000: 'IMAGE_SCN_ALIGN_256BYTES',
109 0x00A00000: 'IMAGE_SCN_ALIGN_512BYTES',
110 0x00B00000: 'IMAGE_SCN_ALIGN_1024BYTES',
111 0x00C00000: 'IMAGE_SCN_ALIGN_2048BYTES',
112 0x00D00000: 'IMAGE_SCN_ALIGN_4096BYTES',
113 0x00E00000: 'IMAGE_SCN_ALIGN_8192BYTES',
114 }),
115 (0x01000000, 'IMAGE_SCN_LNK_NRELOC_OVFL'),
116 (0x02000000, 'IMAGE_SCN_MEM_DISCARDABLE'),
117 (0x04000000, 'IMAGE_SCN_MEM_NOT_CACHED'),
118 (0x08000000, 'IMAGE_SCN_MEM_NOT_PAGED'),
119 (0x10000000, 'IMAGE_SCN_MEM_SHARED'),
120 (0x20000000, 'IMAGE_SCN_MEM_EXECUTE'),
121 (0x40000000, 'IMAGE_SCN_MEM_READ'),
122 (0x80000000, 'IMAGE_SCN_MEM_WRITE'),
123 ])),
124 ('SectionData', ('ptr', 'PointerToRawData', ('blob', 'SizeOfRawData'))),
125 ('Relocations', ('ptr', 'PointerToRelocations', ('array', 'NumberOfRelocations', ('struct', [
126 ('VirtualAddress', ('scalar', '<L', '0x%X')),
127 ('SymbolTableIndex', ('scalar', '<L', '%d' )),
128 ('Type', ('enum', '<H', '%d', ('MachineType', {
129 0x14c: {
130 0x0000: 'IMAGE_REL_I386_ABSOLUTE',
131 0x0001: 'IMAGE_REL_I386_DIR16',
132 0x0002: 'IMAGE_REL_I386_REL16',
133 0x0006: 'IMAGE_REL_I386_DIR32',
134 0x0007: 'IMAGE_REL_I386_DIR32NB',
135 0x0009: 'IMAGE_REL_I386_SEG12',
136 0x000A: 'IMAGE_REL_I386_SECTION',
137 0x000B: 'IMAGE_REL_I386_SECREL',
138 0x000C: 'IMAGE_REL_I386_TOKEN',
139 0x000D: 'IMAGE_REL_I386_SECREL7',
140 0x0014: 'IMAGE_REL_I386_REL32',
141 },
142 }))),
143 ('SymbolName', ('ptr', '+ PointerToSymbolTable * - SymbolTableIndex 1 18', ('scalar', '<8s', symname)))
144 ])))),
145 ]))),
146 ('Symbols', ('ptr', 'PointerToSymbolTable', ('byte-array', '* NumberOfSymbols 18', ('struct', [
147 ('Name', ('scalar', '<8s', symname)),
148 ('Value', ('scalar', '<L', '%d' )),
149 ('SectionNumber', ('scalar', '<H', '%d' )),
150 ('SimpleType', ('enum', '<B', '%d', {
151 0: 'IMAGE_SYM_TYPE_NULL',
152 1: 'IMAGE_SYM_TYPE_VOID',
153 2: 'IMAGE_SYM_TYPE_CHAR',
154 3: 'IMAGE_SYM_TYPE_SHORT',
155 4: 'IMAGE_SYM_TYPE_INT',
156 5: 'IMAGE_SYM_TYPE_LONG',
157 6: 'IMAGE_SYM_TYPE_FLOAT',
158 7: 'IMAGE_SYM_TYPE_DOUBLE',
159 8: 'IMAGE_SYM_TYPE_STRUCT',
160 9: 'IMAGE_SYM_TYPE_UNION',
161 10: 'IMAGE_SYM_TYPE_ENUM',
162 11: 'IMAGE_SYM_TYPE_MOE',
163 12: 'IMAGE_SYM_TYPE_BYTE',
164 13: 'IMAGE_SYM_TYPE_WORD',
165 14: 'IMAGE_SYM_TYPE_UINT',
166 15: 'IMAGE_SYM_TYPE_DWORD',
167 })),
168 ('ComplexType', ('enum', '<B', '%d', {
169 0: 'IMAGE_SYM_DTYPE_NULL',
170 1: 'IMAGE_SYM_DTYPE_POINTER',
171 2: 'IMAGE_SYM_DTYPE_FUNCTION',
172 3: 'IMAGE_SYM_DTYPE_ARRAY',
173 })),
174 ('StorageClass', ('enum', '<B', '%d', {
175 -1: 'IMAGE_SYM_CLASS_END_OF_FUNCTION',
176 0: 'IMAGE_SYM_CLASS_NULL',
177 1: 'IMAGE_SYM_CLASS_AUTOMATIC',
178 2: 'IMAGE_SYM_CLASS_EXTERNAL',
179 3: 'IMAGE_SYM_CLASS_STATIC',
180 4: 'IMAGE_SYM_CLASS_REGISTER',
181 5: 'IMAGE_SYM_CLASS_EXTERNAL_DEF',
182 6: 'IMAGE_SYM_CLASS_LABEL',
183 7: 'IMAGE_SYM_CLASS_UNDEFINED_LABEL',
184 8: 'IMAGE_SYM_CLASS_MEMBER_OF_STRUCT',
185 9: 'IMAGE_SYM_CLASS_ARGUMENT',
186 10: 'IMAGE_SYM_CLASS_STRUCT_TAG',
187 11: 'IMAGE_SYM_CLASS_MEMBER_OF_UNION',
188 12: 'IMAGE_SYM_CLASS_UNION_TAG',
189 13: 'IMAGE_SYM_CLASS_TYPE_DEFINITION',
190 14: 'IMAGE_SYM_CLASS_UNDEFINED_STATIC',
191 15: 'IMAGE_SYM_CLASS_ENUM_TAG',
192 16: 'IMAGE_SYM_CLASS_MEMBER_OF_ENUM',
193 17: 'IMAGE_SYM_CLASS_REGISTER_PARAM',
194 18: 'IMAGE_SYM_CLASS_BIT_FIELD',
195 100: 'IMAGE_SYM_CLASS_BLOCK',
196 101: 'IMAGE_SYM_CLASS_FUNCTION',
197 102: 'IMAGE_SYM_CLASS_END_OF_STRUCT',
198 103: 'IMAGE_SYM_CLASS_FILE',
199 104: 'IMAGE_SYM_CLASS_SECTION',
200 105: 'IMAGE_SYM_CLASS_WEAK_EXTERNAL',
201 107: 'IMAGE_SYM_CLASS_CLR_TOKEN',
202 })),
203 ('NumberOfAuxSymbols', ('scalar', '<B', '%d' )),
204 ('AuxillaryData', ('blob', '* NumberOfAuxSymbols 18')),
205 ])))),
206])
207
208#
209# Definition Interpreter
210#
211
212import sys, types, struct, re
213
214Input = None
215Stack = []
216Fields = {}
217
218Indent = 0
219NewLine = True
220
221def indent():
222 global Indent
223 Indent += 1
224
225def dedent():
226 global Indent
227 Indent -= 1
228
229def write(input):
230 global NewLine
231 output = ""
232
233 for char in input:
234
235 if NewLine:
236 output += Indent * ' '
237 NewLine = False
238
239 output += char
240
241 if char == '\n':
242 NewLine = True
243
244 sys.stdout.write (output)
245
246def read(format):
247 return struct.unpack (format, Input.read(struct.calcsize(format)))
248
249def read_cstr ():
250 output = ""
251 while True:
252 char = Input.read (1)
253 if len (char) == 0:
254 raise RuntimeError ("EOF while reading cstr")
255 if char == '\0':
256 break
257 output += char
258 return output
259
260def push_pos(seek_to = None):
261 Stack [0:0] = [Input.tell ()]
262 if seek_to:
263 Input.seek (seek_to)
264
265def pop_pos():
266 assert(len (Stack) > 0)
267 Input.seek (Stack [0])
268 del Stack [0]
269
270def print_binary_data(size):
271 value = ""
272 while size > 0:
273 if size >= 16:
274 data = Input.read(16)
275 size -= 16
276 else:
277 data = Input.read(size)
278 size = 0
279 value += data
280 bytes = ""
281 text = ""
282 for index in xrange (16):
283 if index < len (data):
284 if index == 8:
285 bytes += "- "
286 ch = ord (data [index])
287 bytes += "%02X " % ch
288 if ch >= 0x20 and ch <= 0x7F:
289 text += data [index]
290 else:
291 text += "."
292 else:
293 if index == 8:
294 bytes += " "
295 bytes += " "
296
297 write ("%s|%s|\n" % (bytes, text))
298 return value
299
300idlit = re.compile ("[a-zA-Z][a-zA-Z0-9_-]*")
301numlit = re.compile ("[0-9]+")
302
303def read_value(expr):
304
305 input = iter (expr.split ())
306
307 def eval():
308
309 token = input.next ()
310
311 if expr == 'cstr':
312 return read_cstr ()
313 if expr == 'true':
314 return True
315 if expr == 'false':
316 return False
317
318 if len (token) > 1 and token [0] in ('=', '@', '<', '!', '>'):
319 val = read(expr)
320 assert (len (val) == 1)
321 return val [0]
322
323 if token == '+':
324 return eval () + eval ()
325 if token == '-':
326 return eval () - eval ()
327 if token == '*':
328 return eval () * eval ()
329 if token == '/':
330 return eval () / eval ()
331
332 if idlit.match (token):
333 return Fields [token]
334 if numlit.match (token):
335 return int (token)
336
337 raise RuntimeError ("unexpected token %s" % repr(token))
338
339 value = eval ()
340
341 try:
342 input.next ()
343 except StopIteration:
344 return value
345 raise RuntimeError("unexpected input at end of expression")
346
347def write_value(format,value):
348 format_type = type (format)
349 if format_type is types.StringType:
350 write (format%value)
351 elif format_type is types.FunctionType:
352 write_value (format (value), value)
353 elif format_type is types.TupleType:
354 Fields ['this'] = value
355 handle_element (format)
356 else:
357 raise RuntimeError("unexpected type: %s" % repr(format_type))
358
359def handle_scalar(entry):
360 iformat = entry [1]
361 oformat = entry [2]
362
363 value = read_value (iformat)
364
365 write_value (oformat, value)
366
367 return value
368
369def handle_enum(entry):
370 iformat = entry [1]
371 oformat = entry [2]
372 definitions = entry [3]
373
374 value = read_value (iformat)
375
376 if type (definitions) is types.TupleType:
377 selector = read_value (definitions [0])
378 definitions = definitions [1] [selector]
379
380 description = definitions[value] if value in definitions else "unknown"
381
382 write ("%s (" % description)
383 write_value (oformat, value)
384 write (")")
385
386 return value
387
388def handle_flags(entry):
389 iformat = entry [1]
390 oformat = entry [2]
391 definitions = entry [3]
392
393 value = read_value (iformat)
394
395 write_value (oformat, value)
396
397 indent ()
398 for entry in definitions:
399 mask = entry [0]
400 name = entry [1]
401 if len (entry) == 3:
402 map = entry [2]
403 selection = value & mask
404 if selection in map:
405 write("\n%s" % map[selection])
406 else:
407 write("\n%s <%d>" % (name, selection))
408 elif len (entry) == 2:
409 if value & mask != 0:
410 write("\n%s" % name)
411 dedent ()
412
413 return value
414
415def handle_struct(entry):
416 global Fields
417 members = entry [1]
418
419 newFields = {}
420
421 write ("{\n");
422 indent ()
423
424 for member in members:
425 name = member [0]
426 type = member [1]
427
428 write("%s = "%name.ljust(24))
429
430 value = handle_element(type)
431
432 write("\n")
433
434 Fields [name] = value
435 newFields [name] = value
436
437 dedent ()
438 write ("}")
439
440 return newFields
441
442def handle_array(entry):
443 length = entry [1]
444 element = entry [2]
445
446 newItems = []
447
448 write ("[\n")
449 indent ()
450
451 value = read_value (length)
452
453 for index in xrange (value):
454 write ("%d = "%index)
455 value = handle_element(element)
456 write ("\n")
457 newItems.append (value)
458
459 dedent ()
460 write ("]")
461
462 return newItems
463
464def handle_byte_array(entry):
465 length = entry [1]
466 element = entry [2]
467
468 newItems = []
469
470 write ("[\n")
471 indent ()
472
473 value = read_value (length)
474 end_of_array = Input.tell () + value
475
476 index = 0
477 while Input.tell () < end_of_array:
478 write ("%d = "%index)
479 value = handle_element(element)
480 write ("\n")
481 newItems.append (value)
482 index += 1
483
484 dedent ()
485 write ("]")
486
487 return newItems
488
489def handle_ptr(entry):
490 offset = entry[1]
491 element = entry [2]
492
493 value = None
494 offset = read_value (offset)
495
496 if offset != 0:
497
498 push_pos (offset)
499
500 value = handle_element (element)
501
502 pop_pos ()
503
504 else:
505 write ("None")
506
507 return value
508
509def handle_blob(entry):
510 length = entry [1]
511
512 write ("\n")
513 indent ()
514
515 value = print_binary_data (read_value (length))
516
517 dedent ()
518
519 return value
520
521def handle_element(entry):
522 handlers = {
523 'struct': handle_struct,
524 'scalar': handle_scalar,
525 'enum': handle_enum,
526 'flags': handle_flags,
527 'ptr': handle_ptr,
528 'blob': handle_blob,
529 'array': handle_array,
530 'byte-array': handle_byte_array,
531 }
532
533 if not entry [0] in handlers:
534 raise RuntimeError ("unexpected type '%s'" % str (entry[0]))
535
536 return handlers [entry [0]] (entry)
537
538Input = open (sys.argv [1], "rb")
539try:
540 handle_element (file)
541finally:
542 Input.close ()
543 Input = None