[lld] r326176 - [ELF] Create and export symbols provided by a linker script if they referenced by DSOs.

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 26 23:18:07 PST 2018


Author: ikudrin
Date: Mon Feb 26 23:18:07 2018
New Revision: 326176

URL: http://llvm.org/viewvc/llvm-project?rev=326176&view=rev
Log:
[ELF] Create and export symbols provided by a linker script if they referenced by DSOs.

It should be possible to resolve undefined symbols in dynamic libraries
using symbols defined in a linker script.

Differential Revision: https://reviews.llvm.org/D43011

Added:
    lld/trunk/test/ELF/linkerscript/Inputs/provide-shared2.s
    lld/trunk/test/ELF/linkerscript/provide-shared2.s
Modified:
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/InputFiles.h
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/SymbolTable.cpp

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=326176&r1=326175&r2=326176&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Mon Feb 26 23:18:07 2018
@@ -1080,6 +1080,11 @@ template <class ELFT> void LinkerDriver:
   if (errorCount())
     return;
 
+  // We want to declare linker script's symbols early,
+  // so that we can version them.
+  // They also might be exported if referenced by DSOs.
+  Script->declareSymbols();
+
   // Handle undefined symbols in DSOs.
   if (!Config->Shared)
     Symtab->scanShlibUndefined<ELFT>();
@@ -1097,10 +1102,6 @@ template <class ELFT> void LinkerDriver:
   if (!Config->Relocatable)
     addReservedSymbols();
 
-  // We want to declare linker script's symbols early,
-  // so that we can version them.
-  Script->declareSymbols();
-
   // Apply version scripts.
   //
   // For a relocatable output, version scripts don't make sense, and

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=326176&r1=326175&r2=326176&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Mon Feb 26 23:18:07 2018
@@ -851,7 +851,7 @@ template <class ELFT> void SharedFile<EL
 
     StringRef Name = CHECK(Sym.getName(this->StringTable), this);
     if (Sym.isUndefined()) {
-      Undefs.push_back(Name);
+      this->Undefs.insert(Name);
       continue;
     }
 

Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=326176&r1=326175&r2=326176&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Mon Feb 26 23:18:07 2018
@@ -93,6 +93,13 @@ public:
     return Symbols;
   }
 
+  // Returns undefined symbols of a shared library.
+  // It is a runtime error to call this function on files of other types.
+  const llvm::DenseSet<StringRef> &getUndefinedSymbols() {
+    assert(FileKind == SharedKind);
+    return Undefs;
+  }
+
   // Filename of .a which contained this file. If this file was
   // not in an archive file, it is the empty string. We use this
   // string for creating error messages.
@@ -114,6 +121,7 @@ protected:
   InputFile(Kind K, MemoryBufferRef M);
   std::vector<InputSectionBase *> Sections;
   std::vector<Symbol *> Symbols;
+  llvm::DenseSet<StringRef> Undefs;
 
 private:
   const Kind FileKind;
@@ -288,7 +296,6 @@ template <class ELFT> class SharedFile :
   typedef typename ELFT::Verdef Elf_Verdef;
   typedef typename ELFT::Versym Elf_Versym;
 
-  std::vector<StringRef> Undefs;
   const Elf_Shdr *VersymSec = nullptr;
   const Elf_Shdr *VerdefSec = nullptr;
 
@@ -296,8 +303,6 @@ public:
   std::vector<const Elf_Verdef *> Verdefs;
   std::string SoName;
 
-  llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; }
-
   static bool classof(const InputFile *F) {
     return F->kind() == Base::SharedKind;
   }

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=326176&r1=326175&r2=326176&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Mon Feb 26 23:18:07 2018
@@ -127,9 +127,13 @@ static bool shouldDefineSym(SymbolAssign
   // If a symbol was in PROVIDE(), we need to define it only
   // when it is a referenced undefined symbol.
   Symbol *B = Symtab->find(Cmd->Name);
-  if (!B || B->isDefined())
-    return false;
-  return true;
+  if (B && !B->isDefined())
+    return true;
+  // It might also be referenced by a DSO.
+  for (InputFile *F : SharedFiles)
+    if (F->getUndefinedSymbols().count(Cmd->Name))
+      return true;
+  return false;
 }
 
 // This function is called from processSectionCommands,

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=326176&r1=326175&r2=326176&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Mon Feb 26 23:18:07 2018
@@ -597,7 +597,7 @@ template <class ELFT> void SymbolTable::
 // Except this, we ignore undefined symbols in DSOs.
 template <class ELFT> void SymbolTable::scanShlibUndefined() {
   for (InputFile *F : SharedFiles) {
-    for (StringRef U : cast<SharedFile<ELFT>>(F)->getUndefinedSymbols()) {
+    for (StringRef U : F->getUndefinedSymbols()) {
       Symbol *Sym = find(U);
       if (!Sym)
         continue;

Added: lld/trunk/test/ELF/linkerscript/Inputs/provide-shared2.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/Inputs/provide-shared2.s?rev=326176&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/Inputs/provide-shared2.s (added)
+++ lld/trunk/test/ELF/linkerscript/Inputs/provide-shared2.s Mon Feb 26 23:18:07 2018
@@ -0,0 +1,3 @@
+.global foo
+.data
+.dc.a foo

Added: lld/trunk/test/ELF/linkerscript/provide-shared2.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/provide-shared2.s?rev=326176&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/provide-shared2.s (added)
+++ lld/trunk/test/ELF/linkerscript/provide-shared2.s Mon Feb 26 23:18:07 2018
@@ -0,0 +1,13 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/provide-shared2.s -o %t2.o
+# RUN: ld.lld %t2.o -o %t2.so -shared
+# RUN: echo "SECTIONS { . = . + SIZEOF_HEADERS; PROVIDE(foo = 42); }" > %t.script
+# RUN: ld.lld -o %t --script %t.script %t.o %t2.so
+# RUN: llvm-readelf --dyn-symbols %t | FileCheck  %s
+
+# CHECK: 1 1: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS foo@
+
+.global _start
+_start:
+        nop




More information about the llvm-commits mailing list