591 lines
16 KiB
Python
Executable File
591 lines
16 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', '1', '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', '0', '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 18', ('scalar', '<8s', symname)))
|
|
])))),
|
|
]))),
|
|
('Symbols', ('ptr', 'PointerToSymbolTable', ('byte-array', '18', '* NumberOfSymbols 18', ('struct', [
|
|
('Name', ('scalar', '<8s', symname)),
|
|
('Value', ('scalar', '<L', '%d' )),
|
|
('SectionNumber', ('scalar', '<H', '%d' )),
|
|
('_Type', ('scalar', '<H', None )),
|
|
('SimpleType', ('enum', '& _Type 15', '%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',
|
|
})), # (Type & 0xF0) >> 4
|
|
('ComplexType', ('enum', '>> & _Type 240 4', '%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 token == '+':
|
|
return eval() + eval()
|
|
if token == '-':
|
|
return eval() - eval()
|
|
if token == '*':
|
|
return eval() * eval()
|
|
if token == '/':
|
|
return eval() / eval()
|
|
if token == '&':
|
|
return eval() & eval()
|
|
if token == '|':
|
|
return eval() | eval()
|
|
if token == '>>':
|
|
return eval() >> eval()
|
|
if token == '<<':
|
|
return eval() << eval()
|
|
|
|
if len(token) > 1 and token[0] in ('=', '@', '<', '!', '>'):
|
|
val = read(expr)
|
|
assert(len(val) == 1)
|
|
return val[0]
|
|
|
|
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)
|
|
elif format_type is types.NoneType:
|
|
pass
|
|
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]
|
|
|
|
if name[0] != "_":
|
|
write("%s = " % name.ljust(24))
|
|
|
|
value = handle_element(type)
|
|
|
|
if name[0] != "_":
|
|
write("\n")
|
|
|
|
Fields[name] = value
|
|
newFields[name] = value
|
|
|
|
dedent()
|
|
write("}")
|
|
|
|
return newFields
|
|
|
|
def handle_array(entry):
|
|
start_index = entry[1]
|
|
length = entry[2]
|
|
element = entry[3]
|
|
|
|
newItems = []
|
|
|
|
write("[\n")
|
|
indent()
|
|
|
|
start_index = read_value(start_index)
|
|
value = read_value(length)
|
|
|
|
for index in xrange(value):
|
|
write("%d = " % (index + start_index))
|
|
value = handle_element(element)
|
|
write("\n")
|
|
newItems.append(value)
|
|
|
|
dedent()
|
|
write("]")
|
|
|
|
return newItems
|
|
|
|
def handle_byte_array(entry):
|
|
ent_size = entry[1]
|
|
length = entry[2]
|
|
element = entry[3]
|
|
|
|
newItems = []
|
|
|
|
write("[\n")
|
|
indent()
|
|
|
|
item_size = read_value(ent_size)
|
|
value = read_value(length)
|
|
end_of_array = Input.tell() + value
|
|
|
|
prev_loc = Input.tell()
|
|
index = 0
|
|
while Input.tell() < end_of_array:
|
|
write("%d = " % index)
|
|
value = handle_element(element)
|
|
write("\n")
|
|
newItems.append(value)
|
|
index += (Input.tell() - prev_loc) / item_size
|
|
prev_loc = Input.tell()
|
|
|
|
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)
|
|
|
|
if len(sys.argv) <= 1 or sys.argv[1] == '-':
|
|
import StringIO
|
|
Input = StringIO.StringIO(sys.stdin.read())
|
|
else:
|
|
Input = open (sys.argv[1], "rb")
|
|
|
|
try:
|
|
handle_element(file)
|
|
finally:
|
|
Input.close()
|
|
Input = None
|