Skip to content

Commit 5bab291

Browse files
committed
Ignore R_MIPS_JALR relocations against non-function symbols
Summary: Current versions of clang would erroneously emit this relocation not only against functions (loaded from the GOT) but also against data symbols (e.g. a table of function pointers). LLD was then changing this into a branch-and-link instruction, causing the program to jump to the data symbol at run time. I discovered this problem when attempting to boot MIPS64 FreeBSD after updating the to the latest upstream master. Reviewers: atanasyan, jrtc27, espindola Reviewed By: atanasyan Subscribers: emaste, sdardis, krytarowski, MaskRay, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D70406
1 parent 3f91705 commit 5bab291

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

lld/ELF/Arch/Mips.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,17 @@ RelExpr MIPS<ELFT>::getRelExpr(RelType type, const Symbol &s,
8383

8484
switch (type) {
8585
case R_MIPS_JALR:
86+
// Older versions of clang would erroneously emit this relocation not only
87+
// against functions (loaded from the GOT) but also against data symbols
88+
// (e.g. a table of function pointers). When we encounter this, ignore the
89+
// relocation and emit a warning instead.
90+
if (!s.isFunc() && s.type != STT_NOTYPE) {
91+
warn(getErrorLocation(loc) +
92+
"found R_MIPS_JALR relocation against non-function symbol " +
93+
toString(s) + ". This is invalid and most likely a compiler bug.");
94+
return R_NONE;
95+
}
96+
8697
// If the target symbol is not preemptible and is not microMIPS,
8798
// it might be possible to replace jalr/jr instruction by bal/b.
8899
// It depends on the target symbol's offset.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# REQUIRES: mips
2+
## Check that we ignore R_MIPS_JALR relocations agains non-function symbols.
3+
## Older versions of clang were erroneously generating them for function pointers
4+
## loaded from any table (not just the GOT) as well as against TLS function
5+
## pointers (when using the local-dynamic model), so we need to ignore these
6+
## relocations to avoid generating binaries that crash when executed.
7+
8+
# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o
9+
# RUN: ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s -check-prefix WARNING-MESSAGE
10+
# RUN: llvm-objdump --no-show-raw-insn --no-leading-addr -d %t.so | FileCheck %s
11+
12+
.set noreorder
13+
test:
14+
.reloc .Ltmp1, R_MIPS_JALR, tls_obj
15+
.Ltmp1:
16+
jr $t9
17+
nop
18+
# WARNING-MESSAGE: warning: found R_MIPS_JALR relocation against non-function symbol tls_obj. This is invalid and most likely a compiler bug.
19+
20+
.reloc .Ltmp2, R_MIPS_JALR, reg_obj
21+
.Ltmp2:
22+
jr $t9
23+
nop
24+
# WARNING-MESSAGE: warning: found R_MIPS_JALR relocation against non-function symbol reg_obj. This is invalid and most likely a compiler bug.
25+
26+
.reloc .Ltmp3, R_MIPS_JALR, untyped
27+
.Ltmp3:
28+
jr $t9
29+
nop
30+
31+
## However, we do perform the optimization for untyped symbols:
32+
untyped:
33+
nop
34+
35+
.type tls_obj,@object
36+
.section .tbss,"awT",@nobits
37+
tls_obj:
38+
.word 0
39+
40+
.type reg_obj,@object
41+
.data
42+
reg_obj:
43+
.word 0
44+
45+
# CHECK-LABEL: Disassembly of section .text:
46+
# CHECK-EMPTY:
47+
# CHECK-NEXT: test:
48+
# CHECK-NEXT: jr $25
49+
# CHECK-NEXT: nop
50+
# CHECK-NEXT: jr $25
51+
# CHECK-NEXT: nop
52+
# CHECK-NEXT: b 8 <untyped>
53+
# CHECK-NEXT: nop

0 commit comments

Comments
 (0)