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