[lld] r271100 - [ELF][MIPS] Always resolve MIPS GP-relative relocations to 'local' definitions
Simon Atanasyan via llvm-commits
llvm-commits at lists.llvm.org
Fri May 27 21:49:58 PDT 2016
Author: atanasyan
Date: Fri May 27 23:49:57 2016
New Revision: 271100
URL: http://llvm.org/viewvc/llvm-project?rev=271100&view=rev
Log:
[ELF][MIPS] Always resolve MIPS GP-relative relocations to 'local' definitions
In case of MIPS, GP-relative relocations always resolve to a definition
in a regular input file, ignoring the one-definition rule. Such
relocations are used to setup GP relative offsets in a function's
prologue. So we, for example, should not attempt to create a dynamic
relocation even if the target symbol is preemptible.
Fixes bug 27880.
Differential Revision: http://reviews.llvm.org/D20664
Added:
lld/trunk/test/ELF/mips-64-gprel-so.s
Modified:
lld/trunk/ELF/Relocations.cpp
Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=271100&r1=271099&r2=271100&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Fri May 27 23:49:57 2016
@@ -65,6 +65,22 @@ static bool refersToGotEntry(RelExpr Exp
Expr == R_TLSGD_PC;
}
+static bool isPreemptible(const SymbolBody &Body, uint32_t Type) {
+ // In case of MIPS GP-relative relocations always resolve to a definition
+ // in a regular input file, ignoring the one-definition rule. So we,
+ // for example, should not attempt to create a dynamic relocation even
+ // if the target symbol is preemptible. There are two two MIPS GP-relative
+ // relocations R_MIPS_GPREL16 and R_MIPS_GPREL32. But only R_MIPS_GPREL16
+ // can be against a preemptible symbol.
+ // To get MIPS relocation type we apply 0xf mask. In case of O32 ABI all
+ // relocation types occupy eight bit. In case of N64 ABI we extract first
+ // relocation from 3-in-1 packet because only the first relocation can
+ // be against a real symbol.
+ if (Config->EMachine == EM_MIPS && (Type & 0xf) == R_MIPS_GPREL16)
+ return false;
+ return Body.isPreemptible();
+}
+
// Returns the number of relocations processed.
template <class ELFT>
static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body,
@@ -116,7 +132,7 @@ static unsigned handleTlsRelocation(uint
// Global-Dynamic relocs can be relaxed to Initial-Exec or Local-Exec
// depending on the symbol being locally defined or not.
- if (Body.isPreemptible()) {
+ if (isPreemptible(Body, Type)) {
C.Relocations.push_back(
{R_RELAX_TLS_GD_TO_IE, Type, Offset, Addend, &Body});
if (!Body.isInGot()) {
@@ -135,7 +151,7 @@ static unsigned handleTlsRelocation(uint
// Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally
// defined.
if (Target->isTlsInitialExecRel(Type) && !Config->Shared &&
- !Body.isPreemptible()) {
+ !isPreemptible(Body, Type)) {
C.Relocations.push_back(
{R_RELAX_TLS_IE_TO_LE, Type, Offset, Addend, &Body});
return 1;
@@ -246,7 +262,7 @@ static bool isStaticLinkTimeConstant(Rel
if (E == R_GOT || E == R_PLT)
return Target->usesOnlyLowPageBits(Type) || !Config->Pic;
- if (Body.isPreemptible())
+ if (isPreemptible(Body, Type))
return false;
if (!Config->Pic)
@@ -348,7 +364,7 @@ static RelExpr adjustExpr(const elf::Obj
const uint8_t *Data, typename ELFT::uint Offset) {
if (Target->needsThunk(Type, File, Body))
return R_THUNK;
- bool Preemptible = Body.isPreemptible();
+ bool Preemptible = isPreemptible(Body, Type);
if (Body.isGnuIFunc()) {
Expr = toPlt(Expr);
} else if (!Preemptible) {
@@ -485,7 +501,7 @@ static void scanRelocs(InputSectionBase<
if (Offset == (uintX_t)-1)
continue;
- bool Preemptible = Body.isPreemptible();
+ bool Preemptible = isPreemptible(Body, Type);
Expr = adjustExpr(File, Body, IsWrite, Expr, Type, Buf, Offset);
if (HasError)
continue;
@@ -504,7 +520,7 @@ static void scanRelocs(InputSectionBase<
}
if (needsPlt(Expr) || Expr == R_THUNK || refersToGotEntry(Expr) ||
- !Body.isPreemptible()) {
+ !isPreemptible(Body, Type)) {
// If the relocation points to something in the file, we can process it.
bool Constant = isStaticLinkTimeConstant<ELFT>(Expr, Type, Body);
Added: lld/trunk/test/ELF/mips-64-gprel-so.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-64-gprel-so.s?rev=271100&view=auto
==============================================================================
--- lld/trunk/test/ELF/mips-64-gprel-so.s (added)
+++ lld/trunk/test/ELF/mips-64-gprel-so.s Fri May 27 23:49:57 2016
@@ -0,0 +1,23 @@
+# Check setup of GP relative offsets in a function's prologue.
+
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -shared -o %t.so
+# RUN: llvm-objdump -d -t %t.so | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK: Disassembly of section .text:
+# CHECK-NEXT: foo:
+# CHECK-NEXT: 10000: 3c 1c 00 01 lui $gp, 1
+# CHECK-NEXT: 10004: 03 99 e0 2d daddu $gp, $gp, $25
+# CHECK-NEXT: 10008: 67 9c 7f f0 daddiu $gp, $gp, 32752
+
+# CHECK: 0000000000027ff0 .got 00000000 .hidden _gp
+# CHECK: 0000000000010000 .text 00000000 foo
+
+ .text
+ .global foo
+foo:
+ lui $gp,%hi(%neg(%gp_rel(foo)))
+ daddu $gp,$gp,$t9
+ daddiu $gp,$gp,%lo(%neg(%gp_rel(foo)))
More information about the llvm-commits
mailing list