llvm/test/Scripts/coff-dump.py
2010-08-30 15:19:56 +00:00

567 lines
14 KiB
Python
Executable File

#!/usr/bin/env python
#===-- coff-dump.py - COFF object file dump utility-------------------------===#
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
#===------------------------------------------------------------------------===#
#
# COFF File Definition
#
def string_table_entry (offset):
return ('ptr', '+ + PointerToSymbolTable * NumberOfSymbols 18 %s' % offset, ('scalar', 'cstr', '%s'))
def secname(value):
if value[0] == '/':
return string_table_entry (value [1:].rstrip('\0'))
else:
return '%s'
def symname(value):
parts = struct.unpack("<2L", value)
if parts [0] == 0:
return string_table_entry (parts [1])
else:
return '%s'
file = ('struct', [
('MachineType', ('enum', '<H', '0x%X', {
0x0: 'IMAGE_FILE_MACHINE_UNKNOWN',
0x1d3: 'IMAGE_FILE_MACHINE_AM33',
0x8664: 'IMAGE_FILE_MACHINE_AMD64',
0x1c0: 'IMAGE_FILE_MACHINE_ARM',
0xebc: 'IMAGE_FILE_MACHINE_EBC',
0x14c: 'IMAGE_FILE_MACHINE_I386',
0x200: 'IMAGE_FILE_MACHINE_IA64',
0x904: 'IMAGE_FILE_MACHINE_M32R',
0x266: 'IMAGE_FILE_MACHINE_MIPS16',
0x366: 'IMAGE_FILE_MACHINE_MIPSFPU',
0x466: 'IMAGE_FILE_MACHINE_MIPSFPU16',
0x1f0: 'IMAGE_FILE_MACHINE_POWERPC',
0x1f1: 'IMAGE_FILE_MACHINE_POWERPCFP',
0x166: 'IMAGE_FILE_MACHINE_R4000',
0x1a2: 'IMAGE_FILE_MACHINE_SH3',
0x1a3: 'IMAGE_FILE_MACHINE_SH3DSP',
0x1a6: 'IMAGE_FILE_MACHINE_SH4',
0x1a8: 'IMAGE_FILE_MACHINE_SH5',
0x1c2: 'IMAGE_FILE_MACHINE_THUMB',
0x169: 'IMAGE_FILE_MACHINE_WCEMIPSV2',
})),
('NumberOfSections', ('scalar', '<H', '%d')),
('TimeDateStamp', ('scalar', '<L', '%d')),
('PointerToSymbolTable', ('scalar', '<L', '0x%0X')),
('NumberOfSymbols', ('scalar', '<L', '%d')),
('SizeOfOptionalHeader', ('scalar', '<H', '%d')),
('Characteristics', ('flags', '<H', '0x%x', [
(0x0001, 'IMAGE_FILE_RELOCS_STRIPPED', ),
(0x0002, 'IMAGE_FILE_EXECUTABLE_IMAGE', ),
(0x0004, 'IMAGE_FILE_LINE_NUMS_STRIPPED', ),
(0x0008, 'IMAGE_FILE_LOCAL_SYMS_STRIPPED', ),
(0x0010, 'IMAGE_FILE_AGGRESSIVE_WS_TRIM', ),
(0x0020, 'IMAGE_FILE_LARGE_ADDRESS_AWARE', ),
(0x0080, 'IMAGE_FILE_BYTES_REVERSED_LO', ),
(0x0100, 'IMAGE_FILE_32BIT_MACHINE', ),
(0x0200, 'IMAGE_FILE_DEBUG_STRIPPED', ),
(0x0400, 'IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP', ),
(0x0800, 'IMAGE_FILE_NET_RUN_FROM_SWAP', ),
(0x1000, 'IMAGE_FILE_SYSTEM', ),
(0x2000, 'IMAGE_FILE_DLL', ),
(0x4000, 'IMAGE_FILE_UP_SYSTEM_ONLY', ),
(0x8000, 'IMAGE_FILE_BYTES_REVERSED_HI', ),
])),
('Sections', ('array', 'NumberOfSections', ('struct', [
('Name', ('scalar', '<8s', secname)),
('VirtualSize', ('scalar', '<L', '%d' )),
('VirtualAddress', ('scalar', '<L', '%d' )),
('SizeOfRawData', ('scalar', '<L', '%d' )),
('PointerToRawData', ('scalar', '<L', '0x%X' )),
('PointerToRelocations', ('scalar', '<L', '0x%X' )),
('PointerToLineNumbers', ('scalar', '<L', '0x%X' )),
('NumberOfRelocations', ('scalar', '<H', '%d' )),
('NumberOfLineNumbers', ('scalar', '<H', '%d' )),
('Charateristics', ('flags', '<L', '0x%X', [
(0x00000008, 'IMAGE_SCN_TYPE_NO_PAD'),
(0x00000020, 'IMAGE_SCN_CNT_CODE'),
(0x00000040, 'IMAGE_SCN_CNT_INITIALIZED_DATA'),
(0x00000080, 'IMAGE_SCN_CNT_UNINITIALIZED_DATA'),
(0x00000100, 'IMAGE_SCN_LNK_OTHER'),
(0x00000200, 'IMAGE_SCN_LNK_INFO'),
(0x00000800, 'IMAGE_SCN_LNK_REMOVE'),
(0x00001000, 'IMAGE_SCN_LNK_COMDAT'),
(0x00008000, 'IMAGE_SCN_GPREL'),
(0x00020000, 'IMAGE_SCN_MEM_PURGEABLE'),
(0x00020000, 'IMAGE_SCN_MEM_16BIT'),
(0x00040000, 'IMAGE_SCN_MEM_LOCKED'),
(0x00080000, 'IMAGE_SCN_MEM_PRELOAD'),
(0x00F00000, 'IMAGE_SCN_ALIGN', {
0x00100000: 'IMAGE_SCN_ALIGN_1BYTES',
0x00200000: 'IMAGE_SCN_ALIGN_2BYTES',
0x00300000: 'IMAGE_SCN_ALIGN_4BYTES',
0x00400000: 'IMAGE_SCN_ALIGN_8BYTES',
0x00500000: 'IMAGE_SCN_ALIGN_16BYTES',
0x00600000: 'IMAGE_SCN_ALIGN_32BYTES',
0x00700000: 'IMAGE_SCN_ALIGN_64BYTES',
0x00800000: 'IMAGE_SCN_ALIGN_128BYTES',
0x00900000: 'IMAGE_SCN_ALIGN_256BYTES',
0x00A00000: 'IMAGE_SCN_ALIGN_512BYTES',
0x00B00000: 'IMAGE_SCN_ALIGN_1024BYTES',
0x00C00000: 'IMAGE_SCN_ALIGN_2048BYTES',
0x00D00000: 'IMAGE_SCN_ALIGN_4096BYTES',
0x00E00000: 'IMAGE_SCN_ALIGN_8192BYTES',
}),
(0x01000000, 'IMAGE_SCN_LNK_NRELOC_OVFL'),
(0x02000000, 'IMAGE_SCN_MEM_DISCARDABLE'),
(0x04000000, 'IMAGE_SCN_MEM_NOT_CACHED'),
(0x08000000, 'IMAGE_SCN_MEM_NOT_PAGED'),
(0x10000000, 'IMAGE_SCN_MEM_SHARED'),
(0x20000000, 'IMAGE_SCN_MEM_EXECUTE'),
(0x40000000, 'IMAGE_SCN_MEM_READ'),
(0x80000000, 'IMAGE_SCN_MEM_WRITE'),
])),
('SectionData', ('ptr', 'PointerToRawData', ('blob', 'SizeOfRawData'))),
('Relocations', ('ptr', 'PointerToRelocations', ('array', 'NumberOfRelocations', ('struct', [
('VirtualAddress', ('scalar', '<L', '0x%X')),
('SymbolTableIndex', ('scalar', '<L', '%d' )),
('Type', ('enum', '<H', '%d', ('MachineType', {
0x14c: {
0x0000: 'IMAGE_REL_I386_ABSOLUTE',
0x0001: 'IMAGE_REL_I386_DIR16',
0x0002: 'IMAGE_REL_I386_REL16',
0x0006: 'IMAGE_REL_I386_DIR32',
0x0007: 'IMAGE_REL_I386_DIR32NB',
0x0009: 'IMAGE_REL_I386_SEG12',
0x000A: 'IMAGE_REL_I386_SECTION',
0x000B: 'IMAGE_REL_I386_SECREL',
0x000C: 'IMAGE_REL_I386_TOKEN',
0x000D: 'IMAGE_REL_I386_SECREL7',
0x0014: 'IMAGE_REL_I386_REL32',
},
0x8664: {
0x0000: 'IMAGE_REL_AMD64_ABSOLUTE',
0x0001: 'IMAGE_REL_AMD64_ADDR64',
0x0002: 'IMAGE_REL_AMD64_ADDR32',
0x0003: 'IMAGE_REL_AMD64_ADDR32NB',
0x0004: 'IMAGE_REL_AMD64_REL32',
0x0005: 'IMAGE_REL_AMD64_REL32_1',
0x0006: 'IMAGE_REL_AMD64_REL32_2',
0x0007: 'IMAGE_REL_AMD64_REL32_3',
0x0008: 'IMAGE_REL_AMD64_REL32_4',
0x0009: 'IMAGE_REL_AMD64_REL32_5',
0x000A: 'IMAGE_REL_AMD64_SECTION',
0x000B: 'IMAGE_REL_AMD64_SECREL',
0x000C: 'IMAGE_REL_AMD64_SECREL7',
0x000D: 'IMAGE_REL_AMD64_TOKEN',
0x000E: 'IMAGE_REL_AMD64_SREL32',
0x000F: 'IMAGE_REL_AMD64_PAIR',
0x0010: 'IMAGE_REL_AMD64_SSPAN32',
},
}))),
('SymbolName', ('ptr', '+ PointerToSymbolTable * - SymbolTableIndex 1 18', ('scalar', '<8s', symname)))
])))),
]))),
('Symbols', ('ptr', 'PointerToSymbolTable', ('byte-array', '* NumberOfSymbols 18', ('struct', [
('Name', ('scalar', '<8s', symname)),
('Value', ('scalar', '<L', '%d' )),
('SectionNumber', ('scalar', '<H', '%d' )),
('SimpleType', ('enum', '<B', '%d', {
0: 'IMAGE_SYM_TYPE_NULL',
1: 'IMAGE_SYM_TYPE_VOID',
2: 'IMAGE_SYM_TYPE_CHAR',
3: 'IMAGE_SYM_TYPE_SHORT',
4: 'IMAGE_SYM_TYPE_INT',
5: 'IMAGE_SYM_TYPE_LONG',
6: 'IMAGE_SYM_TYPE_FLOAT',
7: 'IMAGE_SYM_TYPE_DOUBLE',
8: 'IMAGE_SYM_TYPE_STRUCT',
9: 'IMAGE_SYM_TYPE_UNION',
10: 'IMAGE_SYM_TYPE_ENUM',
11: 'IMAGE_SYM_TYPE_MOE',
12: 'IMAGE_SYM_TYPE_BYTE',
13: 'IMAGE_SYM_TYPE_WORD',
14: 'IMAGE_SYM_TYPE_UINT',
15: 'IMAGE_SYM_TYPE_DWORD',
})),
('ComplexType', ('enum', '<B', '%d', {
0: 'IMAGE_SYM_DTYPE_NULL',
1: 'IMAGE_SYM_DTYPE_POINTER',
2: 'IMAGE_SYM_DTYPE_FUNCTION',
3: 'IMAGE_SYM_DTYPE_ARRAY',
})),
('StorageClass', ('enum', '<B', '%d', {
-1: 'IMAGE_SYM_CLASS_END_OF_FUNCTION',
0: 'IMAGE_SYM_CLASS_NULL',
1: 'IMAGE_SYM_CLASS_AUTOMATIC',
2: 'IMAGE_SYM_CLASS_EXTERNAL',
3: 'IMAGE_SYM_CLASS_STATIC',
4: 'IMAGE_SYM_CLASS_REGISTER',
5: 'IMAGE_SYM_CLASS_EXTERNAL_DEF',
6: 'IMAGE_SYM_CLASS_LABEL',
7: 'IMAGE_SYM_CLASS_UNDEFINED_LABEL',
8: 'IMAGE_SYM_CLASS_MEMBER_OF_STRUCT',
9: 'IMAGE_SYM_CLASS_ARGUMENT',
10: 'IMAGE_SYM_CLASS_STRUCT_TAG',
11: 'IMAGE_SYM_CLASS_MEMBER_OF_UNION',
12: 'IMAGE_SYM_CLASS_UNION_TAG',
13: 'IMAGE_SYM_CLASS_TYPE_DEFINITION',
14: 'IMAGE_SYM_CLASS_UNDEFINED_STATIC',
15: 'IMAGE_SYM_CLASS_ENUM_TAG',
16: 'IMAGE_SYM_CLASS_MEMBER_OF_ENUM',
17: 'IMAGE_SYM_CLASS_REGISTER_PARAM',
18: 'IMAGE_SYM_CLASS_BIT_FIELD',
100: 'IMAGE_SYM_CLASS_BLOCK',
101: 'IMAGE_SYM_CLASS_FUNCTION',
102: 'IMAGE_SYM_CLASS_END_OF_STRUCT',
103: 'IMAGE_SYM_CLASS_FILE',
104: 'IMAGE_SYM_CLASS_SECTION',
105: 'IMAGE_SYM_CLASS_WEAK_EXTERNAL',
107: 'IMAGE_SYM_CLASS_CLR_TOKEN',
})),
('NumberOfAuxSymbols', ('scalar', '<B', '%d' )),
('AuxillaryData', ('blob', '* NumberOfAuxSymbols 18')),
])))),
])
#
# Definition Interpreter
#
import sys, types, struct, re
Input = None
Stack = []
Fields = {}
Indent = 0
NewLine = True
def indent():
global Indent
Indent += 1
def dedent():
global Indent
Indent -= 1
def write(input):
global NewLine
output = ""
for char in input:
if NewLine:
output += Indent * ' '
NewLine = False
output += char
if char == '\n':
NewLine = True
sys.stdout.write (output)
def read(format):
return struct.unpack (format, Input.read(struct.calcsize(format)))
def read_cstr ():
output = ""
while True:
char = Input.read (1)
if len (char) == 0:
raise RuntimeError ("EOF while reading cstr")
if char == '\0':
break
output += char
return output
def push_pos(seek_to = None):
Stack [0:0] = [Input.tell ()]
if seek_to:
Input.seek (seek_to)
def pop_pos():
assert(len (Stack) > 0)
Input.seek (Stack [0])
del Stack [0]
def print_binary_data(size):
value = ""
while size > 0:
if size >= 16:
data = Input.read(16)
size -= 16
else:
data = Input.read(size)
size = 0
value += data
bytes = ""
text = ""
for index in xrange (16):
if index < len (data):
if index == 8:
bytes += "- "
ch = ord (data [index])
bytes += "%02X " % ch
if ch >= 0x20 and ch <= 0x7F:
text += data [index]
else:
text += "."
else:
if index == 8:
bytes += " "
bytes += " "
write ("%s|%s|\n" % (bytes, text))
return value
idlit = re.compile ("[a-zA-Z][a-zA-Z0-9_-]*")
numlit = re.compile ("[0-9]+")
def read_value(expr):
input = iter (expr.split ())
def eval():
token = input.next ()
if expr == 'cstr':
return read_cstr ()
if expr == 'true':
return True
if expr == 'false':
return False
if len (token) > 1 and token [0] in ('=', '@', '<', '!', '>'):
val = read(expr)
assert (len (val) == 1)
return val [0]
if token == '+':
return eval () + eval ()
if token == '-':
return eval () - eval ()
if token == '*':
return eval () * eval ()
if token == '/':
return eval () / eval ()
if idlit.match (token):
return Fields [token]
if numlit.match (token):
return int (token)
raise RuntimeError ("unexpected token %s" % repr(token))
value = eval ()
try:
input.next ()
except StopIteration:
return value
raise RuntimeError("unexpected input at end of expression")
def write_value(format,value):
format_type = type (format)
if format_type is types.StringType:
write (format%value)
elif format_type is types.FunctionType:
write_value (format (value), value)
elif format_type is types.TupleType:
Fields ['this'] = value
handle_element (format)
else:
raise RuntimeError("unexpected type: %s" % repr(format_type))
def handle_scalar(entry):
iformat = entry [1]
oformat = entry [2]
value = read_value (iformat)
write_value (oformat, value)
return value
def handle_enum(entry):
iformat = entry [1]
oformat = entry [2]
definitions = entry [3]
value = read_value (iformat)
if type (definitions) is types.TupleType:
selector = read_value (definitions [0])
definitions = definitions [1] [selector]
if value in definitions:
description = definitions[value]
else:
description = "unknown"
write ("%s (" % description)
write_value (oformat, value)
write (")")
return value
def handle_flags(entry):
iformat = entry [1]
oformat = entry [2]
definitions = entry [3]
value = read_value (iformat)
write_value (oformat, value)
indent ()
for entry in definitions:
mask = entry [0]
name = entry [1]
if len (entry) == 3:
map = entry [2]
selection = value & mask
if selection in map:
write("\n%s" % map[selection])
else:
write("\n%s <%d>" % (name, selection))
elif len (entry) == 2:
if value & mask != 0:
write("\n%s" % name)
dedent ()
return value
def handle_struct(entry):
global Fields
members = entry [1]
newFields = {}
write ("{\n");
indent ()
for member in members:
name = member [0]
type = member [1]
write("%s = "%name.ljust(24))
value = handle_element(type)
write("\n")
Fields [name] = value
newFields [name] = value
dedent ()
write ("}")
return newFields
def handle_array(entry):
length = entry [1]
element = entry [2]
newItems = []
write ("[\n")
indent ()
value = read_value (length)
for index in xrange (value):
write ("%d = "%index)
value = handle_element(element)
write ("\n")
newItems.append (value)
dedent ()
write ("]")
return newItems
def handle_byte_array(entry):
length = entry [1]
element = entry [2]
newItems = []
write ("[\n")
indent ()
value = read_value (length)
end_of_array = Input.tell () + value
index = 0
while Input.tell () < end_of_array:
write ("%d = "%index)
value = handle_element(element)
write ("\n")
newItems.append (value)
index += 1
dedent ()
write ("]")
return newItems
def handle_ptr(entry):
offset = entry[1]
element = entry [2]
value = None
offset = read_value (offset)
if offset != 0:
push_pos (offset)
value = handle_element (element)
pop_pos ()
else:
write ("None")
return value
def handle_blob(entry):
length = entry [1]
write ("\n")
indent ()
value = print_binary_data (read_value (length))
dedent ()
return value
def handle_element(entry):
handlers = {
'struct': handle_struct,
'scalar': handle_scalar,
'enum': handle_enum,
'flags': handle_flags,
'ptr': handle_ptr,
'blob': handle_blob,
'array': handle_array,
'byte-array': handle_byte_array,
}
if not entry [0] in handlers:
raise RuntimeError ("unexpected type '%s'" % str (entry[0]))
return handlers [entry [0]] (entry)
Input = open (sys.argv [1], "rb")
try:
handle_element (file)
finally:
Input.close ()
Input = None