[PATCH] D70406: Ignore R_MIPS_JALR relocations against non-function symbols

Alexander Richardson via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 18 10:14:22 PST 2019


arichardson created this revision.
arichardson added reviewers: atanasyan, jrtc27.
Herald added subscribers: llvm-commits, MaskRay, krytarowski, sdardis, emaste.
Herald added a reviewer: espindola.
Herald added a project: LLVM.

Older 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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D70406

Files:
  lld/ELF/Arch/Mips.cpp
  lld/test/ELF/mips-r-jalr-non-functions.s


Index: lld/test/ELF/mips-r-jalr-non-functions.s
===================================================================
--- /dev/null
+++ lld/test/ELF/mips-r-jalr-non-functions.s
@@ -0,0 +1,60 @@
+# REQUIRES: mips
+## Check that we ignore R_MIPS_JALR relocations agains non-function symbols.
+## Older versions of clang was erroneously generating them for function pointers
+## loaded from any table (not just the GOT), so we need to ignore the relocations
+## to avoid generating binaries that crash when executed.
+
+## This test case was created from the following C source code:
+## int callee(void) { return 0; }
+## typedef int (*fnptr)(void);
+## static fnptr function_table[] = { &callee, &callee };
+## // to prevent the compiler from optimizing away the table:
+## fnptr* get_function_table(void) { return function_table; }
+## int __start(int x) {
+##   return function_table[0]();
+## }
+
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o
+# RUN: ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s -check-prefix WARNING-MESSAGE
+# WARNING-MESSAGE: warning: found R_MIPS_JALR relocation against non-function symbol function_table. This is invalid and most likely a compiler bug.
+# RUN: llvm-objdump -d %t.so | FileCheck %s
+
+	.set	noreorder
+	.set	nomacro
+	.set	noat
+	.text
+
+	.globl	__start
+	.p2align	3
+	.type	__start, at function
+	.ent	__start
+__start:
+	ld	$1, %got_page(function_table)($gp)
+	ld	$t9, %got_ofst(function_table)($1)
+## This relocation should not have been generated by the compiler
+## But we should still be able to handle it
+	.reloc .Ltmp0, R_MIPS_JALR, function_table
+.Ltmp0:
+	jalr	$t9
+	nop
+	.end	__start
+.Lfunc_end2:
+	.size	__start, .Lfunc_end2-__start
+
+	.type	function_table, at object
+	.data
+	.p2align	3
+function_table:
+	.8byte	0
+	.8byte	0
+	.size	function_table, 16
+
+
+# CHECK-LABEL: Disassembly of section .text:
+# CHECK-EMPTY:
+# CHECK-NEXT: 0000000000010370 __start:
+# CHECK-NEXT:    10370: df 81 80 20                  	ld	$1, -32736($gp)
+# CHECK-NEXT:    10374: dc 39 03 80                  	ld	$25, 896($1)
+## This previously generated a "bal 65560 <function_table>" which would crash at run time:
+# CHECK-NEXT:    10378: 03 20 f8 09                  	jalr	$25
+# CHECK-NEXT:    1037c: 00 00 00 00                  	nop
Index: lld/ELF/Arch/Mips.cpp
===================================================================
--- lld/ELF/Arch/Mips.cpp
+++ lld/ELF/Arch/Mips.cpp
@@ -83,6 +83,17 @@
 
   switch (type) {
   case R_MIPS_JALR:
+    // Older 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). When we encounter this, ignore the
+    // relocation and emit a warning instead.
+    if (!s.isFunc()) {
+      warn(getErrorLocation(loc) +
+           "found R_MIPS_JALR relocation against non-function symbol " +
+           toString(s) + ". This is invalid and most likely a compiler bug.");
+      return R_NONE;
+    }
+
     // If the target symbol is not preemptible and is not microMIPS,
     // it might be possible to replace jalr/jr instruction by bal/b.
     // It depends on the target symbol's offset.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D70406.229876.patch
Type: text/x-patch
Size: 3232 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191118/38eace9c/attachment.bin>


More information about the llvm-commits mailing list