b3e16e5015c6485743c6306a775ac15996965f50
[oota-llvm.git] / test / Scripts / coff-dump.py
1 #===-- 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
14 def string_table_entry (offset):
15         return ('ptr', '+ + PointerToSymbolTable * NumberOfSymbols 18 %s' % offset, ('scalar', 'cstr', '%s'))
16
17 def secname(value):
18         if value[0] == '/':
19                 return string_table_entry (value [1:].rstrip('\0'))
20         else:
21                 return '%s'
22
23 def 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
30 file = ('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
212 import sys, types, struct, re
213
214 Input = None
215 Stack = []
216 Fields = {}
217
218 Indent = 0
219 NewLine = True
220
221 def indent():
222         global Indent
223         Indent += 1
224
225 def dedent():
226         global Indent
227         Indent -= 1
228
229 def 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
246 def read(format):
247         return struct.unpack (format, Input.read(struct.calcsize(format)))
248
249 def 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
260 def push_pos(seek_to = None):
261         Stack [0:0] = [Input.tell ()]
262         if seek_to:
263                 Input.seek (seek_to)
264
265 def pop_pos():
266         assert(len (Stack) > 0)
267         Input.seek (Stack [0])
268         del Stack [0]
269
270 def 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
300 idlit = re.compile ("[a-zA-Z][a-zA-Z0-9_-]*")
301 numlit = re.compile ("[0-9]+")
302
303 def 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
347 def 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
359 def 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
369 def 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
388 def 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
415 def 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
442 def 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
464 def 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
489 def 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
509 def 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
521 def 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
538 Input = open (sys.argv [1], "rb")
539 try:
540         handle_element (file)
541 finally:
542         Input.close ()
543         Input = None