Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -231,6 +231,14 @@ Expr == R_RELAX_GOT_PC; } +static bool isForcedLinkTimeConstant(RelExpr E) { + // 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. + return Config->EMachine == EM_MIPS && E == R_GOTREL; +} + template static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type, const SymbolBody &Body) { @@ -241,6 +249,9 @@ E == R_TLSGD || E == R_PPC_PLT_OPD) return true; + if (isForcedLinkTimeConstant(E)) + return true; + // These never do, except if the entire file is position dependent or if // only the low bits are used. if (E == R_GOT || E == R_PLT) @@ -504,7 +515,7 @@ } if (needsPlt(Expr) || Expr == R_THUNK || refersToGotEntry(Expr) || - !Body.isPreemptible()) { + !Body.isPreemptible() || isForcedLinkTimeConstant(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