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:
parent
1d735e49d2
commit
43f7330fda
5 changed files with 78 additions and 19 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue