Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -305,9 +305,12 @@ if (Config->EMachine == EM_MIPS) { // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between - // start of function and gp pointer into GOT. - Config->MipsGpDisp = Symtab.addIgnored("_gp_disp"); - + // start of function and gp pointer into GOT. We have to define it as + // a regular absolute symbol to force the linker to always prefer + // this symbol and does not substitute it by symbols which might be defined + // in legacy input shared libraries. + Config->MipsGpDisp = + Symtab.addAbsolute("_gp_disp", ElfSym::MipsGpDisp); // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer // so that it points to an absolute address which is relative to GOT. // See "Global Data Symbols" in Chapter 6 in the following document: Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -308,6 +308,8 @@ // The content for _gp symbol for MIPS target. static Elf_Sym MipsGp; + // Used to represent _gp_disp symbol for MIPS target. + static Elf_Sym MipsGpDisp; // __rel_iplt_start/__rel_iplt_end for signaling // where R_[*]_IRELATIVE relocations do live. @@ -318,6 +320,7 @@ template typename ElfSym::Elf_Sym ElfSym::IgnoreUndef; template typename ElfSym::Elf_Sym ElfSym::End; template typename ElfSym::Elf_Sym ElfSym::MipsGp; +template typename ElfSym::Elf_Sym ElfSym::MipsGpDisp; template typename ElfSym::Elf_Sym ElfSym::RelaIpltStart; template typename ElfSym::Elf_Sym ElfSym::RelaIpltEnd; Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -122,6 +122,7 @@ ElfSym::End.setBinding(STB_GLOBAL); ElfSym::IgnoreUndef.setBinding(STB_WEAK); ElfSym::IgnoreUndef.setVisibility(STV_HIDDEN); + ElfSym::MipsGpDisp.setBinding(STB_GLOBAL); } void elf2::initSymbols() { Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -602,7 +602,8 @@ // Don't include synthetic symbols like __init_array_start in every output. if (auto *U = dyn_cast>(&B)) - if (&U->Sym == &ElfSym::IgnoreUndef) + if (&U->Sym == &ElfSym::IgnoreUndef || + &U->Sym == &ElfSym::MipsGpDisp) return false; return true; Index: test/ELF/mips-gp-disp.s =================================================================== --- /dev/null +++ test/ELF/mips-gp-disp.s @@ -0,0 +1,30 @@ +# Check that even if _gp_disp symbol is defined in the shared library +# we use our own value. + +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o +# RUN: ld.lld -o %t.exe %t.o %S/Inputs/mips-gp-disp-def.so +# RUN: llvm-readobj -symbols %t.exe | FileCheck -check-prefix=EXE %s +# RUN: llvm-readobj -symbols %S/Inputs/mips-gp-disp-def.so \ +# RUN: | FileCheck -check-prefix=SO %s +# RUN: llvm-objdump -d -t %t.exe | FileCheck -check-prefix=DIS %s + +# REQUIRES: mips + +# EXE-NOT: Name: _gp_disp + +# SO: Name: _gp_disp +# SO-NEXT: Value: 0x182A0 + +# DIS: Disassembly of section .text: +# DIS-NEXT: __start: +# DIS-NEXT: 20000: 3c 08 00 01 lui $8, 1 +# DIS-NEXT: 20004: 21 08 7f f0 addi $8, $8, 32752 +# ^-- 0x37ff0 & 0xffff +# DIS: 00037ff0 *ABS* 00000000 _gp + + .text + .globl __start +__start: + lui $t0,%hi(_gp_disp) + addi $t0,$t0,%lo(_gp_disp) + lw $v0,%call16(_foo)($gp)