[lld] r247019 - Start adding support for symbols in shared libraries.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 8 08:50:05 PDT 2015


Author: rafael
Date: Tue Sep  8 10:50:05 2015
New Revision: 247019

URL: http://llvm.org/viewvc/llvm-project?rev=247019&view=rev
Log:
Start adding support for symbols in shared libraries.

Added:
    lld/trunk/test/elf2/shared.s
Modified:
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/InputFiles.h
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/Symbols.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/elf2/Inputs/i686-simple-library.so

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=247019&r1=247018&r2=247019&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Tue Sep  8 10:50:05 2015
@@ -54,6 +54,24 @@ template <class ELFT> void ELFData<ELFT>
   error(EC);
 }
 
+template <class ELFT>
+typename ELFData<ELFT>::Elf_Sym_Range ELFData<ELFT>::getNonLocalSymbols() {
+  if (!Symtab)
+    return Elf_Sym_Range(nullptr, nullptr);
+
+  ErrorOr<StringRef> StringTableOrErr =
+      ELFObj->getStringTableForSymtab(*Symtab);
+  error(StringTableOrErr.getError());
+  StringTable = *StringTableOrErr;
+
+  Elf_Sym_Range Syms = ELFObj->symbols(Symtab);
+  uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
+  uint32_t FirstNonLocal = Symtab->sh_info;
+  if (FirstNonLocal > NumSymbols)
+    error("Invalid sh_info in symbol table");
+  return llvm::make_range(Syms.begin() + FirstNonLocal, Syms.end());
+}
+
 template <class ELFT> void elf2::ObjectFile<ELFT>::parse() {
   this->openELF(MB);
 
@@ -69,7 +87,7 @@ template <class ELFT> void elf2::ObjectF
   for (const Elf_Shdr &Sec : this->ELFObj->sections()) {
     switch (Sec.sh_type) {
     case SHT_SYMTAB:
-      Symtab = &Sec;
+      this->Symtab = &Sec;
       break;
     case SHT_SYMTAB_SHNDX: {
       ErrorOr<ArrayRef<Elf_Word>> ErrorOrTable =
@@ -101,20 +119,11 @@ template <class ELFT> void elf2::ObjectF
 }
 
 template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSymbols() {
-  ErrorOr<StringRef> StringTableOrErr =
-      this->ELFObj->getStringTableForSymtab(*Symtab);
-  error(StringTableOrErr.getError());
-  StringRef StringTable = *StringTableOrErr;
-
-  Elf_Sym_Range Syms = this->ELFObj->symbols(Symtab);
+  Elf_Sym_Range Syms = this->getNonLocalSymbols();
   uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
-  uint32_t FirstNonLocal = Symtab->sh_info;
-  if (FirstNonLocal > NumSymbols)
-    error("Invalid sh_info in symbol table");
-  Syms = llvm::make_range(Syms.begin() + FirstNonLocal, Syms.end());
-  SymbolBodies.reserve(NumSymbols - FirstNonLocal);
+  SymbolBodies.reserve(NumSymbols);
   for (const Elf_Sym &Sym : Syms)
-    SymbolBodies.push_back(createSymbolBody(StringTable, &Sym));
+    SymbolBodies.push_back(createSymbolBody(this->StringTable, &Sym));
 }
 
 template <class ELFT>
@@ -133,8 +142,8 @@ SymbolBody *elf2::ObjectFile<ELFT>::crea
   case SHN_COMMON:
     return new (Alloc) DefinedCommon<ELFT>(Name, *Sym);
   case SHN_XINDEX:
-    SecIndex =
-        this->ELFObj->getExtendedSymbolTableIndex(Sym, Symtab, SymtabSHNDX);
+    SecIndex = this->ELFObj->getExtendedSymbolTableIndex(Sym, this->Symtab,
+                                                         SymtabSHNDX);
     break;
   }
 
@@ -181,7 +190,30 @@ MemoryBufferRef ArchiveFile::getMember(c
   return *Ret;
 }
 
-template <class ELFT> void SharedFile<ELFT>::parse() { this->openELF(MB); }
+template <class ELFT> void SharedFile<ELFT>::parse() {
+  this->openELF(MB);
+
+  for (const Elf_Shdr &Sec : this->ELFObj->sections()) {
+    if (Sec.sh_type == SHT_DYNSYM) {
+      this->Symtab = &Sec;
+      break;
+    }
+  }
+
+  Elf_Sym_Range Syms = this->getNonLocalSymbols();
+  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(Name, Sym);
+  }
+}
 
 namespace lld {
 namespace elf2 {

Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=247019&r1=247018&r2=247019&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Tue Sep  8 10:50:05 2015
@@ -95,12 +95,18 @@ template <class ELFT> static ELFKind get
 
 template <class ELFT> class ELFData {
 public:
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
+
   llvm::object::ELFFile<ELFT> *getObj() const { return ELFObj.get(); }
 
   uint16_t getEMachine() const { return getObj()->getHeader()->e_machine; }
 
 protected:
   std::unique_ptr<llvm::object::ELFFile<ELFT>> ELFObj;
+  const Elf_Shdr *Symtab = nullptr;
+  StringRef StringTable;
+  Elf_Sym_Range getNonLocalSymbols();
 
   void openELF(MemoryBufferRef MB);
 };
@@ -126,7 +132,7 @@ public:
   ArrayRef<SectionChunk<ELFT> *> getChunks() { return Chunks; }
 
   SymbolBody *getSymbolBody(uint32_t SymbolIndex) {
-    uint32_t FirstNonLocal = Symtab->sh_info;
+    uint32_t FirstNonLocal = this->Symtab->sh_info;
     if (SymbolIndex < FirstNonLocal)
       return nullptr;
     return SymbolBodies[SymbolIndex - FirstNonLocal]->getReplacement();
@@ -141,7 +147,6 @@ private:
   // List of all chunks defined by this file.
   std::vector<SectionChunk<ELFT> *> Chunks;
 
-  const Elf_Shdr *Symtab = nullptr;
   ArrayRef<Elf_Word> SymtabSHNDX;
 };
 
@@ -174,7 +179,17 @@ public:
 
 template <class ELFT>
 class SharedFile : public SharedFileBase, public ELFData<ELFT> {
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
+
+  std::vector<SharedSymbol<ELFT>> SymbolBodies;
+
 public:
+  llvm::MutableArrayRef<SharedSymbol<ELFT>> getSharedSymbols() {
+    return SymbolBodies;
+  }
+
   static bool classof(const InputFile *F) {
     return F->kind() == SharedKind &&
            cast<ELFFileBase>(F)->getELFKind() == getStaticELFKind<ELFT>();

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=247019&r1=247018&r2=247019&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Tue Sep  8 10:50:05 2015
@@ -51,8 +51,11 @@ template <class ELFT> void SymbolTable::
       resolve<ELFT>(Body);
   }
 
-  if (auto *S = dyn_cast<SharedFileBase>(File))
+  if (auto *S = dyn_cast<SharedFile<ELFT>>(File)) {
     SharedFiles.emplace_back(S);
+    for (SharedSymbol<ELFT> &Body : S->getSharedSymbols())
+      resolve<ELFT>(&Body);
+  }
 }
 
 void SymbolTable::addELFFile(ELFFileBase *File) {

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=247019&r1=247018&r2=247019&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Tue Sep  8 10:50:05 2015
@@ -45,6 +45,9 @@ template <class ELFT> int SymbolBody::co
   MostConstrainingVisibility = getMinVisibility(LV, RV);
   Other->MostConstrainingVisibility = MostConstrainingVisibility;
 
+  IsUsedInRegularObj |= Other->IsUsedInRegularObj;
+  Other->IsUsedInRegularObj |= IsUsedInRegularObj;
+
   if (L != R)
     return -1;
 

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=247019&r1=247018&r2=247019&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Tue Sep  8 10:50:05 2015
@@ -41,9 +41,10 @@ public:
     DefinedRegularKind = 0,
     DefinedAbsoluteKind = 1,
     DefinedCommonKind = 2,
-    DefinedLast = 2,
-    UndefinedKind = 3,
-    LazyKind = 4,
+    SharedKind = 3,
+    DefinedLast = 3,
+    UndefinedKind = 4,
+    LazyKind = 5,
   };
 
   Kind kind() const { return static_cast<Kind>(SymbolKind); }
@@ -54,6 +55,8 @@ public:
   bool isStrongUndefined() const { return !IsWeak && isUndefined(); }
   bool isCommon() const { return SymbolKind == DefinedCommonKind; }
   bool isLazy() const { return SymbolKind == LazyKind; }
+  bool isShared() const { return SymbolKind == SharedKind; }
+  bool isUsedInRegularObj() const { return IsUsedInRegularObj; }
 
   // Returns the symbol name.
   StringRef getName() const { return Name; }
@@ -79,12 +82,15 @@ public:
 protected:
   SymbolBody(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility)
       : SymbolKind(K), IsWeak(IsWeak), MostConstrainingVisibility(Visibility),
-        Name(Name) {}
+        Name(Name) {
+    IsUsedInRegularObj = K != SharedKind && K != LazyKind;
+  }
 
 protected:
   const unsigned SymbolKind : 8;
   const unsigned IsWeak : 1;
   unsigned MostConstrainingVisibility : 2;
+  unsigned IsUsedInRegularObj : 1;
   StringRef Name;
   Symbol *Backref = nullptr;
 };
@@ -202,6 +208,19 @@ public:
 template <class ELFT>
 typename Undefined<ELFT>::Elf_Sym Undefined<ELFT>::Synthetic;
 
+template <class ELFT> class SharedSymbol : public ELFSymbolBody<ELFT> {
+  typedef ELFSymbolBody<ELFT> Base;
+  typedef typename Base::Elf_Sym Elf_Sym;
+
+public:
+  static bool classof(const SymbolBody *S) {
+    return S->kind() == Base::SharedKind;
+  }
+
+  SharedSymbol(StringRef Name, const Elf_Sym &Sym)
+      : ELFSymbolBody<ELFT>(Base::SharedKind, Name, Sym) {}
+};
+
 // This class represents a symbol defined in an archive file. It is
 // created from an archive file header, and it knows how to load an
 // object file from an archive to replace itself with a defined

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=247019&r1=247018&r2=247019&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue Sep  8 10:50:05 2015
@@ -297,6 +297,17 @@ static int compareSym(const typename ELF
   return AN - BN;
 }
 
+static bool includeInSymtab(const SymbolBody &B) {
+  if (B.isLazy())
+    return false;
+  if (!B.isUsedInRegularObj())
+    return false;
+  uint8_t V = B.getMostConstrainingVisibility();
+  if (V != STV_DEFAULT && V != STV_PROTECTED)
+    return false;
+  return true;
+}
+
 template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
   uint8_t *BufStart = Buf;
 
@@ -305,14 +316,10 @@ template <class ELFT> void SymbolTableSe
     StringRef Name = P.first;
     Symbol *Sym = P.second;
     SymbolBody *Body = Sym->Body;
-    if (Body->isLazy())
+    if (!includeInSymtab(*Body))
       continue;
     const Elf_Sym &InputSym = cast<ELFSymbolBody<ELFT>>(Body)->Sym;
 
-    uint8_t V = Body->getMostConstrainingVisibility();
-    if (V != STV_DEFAULT && V != STV_PROTECTED)
-      continue;
-
     auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
     ESym->st_name = Builder.getOffset(Name);
 
@@ -330,6 +337,7 @@ template <class ELFT> void SymbolTableSe
       if (!Body->isWeak())
         error(Twine("undefined symbol: ") + Name);
     case SymbolBody::DefinedAbsoluteKind:
+    case SymbolBody::SharedKind:
       break;
     case SymbolBody::LazyKind:
       llvm_unreachable("Lazy symbol got to output symbol table!");
@@ -458,12 +466,9 @@ template <class ELFT> void Writer<ELFT>:
   for (auto &P : Symtab.getSymbols()) {
     StringRef Name = P.first;
     SymbolBody *Body = P.second->Body;
-    if (Body->isLazy())
-      continue;
     if (auto *C = dyn_cast<DefinedCommon<ELFT>>(Body))
       CommonSymbols.push_back(C);
-    uint8_t V = Body->getMostConstrainingVisibility();
-    if (V != STV_DEFAULT && V != STV_PROTECTED)
+    if (!includeInSymtab(*Body))
       continue;
     NumVisible++;
     Builder.add(Name);

Modified: lld/trunk/test/elf2/Inputs/i686-simple-library.so
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/i686-simple-library.so?rev=247019&r1=247018&r2=247019&view=diff
==============================================================================
Binary files lld/trunk/test/elf2/Inputs/i686-simple-library.so (original) and lld/trunk/test/elf2/Inputs/i686-simple-library.so Tue Sep  8 10:50:05 2015 differ

Added: lld/trunk/test/elf2/shared.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/shared.s?rev=247019&view=auto
==============================================================================
--- lld/trunk/test/elf2/shared.s (added)
+++ lld/trunk/test/elf2/shared.s Tue Sep  8 10:50:05 2015
@@ -0,0 +1,38 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
+// RUN: lld -flavor gnu2 %t.o %p/Inputs/i686-simple-library.so -o %t
+// RUN: llvm-readobj -t %t | FileCheck %s
+// REQUIRES: x86
+
+// CHECK:      Symbols [
+// CHECK-NEXT:   Symbol {
+// CHECK-NEXT:     Name:
+// CHECK-NEXT:     Value: 0x0
+// CHECK-NEXT:     Size: 0
+// CHECK-NEXT:     Binding: Local
+// CHECK-NEXT:     Type: None
+// CHECK-NEXT:     Other: 0
+// CHECK-NEXT:     Section: Undefined
+// CHECK-NEXT:   }
+// CHECK-NEXT:   Symbol {
+// CHECK-NEXT:     Name: _start
+// CHECK-NEXT:     Value: 0x1000
+// CHECK-NEXT:     Size: 0
+// CHECK-NEXT:     Binding: Global
+// CHECK-NEXT:     Type: None
+// CHECK-NEXT:     Other: 0
+// CHECK-NEXT:     Section: .text
+// CHECK-NEXT:   }
+// CHECK-NEXT:   Symbol {
+// CHECK-NEXT:     Name: bar
+// CHECK-NEXT:     Value: 0x0
+// CHECK-NEXT:     Size: 0
+// CHECK-NEXT:     Binding: Global
+// CHECK-NEXT:     Type: Function
+// CHECK-NEXT:     Other: 0
+// CHECK-NEXT:     Section: Undefined
+// CHECK-NEXT:   }
+// CHECK-NEXT: ]
+
+.global _start
+_start:
+.long bar




More information about the llvm-commits mailing list