diff --git a/llvm/mc/__init__.py b/llvm/mc/__init__.py index 3e13242..d91bf73 100644 --- a/llvm/mc/__init__.py +++ b/llvm/mc/__init__.py @@ -184,14 +184,21 @@ class Disassembler(object): def bad_instr(self, mcinst): return BadInstr(mcinst, self.tm) - def decode(self, bs, base_addr): + def decode(self, bs, base_addr, align=None): ''' decodes some the bytes in @bs into instructions and yields each instruction as it is decoded. @base_addr is the base address where the instruction bytes are from (not an offset into @bs). yields instructions in the form of (addr, data, inst) where addr is an integer, data is a tuple of integers and inst is an instance of - llvm.mc.Instr + llvm.mc.Instr. @align specifies the byte alignment of instructions and + is only used if an un-decodable instruction is encountered, in which + case the disassembler will skip the following bytes until the next + aligned address. if @align is unspecified, the default alignment + for the architecture will be used, however this may not be ideal + for disassembly. for example, the default alignment for ARM is 1, but you + probably want it to be 4 for the purposes of disassembling ARM + instructions. ''' if isinstance(bs, str) and sys.version_info.major >= 3: @@ -201,7 +208,8 @@ class Disassembler(object): code = api.llvm.StringRefMemoryObject.new(bs, base_addr) idx = 0 - align = self.mai.getMinInstAlignment() + if not isinstance(align, int) or align < 1: + align = self.mai.getMinInstAlignment() while(idx < code.getExtent()): inst = api.llvm.MCInst.new() diff --git a/test/example-disassemble.py b/test/example-disassemble.py index 489872a..75ffb18 100644 --- a/test/example-disassemble.py +++ b/test/example-disassemble.py @@ -8,7 +8,7 @@ if llvm.version >= (3, 4): llvm.target.initialize_all() - def print_instructions(dasm, bs): + def print_instructions(dasm, bs, align=None): branch_properties = [ 'is_branch', 'is_cond_branch', @@ -21,7 +21,7 @@ if llvm.version >= (3, 4): ] print("print instructions") - for (addr, data, inst) in dasm.decode(bs, 0x4000): + for (addr, data, inst) in dasm.decode(bs, 0x4000, align): if inst is None: print("\t0x%x => (bad)" % (addr)) @@ -55,6 +55,10 @@ if llvm.version >= (3, 4): "\xea\x00\x00\x06", "\xe2\x4d\xd0\x20", "\xe2\x8d\xb0\x04", - "\xe5\x0b\x00\x20" + "\xe5\x0b\x00\x20", + "\x03\x30\x22\xe0", #bad instruction to test alignment + "\x73\x20\xef\xe6", #bad instruction to test alignment + "\x18\x00\x1b\xe5", + "\x10\x30\xa0\xe3" ] - print_instructions(Disassembler(arm), "".join(map(lambda s: s[::-1], code))) + print_instructions(Disassembler(arm), "".join(map(lambda s: s[::-1], code)), 4)