Add some win64 coff goodness.
[oota-llvm.git] / test / Scripts / coff-dump.py
1 #!/usr/bin/env python
2 #===-- 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
15 def string_table_entry (offset):
16         return ('ptr', '+ + PointerToSymbolTable * NumberOfSymbols 18 %s' % offset, ('scalar', 'cstr', '%s'))
17
18 def secname(value):
19         if value[0] == '/':
20                 return string_table_entry (value [1:].rstrip('\0'))
21         else:
22                 return '%s'
23
24 def 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
31 file = ('struct', [
32         ('MachineType', ('enum', '<H', '0x%X', {
33                 0x0:    'IMAGE_FILE_MACHINE_UNKNOWN',
34                 0x1d3:  'IMAGE_FILE_MACHINE_AM33',
35                 0x8664: '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                                 0x8664: {
144                                         0x0000: 'IMAGE_REL_AMD64_ABSOLUTE',
145                                         0x0001: 'IMAGE_REL_AMD64_ADDR64',
146                                         0x0002: 'IMAGE_REL_AMD64_ADDR32',
147                                         0x0003: 'IMAGE_REL_AMD64_ADDR32NB',
148                                         0x0004: 'IMAGE_REL_AMD64_REL32',
149                                         0x0005: 'IMAGE_REL_AMD64_REL32_1',
150                                         0x0006: 'IMAGE_REL_AMD64_REL32_2',
151                                         0x0007: 'IMAGE_REL_AMD64_REL32_3',
152                                         0x0008: 'IMAGE_REL_AMD64_REL32_4',
153                                         0x0009: 'IMAGE_REL_AMD64_REL32_5',
154                                         0x000A: 'IMAGE_REL_AMD64_SECTION',
155                                         0x000B: 'IMAGE_REL_AMD64_SECREL',
156                                         0x000C: 'IMAGE_REL_AMD64_SECREL7',
157                                         0x000D: 'IMAGE_REL_AMD64_TOKEN',
158                                         0x000E: 'IMAGE_REL_AMD64_SREL32',
159                                         0x000F: 'IMAGE_REL_AMD64_PAIR',
160                                         0x0010: 'IMAGE_REL_AMD64_SSPAN32',
161                                 },
162                         }))),
163                         ('SymbolName',       ('ptr', '+ PointerToSymbolTable * - SymbolTableIndex 1 18', ('scalar',  '<8s', symname)))
164                 ])))),
165         ]))),
166         ('Symbols', ('ptr', 'PointerToSymbolTable', ('byte-array', '* NumberOfSymbols 18',  ('struct', [
167                 ('Name',                ('scalar',  '<8s', symname)),
168                 ('Value',               ('scalar',  '<L',  '%d'   )),
169                 ('SectionNumber',       ('scalar',  '<H',  '%d'   )),
170                 ('SimpleType',          ('enum',    '<B',  '%d', {
171                         0: 'IMAGE_SYM_TYPE_NULL',
172                         1: 'IMAGE_SYM_TYPE_VOID',
173                         2: 'IMAGE_SYM_TYPE_CHAR',
174                         3: 'IMAGE_SYM_TYPE_SHORT',
175                         4: 'IMAGE_SYM_TYPE_INT',
176                         5: 'IMAGE_SYM_TYPE_LONG',
177                         6: 'IMAGE_SYM_TYPE_FLOAT',
178                         7: 'IMAGE_SYM_TYPE_DOUBLE',
179                         8: 'IMAGE_SYM_TYPE_STRUCT',
180                         9: 'IMAGE_SYM_TYPE_UNION',
181                         10: 'IMAGE_SYM_TYPE_ENUM',
182                         11: 'IMAGE_SYM_TYPE_MOE',
183                         12: 'IMAGE_SYM_TYPE_BYTE',
184                         13: 'IMAGE_SYM_TYPE_WORD',
185                         14: 'IMAGE_SYM_TYPE_UINT',
186                         15: 'IMAGE_SYM_TYPE_DWORD',
187                 })),
188                 ('ComplexType',         ('enum',    '<B',  '%d', {
189                         0: 'IMAGE_SYM_DTYPE_NULL',
190                         1: 'IMAGE_SYM_DTYPE_POINTER',
191                         2: 'IMAGE_SYM_DTYPE_FUNCTION',
192                         3: 'IMAGE_SYM_DTYPE_ARRAY',
193                 })),
194                 ('StorageClass',        ('enum',    '<B',  '%d', {
195                         -1:     'IMAGE_SYM_CLASS_END_OF_FUNCTION',
196                         0: 'IMAGE_SYM_CLASS_NULL',
197                         1: 'IMAGE_SYM_CLASS_AUTOMATIC',
198                         2: 'IMAGE_SYM_CLASS_EXTERNAL',
199                         3: 'IMAGE_SYM_CLASS_STATIC',
200                         4: 'IMAGE_SYM_CLASS_REGISTER',
201                         5: 'IMAGE_SYM_CLASS_EXTERNAL_DEF',
202                         6: 'IMAGE_SYM_CLASS_LABEL',
203                         7: 'IMAGE_SYM_CLASS_UNDEFINED_LABEL',
204                         8: 'IMAGE_SYM_CLASS_MEMBER_OF_STRUCT',
205                         9: 'IMAGE_SYM_CLASS_ARGUMENT',
206                         10: 'IMAGE_SYM_CLASS_STRUCT_TAG',
207                         11: 'IMAGE_SYM_CLASS_MEMBER_OF_UNION',
208                         12: 'IMAGE_SYM_CLASS_UNION_TAG',
209                         13: 'IMAGE_SYM_CLASS_TYPE_DEFINITION',
210                         14: 'IMAGE_SYM_CLASS_UNDEFINED_STATIC',
211                         15: 'IMAGE_SYM_CLASS_ENUM_TAG',
212                         16: 'IMAGE_SYM_CLASS_MEMBER_OF_ENUM',
213                         17: 'IMAGE_SYM_CLASS_REGISTER_PARAM',
214                         18: 'IMAGE_SYM_CLASS_BIT_FIELD',
215                         100: 'IMAGE_SYM_CLASS_BLOCK',
216                         101: 'IMAGE_SYM_CLASS_FUNCTION',
217                         102: 'IMAGE_SYM_CLASS_END_OF_STRUCT',
218                         103: 'IMAGE_SYM_CLASS_FILE',
219                         104: 'IMAGE_SYM_CLASS_SECTION',
220                         105: 'IMAGE_SYM_CLASS_WEAK_EXTERNAL',
221                         107: 'IMAGE_SYM_CLASS_CLR_TOKEN',
222                 })),
223                 ('NumberOfAuxSymbols',  ('scalar',  '<B',  '%d'  )),
224                 ('AuxillaryData', ('blob', '* NumberOfAuxSymbols 18')),
225         ])))),
226 ])
227
228 #
229 # Definition Interpreter
230 #
231
232 import sys, types, struct, re
233
234 Input = None
235 Stack = []
236 Fields = {}
237
238 Indent = 0
239 NewLine = True
240
241 def indent():
242         global Indent
243         Indent += 1
244
245 def dedent():
246         global Indent
247         Indent -= 1
248
249 def write(input):
250         global NewLine
251         output = ""
252         
253         for char in input:
254                 
255                 if NewLine:
256                         output += Indent * '  '
257                         NewLine = False
258                         
259                 output += char
260                 
261                 if char == '\n':
262                         NewLine = True
263         
264         sys.stdout.write (output)
265
266 def read(format):
267         return struct.unpack (format, Input.read(struct.calcsize(format)))
268
269 def read_cstr ():
270         output = ""
271         while True:
272                 char = Input.read (1)
273                 if len (char) == 0:
274                         raise RuntimeError ("EOF while reading cstr")
275                 if char == '\0':
276                         break
277                 output += char
278         return output
279
280 def push_pos(seek_to = None):
281         Stack [0:0] = [Input.tell ()]
282         if seek_to:
283                 Input.seek (seek_to)
284
285 def pop_pos():
286         assert(len (Stack) > 0)
287         Input.seek (Stack [0])
288         del Stack [0]
289
290 def print_binary_data(size):
291         value = ""
292         while size > 0:
293                 if size >= 16:
294                         data = Input.read(16)
295                         size -= 16
296                 else:
297                         data = Input.read(size)
298                         size = 0
299                 value += data
300                 bytes = ""
301                 text = ""
302                 for index in xrange (16):
303                         if index < len (data):
304                                 if index == 8:
305                                         bytes += "- "
306                                 ch = ord (data [index])
307                                 bytes += "%02X " % ch
308                                 if ch >= 0x20 and ch <= 0x7F:
309                                         text += data [index]
310                                 else:
311                                         text += "."
312                         else:
313                                 if index == 8:
314                                         bytes += "  "
315                                 bytes += "   "
316                 
317                 write ("%s|%s|\n" % (bytes, text))
318         return value
319
320 idlit = re.compile ("[a-zA-Z][a-zA-Z0-9_-]*")
321 numlit = re.compile ("[0-9]+")
322
323 def read_value(expr):
324
325         input = iter (expr.split ())
326         
327         def eval():
328                 
329                 token = input.next ()
330                 
331                 if expr == 'cstr':
332                         return read_cstr ()
333                 if expr == 'true':
334                         return True
335                 if expr == 'false':
336                         return False
337                 
338                 if len (token) > 1 and token [0] in ('=', '@', '<', '!', '>'):
339                         val = read(expr)
340                         assert (len (val) == 1)
341                         return val [0]
342                 
343                 if token == '+':
344                         return eval () + eval ()
345                 if token == '-':
346                         return eval () - eval ()
347                 if token == '*':
348                         return eval () * eval ()
349                 if token == '/':
350                         return eval () / eval ()
351                 
352                 if idlit.match (token):
353                         return Fields [token]
354                 if numlit.match (token):
355                         return int (token)
356                 
357                 raise RuntimeError ("unexpected token %s" % repr(token))
358         
359         value = eval ()
360         
361         try:
362                 input.next ()
363         except StopIteration:
364                 return value
365         raise RuntimeError("unexpected input at end of expression")
366
367 def write_value(format,value):
368         format_type = type (format)
369         if format_type is types.StringType:
370                 write (format%value)
371         elif format_type is types.FunctionType:
372                 write_value (format (value), value)
373         elif format_type is types.TupleType:
374                 Fields ['this'] = value
375                 handle_element (format)
376         else:
377                 raise RuntimeError("unexpected type: %s" % repr(format_type))
378
379 def handle_scalar(entry):
380         iformat = entry [1]
381         oformat = entry [2]
382         
383         value = read_value (iformat)
384         
385         write_value (oformat, value)
386         
387         return value
388
389 def handle_enum(entry):
390         iformat = entry [1]
391         oformat = entry [2]
392         definitions = entry [3]
393         
394         value = read_value (iformat)
395         
396         if type (definitions) is types.TupleType:
397                 selector = read_value (definitions [0])
398                 definitions = definitions [1] [selector]
399         
400         description = definitions[value] if value in definitions else "unknown"
401         
402         write ("%s (" % description)
403         write_value (oformat, value)
404         write (")")
405         
406         return value
407
408 def handle_flags(entry):
409         iformat = entry [1]
410         oformat = entry [2]
411         definitions = entry [3]
412         
413         value = read_value (iformat)
414         
415         write_value (oformat, value)
416         
417         indent ()
418         for entry in definitions:
419                 mask = entry [0]
420                 name = entry [1]
421                 if len (entry) == 3:
422                         map = entry [2]
423                         selection = value & mask
424                         if selection in map:
425                                 write("\n%s" % map[selection])
426                         else:
427                                 write("\n%s <%d>" % (name, selection))
428                 elif len (entry) == 2:
429                         if value & mask != 0:
430                                 write("\n%s" % name)
431         dedent ()
432         
433         return value
434
435 def handle_struct(entry):
436         global Fields
437         members = entry [1]
438         
439         newFields = {}
440         
441         write ("{\n");
442         indent ()
443         
444         for member in members:
445                 name = member [0]
446                 type = member [1]
447                 
448                 write("%s = "%name.ljust(24))
449                 
450                 value = handle_element(type)
451                 
452                 write("\n")
453                 
454                 Fields [name] = value
455                 newFields [name] = value
456         
457         dedent ()
458         write ("}")
459         
460         return newFields
461
462 def handle_array(entry):
463         length = entry [1]
464         element = entry [2]
465         
466         newItems = []
467         
468         write ("[\n")
469         indent ()
470         
471         value = read_value (length)
472         
473         for index in xrange (value):
474                 write ("%d = "%index)
475                 value = handle_element(element)
476                 write ("\n")
477                 newItems.append (value)
478         
479         dedent ()
480         write ("]")
481         
482         return newItems
483
484 def handle_byte_array(entry):
485         length = entry [1]
486         element = entry [2]
487         
488         newItems = []
489         
490         write ("[\n")
491         indent ()
492         
493         value = read_value (length)
494         end_of_array = Input.tell () + value
495
496         index = 0
497         while Input.tell () < end_of_array:
498                 write ("%d = "%index)
499                 value = handle_element(element)
500                 write ("\n")
501                 newItems.append (value)
502                 index += 1
503         
504         dedent ()
505         write ("]")
506         
507         return newItems
508
509 def handle_ptr(entry):
510         offset = entry[1]
511         element = entry [2]
512         
513         value = None
514         offset = read_value (offset)
515         
516         if offset != 0:
517                 
518                 push_pos (offset)
519                 
520                 value = handle_element (element)
521                 
522                 pop_pos ()
523         
524         else:
525                 write ("None")
526         
527         return value
528
529 def handle_blob(entry):
530         length = entry [1]
531         
532         write ("\n")
533         indent ()
534         
535         value = print_binary_data (read_value (length))
536         
537         dedent ()
538         
539         return value
540
541 def handle_element(entry):
542         handlers = {
543                 'struct':      handle_struct,
544                 'scalar':      handle_scalar,
545                 'enum':        handle_enum,
546                 'flags':       handle_flags,
547                 'ptr':         handle_ptr,
548                 'blob':        handle_blob,
549                 'array':       handle_array,
550                 'byte-array':  handle_byte_array,
551         }
552         
553         if not entry [0] in handlers:
554                 raise RuntimeError ("unexpected type '%s'" % str (entry[0]))
555         
556         return handlers [entry [0]] (entry)
557
558 Input = open (sys.argv [1], "rb")
559 try:
560         handle_element (file)
561 finally:
562         Input.close ()
563         Input = None