https://sourceware.org/bugzilla/show_bug.cgi?id=34558
Bug ID: 34558
Summary: BPF: gotol +N mis-assembled as goto with reloc against
undefined symbol `l`
Product: binutils
Version: 2.46.1
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: gas
Assignee: unassigned at sourceware dot org
Reporter: vineet.gupta at linux dot dev
Target Milestone: 2.46
Target: bpf
In the BPF pseudo-C assembly dialect (`-mdialect=pseudoc`), the 32-bit
unconditional jump `gotol` is mis-parsed when its operand carries an explicit
sign. Instead of the intended `JA|K|JMP32` (opcode `0x06`, displacement in the
32-bit `imm` field), gas emits `JA|K|JMP` (opcode `0x05`, displacement in the
16-bit `off` field) together with an `R_BPF_GNU_64_16` relocation against a
newly invented undefined global symbol named `l`.
The parser appears to match the shorter mnemonic `goto` first and then consume
the trailing `l` as the start of the operand expression, so `gotol +1` is
treated as `goto l+1`. This is confirmed byte-for-byte: assembling `gotol +1`
and `goto l+1` produces identical objects, both with an `R_BPF_GNU_64_16`
relocation against `l`.
With an unsigned literal (`gotol 1`) or a label (`gotol 1f`), the operand
`l 1` / `l 1f` is not a valid single expression, so the shorter match fails,
gas backtracks to `gotol`, and the correct `0x06` encoding is produced. Hence
only the signed forms are affected.
LLVM's assembler accepts `gotol +1` and `gotol 1` identically (both `0x06`),
and `llvm-objdump` prints the signed form `gotol +0x1`. So gas rejects — or
rather, silently miscompiles — the documented syntax that the other BPF
toolchain emits and accepts.
```asm
.text
/* 1. BAD: canonical spelling per the BPF ISA documentation. */
.globl tc_signed_plus
tc_signed_plus:
gotol +1
exit
/* 2. BAD: same, negative displacement. */
.globl tc_signed_minus
tc_signed_minus:
gotol -1
exit
/* 3. OK: unsigned literal. */
.globl tc_unsigned
tc_unsigned:
gotol 1
exit
/* 4. OK: label operand. */
.globl tc_label
tc_label:
gotol 1f
exit
1:
exit
```
```sh
bpf-unknown-none-as -mdialect=pseudoc -misa-spec=v4 gotol.s -o gotol.o
bpf-unknown-none-objdump -dr gotol.o
```
Found while enabling the Linux BPF selftests to build with `bpf-gcc`.
`tools/testing/selftests/bpf/progs/compute_live_registers.c` contains gotol +1
--
You are receiving this mail because:
You are on the CC list for the bug.