llvm-6502/test/Scripts/macho-dump
Daniel Dunbar fb4a6b3976 llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.

 - MCAssembler is the actual assembler backend, which is designed to have a
   reasonable API. This will eventually grow to support multiple object file
   implementations, but for now its Mach-O/i386 only.

 - MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
   e.g. converting the various directives into fragments, managing state like
   the current section, and so on.

 - llvm-mc will use the new backend via '-filetype=obj', which may eventually
   be, but is not yet, since I hear that people like assemblers which actually
   assemble.

 - The only thing that works at the moment is changing sections. For the time
   being I have a Python Mach-O dumping tool in test/scripts so this stuff can
   be easily tested, eventually I expect to replace this with a real LLVM tool.

 - More doxyments to come.

I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79612 91177308-0d34-0410-b5e6-96231b3b80d8
2009-08-21 09:11:24 +00:00

160 lines
4.5 KiB
Python
Executable File

#!/usr/bin/env python
import struct
import sys
class Reader:
def __init__(self, path):
if path == '-':
self.file = sys.stdin
else:
self.file = open(path,'rb')
self.isLSB = None
self.pos = 0
def setLSB(self, isLSB):
self.isLSB = bool(isLSB)
def tell(self):
return self.pos
def read(self, N):
data = self.file.read(N)
self.pos += len(data)
if len(data) != N:
raise ValueError,"Out of data!"
return data
def read32(self):
return struct.unpack('><'[self.isLSB] + 'I', self.read(4))[0]
def dumpmacho(path, opts):
f = Reader(path)
magic = f.read(4)
if magic == '\xFE\xED\xFA\xCE':
f.setLSB(False)
elif magic == '\xCE\xFA\xED\xFE':
f.setLSB(True)
else:
raise ValueError,"Not a Mach-O object file: %r (bad magic)" % path
print "('cputype', %r)" % f.read32()
print "('cpusubtype', %r)" % f.read32()
filetype = f.read32()
print "('filetype', %r)" % filetype
numLoadCommands = f.read32()
print "('num_load_commands', %r)" % filetype
loadCommandsSize = f.read32()
print "('load_commands_size', %r)" % loadCommandsSize
print "('flag', %r)" % f.read32()
start = f.tell()
print "('load_commands', ["
for i in range(numLoadCommands):
dumpLoadCommand(f, i, opts)
print "])"
if f.tell() - start != loadCommandsSize:
raise ValueError,"%s: warning: invalid load commands size: %r" % (sys.argv, loadCommandsSize)
def dumpLoadCommand(f, i, opts):
start = f.tell()
print " # Load Command %r" % i
cmd = f.read32()
print " (('command', %r)" % cmd
cmdSize = f.read32()
print " ('size', %r)" % cmdSize
if cmd == 1:
dumpSegmentLoadCommand32(f, opts)
elif cmd == 2:
dumpSymtabCommand(f, opts)
elif cmd == 11:
dumpDysymtabCommand(f, opts)
else:
print >>sys.stderr,"%s: warning: unknown load command: %r" % (sys.argv[0], cmd)
f.read(cmdSize - 8)
print " ),"
if f.tell() - start != cmdSize:
raise ValueError,"%s: warning: invalid load command size: %r" % (sys.argv, cmdSize)
def dumpSegmentLoadCommand32(f, opts):
print " ('segment_name', %r)" % f.read(16)
print " ('vm_addr', %r)" % f.read32()
print " ('vm_size', %r)" % f.read32()
print " ('file_offset', %r)" % f.read32()
print " ('file_size', %r)" % f.read32()
print " ('maxprot', %r)" % f.read32()
print " ('initprot', %r)" % f.read32()
numSections = f.read32()
print " ('num_sections', %r)" % numSections
print " ('flags', %r)" % f.read32()
print " ('sections', ["
for i in range(numSections):
dumpSection32(f, i, opts)
print " ])"
def dumpSymtabCommand(f, opts):
print " ('symoff', %r)" % f.read32()
print " ('nsyms', %r)" % f.read32()
print " ('stroff', %r)" % f.read32()
print " ('strsize', %r)" % f.read32()
def dumpDysymtabCommand(f, opts):
print " ('ilocalsym', %r)" % f.read32()
print " ('nlocalsym', %r)" % f.read32()
print " ('iextdefsym', %r)" % f.read32()
print " ('nextdefsym', %r)" % f.read32()
print " ('iundefsym', %r)" % f.read32()
print " ('nundefsym', %r)" % f.read32()
print " ('tocoff', %r)" % f.read32()
print " ('ntoc', %r)" % f.read32()
print " ('modtaboff', %r)" % f.read32()
print " ('nmodtab', %r)" % f.read32()
print " ('extrefsymoff', %r)" % f.read32()
print " ('nextrefsyms', %r)" % f.read32()
print " ('indirectsymoff', %r)" % f.read32()
print " ('nindirectsyms', %r)" % f.read32()
print " ('extreloff', %r)" % f.read32()
print " ('nextrel', %r)" % f.read32()
print " ('locreloff', %r)" % f.read32()
print " ('nlocrel', %r)" % f.read32()
def dumpSection32(f, i, opts):
print " # Section %r" % i
print " (('section_name', %r)" % f.read(16)
print " ('segment_name', %r)" % f.read(16)
print " ('address', %r)" % f.read32()
print " ('size', %r)" % f.read32()
print " ('offset', %r)" % f.read32()
print " ('alignment', %r)" % f.read32()
print " ('reloc_offset', %r)" % f.read32()
print " ('num_reloc', %r)" % f.read32()
print " ('flags', %#x)" % f.read32()
print " ('reserved1', %r)" % f.read32()
print " ('reserved2', %r)" % f.read32()
print " ),"
def main():
from optparse import OptionParser, OptionGroup
parser = OptionParser("usage: %prog [options] {files}")
(opts, args) = parser.parse_args()
if not args:
args.append('-')
for arg in args:
dumpmacho(arg, opts)
if __name__ == '__main__':
main()