added align parameter to llvm.mc.Disassembler.decode

i cant find any method in llvm to automatically get the
correct instruction alignment for disassembling. i thought
it would be MCAsmInfo.getMinInstAlignment, but that value is
1 for the ARM target machine. since that is clearly the wrong
instruction alignment for disassembling arm, the user should
be able to configure the alignment to whatever is needed.
This commit is contained in:
anthony cantor 2013-09-05 17:51:48 -06:00 committed by Siu Kwan Lam
commit aa264cee2d
2 changed files with 19 additions and 7 deletions

View file

@ -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()

View file

@ -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)