moved the MC data type access to TargetMachine

Disassembler now simply needs a TargetMachine object
and it will be able to access all the descriptor objects
it needs for disassembly through the target machine.
This commit is contained in:
anthony cantor 2013-08-17 20:21:51 -06:00 • committed by Siu Kwan Lam
commit cbf4a61a17
5 changed files with 103 additions and 88 deletions

View file

@ -8,12 +8,20 @@ import contextlib
from llvmpy import api
from llvmpy.api.llvm import MCDisassembler
class Instr:
def __init__(self, mcinst):
class Instr(object):
def __init__(self, mcinst, target_machine):
'''
@mcinst: an MCInst object
@target_machine: an llvm.target.TargetMachine object
'''
self.mcinst = mcinst
if not self.mcinst:
raise llvm.LLVMException("null MCInst argument")
self.tm = target_machine
def __repr__(self):
return repr(self.mcinst)
@ -34,103 +42,45 @@ class Instr:
class BadInstr(Instr):
pass
class Disassembler:
class Disassembler(object):
def __init__(self, mcdisasm, mri, mai, mii, mia, mip):
self.mcdisasm = mcdisasm
if not self.mcdisasm:
raise llvm.LLVMException("null MCDisassembler argument")
def __init__(self, target_machine):
self.tm = target_machine
self.mri = mri
self.mai = mai
self.mii = mii
self.mia = mia
self.mip = mip
@property
def mdasm(self):
return self.tm.disassembler
def __repr__(self):
return repr(self.mcdisasm)
@property
def mai(self):
return self.tm.asm_info
@staticmethod
def new_from_target(target, triple, cpu, features):
def raise_on_false(name, obj):
if not obj:
raise llvm.LLVMException("Could not create %s" % name)
def instr(self, mcinst):
return Instr(mcinst, self)
sti = target.createMCSubtargetInfo(triple, cpu, features)
raise_on_false("subtarget info", sti)
mri = target.createMCRegInfo(triple)
raise_on_false("register info", mri)
mai = target.createMCAsmInfo(mri, triple)
raise_on_false("asm info", mai)
mii = target.createMCInstrInfo()
raise_on_false("instr info", mii)
mia = target.createMCInstrAnalysis(mii)
raise_on_false("instr analysis", mia)
mip = target.createMCInstPrinter(mai.getAssemblerDialect(),
mai, mii, mri, sti)
return Disassembler(target.createMCDisassembler(sti),
mri, mai, mii, mia, mip)
@staticmethod
def new_from_triple(triple='', cpu='', features=''):
if not triple:
triple = api.llvm.sys.getDefaultTargetTriple()
print repr(triple)
with contextlib.closing(BytesIO()) as error:
target = api.llvm.TargetRegistry.lookupTarget(triple, error)
if not target:
raise llvm.LLVMException(error.read())
if not target.hasMCDisassembler():
raise llvm.LLVMException(target, "No disassembler provided for %s." % triple)
return Disassembler.new_from_target(target, triple, cpu, features)
@staticmethod
def new_from_name(name, cpu='', features=''):
name = name.strip()
for target in api.llvm.TargetRegistry.targetsList():
if name == target.getName():
return Disassembler.new_from_target(target, name, cpu, features)
raise llvm.LLVMException("failed to find target with name %s" % name)
@staticmethod
def x86():
return Disassembler.new_from_name('x86')
@staticmethod
def x86_64():
return Disassembler.new_from_name('x86-64')
@staticmethod
def arm():
return Disassembler.new_from_name('arm')
@staticmethod
def thumb():
return Disassembler.new_from_name('thumb')
def bad_instr(self, mcinst):
return BadInstr(mcinst, self)
#decode some bytes into instructions. yields each instruction
#as it is decoded.
def decode(self, bs):
code = api.llvm.StringRefMemoryObject.new(bs, 0)
idx = code.getBase()
align = self.mai.getMinInstAlignment()
while(idx < code.getExtent()):
inst = api.llvm.MCInst.new()
status, size = self.mcdisasm.getInstruction(inst, code, idx)
status, size = self.mdasm.getInstruction(inst, code, idx)
if status == MCDisassembler.DecodeStatus.Fail:
yield (idx, None)
elif status == MCDisassembler.DecodeStatus.SoftFail:
yield (idx, BadInstr(inst))
yield (idx, self.bad_instr(inst))
else:
yield (idx, Instr(inst))
yield (idx, self.instr(inst))
if size <= 1:
idx += 1
if size < 1:
idx += (align - (idx % align))
else:
idx += size

View file

@ -187,3 +187,44 @@ class TargetMachine(llvm.Wrapper):
def feature_string(self):
return self._ptr.getTargetFeatureString()
@property
def target(self):
return self._ptr.getTarget()
if llvm.version >= (3, 4):
@property
def reg_info(self):
if not getattr(self, '_mri', False):
self._mri = self.target.createMCRegInfo(self.triple)
return self._mri
@property
def subtarget_info(self):
return self._ptr.getSubtargetImpl()
@property
def asm_info(self):
return self._ptr.getMCAsmInfo()
@property
def instr_info(self):
return self._ptr.getInstrInfo()
@property
def instr_analysis(self):
if not getattr(self, '_mia', False):
self._mia = self.target.getMCInstrAnalysis(self.instr_info)
return self._mia
@property
def disassembler(self):
if not getattr(self, '_dasm', False):
self._dasm = self.target.createMCDisassembler(self.subtarget_info)
return self._dasm
def is_little_endian(self):
return self.asm_info.isLittleEndian()