llvm / llvm/llvm-project

X86Disassembler drops EA_DISP_32 when building the MCInst.

Open
#214,859 3 comments 0 reactions 0 assignees View on GitHub
backend:X86
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

`vmovsldup .rodata+N(%rax), %zmm20`

This instruction pattern can be encoded with 4-byte disp32 (ModRM = 0xa0).

When X86Disassembler decodes an instruction like this containing a relocation entry (or zero / small displacement), the displacement operand in MCInst is temporarily represented as 0.
Then when such MCInst gets encoded again(e.g., by BOLT), the instruction length changes as the emitter shrinks disp32 to disp0, resulting in a BOLT warning.
```sh
BOLT-WARNING: mismatched encoding detected
input: 62 e1 7e 48 12 a0 00 00 00 00
output: 62 e1 7e 48 12 20
BOLT-WARNING: internal assembler/disassembler error detected for AVX512 instruction:
400000620: vmovsldup .rodata+1578(%rax), %zmm20
```

### Reproduction
Im using 23.0.0git version `llvm-mc`.
```sh
$ echo "0x62 0xe1 0x7e 0x48 0x12 0xa0 0x40 0x00 0x00 0x00" | llvm-mc -triple=x86_64 --disassemble
# output: vmovsldup 64(%rax), %zmm20
# expected: {disp32} vmovsldup 64(%rax), %zmm20

$ echo "0x62 0xe1 0x7e 0x48 0x12 0xa0 0x00 0x00 0x00 0x00" | llvm-mc -triple=x86_64 --disassemble | llvm-mc -triple=x86_64 -show-encoding
# output: vmovsldup (%rax), %zmm20 # encoding: [0x62,0xe1,0x7e,0x48,0x12,0x20]
```

I assume the X86 emitter must be able to decide the best encoding when there is no `IP_USE_DISP32`, so I've tried patching the x86 disassembler to set `IP_USE_DISP32` into `MCInst::Flags`, but this breaks Disassembler tests as `{disp32}` gets printed in asm.

Please let me know if there is a better way to fix it.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the two llvm-mc commands in the issue and compare the decoded MCInst with its re-encoded bytes. Read the X86Disassembler and X86 emitter paths involved in preserving displacement width, then verify that the 4-byte disp32 encoding survives round-tripping without incorrectly printing {disp32} in ordinary disassembly tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.