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