llvm / llvm/llvm-project

[BOLT] BOLT reorders .rela.plt without updating PLT stub relocation indices

Open
#207,222 8 comments 0 reactions 0 assignees View on GitHub
BOLT
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Full disclaimer: I used Codex to help me diagnose this issue and create a reproducer. I did, however, try to understand the issue and describe it in my own words to the best of my abilities (with my limited ELF knowledge).

I looked through the open issues and couldn't find one, please excuse me if I missed it.

It seems that BOLT reorders .rela.plt entries without also updating the corresponding PLT stub relocation indices.

```console
$ llvm-bolt --version
LLVM (http://llvm.org/):
LLVM version 22.1.5

$ gcc version 15.2.0 (GCC)
gcc version 15.2.0 (GCC)
Target: x86_64-unknown-linux-gnu

$ clang
clang version 21.1.8
Target: x86_64-unknown-linux-gnu
```

**main.c**

```c
extern int long_name(void);

__attribute__((target_clones("default,avx2")))
int foo(int x) {
return x + 1;
}

int main(void) {
if (foo(1) != 2) {
return 1;
}
if (long_name() != 0) {
return 1;
}
return 0;
}
```

**example.c**

```c
int long_name(void) {
return 0;
}
```

**Build steps**

```bash
gcc -o2 -g -fPIC -shared -o libexample.so example.c
gcc -o2 -g -fno-pie -no-pie -Wl,--emit-relocs -Wl,-rpath,'$ORIGIN' -o repro main.c -L. -lexample
llvm-bolt repro -o repro.bolt

./repro.bolt
```

```
Inconsistency detected by ld.so: dl-runtime.c: 63: _dl_fixup: Assertion `ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT' failed!
```

If we look at the original binary:

```
$ readelf -r --use-dynamic repro

'RELA' relocation section at offset 0x400548 contains 48 bytes:
Offset Info Type Sym. Value Sym. Name + Addend
000000404fd8 000100000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.34 + 0
000000404fe0 000200000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0

'PLT' relocation section at offset 0x400578 contains 48 bytes:
Offset Info Type Sym. Value Sym. Name + Addend
000000405008 000300000007 R_X86_64_JUMP_SLO 0000000000000000 long_name + 0
000000405000 000000000025 R_X86_64_IRELATIV 4024e5
```

Compared to the binary created by BOLT:

```
$ readelf -r --use-dynamic repro.bolt

'RELA' relocation section at offset 0x400548 contains 48 bytes:
Offset Info Type Sym. Value Sym. Name + Addend
000000404fd8 000100000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.34 + 0
000000404fe0 000200000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0

'PLT' relocation section at offset 0x400578 contains 48 bytes:
Offset Info Type Sym. Value Sym. Name + Addend
000000405000 000000000025 R_X86_64_IRELATIV 8014c0
000000405008 000300000007 R_X86_64_JUMP_SLO 0000000000000000 long_name + 0
```

We see `000000405008` and `000000405000` have been swapped. But if we look at the stubs:

```
$ objdump -d -j .plt repro.bolt

repro.bolt: file format elf64-x86-64

Disassembly of section .plt:

0000000000401020 <.plt>:
401020: ff 35 ca 3f 00 00 push 0x3fca(%rip) # 404ff0 <_GLOBAL_OFFSET_TABLE_+0x8>
401026: ff 25 cc 3f 00 00 jmp *0x3fcc(%rip) # 404ff8 <_GLOBAL_OFFSET_TABLE_+0x10>
40102c: 0f 1f 40 00 nopl 0x0(%rax)

0000000000401030 <*ABS*+0x8014c0@plt>:
401030: ff 25 ca 3f 00 00 jmp *0x3fca(%rip) # 405000 <_GLOBAL_OFFSET_TABLE_+0x18>
401036: 68 01 00 00 00 push $0x1
40103b: e9 e0 ff ff ff jmp 401020 <.plt>

0000000000401040 :
401040: ff 25 c2 3f 00 00 jmp *0x3fc2(%rip) # 405008
401046: 68 00 00 00 00 push $0x0
40104b: e9 d0 ff ff ff jmp 401020 <.plt>
```

We see that `long_name` still pushes index `0` instead of `1`, and vice versa for `foo`.

Running the binary with `LD_BIND_NOW=1 ./repro.bolt` on the other hand works fine.

Contributor guide

Open the contributing guide

Research direction

Start with the main.c and example.c reproducer and run the listed llvm-bolt, readelf, and objdump commands to compare relocation ordering with PLT stub indices. Trace BOLT's handling of .rela.plt and PLT stubs, then verify that lazy binding runs successfully for repro.bolt and that the relocation and pushed indices remain consistent.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, linux
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.