capstone-engine / capstone

Capstone disassembly/disassembler framework for ARM, ARM64 (ARMv8), Alpha, BPF, Ethereum VM, HPPA, LoongArch, M68K, M680X, Mips, MOS65XX, PPC, RISC-V(rv32G/rv64G), SH, Sparc, SystemZ, TMS320C64X, TriCore, Webassembly, XCore and X86.
http://www.capstone-engine.org
7.64k stars 1.56k forks source link

CS_ARCH_ARM64 missing operands #2230

Open libinyxsn opened 11 months ago

libinyxsn commented 11 months ago

env: python capstone v5.0.1

code:

from capstone import *
from capstone.arm64 import *

CODE = b"\xe1\x0b\x40\xb9\x20\x04\x81\xda\x20\x08\x02\x8b"

md = Cs(CS_ARCH_ARM64, CS_MODE_ARM | CS_MODE_LITTLE_ENDIAN)
md.detail = True

for insn in md.disasm(CODE, 0x38):
    print("0x%x:\t%s\t%s" %(insn.address, insn.mnemonic, insn.op_str))

    if len(insn.operands) > 0:
        print("\tNumber of operands: %u" %len(insn.operands))
        c = -1
        for i in insn.operands:
            c += 1
            if i.type == ARM64_OP_REG:
                print("\t\toperands[%u].type: REG = %s" %(c, insn.reg_name(i.value.reg)))
            if i.type == ARM64_OP_IMM:
                print("\t\toperands[%u].type: IMM = 0x%x" %(c, i.value.imm))
            if i.type == ARM64_OP_CIMM:
                print("\t\toperands[%u].type: C-IMM = %u" %(c, i.value.imm))
            if i.type == ARM64_OP_FP:
                print("\t\toperands[%u].type: FP = %f" %(c, i.value.fp))
            if i.type == ARM64_OP_MEM:
                print("\t\toperands[%u].type: MEM" %c)
                if i.value.mem.base != 0:
                    print("\t\t\toperands[%u].mem.base: REG = %s" \
                        %(c, insn.reg_name(i.value.mem.base)))
                if i.value.mem.index != 0:
                    print("\t\t\toperands[%u].mem.index: REG = %s" \
                        %(c, insn.reg_name(i.value.mem.index)))
                if i.value.mem.disp != 0:
                    print("\t\t\toperands[%u].mem.disp: 0x%x" \
                        %(c, i.value.mem.disp))

            if i.shift.type != ARM64_SFT_INVALID and i.shift.value:
                print("\t\t\tShift: type = %u, value = %u" \
                    %(i.shift.type, i.shift.value))

            if i.ext != ARM64_EXT_INVALID:
                print("\t\t\tExt: %u" %i.ext)

    if insn.writeback:
        print("\tWrite-back: True")
    if not insn.cc in [ARM64_CC_AL, ARM64_CC_INVALID]:
        print("\tCode condition: %u" %insn.cc)
    if insn.update_flags:
        print("\tUpdate-flags: True")

output:

0x38:   ldr     w1, [sp, #8]
        Number of operands: 1          !!!!!!wrong
                operands[0].type: REG = w1   
0x3c:   cneg    x0, x1, ne
        Number of operands: 2
                operands[0].type: REG = x0
                operands[1].type: REG = x1
        Code condition: 2
0x40:   add     x0, x1, x2, lsl #2
        Number of operands: 3
                operands[0].type: REG = x0
                operands[1].type: REG = x1
                operands[2].type: REG = x2
                        Shift: type = 1, value = 2

'ldr w1, [sp, #8]' operands is wrong.

Rot127 commented 11 months ago

This is fixed on the most recent next branch:

./cstool -d aarch64 "\xe1\x0b\x40\xb9\x20\x04\x81\xda\x20\x08\x02\x8b"
 0  e1 0b 40 b9  ldr    w1, [sp, #8]
    ID: 581 (ldr)
    op_count: 2
        operands[0].type: REG = w1
        operands[0].access: WRITE
        operands[1].type: MEM
            operands[1].mem.base: REG = sp
            operands[1].mem.disp: 0x8
        operands[1].access: READ
    Registers read: sp
    Registers modified: w1

 4  20 04 81 da  cneg   x0, x1, ne
    ID: 272 (csneg)
    Is alias: 1627 (cneg) with ALIAS operand set
    op_count: 2
        operands[0].type: REG = x0
        operands[0].access: WRITE
        operands[1].type: REG = x1
        operands[1].access: READ
    Code-condition: 1
    Registers read: nzcv x1
    Registers modified: x0

 8  20 08 02 8b  add    x0, x1, x2, lsl #2
    ID: 21 (add)
    op_count: 3
        operands[0].type: REG = x0
        operands[0].access: WRITE
        operands[1].type: REG = x1
        operands[1].access: READ
        operands[2].type: REG = x2
        operands[2].access: READ
            Shift: type = 1, value = 2
    Registers read: x1 x2
    Registers modified: x0

Especially for ARM and AArch64 I would recommend you to use it. It has way more and and correct details. Please checkout https://github.com/capstone-engine/capstone/blob/next/docs/cs_v6_release_guide.md for details