Source code for vstruct.defs.macho
'''
Structure definitions for the OSX MachO binary format.
'''
import struct
import vstruct
from vstruct.defs.macho.fat import *
from vstruct.defs.macho.const import *
from vstruct.defs.macho.stabs import *
from vstruct.defs.macho.loader import *
[docs]class mach_o(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self._raw_bytes = ''
self._symbols = None
self.mach_header = mach_header()
self.load_commands = vstruct.VStruct()
[docs] def getSymbols(self):
if self._symbols != None:
return self._symbols
self._symbols = []
for fname,vs in self.load_commands:
if vs.cmd != LC_SYMTAB:
continue
strbytes = self._raw_bytes[vs.stroff:vs.stroff+vs.strsize]
#print repr(strbytes)
strtab = strbytes.split('\x00')
#print strtab
offset = vs.symoff
print 'NSYMS:',vs.nsyms
for i in xrange(vs.nsyms):
n = nlist() # FIXME 64!
offset = n.vsParse(self._raw_bytes, offset)
#symstr = strtab[n.n_strx]
# FIXME this is slow!
symstr = strbytes[n.n_strx:].split('\x00', 1)[0]
#print n.tree()
#print symstr
[docs] def getLibDeps(self):
'''
Return a list of the library files this Mach-O is dependant on
'''
ret = []
for fname, vs in self.load_commands:
if vs.cmd != LC_LOAD_DYLIB:
continue
ret.append(vs.namedata)
return ret
[docs] def getSegments(self):
'''
Return a list of (segname, rva, perms, bytes) tuples for the memory
segments defined by the loader commands
'''
ret = []
for fname, vs in self.load_commands:
if vs.cmd != LC_SEGMENT:
print hex(vs.cmd),hex(vs.cmdsize) # 2, 5, b, e
continue
# Slice the segment bytes from raw bytes
fbytes = self._raw_bytes[ vs.fileoff: vs.fileoff + vs.filesize ]
# Pad out to virtual size
fbytes = fbytes.ljust(vs.vmsize, '\x00')
ret.append((vs.segname, vs.vmaddr, vs.initprot, fbytes))
return ret
[docs] def vsParse(self, bytes, offset=0):
self._raw_bytes = bytes[offset:]
offset = self.mach_header.vsParse(bytes, offset=offset)
#print bytes[offset:].encode('hex')
for i in xrange(self.mach_header.ncmds):
# should we use endian from header?
cmdtype, cmdlen = struct.unpack('<II', bytes[offset:offset+8])
cmdclass = getCommandClass(cmdtype)
cmdobj = cmdclass()
cmdobj.vsParse(bytes, offset=offset)
self.load_commands.vsAddField('cmd%d' % i, cmdobj)
offset += cmdobj.cmdsize