llvm.mc.Disassembler.decode now yields the byte sequence which generated the instruction

added custom method to extra.h to return a PyBytes object
from the bytes read from MemoryObject.readBytes.

also moved the generic methods from StringRefMemoryObject
up to MemoryObject
This commit is contained in:
anthony cantor 2013-09-02 23:55:51 -06:00 committed by Siu Kwan Lam
commit 43f7330fda
5 changed files with 78 additions and 19 deletions

View file

@ -126,9 +126,11 @@ class Disassembler(object):
def decode(self, bs, base_addr):
'''
decodes some the bytes in @bs into instructions and yields
each instructionas it is decoded. @base_addr is the base address
each instruction as it is decoded. @base_addr is the base address
where the instruction bytes are from (not an offset into
@bs)
@bs). yields instructions in the form of (addr, data, inst) where
addr is an integer, data is a bytearray and inst is an instance of
llvm.mc.Instr
'''
if not isinstance(bs, bytes):
@ -146,15 +148,27 @@ class Disassembler(object):
addr = code.getBase() + idx
status, size = self.mdasm.getInstruction(inst, code, addr)
if status == MCDisassembler.DecodeStatus.Fail:
yield (addr, None)
elif status == MCDisassembler.DecodeStatus.SoftFail:
yield (addr, self.bad_instr(inst))
else:
yield (addr, self.instr(inst))
if size < 1:
idx += (align - (idx % align))
else:
idx += size
size = (align - (idx % align))
amt_left = code.getExtent() - idx
if amt_left >= size:
data = code.readBytes(addr, size)
elif amt_left < 1:
break
else:
data = code.readBytes(addr, amt_left)
if sys.version_info.major < 3:
data = bytearray(map(lambda b: ord(b), data))
else:
data = bytearray(data)
if status == MCDisassembler.DecodeStatus.Fail:
yield (addr, data, None)
elif status == MCDisassembler.DecodeStatus.SoftFail:
yield (addr, data, self.bad_instr(inst))
else:
yield (addr, data, self.instr(inst))
idx += size

View file

@ -955,6 +955,36 @@ PyObject* TargetRegistry_targets_list()
"llvm::Target", "llvm::Target");
}
static
PyObject* MemoryObject_readBytes(const llvm::MemoryObject *mobj,
uint64_t addr,
uint64_t size
)
{
int status;
uint8_t *bytes;
PyObject* po;
if(size < 1)
goto fail;
bytes = new uint8_t[size];
if(bytes == NULL)
goto fail;
status = mobj->readBytes(addr, size, bytes);
if(status != 0) {
delete bytes;
goto fail;
}
po = PyBytes_FromStringAndSize((const char *) bytes, size);
delete bytes;
return po;
fail:
Py_RETURN_NONE;
}
#if LLVM_VERSION_MAJOR >= 3 and LLVM_VERSION_MINOR >= 4
static
@ -972,6 +1002,7 @@ PyObject* MCDisassembler_getInstruction(llvm::MCDisassembler *disasm,
llvm::nulls(), llvm::nulls());
return Py_BuildValue("(i,i)", int(status), size);
}
#endif /* llvm >= 3.4 */
static

View file

@ -8,7 +8,23 @@ if LLVM_VERSION >= (3, 4):
@MemoryObject
class MemoryObject:
pass
_include_ = "llvm/Support/MemoryObject.h"
getBase = Method(cast(Uint64, int))
getExtent = Method(cast(Uint64, int))
readBytes = CustomMethod('MemoryObject_readBytes',
PyObjectPtr,
cast(int, Uint64), #address
cast(int, Uint64) #size
)
@CustomPythonMethod
def readAll(self):
result = self.readBytes(self.getBase(), self.getExtent())
if not result:
raise Exception("expected readBytes to be successful!")
return result
if LLVM_VERSION >= (3, 4):
@StringRefMemoryObject
@ -16,6 +32,3 @@ if LLVM_VERSION >= (3, 4):
_include_ = "llvm/Support/StringRefMemoryObject.h"
new = Constructor(cast(bytes, StringRef), cast(int, Uint64))
getBase = Method(cast(Uint64, int))
getExtent = Method(cast(Uint64, int))

View file

@ -10,7 +10,8 @@ if llvm.version >= (3, 4):
def print_instructions(dasm, bs):
print("print instructions")
for (addr, inst) in dasm.decode(bs, 0x4000):
for (addr, data, inst) in dasm.decode(bs, 0x4000):
if inst is None:
print("\t0x%x => (bad)" % (addr))
else:
@ -22,7 +23,7 @@ if llvm.version >= (3, 4):
print("\t\tflags = 0x%x, tsflags = 0x%x" % (inst.flags, inst.ts_flags))
for line in str(inst).split("\n"):
print("\t%s" % (line))
print("\t\t%-24s %s" % ("".join(map(lambda b: "%02x" % b, data))+":", line.strip()))
x86 = TargetMachine.x86()

View file

@ -659,7 +659,7 @@ def do_llvm_mc():
tm = TargetMachine.x86()
dasm = mc.Disassembler(tm)
for (offset, instr) in dasm.decode("c3", 0):
for (offset, data, instr) in dasm.decode("c3", 0):
pass
def main():