coff-dump.py revision 6580a7a6cc637f6d757b8d4fc6faebfa334dbbb0
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 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 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 ('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 232import sys, types, struct, re 233 234Input = None 235Stack = [] 236Fields = {} 237 238Indent = 0 239NewLine = True 240 241def indent(): 242 global Indent 243 Indent += 1 244 245def dedent(): 246 global Indent 247 Indent -= 1 248 249def 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 266def read(format): 267 return struct.unpack(format, Input.read(struct.calcsize(format))) 268 269def 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 280def push_pos(seek_to = None): 281 Stack [0:0] = [Input.tell()] 282 if seek_to: 283 Input.seek(seek_to) 284 285def pop_pos(): 286 assert(len(Stack) > 0) 287 Input.seek(Stack[0]) 288 del Stack[0] 289 290def 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 320idlit = re.compile("[a-zA-Z][a-zA-Z0-9_-]*") 321numlit = re.compile("[0-9]+") 322 323def 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 367def 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 379def 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 389def 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 if value in definitions: 401 description = definitions[value] 402 else: 403 description = "unknown" 404 405 write("%s (" % description) 406 write_value(oformat, value) 407 write(")") 408 409 return value 410 411def handle_flags(entry): 412 iformat = entry[1] 413 oformat = entry[2] 414 definitions = entry[3] 415 416 value = read_value(iformat) 417 418 write_value(oformat, value) 419 420 indent() 421 for entry in definitions: 422 mask = entry[0] 423 name = entry[1] 424 if len (entry) == 3: 425 map = entry[2] 426 selection = value & mask 427 if selection in map: 428 write("\n%s" % map[selection]) 429 else: 430 write("\n%s <%d>" % (name, selection)) 431 elif len(entry) == 2: 432 if value & mask != 0: 433 write("\n%s" % name) 434 dedent() 435 436 return value 437 438def handle_struct(entry): 439 global Fields 440 members = entry[1] 441 442 newFields = {} 443 444 write("{\n"); 445 indent() 446 447 for member in members: 448 name = member[0] 449 type = member[1] 450 451 write("%s = "%name.ljust(24)) 452 453 value = handle_element(type) 454 455 write("\n") 456 457 Fields[name] = value 458 newFields[name] = value 459 460 dedent() 461 write("}") 462 463 return newFields 464 465def handle_array(entry): 466 start_index = entry[1] 467 length = entry[2] 468 element = entry[3] 469 470 newItems = [] 471 472 write("[\n") 473 indent() 474 475 start_index = read_value(start_index) 476 value = read_value(length) 477 478 for index in xrange(value): 479 write("%d = " % (index + start_index)) 480 value = handle_element(element) 481 write("\n") 482 newItems.append(value) 483 484 dedent() 485 write("]") 486 487 return newItems 488 489def handle_byte_array(entry): 490 ent_size = entry[1] 491 length = entry[2] 492 element = entry[3] 493 494 newItems = [] 495 496 write("[\n") 497 indent() 498 499 item_size = read_value(ent_size) 500 value = read_value(length) 501 end_of_array = Input.tell() + value 502 503 prev_loc = Input.tell() 504 index = 0 505 while Input.tell() < end_of_array: 506 write("%d = " % index) 507 value = handle_element(element) 508 write("\n") 509 newItems.append(value) 510 index += (Input.tell() - prev_loc) / item_size 511 prev_loc = Input.tell() 512 513 dedent() 514 write("]") 515 516 return newItems 517 518def handle_ptr(entry): 519 offset = entry[1] 520 element = entry[2] 521 522 value = None 523 offset = read_value(offset) 524 525 if offset != 0: 526 527 push_pos(offset) 528 529 value = handle_element(element) 530 531 pop_pos() 532 533 else: 534 write("None") 535 536 return value 537 538def handle_blob(entry): 539 length = entry[1] 540 541 write("\n") 542 indent() 543 544 value = print_binary_data(read_value(length)) 545 546 dedent() 547 548 return value 549 550def handle_element(entry): 551 handlers = { 552 'struct': handle_struct, 553 'scalar': handle_scalar, 554 'enum': handle_enum, 555 'flags': handle_flags, 556 'ptr': handle_ptr, 557 'blob': handle_blob, 558 'array': handle_array, 559 'byte-array': handle_byte_array, 560 } 561 562 if not entry[0] in handlers: 563 raise RuntimeError ("unexpected type '%s'" % str (entry[0])) 564 565 return handlers[entry[0]](entry) 566 567if len(sys.argv) <= 1 or sys.argv[1] == '-': 568 import StringIO 569 Input = StringIO.StringIO(sys.stdin.read()) 570else: 571 Input = open (sys.argv[1], "rb") 572 573try: 574 handle_element(file) 575finally: 576 Input.close() 577 Input = None 578