diff options
Diffstat (limited to 'lld/ELF')
-rw-r--r-- | lld/ELF/Driver.cpp | 5 | ||||
-rw-r--r-- | lld/ELF/SymbolTable.cpp | 7 | ||||
-rw-r--r-- | lld/ELF/SymbolTable.h | 1 | ||||
-rw-r--r-- | lld/ELF/Symbols.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/Symbols.h | 7 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 3 |
6 files changed, 21 insertions, 4 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index ea1a51cc98b..f00d97851e4 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -304,8 +304,9 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { 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. Use 'strong' variant of + // the addIgnored to prevent '_gp_disp' substitution. + Config->MipsGpDisp = Symtab.addIgnoredStrong("_gp_disp"); // 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. diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 7825e64784d..a66bb04df3e 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -123,6 +123,13 @@ SymbolBody *SymbolTable<ELFT>::addIgnored(StringRef Name) { return addAbsolute(Name, ElfSym<ELFT>::IgnoreUndef); } +// The 'strong' variant of the addIgnored. Adds symbol which has a global +// binding and cannot be substituted. +template <class ELFT> +SymbolBody *SymbolTable<ELFT>::addIgnoredStrong(StringRef Name) { + return addAbsolute(Name, ElfSym<ELFT>::IgnoreUndefStrong); +} + // Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM. // Used to implement --wrap. template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) { diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index 26cbe8ae219..16ed821bf01 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -55,6 +55,7 @@ public: SymbolBody *addSynthetic(StringRef Name, OutputSectionBase<ELFT> &Section, uintX_t Value); SymbolBody *addIgnored(StringRef Name); + SymbolBody *addIgnoredStrong(StringRef Name); void scanShlibUndefined(); SymbolBody *find(StringRef Name); diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index ba6317a4c06..6bc9e1f79ce 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -122,6 +122,8 @@ template <class ELFT> static void doInitSymbols() { ElfSym<ELFT>::End.setBinding(STB_GLOBAL); ElfSym<ELFT>::IgnoreUndef.setBinding(STB_WEAK); ElfSym<ELFT>::IgnoreUndef.setVisibility(STV_HIDDEN); + ElfSym<ELFT>::IgnoreUndefStrong.setBinding(STB_GLOBAL); + ElfSym<ELFT>::IgnoreUndefStrong.setVisibility(STV_HIDDEN); } void elf2::initSymbols() { diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 59135bfe1f5..3eea383f8dd 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -300,8 +300,11 @@ template <class ELFT> struct ElfSym { typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym; // Used to represent an undefined symbol which we don't want - // to add to the output file's symbol table. + // to add to the output file's symbol table. The `IgnoreUndef` + // has weak binding and can be substituted. The `InoreUndefStrong` + // has global binding and gets priority over symbols from shared libs. static Elf_Sym IgnoreUndef; + static Elf_Sym IgnoreUndefStrong; // The content for _end and end symbols. static Elf_Sym End; @@ -316,6 +319,8 @@ template <class ELFT> struct ElfSym { }; template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::IgnoreUndef; +template <class ELFT> +typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::IgnoreUndefStrong; template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::End; template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::MipsGp; template <class ELFT> diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index b8a2f4f8007..c61db87478e 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -599,7 +599,8 @@ template <class ELFT> static bool includeInSymtab(const SymbolBody &B) { // Don't include synthetic symbols like __init_array_start in every output. if (auto *U = dyn_cast<DefinedRegular<ELFT>>(&B)) - if (&U->Sym == &ElfSym<ELFT>::IgnoreUndef) + if (&U->Sym == &ElfSym<ELFT>::IgnoreUndef || + &U->Sym == &ElfSym<ELFT>::IgnoreUndefStrong) return false; return true; |