[lld] r257449 - [ELF][MIPS] Prevent substitution of _gp_disp symbol
Simon Atanasyan via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 11 22:23:57 PST 2016
Author: atanasyan
Date: Tue Jan 12 00:23:57 2016
New Revision: 257449
URL: http://llvm.org/viewvc/llvm-project?rev=257449&view=rev
Log:
[ELF][MIPS] Prevent substitution of _gp_disp symbol
On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
start of function and gp pointer into GOT. To make seal with such symbol
we add new method addIgnoredStrong(). It adds ignored symbol with global
binding to prevent the symbol substitution. The addIgnored call is not
enough here because this call adds a weak symbol which might be
substituted by symbol from shared library.
Differential Revision: http://reviews.llvm.org/D16084
Added:
lld/trunk/test/ELF/Inputs/mips-gp-disp-def.s
lld/trunk/test/ELF/mips-gp-disp.s
Modified:
lld/trunk/ELF/Driver.cpp
lld/trunk/ELF/SymbolTable.cpp
lld/trunk/ELF/SymbolTable.h
lld/trunk/ELF/Symbols.cpp
lld/trunk/ELF/Symbols.h
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=257449&r1=257448&r2=257449&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Tue Jan 12 00:23:57 2016
@@ -304,8 +304,9 @@ template <class ELFT> void LinkerDriver:
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.
Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=257449&r1=257448&r2=257449&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Tue Jan 12 00:23:57 2016
@@ -123,6 +123,13 @@ SymbolBody *SymbolTable<ELFT>::addIgnore
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) {
Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=257449&r1=257448&r2=257449&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Tue Jan 12 00:23:57 2016
@@ -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);
Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=257449&r1=257448&r2=257449&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Tue Jan 12 00:23:57 2016
@@ -122,6 +122,8 @@ template <class ELFT> static void doInit
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() {
Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=257449&r1=257448&r2=257449&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Tue Jan 12 00:23:57 2016
@@ -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>
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=257449&r1=257448&r2=257449&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue Jan 12 00:23:57 2016
@@ -599,7 +599,8 @@ template <class ELFT> static bool includ
// 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;
Added: lld/trunk/test/ELF/Inputs/mips-gp-disp-def.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/mips-gp-disp-def.s?rev=257449&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/mips-gp-disp-def.s (added)
+++ lld/trunk/test/ELF/Inputs/mips-gp-disp-def.s Tue Jan 12 00:23:57 2016
@@ -0,0 +1,8 @@
+# We cannot create a shared library with defined _gp_disp symbol
+# so we use a workaround - create a library with XXXXXXXX symbols
+# and use 'sed' to replace it by _gp_disp right in the binary file.
+ .data
+ .globl XXXXXXXX
+ .space 16
+XXXXXXXX:
+ .space 4
Added: lld/trunk/test/ELF/mips-gp-disp.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-gp-disp.s?rev=257449&view=auto
==============================================================================
--- lld/trunk/test/ELF/mips-gp-disp.s (added)
+++ lld/trunk/test/ELF/mips-gp-disp.s Tue Jan 12 00:23:57 2016
@@ -0,0 +1,33 @@
+# 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 \
+# RUN: %S/Inputs/mips-gp-disp-def.s -o %t-ext.o
+# RUN: ld.lld -shared -o %t-ext-int.so %t-ext.o
+# RUN: sed -e 's/XXXXXXXX/_gp_disp/g' %t-ext-int.so > %t-ext.so
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld -shared -o %t.so %t.o %t-ext.so
+# RUN: llvm-readobj -symbols %t.so | FileCheck -check-prefix=INT-SO %s
+# RUN: llvm-readobj -symbols %t-ext.so | FileCheck -check-prefix=EXT-SO %s
+# RUN: llvm-objdump -d -t %t.so | FileCheck -check-prefix=DIS %s
+
+# REQUIRES: mips
+
+# INT-SO-NOT: Name: _gp_disp
+
+# EXT-SO: Name: _gp_disp
+# EXT-SO-NEXT: Value: 0x20010
+
+# DIS: Disassembly of section .text:
+# DIS-NEXT: __start:
+# DIS-NEXT: 10000: 3c 08 00 01 lui $8, 1
+# DIS-NEXT: 10004: 21 08 7f f0 addi $8, $8, 32752
+# ^-- 0x37ff0 & 0xffff
+# DIS: 00027ff0 *ABS* 00000000 _gp
+
+ .text
+ .globl __start
+__start:
+ lui $t0,%hi(_gp_disp)
+ addi $t0,$t0,%lo(_gp_disp)
+ lw $v0,%call16(_foo)($gp)
More information about the llvm-commits
mailing list