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
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -14,10 +14,17 @@ MCInstrInfo = llvm.Class()
|
|||
MCInstrAnalysis = llvm.Class()
|
||||
MCInstPrinter = llvm.Class()
|
||||
|
||||
TargetSubtargetInfo = llvm.Class(MCSubtargetInfo)
|
||||
TargetInstrInfo = llvm.Class(MCInstrInfo)
|
||||
|
||||
@MCSubtargetInfo
|
||||
class MCSubtargetInfo:
|
||||
pass
|
||||
|
||||
@TargetSubtargetInfo
|
||||
class TargetSubtargetInfo:
|
||||
_include_ = 'llvm/Target/TargetSubtargetInfo.h'
|
||||
|
||||
@MCExpr
|
||||
class MCExpr:
|
||||
_include_ = "llvm/MC/MCExpr.h"
|
||||
|
|
@ -65,6 +72,10 @@ class MCRegisterInfo:
|
|||
class MCInstrInfo:
|
||||
_include_ = "llvm/MC/MCInstrInfo.h"
|
||||
|
||||
@TargetInstrInfo
|
||||
class TargetInstrInfo:
|
||||
_include_ = 'llvm/Target/TargetInstrInfo.h'
|
||||
|
||||
@MCInstrAnalysis
|
||||
class MCInstrAnalysis:
|
||||
_include_ = "llvm/MC/MCInstrAnalysis.h"
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ from src.ADT.StringRef import StringRef
|
|||
from src.Support.CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc
|
||||
from src.GlobalValue import GlobalValue
|
||||
from src.DataLayout import DataLayout
|
||||
if LLVM_VERSION >= (3, 4):
|
||||
from src.MC import MCAsmInfo, TargetInstrInfo, TargetSubtargetInfo
|
||||
|
||||
if LLVM_VERSION < (3, 3):
|
||||
from src.TargetTransformInfo import (ScalarTargetTransformInfo,
|
||||
|
|
@ -55,4 +57,10 @@ class TargetMachine:
|
|||
cast(bool, Bool)
|
||||
).require_only(3)
|
||||
|
||||
if LLVM_VERSION >= (3, 4):
|
||||
getSubtargetImpl = Method(const(ptr(TargetSubtargetInfo)))
|
||||
|
||||
getMCAsmInfo = Method(const(ptr(MCAsmInfo)))
|
||||
|
||||
getInstrInfo = Method(const(ptr(TargetInstrInfo)))
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ import llvm
|
|||
|
||||
if llvm.version >= (3, 4):
|
||||
|
||||
from llvm.target import TargetMachine
|
||||
from llvm import mc
|
||||
from llvm.mc import Disassembler
|
||||
from llvmpy import api
|
||||
|
||||
llvm.initialize_all_target_components()
|
||||
llvm.target.initialize_all()
|
||||
|
||||
def op_str(op):
|
||||
s = []
|
||||
|
|
@ -37,7 +37,7 @@ if llvm.version >= (3, 4):
|
|||
if inst is None:
|
||||
print("\t%r=>(bad): 0, []" % (offset))
|
||||
else:
|
||||
if isinstance(inst, mc.BadInstr):
|
||||
if isinstance(inst, mc.BadInstr):
|
||||
print("\t%r=>(bad)%r: %r" % (offset, inst, len(inst)))
|
||||
else:
|
||||
print("\t%r=>%r: %r" % (offset, inst, len(inst)))
|
||||
|
|
@ -46,11 +46,16 @@ if llvm.version >= (3, 4):
|
|||
print("\t\t%s" % op_str(op))
|
||||
|
||||
|
||||
print("x86:")
|
||||
print_instructions(Disassembler.x86(), "\x01\xc3\xc3\xcc\x90")
|
||||
print("x86-64:")
|
||||
print_instructions(Disassembler.x86_64(), "\x55\x48\x89\xe8")
|
||||
print("arm:")
|
||||
x86 = TargetMachine.x86()
|
||||
print("x86: LE=%s" % x86.is_little_endian())
|
||||
print_instructions(Disassembler(x86), "\x01\xc3\xc3\xcc\x90")
|
||||
|
||||
x86_64 = TargetMachine.x86_64()
|
||||
print("x86-64: LE=%s" % x86_64.is_little_endian())
|
||||
print_instructions(Disassembler(x86_64), "\x55\x48\x89\xe8")
|
||||
|
||||
arm = TargetMachine.arm()
|
||||
print("arm: LE=%s" % arm.is_little_endian())
|
||||
code = [
|
||||
"\xe9\x2d\x48\x00",
|
||||
"\xea\x00\x00\x06",
|
||||
|
|
@ -58,4 +63,4 @@ if llvm.version >= (3, 4):
|
|||
"\xe2\x8d\xb0\x04",
|
||||
"\xe5\x0b\x00\x20"
|
||||
]
|
||||
print_instructions(Disassembler.arm(), "".join(map(lambda s: s[::-1], code)))
|
||||
print_instructions(Disassembler(arm), "".join(map(lambda s: s[::-1], code)))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue