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):
|
def decode(self, bs, base_addr):
|
||||||
'''
|
'''
|
||||||
decodes some the bytes in @bs into instructions and yields
|
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
|
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):
|
if not isinstance(bs, bytes):
|
||||||
|
|
@ -146,15 +148,27 @@ class Disassembler(object):
|
||||||
addr = code.getBase() + idx
|
addr = code.getBase() + idx
|
||||||
status, size = self.mdasm.getInstruction(inst, code, addr)
|
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:
|
if size < 1:
|
||||||
idx += (align - (idx % align))
|
size = (align - (idx % align))
|
||||||
else:
|
|
||||||
idx += size
|
|
||||||
|
|
||||||
|
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");
|
"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
|
#if LLVM_VERSION_MAJOR >= 3 and LLVM_VERSION_MINOR >= 4
|
||||||
static
|
static
|
||||||
|
|
@ -972,6 +1002,7 @@ PyObject* MCDisassembler_getInstruction(llvm::MCDisassembler *disasm,
|
||||||
llvm::nulls(), llvm::nulls());
|
llvm::nulls(), llvm::nulls());
|
||||||
return Py_BuildValue("(i,i)", int(status), size);
|
return Py_BuildValue("(i,i)", int(status), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* llvm >= 3.4 */
|
#endif /* llvm >= 3.4 */
|
||||||
|
|
||||||
static
|
static
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,23 @@ if LLVM_VERSION >= (3, 4):
|
||||||
|
|
||||||
@MemoryObject
|
@MemoryObject
|
||||||
class 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):
|
if LLVM_VERSION >= (3, 4):
|
||||||
@StringRefMemoryObject
|
@StringRefMemoryObject
|
||||||
|
|
@ -16,6 +32,3 @@ if LLVM_VERSION >= (3, 4):
|
||||||
_include_ = "llvm/Support/StringRefMemoryObject.h"
|
_include_ = "llvm/Support/StringRefMemoryObject.h"
|
||||||
|
|
||||||
new = Constructor(cast(bytes, StringRef), cast(int, Uint64))
|
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):
|
def print_instructions(dasm, bs):
|
||||||
print("print instructions")
|
print("print instructions")
|
||||||
for (addr, inst) in dasm.decode(bs, 0x4000):
|
for (addr, data, inst) in dasm.decode(bs, 0x4000):
|
||||||
|
|
||||||
if inst is None:
|
if inst is None:
|
||||||
print("\t0x%x => (bad)" % (addr))
|
print("\t0x%x => (bad)" % (addr))
|
||||||
else:
|
else:
|
||||||
|
|
@ -22,7 +23,7 @@ if llvm.version >= (3, 4):
|
||||||
|
|
||||||
print("\t\tflags = 0x%x, tsflags = 0x%x" % (inst.flags, inst.ts_flags))
|
print("\t\tflags = 0x%x, tsflags = 0x%x" % (inst.flags, inst.ts_flags))
|
||||||
for line in str(inst).split("\n"):
|
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()
|
x86 = TargetMachine.x86()
|
||||||
|
|
|
||||||
|
|
@ -659,7 +659,7 @@ def do_llvm_mc():
|
||||||
tm = TargetMachine.x86()
|
tm = TargetMachine.x86()
|
||||||
dasm = mc.Disassembler(tm)
|
dasm = mc.Disassembler(tm)
|
||||||
|
|
||||||
for (offset, instr) in dasm.decode("c3", 0):
|
for (offset, data, instr) in dasm.decode("c3", 0):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue