capstone-engine / capstone

Capstone disassembly/disassembler framework for ARM, ARM64 (ARMv8), Alpha, BPF, Ethereum VM, HPPA, M68K, M680X, Mips, MOS65XX, PPC, RISC-V(rv32G/rv64G), SH, Sparc, SystemZ, TMS320C64X, TriCore, Webassembly, XCore and X86.

Home Page:http://www.capstone-engine.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Missing Operands in ARM Thumb Mode Disassembly with Capstone 5.0.1280

AntoineBlaud opened this issue · comments

Issue Description:

When disassembling ARM Thumb instructions using Capstone with the CS_MODE_THUMB mode enabled, there is a problem where some instructions have missing operands.

Observed Behavior:

Some instructions, particularly ldr and str, when disassembled using Capstone with ARM Thumb mode, have only one operand reported, missing the memory operand information which includes the base register, index register, scale, and displacement.

Environment:

  • Capstone version: 5.0.1280
  • Capstone version: 4.0.1024

Code Snippet:

from capstone import *
from capstone.arm_const import ARM_OP_MEM, ARM_OP_REG, ARM_OP_IMM

CODE = b'\x00h\x00h\x07\x90\x0bhk\xb1\x87I\x02\xad\x87J'

def get_reg_name(cs, reg):
    name = cs.reg_name(reg)
    if isinstance(name, str):
        return name.upper()
    return None

print("Capstone", cs_version())

md = Cs(CS_ARCH_ARM, CS_MODE_THUMB)
md.detail = True
for insn in md.disasm(CODE, 0x1000):
    print("0x%x:\t%s\t%s" %(insn.address, insn.mnemonic, insn.op_str))
    print("  Number of Operands:", len(insn.operands))
    for op in insn.operands:
        if op.type == ARM_OP_MEM:
            print("  Operand Type: Memory")
            print("  Base Register:", get_reg_name(md, op.mem.base))
            print("  Index Register:", get_reg_name(md, op.mem.index))
            print("  Scale:", op.mem.scale)
            print("  Disp:", op.mem.disp)
        elif op.type == ARM_OP_REG:
            print("  Operand Type: Register")
            print("  Register:", get_reg_name(md, op.reg))
        elif op.type == ARM_OP_IMM:
            print("  Operand Type: Immediate")
            print("  Value:", op.imm)
        else:
            print("  Operand Type:", op.type)

Output:
Capstone version: 4.0.1024

Capstone (4, 0, 1024)
0x1000: ldr     r0, [r0]
  Number of Operands: 2
  Operand Type: Register
  Register: R0
  Operand Type: Memory
  Base Register: R0
  Index Register: None
  Scale: 1
  Disp: 0
0x1002: ldr     r0, [r0]
  Number of Operands: 2
  Operand Type: Register
  Register: R0
  Operand Type: Memory
  Base Register: R0
  Index Register: None
  Scale: 1
  Disp: 0
0x1004: str     r0, [sp, #0x1c]
  Number of Operands: 2
  Operand Type: Register
  Register: R0
  Operand Type: Memory
  Base Register: SP
  Index Register: None
  Scale: 1
  Disp: 28
0x1006: ldr     r3, [r1]
  Number of Operands: 2
  Operand Type: Register
  Register: R3
  Operand Type: Memory
  Base Register: R1
  Index Register: None
  Scale: 1
  Disp: 0
0x1008: cbz     r3, #0x1026
  Number of Operands: 2
  Operand Type: Register
  Register: R3
  Operand Type: Immediate
  Value: 4134
0x100a: ldr     r1, [pc, #0x21c]
  Number of Operands: 2
  Operand Type: Register
  Register: R1
  Operand Type: Memory
  Base Register: PC
  Index Register: None
  Scale: 1
  Disp: 540
0x100c: add     r5, sp, #8
  Number of Operands: 3
  Operand Type: Register
  Register: R5
  Operand Type: Register
  Register: SP
  Operand Type: Immediate
  Value: 8
0x100e: ldr     r2, [pc, #0x21c]
  Number of Operands: 2
  Operand Type: Register
  Register: R2
  Operand Type: Memory
  Base Register: PC
  Index Register: None
  Scale: 1
  Disp: 540

Capstone version: 5.0.1280

Capstone (5, 0, 1280)
0x1000: ldr     r0, [r0]
  Number of Operands: 1
  Operand Type: Register
  Register: R0
0x1002: ldr     r0, [r0]
  Number of Operands: 1
  Operand Type: Register
  Register: R0
0x1004: str     r0, [sp, #0x1c]
  Number of Operands: 1
  Operand Type: Register
  Register: R0
0x1006: ldr     r3, [r1]
  Number of Operands: 1
  Operand Type: Register
  Register: R3
0x1008: cbz     r3, #0x1026
  Number of Operands: 2
  Operand Type: Register
  Register: R3
  Operand Type: Immediate
  Value: 4134
0x100a: ldr     r1, [pc, #0x21c]
  Number of Operands: 2
  Operand Type: Register
  Register: R1
  Operand Type: Memory
  Base Register: PC
  Index Register: None
  Scale: 1
  Disp: 540
0x100c: add     r5, sp, #8
  Number of Operands: 3
  Operand Type: Register
  Register: R5
  Operand Type: Register
  Register: SP
  Operand Type: Immediate
  Value: 8
0x100e: ldr     r2, [pc, #0x21c]
  Number of Operands: 2
  Operand Type: Register
  Register: R2
  Operand Type: Memory
  Base Register: PC
  Index Register: None
  Scale: 1

Can you please check those instructions against the current next branch? There is a huge update for ARM in v6 and hence in the next branch.

Maybe related to #2260. @AntoineBlaud please try the cstool of your installed capstone version and check if it gives the correct output. I am trying to debug this issue and more info will be helpful.

Hello @udiboy1209 ,

I suspect the error originates from the Python library bindings. While version 5.0.0 functions correctly, version 5.0.1 triggers the reported error with the same Capstone library version (5.0.1280)

However, I tried using cstool, but the results completely mismatch the decompilation results provided so far. I tested both ARM and Thumb modes.