diff --git a/llvm/mc/__init__.py b/llvm/mc/__init__.py index 0a7da1d..5143e86 100644 --- a/llvm/mc/__init__.py +++ b/llvm/mc/__init__.py @@ -5,7 +5,7 @@ if llvm.version < (3, 4): from io import BytesIO import contextlib -from llvmpy import api +from llvmpy import api, extra from llvmpy.api.llvm import MCDisassembler class Operand(object): @@ -22,7 +22,7 @@ class Operand(object): self.tm = target_machine - def __repr__(self): + def __str__(self): s = "invalid" if self.op.isReg(): s = "reg(%s)" % (self.reg_name()) @@ -37,6 +37,9 @@ class Operand(object): return s + def __repr__(self): + return str(self) + def reg_name(self): if self.op.isReg(): s = self.tm.reg_info.getName(self.op.getReg()) @@ -61,10 +64,16 @@ class Instr(object): self.tm = target_machine + def __str__(self): + os = extra.make_raw_ostream_for_printing() + self.tm.inst_printer.printInst(self.mcinst, os, "") + return str(os.str()) + def __repr__(self): - return repr(self.mcinst) + return str(self) def __len__(self): + ''' the number of operands ''' return int(self.mcinst.size()) def operands(self): @@ -100,28 +109,29 @@ class Disassembler(object): def bad_instr(self, mcinst): return BadInstr(mcinst, self.tm) - def decode(self, bs, addr): + def decode(self, bs, base_addr): ''' decodes some the bytes in @bs into instructions and yields - each instructionas it is decoded. @addr is the base address + each instructionas it is decoded. @base_addr is the base address where the instruction bytes are from (not an offset into @bs) ''' - code = api.llvm.StringRefMemoryObject.new(bs, addr) - idx = code.getBase() + code = api.llvm.StringRefMemoryObject.new(bs, base_addr) + idx = 0 align = self.mai.getMinInstAlignment() while(idx < code.getExtent()): inst = api.llvm.MCInst.new() - status, size = self.mdasm.getInstruction(inst, code, idx) + addr = code.getBase() + idx + status, size = self.mdasm.getInstruction(inst, code, addr) if status == MCDisassembler.DecodeStatus.Fail: - yield (idx, None) + yield (addr, None) elif status == MCDisassembler.DecodeStatus.SoftFail: - yield (idx, self.bad_instr(inst)) + yield (addr, self.bad_instr(inst)) else: - yield (idx, self.instr(inst)) + yield (addr, self.instr(inst)) if size < 1: idx += (align - (idx % align)) diff --git a/llvm/target.py b/llvm/target.py index cdbd1d8..0e8045b 100644 --- a/llvm/target.py +++ b/llvm/target.py @@ -225,6 +225,19 @@ class TargetMachine(llvm.Wrapper): return self._dasm + @property + def inst_printer(self): + if not getattr(self, '_mip', False): + self._mip = self.target.createMCInstPrinter( + self.asm_info.getAssemblerDialect(), + self.asm_info, + self.instr_info, + self.reg_info, + self.subtarget_info + ) + + return self._mip + def is_little_endian(self): return self.asm_info.isLittleEndian() diff --git a/llvmpy/src/MC/__init__.py b/llvmpy/src/MC/__init__.py index 1da7b0e..c8b0f09 100644 --- a/llvmpy/src/MC/__init__.py +++ b/llvmpy/src/MC/__init__.py @@ -2,6 +2,7 @@ from binding import * from ..namespace import llvm from ..Support.StringRefMemoryObject import MemoryObject from ..Support.raw_ostream import raw_ostream +from src.ADT.StringRef import StringRef MCSubtargetInfo = llvm.Class() MCDisassembler = llvm.Class() @@ -90,6 +91,12 @@ class MCInstrAnalysis: class MCInstPrinter: _include_ = "llvm/MC/MCInstPrinter.h" + printInst = Method(Void, + const(ptr(MCInst)), #MI + ref(raw_ostream), #OS + cast(str, StringRef) #Annot + ) + @MCDisassembler class MCDisassembler: _include_ = "llvm/MC/MCDisassembler.h" diff --git a/test/example-disassemble.py b/test/example-disassemble.py index 1ccfe05..c1c3098 100644 --- a/test/example-disassemble.py +++ b/test/example-disassemble.py @@ -9,17 +9,19 @@ if llvm.version >= (3, 4): llvm.target.initialize_all() def print_instructions(dasm, bs): - for (offset, inst) in dasm.decode(bs, 0): + print("print instructions") + for (addr, inst) in dasm.decode(bs, 0x4000): if inst is None: - print("\t%r=>(bad): 0, []" % (offset)) + print("\t0x%x => (bad)" % (addr)) else: + ops = ", ".join(map(lambda op: repr(op), inst.operands())) if isinstance(inst, mc.BadInstr): - print("\t%r=>(bad)%r: %r" % (offset, inst, len(inst))) + print("\t0x%x (bad) ops = %s" % (addr, ops)) else: - print("\t%r=>%r: %r" % (offset, inst, len(inst))) - - for op in inst.operands(): - print("\t\t%s" % repr(op)) + print("\t0x%x ops = %s" % (addr, ops)) + + for line in str(inst).split("\n"): + print("\t%s" % (line)) x86 = TargetMachine.x86()