Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -65,6 +65,16 @@ Expr == R_TLSGD_PC; } +static bool isPreemptible(const SymbolBody &Body, RelExpr Expr) { + // 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. + if (Config->EMachine == EM_MIPS && Expr == R_GOTREL) + return false; + return Body.isPreemptible(); +} + // Returns the number of relocations processed. template static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, @@ -116,7 +126,7 @@ // 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, Expr)) { C.Relocations.push_back( {R_RELAX_TLS_GD_TO_IE, Type, Offset, Addend, &Body}); if (!Body.isInGot()) { @@ -135,7 +145,7 @@ // 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, Expr)) { C.Relocations.push_back( {R_RELAX_TLS_IE_TO_LE, Type, Offset, Addend, &Body}); return 1; @@ -246,7 +256,7 @@ if (E == R_GOT || E == R_PLT) return Target->usesOnlyLowPageBits(Type) || !Config->Pic; - if (Body.isPreemptible()) + if (isPreemptible(Body, E)) return false; if (!Config->Pic) @@ -348,7 +358,7 @@ 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, Expr); if (Body.isGnuIFunc()) { Expr = toPlt(Expr); } else if (!Preemptible) { @@ -485,7 +495,7 @@ if (Offset == (uintX_t)-1) continue; - bool Preemptible = Body.isPreemptible(); + bool Preemptible = isPreemptible(Body, Expr); Expr = adjustExpr(File, Body, IsWrite, Expr, Type, Buf, Offset); if (HasError) continue; @@ -504,7 +514,7 @@ } if (needsPlt(Expr) || Expr == R_THUNK || refersToGotEntry(Expr) || - !Body.isPreemptible()) { + !isPreemptible(Body, Expr)) { // If the relocation points to something in the file, we can process it. bool Constant = isStaticLinkTimeConstant(Expr, Type, Body); Index: test/ELF/mips-gprel32-relocs-so.s =================================================================== --- /dev/null +++ test/ELF/mips-gprel32-relocs-so.s @@ -0,0 +1,24 @@ +# Check R_MIPS_GPREL32 relocation calculation in case of DSO output. +# GP-relative relocation always resolve to a definition in a regular input file. + +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o +# RUN: ld.lld -shared -o %t.so %t.o +# RUN: llvm-objdump -s -t %t.so | FileCheck %s + +# REQUIRES: mips + + .text + .global foo +foo: + nop + + .section .rodata, "a" + .gpword foo + +# CHECK: Contents of section .rodata: +# CHECK: 0114 fffe8010 +# ^ 0x10000 - 0x27ff0 + +# CHECK: SYMBOL TABLE: +# CHECK: 00027ff0 .got 00000000 .hidden _gp +# CHECK: 00010000 .text 00000000 foo