1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
"""
Class to read the symbol table from a Mach-O header
"""
from __future__ import with_statement
import sys
from macholib.mach_o import (
MH_CIGAM_64,
MH_MAGIC_64,
dylib_module,
dylib_reference,
dylib_table_of_contents,
nlist,
nlist_64,
relocation_info,
)
__all__ = ["SymbolTable"]
if sys.version_info[0] == 2:
range = xrange # noqa: F821
class SymbolTable(object):
def __init__(self, macho, header=None, openfile=None):
if openfile is None:
openfile = open
if header is None:
header = macho.headers[0]
self.macho_header = header
with openfile(macho.filename, "rb") as fh:
self.symtab = header.getSymbolTableCommand()
self.dysymtab = header.getDynamicSymbolTableCommand()
if self.symtab is not None:
self.nlists = self.readSymbolTable(fh)
if self.dysymtab is not None:
self.readDynamicSymbolTable(fh)
def readSymbolTable(self, fh):
cmd = self.symtab
fh.seek(self.macho_header.offset + cmd.stroff)
strtab = fh.read(cmd.strsize)
fh.seek(self.macho_header.offset + cmd.symoff)
nlists = []
if self.macho_header.MH_MAGIC in [MH_MAGIC_64, MH_CIGAM_64]:
cls = nlist_64
else:
cls = nlist
for _i in range(cmd.nsyms):
cmd = cls.from_fileobj(fh, _endian_=self.macho_header.endian)
if cmd.n_un == 0:
nlists.append((cmd, ""))
else:
nlists.append(
(
cmd,
strtab[cmd.n_un : strtab.find(b"\x00", cmd.n_un)], # noqa: E203
)
)
return nlists
def readDynamicSymbolTable(self, fh):
cmd = self.dysymtab
nlists = self.nlists
self.localsyms = nlists[
cmd.ilocalsym : cmd.ilocalsym + cmd.nlocalsym # noqa: E203
]
self.extdefsyms = nlists[
cmd.iextdefsym : cmd.iextdefsym + cmd.nextdefsym # noqa: E203
]
self.undefsyms = nlists[
cmd.iundefsym : cmd.iundefsym + cmd.nundefsym # noqa: E203
]
if cmd.tocoff == 0:
self.toc = None
else:
self.toc = self.readtoc(fh, cmd.tocoff, cmd.ntoc)
def readtoc(self, fh, off, n):
fh.seek(self.macho_header.offset + off)
return [dylib_table_of_contents.from_fileobj(fh) for i in range(n)]
def readmodtab(self, fh, off, n):
fh.seek(self.macho_header.offset + off)
return [dylib_module.from_fileobj(fh) for i in range(n)]
def readsym(self, fh, off, n):
fh.seek(self.macho_header.offset + off)
refs = []
for _i in range(n):
ref = dylib_reference.from_fileobj(fh)
isym, flags = divmod(ref.isym_flags, 256)
refs.append((self.nlists[isym], flags))
return refs
def readrel(self, fh, off, n):
fh.seek(self.macho_header.offset + off)
return [relocation_info.from_fileobj(fh) for i in range(n)]
|