Index: lld/trunk/ELF/OutputSections.cpp =================================================================== --- lld/trunk/ELF/OutputSections.cpp +++ lld/trunk/ELF/OutputSections.cpp @@ -1509,6 +1509,14 @@ ESym->st_shndx = OutSec->SectionIndex; else if (isa>(Body)) ESym->st_shndx = SHN_ABS; + + // On MIPS we need to mark symbol which has a PLT entry and requires pointer + // equality by STO_MIPS_PLT flag. That is necessary to help dynamic linker + // distinguish such symbols and MIPS lazy-binding stubs. + // https://sourceware.org/ml/binutils/2008-07/txt00000.txt + if (Config->EMachine == EM_MIPS && Body->isInPlt() && + Body->NeedsCopyOrPltAddr) + ESym->st_other |= ELF::STO_MIPS_PLT; ++ESym; } } Index: lld/trunk/ELF/Target.cpp =================================================================== --- lld/trunk/ELF/Target.cpp +++ lld/trunk/ELF/Target.cpp @@ -228,6 +228,7 @@ uint8_t *PairedLoc = nullptr) const override; bool isHintRel(uint32_t Type) const override; bool isRelRelative(uint32_t Type) const override; + bool refersToGotEntry(uint32_t Type) const override; }; } // anonymous namespace @@ -1705,8 +1706,12 @@ template bool MipsTargetInfo::needsGot(uint32_t Type, SymbolBody &S) const { - return needsPlt(Type, S) || Type == R_MIPS_GOT16 || - Type == R_MIPS_CALL16; + return needsPlt(Type, S) || refersToGotEntry(Type); +} + +template +bool MipsTargetInfo::refersToGotEntry(uint32_t Type) const { + return Type == R_MIPS_GOT16 || Type == R_MIPS_CALL16; } template @@ -1716,8 +1721,6 @@ return false; if (Type == R_MIPS_26 && canBePreempted(&S, false)) return true; - if (!isRelRelative(Type) && S.isShared()) - return true; return false; } Index: lld/trunk/test/ELF/mips-sto-plt.s =================================================================== --- lld/trunk/test/ELF/mips-sto-plt.s +++ lld/trunk/test/ELF/mips-sto-plt.s @@ -0,0 +1,65 @@ +# Check assigning STO_MIPS_PLT flag to symbol needs a pointer equality. + +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ +# RUN: %S/Inputs/mips-dynamic.s -o %t.so.o +# RUN: ld.lld %t.so.o -shared -o %t.so +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o +# RUN: ld.lld %t.o %t.so -o %t.exe +# RUN: llvm-readobj -dt -mips-plt-got %t.exe | FileCheck %s + +# REQUIRES: mips + +# CHECK: Symbol { +# CHECK: Name: foo0@ +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: } +# CHECK: Symbol { +# CHECK: Name: foo1@ +# CHECK-NEXT: Value: 0x20050 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Other: 8 +# ^-- STO_MIPS_PLT +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: } + +# CHECK: Primary GOT { +# CHECK: Local entries [ +# CHECK-NEXT: ] +# CHECK-NEXT: Global entries [ +# CHECK-NEXT: ] +# CHECK: PLT GOT { +# CHECK: Entries [ +# CHECK-NEXT: Entry { +# CHECK-NEXT: Address: +# CHECK-NEXT: Initial: +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: Name: foo0 +# CHECK-NEXT: } +# CHECK-NEXT: Entry { +# CHECK-NEXT: Address: +# CHECK-NEXT: Initial: +# CHECK-NEXT: Value: 0x20050 +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: Name: foo1 +# CHECK-NEXT: } +# CHECK-NEXT: ] + + .text + .globl __start +__start: + jal foo0 # R_MIPS_26 against 'foo0' from DSO + lui $t0,%hi(foo1) # R_MIPS_HI16/LO16 against 'foo1' from DSO + addi $t0,$t0,%lo(foo1) + +loc: + nop