[lld] r250176 - ELF2: Fix BSD's __progname symbol issue.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 13 09:34:14 PDT 2015


Author: ruiu
Date: Tue Oct 13 11:34:14 2015
New Revision: 250176

URL: http://llvm.org/viewvc/llvm-project?rev=250176&view=rev
Log:
ELF2: Fix BSD's __progname symbol issue.

BSD's DSO files have undefined symbol "__progname" which is defined
in crt1.o. On that system, both user programs and system shared
libraries depend on each other.

In general, we need to put symbols defined by user programs which are
referenced by shared libraries to user program's .dynsym.

http://reviews.llvm.org/D13637

Added:
    lld/trunk/test/elf2/progname.s
Modified:
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/InputFiles.h
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/SymbolTable.h

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=250176&r1=250175&r2=250176&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Tue Oct 13 11:34:14 2015
@@ -227,5 +227,6 @@ template <class ELFT> void LinkerDriver:
     Config->OutputFile = "a.out";
 
   // Write the result to the file.
+  Symtab.finalize();
   writeResult<ELFT>(&Symtab);
 }

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=250176&r1=250175&r2=250176&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Tue Oct 13 11:34:14 2015
@@ -301,14 +301,14 @@ template <class ELFT> void SharedFile<EL
   uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
   SymbolBodies.reserve(NumSymbols);
   for (const Elf_Sym &Sym : Syms) {
-    if (Sym.isUndefined())
-      continue;
-
     ErrorOr<StringRef> NameOrErr = Sym.getName(this->StringTable);
     error(NameOrErr.getError());
     StringRef Name = *NameOrErr;
 
-    SymbolBodies.emplace_back(this, Name, Sym);
+    if (Sym.isUndefined())
+      Undefs.push_back(Name);
+    else
+      SymbolBodies.emplace_back(this, Name, Sym);
   }
 }
 

Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=250176&r1=250175&r2=250176&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Tue Oct 13 11:34:14 2015
@@ -169,6 +169,7 @@ template <class ELFT> class SharedFile :
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
 
   std::vector<SharedSymbol<ELFT>> SymbolBodies;
+  std::vector<StringRef> Undefs;
   StringRef SoName;
 
 public:
@@ -177,6 +178,8 @@ public:
     return SymbolBodies;
   }
 
+  llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; }
+
   static bool classof(const InputFile *F) {
     return F->kind() == Base::SharedKind;
   }

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=250176&r1=250175&r2=250176&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Tue Oct 13 11:34:14 2015
@@ -181,6 +181,13 @@ template <class ELFT> Symbol *SymbolTabl
   return Sym;
 }
 
+template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) {
+  auto It = Symtab.find(Name);
+  if (It == Symtab.end())
+    return nullptr;
+  return It->second->Body;
+}
+
 template <class ELFT> void SymbolTable<ELFT>::addLazy(Lazy *New) {
   Symbol *Sym = insert(New);
   if (Sym->Body == New)
@@ -230,6 +237,20 @@ template <class ELFT> void SymbolTable<E
   addFile(std::move(File));
 }
 
+template <class ELFT> void SymbolTable<ELFT>::finalize() {
+  // This code takes care of the case in which shared libraries depend on
+  // the user program (not the other way, which is usual). Shared libraries
+  // may have undefined symbols, expecting that the user program provides
+  // the definitions for them. An example is BSD's __progname symbol.
+  // We need to put such symbols to the main program's .dynsym so that
+  // shared libraries can find them.
+  for (std::unique_ptr<SharedFile<ELFT>> &File : SharedFiles)
+    for (StringRef U : File->getUndefinedSymbols())
+      if (SymbolBody *Sym = find(U))
+        if (Sym->isDefined())
+          Sym->setUsedInDynamicReloc();
+}
+
 template class lld::elf2::SymbolTable<ELF32LE>;
 template class lld::elf2::SymbolTable<ELF32BE>;
 template class lld::elf2::SymbolTable<ELF64LE>;

Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=250176&r1=250175&r2=250176&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Tue Oct 13 11:34:14 2015
@@ -52,6 +52,7 @@ public:
   void addSyntheticSym(StringRef Name, OutputSection<ELFT> &Section,
                        typename llvm::object::ELFFile<ELFT>::uintX_t Value);
   void addIgnoredSym(StringRef Name);
+  void finalize();
 
 private:
   Symbol *insert(SymbolBody *New);
@@ -60,6 +61,7 @@ private:
   void addMemberFile(Lazy *Body);
   void checkCompatibility(std::unique_ptr<InputFile> &File);
   void resolve(SymbolBody *Body);
+  SymbolBody *find(StringRef Name);
   void reportConflict(const Twine &Message, const SymbolBody &Old,
                       const SymbolBody &New, bool Warning);
 

Added: lld/trunk/test/elf2/progname.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/progname.s?rev=250176&view=auto
==============================================================================
--- lld/trunk/test/elf2/progname.s (added)
+++ lld/trunk/test/elf2/progname.s Tue Oct 13 11:34:14 2015
@@ -0,0 +1,20 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
+// RUN: echo '.global __progname' > %t2.s
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %t2.s -o %t2.o
+// RUN: ld.lld2 -shared %t2.o -o %t2.so
+// RUN: ld.lld2 -o %t %t.o %t2.so
+// RUN: llvm-readobj -dyn-symbols %t | FileCheck %s
+
+// CHECK:      Name:     __progname@
+// CHECK-NEXT: Value:    0x11000
+// CHECK-NEXT: Size:     0
+// CHECK-NEXT: Binding:  Global (0x1)
+// CHECK-NEXT: Type:     None (0x0)
+// CHECK-NEXT: Other:    0
+// CHECK-NEXT: Section:  .text
+// CHECK-NEXT: }
+
+.global _start, __progname
+_start:
+__progname:
+  nop




More information about the llvm-commits mailing list