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.36k stars 1.54k forks source link

Invalid information for ARM memory operand on next #2281

Open Quentin01 opened 7 months ago

Quentin01 commented 7 months ago

Hi,

I just checked a bunch of instructions with cstool and it seems that the some information about a memory operand are broken in next.

 0  02 00 91 e7  ldr    r0, [r1, r2]
    ID: 4 (ldr)
    op_count: 2
        operands[0].type: REG = r0
        operands[0].access: WRITE
        operands[1].type: MEM
            operands[1].mem.base: REG = r1
            operands[1].mem.index: REG = r2
            operands[1].mem.scale: 0
        operands[1].access: READ
    Registers read: r1 r2
    Registers modified: r0
    Groups: IsARM
 0  02 01 91 e7  ldr    r0, [r1, r2, lsl #2]
    ID: 4 (ldr)
    op_count: 2
        operands[0].type: REG = r0
        operands[0].access: WRITE
        operands[1].type: MEM
            operands[1].mem.base: REG = r1
            operands[1].mem.index: REG = r2
            operands[1].mem.scale: 0
        operands[1].access: READ
            Shift: 2 = 2
    Registers read: r1 r2
    Registers modified: r0
    Groups: IsARM
 0  62 01 91 e7  ldr    r0, [r1, r2, ror #2]
    ID: 4 (ldr)
    op_count: 2
        operands[0].type: REG = r0
        operands[0].access: WRITE
        operands[1].type: MEM
            operands[1].mem.base: REG = r1
            operands[1].mem.index: REG = r2
            operands[1].mem.scale: 0
        operands[1].access: READ
            Shift: 4 = 2
    Registers read: r1 r2
    Registers modified: r0
    Groups: IsARM 
 0  02 01 91 e7  ldr    r0, [r1, r2, lsl #2]
    ID: 4 (ldr)
    op_count: 2
        operands[0].type: REG = r0
        operands[0].access: WRITE
        operands[1].type: MEM
            operands[1].mem.base: REG = r1
            operands[1].mem.index: REG = r2
            operands[1].mem.scale: 0
        operands[1].access: READ
            Shift: 2 = 2
    Registers read: r1 r2
    Registers modified: r0
    Groups: IsARM
 0  01 01 80 e0  add    r0, r0, r1, lsl #2
    ID: 31 (add)
    op_count: 3
        operands[0].type: REG = r0
        operands[0].access: WRITE
        operands[1].type: REG = r0
        operands[1].access: READ
        operands[2].type: REG = r1
        operands[2].access: READ
            Shift: 2 = 2
    Registers read: r0 r1
    Registers modified: r0
    Groups: IsARM

I think that the scale and lshift issues are probably related to the recent reword on ARM by @Rot127 in #1949, but I'm not sure. I didn't test those instructions on the v5 but as I previously saw some instructions having a correct scale I think it is working on the v5.

Thanks

Quentin01 commented 6 months ago

Another issue, is that rrx shift isn't working too, here is an example:

 0  61 00 10 e7  ldr    r0, [r0, -r1, rrx]
    ID: 4 (ldr)
    op_count: 2
        operands[0].type: REG = r0
        operands[0].access: WRITE
        operands[1].type: MEM
            operands[1].mem.base: REG = r0
            operands[1].mem.index: REG = r1
            operands[1].mem.scale: 0
        operands[1].access: READ
    Registers read: r0 r1
    Registers modified: r0
    Groups: IsARM
Rot127 commented 6 months ago

Thank you for the report! The underlying problem of it is, that there were and are not many tests for the detail information. This makes issues like yours so valuable. We work on it for v6 though, see https://github.com/capstone-engine/capstone/issues/1984

disp is working with subtracted being set to True accordingly, but why are you using a field not in arm_op_mem? e.g in AArch64, the disp will just be negative and there isn't a subtracted field.

This is because in the ARM ISA the U bit indicates explicitly, if an immediate is subtracted or not (see for example ARMv8 ISA (DDI0553B.v) - C2.4.74 LDC, LDC2 (immediate) - Assembler symbols for all encodings). While in the AArch64 ISA it is not described as such, but the immediate is simply a signed integer.

To be closer to the ARM ISA, I decided to keep the subtracted flag.

scale is always 0 instead of being 1 or -1, here are some examples:

Thanks, this is probably because I changed the default value to 0 for the mem scale instead of 1. Will be fixed in the PR for this issue.

what's the point of having lshift in arm_op_mem as we can have a whole lot of other shift that aren't left shift, here is an example

Nice catch with all the shifting things. This must have slipped through the todo list in https://github.com/capstone-engine/capstone/pull/1949. The memory operand lshift is not set correctly in v5 either. It is probably still broken, because I copied the behavior.

Rot127 commented 1 week ago

@Quentin01

Another issue, is that rrx shift isn't working too, here is an example:

I fixed cstool now to also print rrx. The shift type itself was set correctly, but not printed by cstool because shift.value is 0 for rrx.