[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