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:
parent
0e265a2cc5
commit
cbf4a61a17
5 changed files with 103 additions and 88 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue