#!/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', '> 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', ' 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