[gdb/tdep] Fix vmovdqu decoding

PR tdep/31952 reports that displaced stepping over an instruction pointer
relative insn "vmovdqu 0x20(%rip),%ymm1" gives the wrong results.

This is caused by misclassification of the insn in amd64_get_insn_details,
which results in details.modrm_offset == -1, while the instruction in fact
does have a modrm byte.

The instruction is encoded as follows:
...
  400557:       c5 fe 6f 0d 20 00 00 00    vmovdqu 0x20(%rip),%ymm1
...
where:
- "0xc5 0xfe" is the vex2 prefix,
- "0x6f" is the opcode,
- "0x0d" is the modrm byte, and
- "0x20 0x00 0x00 0x00" is a 32-bit displacement.

The problem is related to details.opcode_len, which is 1.

While it is true that the length of the opcode in the insn (0x6f) is 1 byte,
the vex2 prefix implies that we're encoding an 2-byte opcode beginnning
with 0x0f [1].

Consequently, we should be using the twobyte_has_modrm map rather than the
onebyte_has_modrm map.

Fix this in amd64_get_insn_details, and add a selftest to check this.

Tested on x86_64-linux.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31952

[1] https://en.wikipedia.org/wiki/VEX_prefix
1 file changed