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 ('_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 233import sys, types, struct, re 234 235Input = None 236Stack = [] 237Fields = {} 238 239Indent = 0 240NewLine = True 241 242def indent(): 243 global Indent 244 Indent += 1 245 246def dedent(): 247 global Indent 248 Indent -= 1 249 250def 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 267def read(format): 268 return struct.unpack(format, Input.read(struct.calcsize(format))) 269 270def 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 281def push_pos(seek_to = None): 282 Stack [0:0] = [Input.tell()] 283 if seek_to: 284 Input.seek(seek_to) 285 286def pop_pos(): 287 assert(len(Stack) > 0) 288 Input.seek(Stack[0]) 289 del Stack[0] 290 291def 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 321idlit = re.compile("[a-zA-Z_][a-zA-Z0-9_-]*") 322numlit = re.compile("[0-9]+") 323 324def 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 376def 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 390def 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 400def 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 422def 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 449def 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 478def 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 502def 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 531def 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 551def 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 563def 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 580if len(sys.argv) <= 1 or sys.argv[1] == '-': 581 import StringIO 582 Input = StringIO.StringIO(sys.stdin.read()) 583else: 584 Input = open (sys.argv[1], "rb") 585 586try: 587 handle_element(file) 588finally: 589 Input.close() 590 Input = None 591