[lld] r175941 - [ELF][Writer] Add dynamic string and symbol table.

Michael J. Spencer bigcheesegs at gmail.com
Fri Feb 22 17:02:31 PST 2013


Author: mspencer
Date: Fri Feb 22 19:02:31 2013
New Revision: 175941

URL: http://llvm.org/viewvc/llvm-project?rev=175941&view=rev
Log:
[ELF][Writer] Add dynamic string and symbol table.

Added:
    lld/trunk/test/elf/dynamic-symbols.test
Modified:
    lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
    lld/trunk/lib/ReaderWriter/ELF/Writer.cpp
    lld/trunk/test/elf/sections.objtxt

Modified: lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h?rev=175941&r1=175940&r2=175941&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h Fri Feb 22 19:02:31 2013
@@ -31,6 +31,7 @@
 
 namespace lld {
 namespace elf {
+template <class> class MergedSections;
 using namespace llvm::ELF;
 
 /// \brief An ELF section.
@@ -39,8 +40,8 @@ public:
   /// \param type the ELF SHT_* type of the section.
   Section(const ELFTargetInfo &ti, StringRef name,
           typename Chunk<ELFT>::Kind k = Chunk<ELFT>::K_ELFSection)
-      : Chunk<ELFT>(name, k, ti), _flags(0), _entSize(0), _type(0), _link(0),
-        _info(0), _segmentType(SHT_NULL) {}
+      : Chunk<ELFT>(name, k, ti), _parent(nullptr), _flags(0), _entSize(0),
+        _type(0), _link(0), _info(0), _segmentType(SHT_NULL) {}
 
   /// \brief Modify the section contents before assigning virtual addresses
   //  or assigning file offsets
@@ -82,12 +83,18 @@ public:
     this->_segmentType = segmentType;
   }
 
+  void setMergedSection(MergedSections<ELFT> *ms) {
+    _parent = ms;
+  }
+
   static bool classof(const Chunk<ELFT> *c) {
     return c->kind() == Chunk<ELFT>::K_ELFSection ||
            c->kind() == Chunk<ELFT>::K_AtomSection;
   }
 
 protected:
+  /// \brief MergedSections this Section is a member of, or nullptr.
+  MergedSections<ELFT> *_parent;
   /// \brief ELF SHF_* flags.
   uint64_t _flags;
   /// \brief The size of each entity.
@@ -386,6 +393,10 @@ public:
     _virtualAddr = addr;
   }
 
+  void setLink(uint64_t link) { _link = link; }
+
+  void setInfo(uint64_t info) { _shInfo = info; }
+
   inline range<ChunkIter> sections() { return _sections; }
 
   // The below functions returns the properties of the MergeSection
@@ -460,12 +471,14 @@ MergedSections<ELFT>::appendSection(Chun
   if (c->align2() > _align2)
     _align2 = c->align2();
   if (const auto section = dyn_cast<Section<ELFT>>(c)) {
+    assert(!_link && "Section already has a link!");
     _link = section->getLink();
     _shInfo = section->getInfo();
     _entSize = section->getEntSize();
     _type = section->getType();
     if (_flags < section->getFlags())
       _flags = section->getFlags();
+    section->setMergedSection(this);
   }
   _kind = c->kind();
   _sections.push_back(c);
@@ -475,7 +488,8 @@ MergedSections<ELFT>::appendSection(Chun
 template<class ELFT>
 class StringTable : public Section<ELFT> {
 public:
-  StringTable(const ELFTargetInfo &, const char *str, int32_t order);
+  StringTable(const ELFTargetInfo &, const char *str, int32_t order,
+              bool dynamic = false);
 
   uint64_t addString(StringRef symname);
 
@@ -502,7 +516,7 @@ private:
 
 template <class ELFT>
 StringTable<ELFT>::StringTable(const ELFTargetInfo &ti, const char *str,
-                               int32_t order)
+                               int32_t order, bool dynamic)
     : Section<ELFT>(ti, str) {
   // the string table has a NULL entry for which
   // add an empty string
@@ -511,6 +525,10 @@ StringTable<ELFT>::StringTable(const ELF
   this->_align2 = 1;
   this->setOrder(order);
   this->_type = SHT_STRTAB;
+  if (dynamic) {
+    this->_flags = SHF_ALLOC;
+    this->_msize = this->_fsize;
+  }
 }
 
 template <class ELFT> uint64_t StringTable<ELFT>::addString(StringRef symname) {
@@ -522,6 +540,8 @@ template <class ELFT> uint64_t StringTab
     _strings.push_back(symname);
     uint64_t offset = this->_fsize;
     this->_fsize += symname.size() + 1;
+    if (this->_flags & SHF_ALLOC)
+      this->_msize = this->_fsize;
     _stringMap[symname] = offset;
     return offset;
   }
@@ -544,9 +564,20 @@ void StringTable<ELFT>::write(ELFWriter
 /// \brief The SymbolTable class represents the symbol table in a ELF file
 template<class ELFT>
 class SymbolTable : public Section<ELFT> {
-public:
+  typedef typename llvm::object::ELFDataTypeTypedefHelper<ELFT>::Elf_Addr
+      Elf_Addr;
   typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
 
+  struct SymbolEntry {
+    SymbolEntry(const Atom *a, const Elf_Sym &sym) : _atom(a), _symbol(sym) {}
+
+    SymbolEntry() : _atom(nullptr) {}
+
+    const Atom *_atom;
+    Elf_Sym _symbol;
+  };
+
+public:
   SymbolTable(const ELFTargetInfo &ti, const char *str, int32_t order);
 
   void addSymbol(const Atom *atom, int32_t sectionIndex, uint64_t addr = 0);
@@ -560,7 +591,7 @@ public:
 private:
   llvm::BumpPtrAllocator _symbolAllocate;
   StringTable<ELFT> *_stringSection;
-  std::vector<Elf_Sym*> _symbolTable;
+  std::vector<SymbolEntry> _symbolTable;
 };
 
 /// ELF Symbol Table 
@@ -569,53 +600,53 @@ SymbolTable<ELFT>::SymbolTable(const ELF
                                int32_t order)
     : Section<ELFT>(ti, str) {
   this->setOrder(order);
-  Elf_Sym *symbol = new (_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
-  memset((void *)symbol, 0, sizeof(Elf_Sym));
-  _symbolTable.push_back(symbol);
+  Elf_Sym symbol;
+  std::memset(&symbol, 0, sizeof(Elf_Sym));
+  _symbolTable.push_back(SymbolEntry(nullptr, symbol));
   this->_entSize = sizeof(Elf_Sym);
   this->_fsize = sizeof(Elf_Sym);
-  this->_align2 = sizeof(void *);
+  this->_align2 = sizeof(Elf_Addr);
   this->_type = SHT_SYMTAB;
 }
 
 template <class ELFT>
 void SymbolTable<ELFT>::addSymbol(const Atom *atom, int32_t sectionIndex,
                                   uint64_t addr) {
-  Elf_Sym *symbol = new(_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
+  Elf_Sym symbol;
   unsigned char binding = 0, type = 0;
-  symbol->st_name = _stringSection->addString(atom->name());
-  symbol->st_size = 0;
-  symbol->st_shndx = sectionIndex;
-  symbol->st_value = 0;
-  symbol->st_other = llvm::ELF::STV_DEFAULT;
+  symbol.st_name = _stringSection->addString(atom->name());
+  symbol.st_size = 0;
+  symbol.st_shndx = sectionIndex;
+  symbol.st_value = 0;
+  symbol.st_other = llvm::ELF::STV_DEFAULT;
   if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom)){
-    symbol->st_size = da->size();
+    symbol.st_size = da->size();
     DefinedAtom::ContentType ct;
     switch (ct = da->contentType()){
     case DefinedAtom::typeCode:
     case DefinedAtom::typeStub:
-      symbol->st_value = addr;
+      symbol.st_value = addr;
       type = llvm::ELF::STT_FUNC;
       break;
     case DefinedAtom::typeResolver:
-      symbol->st_value = addr;
+      symbol.st_value = addr;
       type = llvm::ELF::STT_GNU_IFUNC;
       break;
     case DefinedAtom::typeDataFast:
     case DefinedAtom::typeData:
     case DefinedAtom::typeConstant:
     case DefinedAtom::typeGOT:
-      symbol->st_value = addr;
+      symbol.st_value = addr;
       type = llvm::ELF::STT_OBJECT;
       break;
     case DefinedAtom::typeZeroFill:
       type = llvm::ELF::STT_OBJECT;
-      symbol->st_value = addr;
+      symbol.st_value = addr;
       break;
     case DefinedAtom::typeTLVInitialData:
     case DefinedAtom::typeTLVInitialZeroFill:
       type = llvm::ELF::STT_TLS;
-      symbol->st_value = addr;
+      symbol.st_value = addr;
       break;
     default:
       type = llvm::ELF::STT_NOTYPE;
@@ -626,10 +657,10 @@ void SymbolTable<ELFT>::addSymbol(const
       binding = llvm::ELF::STB_GLOBAL;
   } else if (const AbsoluteAtom *aa = dyn_cast<const AbsoluteAtom>(atom)){
     type = llvm::ELF::STT_OBJECT;
-    symbol->st_shndx = llvm::ELF::SHN_ABS;
+    symbol.st_shndx = llvm::ELF::SHN_ABS;
     switch (aa->scope()) {
     case AbsoluteAtom::scopeLinkageUnit:
-      symbol->st_other = llvm::ELF::STV_HIDDEN;
+      symbol.st_other = llvm::ELF::STV_HIDDEN;
       binding = llvm::ELF::STB_LOCAL;
       break;
     case AbsoluteAtom::scopeTranslationUnit:
@@ -639,32 +670,42 @@ void SymbolTable<ELFT>::addSymbol(const
       binding = llvm::ELF::STB_GLOBAL;
       break;
     }
-    symbol->st_value = addr;
+    symbol.st_value = addr;
+  } else if (isa<const SharedLibraryAtom>(atom)) {
+    type = llvm::ELF::STT_FUNC;
+    symbol.st_shndx = llvm::ELF::SHN_UNDEF;
+    binding = llvm::ELF::STB_GLOBAL;
   } else {
-   symbol->st_value = 0;
-   type = llvm::ELF::STT_NOTYPE;
-   binding = llvm::ELF::STB_WEAK;
+    symbol.st_value = 0;
+    type = llvm::ELF::STT_NOTYPE;
+    binding = llvm::ELF::STB_WEAK;
   }
-  symbol->setBindingAndType(binding, type);
-  _symbolTable.push_back(symbol);
+  symbol.setBindingAndType(binding, type);
+  _symbolTable.push_back(SymbolEntry(atom, symbol));
   this->_fsize += sizeof(Elf_Sym);
+  if (this->_flags & SHF_ALLOC)
+    this->_msize = this->_fsize;
 }
 
 template <class ELFT> void SymbolTable<ELFT>::finalize() {
   // sh_info should be one greater than last symbol with STB_LOCAL binding
   // we sort the symbol table to keep all local symbols at the beginning
   std::stable_sort(_symbolTable.begin(), _symbolTable.end(),
-  [](const Elf_Sym *A, const Elf_Sym *B) {
-     return A->getBinding() < B->getBinding();
+                   [](const SymbolEntry & A, const SymbolEntry & B) {
+    return A._symbol.getBinding() < B._symbol.getBinding();
   });
   uint16_t shInfo = 0;
-  for (auto i : _symbolTable) {
-    if (i->getBinding() != llvm::ELF::STB_LOCAL)
+  for (const auto &i : _symbolTable) {
+    if (i._symbol.getBinding() != llvm::ELF::STB_LOCAL)
       break;
     shInfo++;
   }
   this->_info = shInfo;
   this->_link = _stringSection->ordinal();
+  if (this->_parent) {
+    this->_parent->setInfo(this->_info);
+    this->_parent->setLink(this->_link);
+  }
 }
 
 template <class ELFT>
@@ -672,12 +713,22 @@ void SymbolTable<ELFT>::write(ELFWriter
                               llvm::FileOutputBuffer &buffer) {
   uint8_t *chunkBuffer = buffer.getBufferStart();
   uint8_t *dest = chunkBuffer + this->fileOffset();
-  for (auto sti : _symbolTable) {
-    memcpy(dest, sti, sizeof(Elf_Sym));
+  for (const auto &sti : _symbolTable) {
+    memcpy(dest, &sti._symbol, sizeof(Elf_Sym));
     dest += sizeof(Elf_Sym);
   }
 }
 
+template <class ELFT> class DynamicSymbolTable : public SymbolTable<ELFT> {
+public:
+  DynamicSymbolTable(const ELFTargetInfo &ti, const char *str, int32_t order)
+      : SymbolTable<ELFT>(ti, str, order) {
+    this->_type = SHT_DYNSYM;
+    this->_flags = SHF_ALLOC;
+    this->_msize = this->_fsize;
+  }
+};
+
 template <class ELFT> class RelocationTable : public Section<ELFT> {
 public:
   typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;

Modified: lld/trunk/lib/ReaderWriter/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Writer.cpp?rev=175941&r1=175940&r2=175941&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Writer.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Writer.cpp Fri Feb 22 19:02:31 2013
@@ -38,10 +38,10 @@ private:
   void buildChunks(const File &file);
   virtual error_code writeFile(const File &File, StringRef path);
   void buildAtomToAddressMap();
-  void buildSymbolTable ();
+  void buildStaticSymbolTable(const File &file);
+  void buildDynamicSymbolTable(const File &file);
   void buildSectionHeaderTable();
   void assignSectionsWithNoSegments();
-  void addAbsoluteUndefinedSymbols(const File &File);
   void addDefaultAtoms();
   void addFiles(InputFiles&);
   void finalizeDefaultAtomValues();
@@ -69,6 +69,8 @@ private:
   /// \name Dynamic sections.
   /// @{
   LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>) _dynamicTable;
+  LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>) _dynamicSymbolTable;
+  LLD_UNIQUE_BUMP_PTR(StringTable<ELFT>) _dynamicStringTable;
   LLD_UNIQUE_BUMP_PTR(InterpSection<ELFT>) _interpSection;
   /// @}
   CRuntimeFile<ELFT> _runtimeFile;
@@ -86,36 +88,32 @@ ExecutableWriter<ELFT>::ExecutableWriter
 
 template <class ELFT>
 void ExecutableWriter<ELFT>::buildChunks(const File &file) {
-  for (const DefinedAtom *definedAtom : file.defined() ) {
+  for (const DefinedAtom *definedAtom : file.defined())
     _layout->addAtom(definedAtom);
-  }
-  /// Add all the absolute atoms to the layout
-  for (const AbsoluteAtom *absoluteAtom : file.absolute()) {
+  for (const AbsoluteAtom *absoluteAtom : file.absolute())
     _layout->addAtom(absoluteAtom);
-  }
 }
 
-template<class ELFT>
-void ExecutableWriter<ELFT>::buildSymbolTable () {
+template <class ELFT>
+void ExecutableWriter<ELFT>::buildStaticSymbolTable(const File &file) {
   for (auto sec : _layout->sections())
     if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
       for (const auto &atom : section->atoms())
         _symtab->addSymbol(atom->_atom, section->ordinal(), atom->_virtualAddr);
-}
-
-template<class ELFT>
-void
-ExecutableWriter<ELFT>::addAbsoluteUndefinedSymbols(const File &file) {
-  // add all the absolute symbols that the layout contains to the output symbol
-  // table
   for (auto &atom : _layout->absoluteAtoms())
     _symtab->addSymbol(atom->_atom, ELF::SHN_ABS, atom->_virtualAddr);
   for (const UndefinedAtom *a : file.undefined())
     _symtab->addSymbol(a, ELF::SHN_UNDEF);
 }
 
-template<class ELFT>
-void ExecutableWriter<ELFT>::buildAtomToAddressMap () {
+template <class ELFT>
+void ExecutableWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
+  for (const auto sla : file.sharedLibrary()) {
+    _dynamicSymbolTable->addSymbol(sla, ELF::SHN_UNDEF);
+  }
+}
+
+template <class ELFT> void ExecutableWriter<ELFT>::buildAtomToAddressMap() {
   for (auto sec : _layout->sections())
     if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
       for (const auto &atom : section->atoms())
@@ -243,6 +241,9 @@ error_code ExecutableWriter<ELFT>::write
   // section string table
   createDefaultSections();
 
+  if (_targetInfo.isDynamic())
+    buildDynamicSymbolTable(file);
+
   // Set the Layout
   _layout->assignSectionsToSegments();
   _layout->assignFileOffsets();
@@ -255,10 +256,7 @@ error_code ExecutableWriter<ELFT>::write
   buildAtomToAddressMap();
 
   // Create symbol table and section string table
-  buildSymbolTable();
-
-  // add other symbols
-  addAbsoluteUndefinedSymbols(file);
+  buildStaticSymbolTable(file);
 
   // Finalize the layout by calling the finalize() functions
   _layout->finalize();
@@ -342,11 +340,19 @@ void ExecutableWriter<ELFT>::createDefau
   if (_targetInfo.isDynamic()) {
     _dynamicTable.reset(new (_alloc) DynamicTable<ELFT>(
         _targetInfo, ".dynamic", DefaultLayout<ELFT>::ORDER_DYNAMIC));
+    _dynamicStringTable.reset(new (_alloc) StringTable<ELFT>(
+        _targetInfo, ".dynstr", DefaultLayout<ELFT>::ORDER_DYNAMIC_STRINGS,
+        true));
+    _dynamicSymbolTable.reset(new (_alloc) DynamicSymbolTable<ELFT>(
+        _targetInfo, ".dynsym", DefaultLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS));
     _interpSection.reset(new (_alloc) InterpSection<ELFT>(
         _targetInfo, ".interp", DefaultLayout<ELFT>::ORDER_INTERP,
         _targetInfo.getInterpreter()));
     _layout->addSection(_dynamicTable.get());
+    _layout->addSection(_dynamicStringTable.get());
+    _layout->addSection(_dynamicSymbolTable.get());
     _layout->addSection(_interpSection.get());
+    _dynamicSymbolTable->setStringSection(_dynamicStringTable.get());
   }
 
   // give a chance for the target to add sections

Added: lld/trunk/test/elf/dynamic-symbols.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/dynamic-symbols.test?rev=175941&view=auto
==============================================================================
--- lld/trunk/test/elf/dynamic-symbols.test (added)
+++ lld/trunk/test/elf/dynamic-symbols.test Fri Feb 22 19:02:31 2013
@@ -0,0 +1,8 @@
+RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \
+RUN:   %p/Inputs/shared.so-x86-64 -output=%t -entry=main \
+RUN:   -output-type=dynamic
+RUN: llvm-readobj %t | FileCheck %s
+
+CHECK: Dynamic Symbols:
+CHECK:   foo FUNC {{[0-9a-f]+}} 0 {{[0-9a-f]+}} undef,global
+CHECK:   Total: 1

Modified: lld/trunk/test/elf/sections.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/sections.objtxt?rev=175941&r1=175940&r2=175941&view=diff
==============================================================================
--- lld/trunk/test/elf/sections.objtxt (original)
+++ lld/trunk/test/elf/sections.objtxt Fri Feb 22 19:02:31 2013
@@ -31,5 +31,5 @@ ED: 'sh_link', 0x00000000
 ED: 'sh_addralign', 0x00000001
 ED: Section 7
 ED: 'sh_link', 0x00000008
-ED: 'sh_addralign', 0x00000008
+ED: 'sh_addralign', 0x00000004
 ED: 'sh_entsize', 0x00000010





More information about the llvm-commits mailing list