[lld] r178323 - [ELF] Add dynamic hash table and get simple dynamic libraries working with Hexagon

Shankar Easwaran shankare at codeaurora.org
Thu Mar 28 17:53:26 PDT 2013


Author: shankare
Date: Thu Mar 28 19:53:25 2013
New Revision: 178323

URL: http://llvm.org/viewvc/llvm-project?rev=178323&view=rev
Log:
[ELF] Add dynamic hash table and get simple dynamic libraries working with Hexagon

Added:
    lld/trunk/test/elf/Hexagon/dynlib-hash.test
    lld/trunk/test/elf/Hexagon/dynlib-syms.test
Modified:
    lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicAtoms.h
    lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h
    lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h
    lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
    lld/trunk/test/elf/Hexagon/dynlib-gotoff.test
    lld/trunk/test/elf/dynamic.test

Modified: lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicAtoms.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicAtoms.h?rev=178323&r1=178322&r2=178323&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicAtoms.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicAtoms.h Thu Mar 28 19:53:25 2013
@@ -20,16 +20,40 @@ class HexagonGOTAtom : public GOTAtom {
   static const uint8_t _defaultContent[8];
 
 public:
-  HexagonGOTAtom(const File &f, StringRef secName)
-      : GOTAtom(f, secName) {
+  HexagonGOTAtom(const File &f) : GOTAtom(f, ".got") {}
+
+  virtual ArrayRef<uint8_t> rawContent() const {
+    return ArrayRef<uint8_t>(_defaultContent, 8);
   }
 
+  virtual Alignment alignment() const { return Alignment(2); }
+};
+
+class HexagonGOTPLTAtom : public GOTAtom {
+  static const uint8_t _defaultContent[8];
+
+public:
+  HexagonGOTPLTAtom(const File &f) : GOTAtom(f, ".got.plt") {}
+
   virtual ArrayRef<uint8_t> rawContent() const {
     return ArrayRef<uint8_t>(_defaultContent, 8);
   }
 };
 
+class HexagonGOTPLT0Atom : public GOTAtom {
+  static const uint8_t _defaultContent[16];
+
+public:
+  HexagonGOTPLT0Atom(const File &f) : GOTAtom(f, ".got.plt") {}
+
+  virtual ArrayRef<uint8_t> rawContent() const {
+    return ArrayRef<uint8_t>(_defaultContent, 16);
+  }
+};
+
 const uint8_t HexagonGOTAtom::_defaultContent[8] = { 0 };
+const uint8_t HexagonGOTPLTAtom::_defaultContent[8] = { 0 };
+const uint8_t HexagonGOTPLT0Atom::_defaultContent[16] = { 0 };
 
 class HexagonPLTAtom : public PLTAtom {
   static const uint8_t _defaultContent[16];

Modified: lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp?rev=178323&r1=178322&r2=178323&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp Thu Mar 28 19:53:25 2013
@@ -54,7 +54,7 @@ protected:
   /// \brief Create a GOT entry containing 0.
   const GOTAtom *getNullGOT() {
     if (!_null) {
-      _null = new (_file._alloc) HexagonGOTAtom(_file, ".got.plt");
+      _null = new (_file._alloc) HexagonGOTPLTAtom(_file);
 #ifndef NDEBUG
       _null->_name = "__got_null";
 #endif
@@ -132,9 +132,7 @@ protected:
 class DynamicGOTPLTPass LLVM_FINAL : public GOTPLTPass<DynamicGOTPLTPass> {
 public:
   DynamicGOTPLTPass(const elf::HexagonTargetInfo &ti) : GOTPLTPass(ti) {
-    // Fill in the null entry.
-    getNullGOT();
-    _got0 = new (_file._alloc) HexagonGOTAtom(_file, ".got.plt");
+    _got0 = new (_file._alloc) HexagonGOTPLT0Atom(_file);
 #ifndef NDEBUG
     _got0->_name = "__got0";
 #endif
@@ -145,7 +143,7 @@ public:
       return _PLT0;
     _PLT0 = new (_file._alloc) HexagonPLT0Atom(_file);
     _PLT0->addReference(R_HEX_B32_PCREL_X, 0, _got0, 0);
-    _PLT0->addReference(R_HEX_6_PCREL_X, 4, _got0, 0);
+    _PLT0->addReference(R_HEX_6_PCREL_X, 4, _got0, 4);
     DEBUG_WITH_TYPE("PLT", llvm::dbgs() << "[ PLT0/GOT0 ] "
                                         << "Adding plt0/got0 \n");
     return _PLT0;
@@ -155,7 +153,7 @@ public:
     auto plt = _pltMap.find(a);
     if (plt != _pltMap.end())
       return plt->second;
-    auto ga = new (_file._alloc) HexagonGOTAtom(_file, ".got.plt");
+    auto ga = new (_file._alloc) HexagonGOTPLTAtom(_file);
     ga->addReference(R_HEX_JMP_SLOT, 0, a, 0);
     auto pa = new (_file._alloc) HexagonPLTAtom(_file, ".plt");
     pa->addReference(R_HEX_B32_PCREL_X, 0, ga, 0);
@@ -183,7 +181,7 @@ public:
     auto got = _gotMap.find(a);
     if (got != _gotMap.end())
       return got->second;
-    auto ga = new (_file._alloc) HexagonGOTAtom(_file, ".got");
+    auto ga = new (_file._alloc) HexagonGOTAtom(_file);
     ga->addReference(R_HEX_GLOB_DAT, 0, a, 0);
 
 #ifndef NDEBUG
@@ -198,7 +196,7 @@ public:
   }
 
   ErrorOr<void> handleGOTREL(const Reference &ref) {
-    // Turn this so that the target is set to the GOT entry 
+    // Turn this so that the target is set to the GOT entry
     const_cast<Reference &>(ref).setTarget(getGOTEntry(ref.target()));
     return error_code::success();
   }

Modified: lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h?rev=178323&r1=178322&r2=178323&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h Thu Mar 28 19:53:25 2013
@@ -170,8 +170,10 @@ public:
 
   void addDefaultAtoms() {
     _hexagonRuntimeFile.addAbsoluteAtom("_SDA_BASE_");
-    if (_targetInfo.isDynamic())
+    if (_targetInfo.isDynamic()) {
       _hexagonRuntimeFile.addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_");
+      _hexagonRuntimeFile.addAbsoluteAtom("_DYNAMIC");
+    }
   }
 
   virtual void addFiles(InputFiles &inputFiles) {
@@ -192,6 +194,12 @@ public:
         _gotSymAtom->_virtualAddr = gotpltSection->virtualAddr();
       else
         _gotSymAtom->_virtualAddr = 0;
+      auto dynamicAtomIter = _targetLayout.findAbsoluteAtom("_DYNAMIC");
+      auto dynamicSection = _targetLayout.findOutputSection(".dynamic");
+      if (dynamicSection)
+        (*dynamicAtomIter)->_virtualAddr = dynamicSection->virtualAddr();
+      else
+        (*dynamicAtomIter)->_virtualAddr = 0;
     }
   }
 

Modified: lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h?rev=178323&r1=178322&r2=178323&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h Thu Mar 28 19:53:25 2013
@@ -156,6 +156,15 @@ void OutputELFWriter<ELFT>::buildDynamic
     dyn.d_un.d_val = _dynamicStringTable->addString(loadName.getKey());
     _dynamicTable->addEntry(dyn);
   }
+  // The dynamic symbol table need to be sorted earlier because the hash
+  // table needs to be built using the dynamic symbol table. It would be
+  // late to sort the symbols due to that in finalize. In the dynamic symbol
+  // table finalize, we call the symbol table finalize and we dont want to
+  // sort again
+  _dynamicSymbolTable->sortSymbols();
+
+  // Add the dynamic symbols into the hash table
+  _dynamicSymbolTable->addSymbolsToHashTable();
 }
 
 template <class ELFT> void OutputELFWriter<ELFT>::buildAtomToAddressMap() {
@@ -227,14 +236,20 @@ void OutputELFWriter<ELFT>::createDefaul
         _targetInfo, ".dynsym", DefaultLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS));
     _hashTable.reset(new (_alloc) HashSection<ELFT>(
         _targetInfo, ".hash", DefaultLayout<ELFT>::ORDER_HASH));
+    // Set the hash table in the dynamic symbol table so that the entries in the
+    // hash table can be created
+    _dynamicSymbolTable->setHashTable(_hashTable.get());
+    _hashTable->setSymbolTable(_dynamicSymbolTable.get());
     _layout->addSection(_dynamicTable.get());
     _layout->addSection(_dynamicStringTable.get());
     _layout->addSection(_dynamicSymbolTable.get());
     _layout->addSection(_hashTable.get());
     _dynamicSymbolTable->setStringSection(_dynamicStringTable.get());
+    _dynamicTable->setSymbolTable(_dynamicSymbolTable.get());
+    _dynamicTable->setHashTable(_hashTable.get());
     if (_layout->hasDynamicRelocationTable())
-      _layout->getDynamicRelocationTable()->setSymbolTable(
-          _dynamicSymbolTable.get());
+      _layout->getDynamicRelocationTable()
+          ->setSymbolTable(_dynamicSymbolTable.get());
     if (_layout->hasPLTRelocationTable())
       _layout->getPLTRelocationTable()->setSymbolTable(
           _dynamicSymbolTable.get());
@@ -288,8 +303,7 @@ error_code OutputELFWriter<ELFT>::buildO
   assignSectionsWithNoSegments();
 
   if (_targetInfo.isDynamic())
-    _dynamicTable->updateDynamicTable(_hashTable.get(),
-                                      _dynamicSymbolTable.get());
+    _dynamicTable->updateDynamicTable();
 
   return error_code::success();
 }

Modified: lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h?rev=178323&r1=178322&r2=178323&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h Thu Mar 28 19:53:25 2013
@@ -612,6 +612,15 @@ public:
     return std::distance(_symbolTable.begin(), se);
   }
 
+  virtual void finalize() { finalize(true); }
+
+  virtual void sortSymbols() {
+    std::stable_sort(_symbolTable.begin(), _symbolTable.end(),
+                     [](const SymbolEntry & A, const SymbolEntry & B) {
+      return A._symbol.getBinding() < B._symbol.getBinding();
+    });
+  }
+
   virtual void addAbsoluteAtom(Elf_Sym &sym, const AbsoluteAtom *aa,
                                int64_t addr);
 
@@ -622,7 +631,7 @@ public:
 
   virtual void addSharedLibAtom(Elf_Sym &sym, const SharedLibraryAtom *sla);
 
-  virtual void finalize();
+  virtual void finalize(bool sort = true);
 
   virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer);
 
@@ -774,13 +783,12 @@ void SymbolTable<ELFT>::addSymbol(const
     this->_msize = this->_fsize;
 }
 
-template <class ELFT> void SymbolTable<ELFT>::finalize() {
+template <class ELFT> void SymbolTable<ELFT>::finalize(bool sort) {
   // 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 SymbolEntry & A, const SymbolEntry & B) {
-    return A._symbol.getBinding() < B._symbol.getBinding();
-  });
+  if (sort)
+    sortSymbols();
+
   uint16_t shInfo = 0;
   for (const auto &i : _symbolTable) {
     if (i._symbol.getBinding() != llvm::ELF::STB_LOCAL)
@@ -806,15 +814,32 @@ void SymbolTable<ELFT>::write(ELFWriter
   }
 }
 
+template <class ELFT> class HashSection;
+
 template <class ELFT> class DynamicSymbolTable : public SymbolTable<ELFT> {
 public:
   DynamicSymbolTable(const ELFTargetInfo &ti, const char *str, int32_t order)
-      : SymbolTable<ELFT>(ti, str, order) {
+      : SymbolTable<ELFT>(ti, str, order), _hashTable(nullptr) {
     this->_type = SHT_DYNSYM;
     this->_flags = SHF_ALLOC;
     this->_msize = this->_fsize;
   }
 
+  // Set the dynamic hash table for symbols to be added into
+  void setHashTable(HashSection<ELFT> *hashTable) { _hashTable = hashTable; }
+
+  // Add all the dynamic symbos to the hash table
+  void addSymbolsToHashTable() {
+    int index = 0;
+    for (auto &ste : this->_symbolTable) {
+      if (!ste._atom)
+        _hashTable->addSymbol("", index);
+      else
+        _hashTable->addSymbol(ste._atom->name(), index);
+      ++index;
+    }
+  }
+
   virtual void finalize() {
     // Defined symbols which have been added into the dynamic symbol table
     // dont have their addresses known until addresses have been assigned
@@ -825,9 +850,13 @@ public:
         continue;
       ste._symbol.st_value = atomLayout->_virtualAddr;
     }
-    SymbolTable<ELFT>::finalize();
+
+    // Dont sort the symbols
+    SymbolTable<ELFT>::finalize(false);
   }
 
+private:
+  HashSection<ELFT> *_hashTable;
 };
 
 template <class ELFT> class RelocationTable : public Section<ELFT> {
@@ -865,7 +894,7 @@ public:
     return true;
   }
 
-  void setSymbolTable(const SymbolTable<ELFT> *symbolTable) {
+  void setSymbolTable(const DynamicSymbolTable<ELFT> *symbolTable) {
     _symbolTable = symbolTable;
   }
 
@@ -886,22 +915,26 @@ public:
       r->setSymbolAndType(index, rel.second->kind());
       r->r_offset =
           writer->addressOfAtom(rel.first) + rel.second->offsetInAtom();
-      r->r_addend =
-          writer->addressOfAtom(rel.second->target()) + rel.second->addend();
+      // FIXME: The addend is used only by IRELATIVE relocations while static
+      // linking executable statically, check to see how does dynamic linking
+      // work with IFUNC and change accordingly
+      if (!this->_targetInfo.isDynamic())
+        r->r_addend =
+            writer->addressOfAtom(rel.second->target()) + rel.second->addend();
       dest += sizeof(Elf_Rela);
-      DEBUG_WITH_TYPE("ELFRelocationTable",
-                      llvm::dbgs()
-                      << kindOrUnknown(this->_targetInfo.stringFromRelocKind(
-                             rel.second->kind())) << " relocation at "
-                      << rel.first->name() << "@" << r->r_offset << " to "
-                      << rel.second->target()->name() << "@" << r->r_addend
-                      << "\n");
+      DEBUG_WITH_TYPE(
+          "ELFRelocationTable",
+          llvm::dbgs() << kindOrUnknown(this->_targetInfo.stringFromRelocKind(
+                              rel.second->kind())) << " relocation at "
+                       << rel.first->name() << "@" << r->r_offset << " to "
+                       << rel.second->target()->name() << "@" << r->r_addend
+                       << "\n");
     }
   }
 
 private:
-  std::vector<std::pair<const DefinedAtom *, const Reference *>> _relocs;
-  const SymbolTable<ELFT> *_symbolTable;
+  std::vector<std::pair<const DefinedAtom *, const Reference *> > _relocs;
+  const DynamicSymbolTable<ELFT> *_symbolTable;
 };
 
 template <class ELFT> class HashSection;
@@ -981,15 +1014,30 @@ public:
     }
   }
 
-  void updateDynamicTable(HashSection<ELFT> *hashTable,
-                          DynamicSymbolTable<ELFT> *dynamicSymbolTable) {
+  virtual void finalize() {
+    StringTable<ELFT> *dynamicStringTable =
+        _dynamicSymbolTable->getStringTable();
+    this->_link = dynamicStringTable->ordinal();
+    if (this->_parent) {
+      this->_parent->setInfo(this->_info);
+      this->_parent->setLink(this->_link);
+    }
+  }
+
+  void setSymbolTable(DynamicSymbolTable<ELFT> *dynsym) {
+    _dynamicSymbolTable = dynsym;
+  }
+
+  void setHashTable(HashSection<ELFT> *hsh) { _hashTable = hsh; }
+
+  void updateDynamicTable() {
     StringTable<ELFT> *dynamicStringTable =
-        dynamicSymbolTable->getStringTable();
-    _entries[_dt_hash].d_un.d_val = hashTable->virtualAddr();
+        _dynamicSymbolTable->getStringTable();
+    _entries[_dt_hash].d_un.d_val = _hashTable->virtualAddr();
     _entries[_dt_strtab].d_un.d_val = dynamicStringTable->virtualAddr();
-    _entries[_dt_symtab].d_un.d_val = dynamicSymbolTable->virtualAddr();
+    _entries[_dt_symtab].d_un.d_val = _dynamicSymbolTable->virtualAddr();
     _entries[_dt_strsz].d_un.d_val = dynamicStringTable->memSize();
-    _entries[_dt_syment].d_un.d_val = dynamicSymbolTable->getEntSize();
+    _entries[_dt_syment].d_un.d_val = _dynamicSymbolTable->getEntSize();
     if (_layout->hasDynamicRelocationTable()) {
       auto relaTbl = _layout->getDynamicRelocationTable();
       _entries[_dt_rela].d_un.d_val = relaTbl->virtualAddr();
@@ -1020,6 +1068,8 @@ private:
   std::size_t _dt_pltrel;
   std::size_t _dt_jmprel;
   TargetLayout<ELFT> *_layout;
+  DynamicSymbolTable<ELFT> *_dynamicSymbolTable;
+  HashSection<ELFT> *_hashTable;
 };
 
 template <class ELFT> class InterpSection : public Section<ELFT> {
@@ -1047,6 +1097,26 @@ private:
   StringRef _interp;
 };
 
+/// The hash table in the dynamic linker is organized into
+///
+///     [ nbuckets              ]
+///     [ nchains               ]
+///     [ buckets[0]            ]
+///     .........................
+///     [ buckets[nbuckets-1]   ]
+///     [ chains[0]             ]
+///     .........................
+///     [ chains[nchains - 1]   ]
+///
+/// nbuckets - total number of hash buckets
+/// nchains is equal to the number of dynamic symbols.
+///
+/// The symbol is searched by the dynamic linker using the below approach.
+///  * Calculate the hash of the symbol that needs to be searched
+///  * Take the value from the buckets[hash % nbuckets] as the index of symbol
+///  * Compare the symbol's name, if true return, if false, look through the
+///  * array since there was a collision
+
 template <class ELFT> class HashSection : public Section<ELFT> {
   struct SymbolTableEntry {
     StringRef _name;
@@ -1055,16 +1125,22 @@ template <class ELFT> class HashSection
 
 public:
   HashSection(const ELFTargetInfo &ti, StringRef name, int32_t order)
-      : Section<ELFT>(ti, name) {
+      : Section<ELFT>(ti, name), _symbolTable(nullptr) {
     this->setOrder(order);
-    this->_align2 = 4; // Alignment of Elf32_Word.
+    this->_entSize = 4;
     this->_type = SHT_HASH;
     this->_flags = SHF_ALLOC;
-    // The size of nbucket and nchain.
-    this->_fsize = 8;
-    this->_msize = this->_fsize;
+    // Set the alignment properly depending on the target architecture
+    if (ti.is64Bits())
+      this->_align2 = 8;
+    else
+      this->_align2 = 4;
+    this->_fsize = 0;
+    this->_msize = 0;
   }
 
+  /// \brief add the dynamic symbol into the table so that the
+  /// hash could be calculated
   void addSymbol(StringRef name, uint32_t index) {
     SymbolTableEntry ste;
     ste._name = name;
@@ -1072,16 +1148,84 @@ public:
     _entries.push_back(ste);
   }
 
+  /// \brief Set the dynamic symbol table
+  void setSymbolTable(const DynamicSymbolTable<ELFT> *symbolTable) {
+    _symbolTable = symbolTable;
+  }
+
+  // The size of the section has to be determined so that fileoffsets
+  // may be properly assigned. Lets calculate the buckets and the chains
+  // and fill the chains and the buckets hash table used by the dynamic
+  // linker and update the filesize and memory size accordingly
+  virtual void doPreFlight() {
+    // The number of buckets to use for a certain number of symbols.
+    // If there are less than 3 symbols, 1 bucket will be used. If
+    // there are less than 17 symbols, 3 buckets will be used, and so
+    // forth. The bucket numbers are defined by GNU ld. We use the
+    // same rules here so we generate hash sections with the same
+    // size as those generated by GNU ld.
+    uint32_t hashBuckets[] = { 1, 3, 17, 37, 67, 97, 131, 197, 263, 521, 1031,
+                               2053, 4099, 8209, 16411, 32771, 65537, 131101,
+                               262147 };
+    int hashBucketsCount = sizeof(hashBuckets) / sizeof(uint32_t);
+
+    unsigned int bucketsCount = 0;
+    unsigned int dynSymCount = _entries.size();
+
+    // Get the number of buckes that we want to use
+    for (int i = 0; i < hashBucketsCount; ++i) {
+      if (dynSymCount < hashBuckets[i])
+        break;
+      bucketsCount = hashBuckets[i];
+    }
+    _buckets.resize(bucketsCount);
+    _chains.resize(_entries.size());
+
+    // Create the hash table for the dynamic linker
+    for (auto ai : _entries) {
+      unsigned int dynsymIndex = ai._index;
+      unsigned int bucketpos = llvm::object::elf_hash(ai._name) % bucketsCount;
+      _chains[dynsymIndex] = _buckets[bucketpos];
+      _buckets[bucketpos] = dynsymIndex;
+    }
+
+    this->_fsize = (2 + _chains.size() + _buckets.size()) * sizeof(uint32_t);
+    this->_msize = this->_fsize;
+  }
+
+  virtual void finalize() {
+    this->_link = _symbolTable ? _symbolTable->ordinal() : 0;
+    if (this->_parent)
+      this->_parent->setLink(this->_link);
+  }
+
   virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) {
     uint8_t *chunkBuffer = buffer.getBufferStart();
     uint8_t *dest = chunkBuffer + this->fileOffset();
-    // TODO: Calculate hashes and build the hash table in finalize. We currently
-    // just emit an empty hash table so the dynamic loader doesn't crash.
-    std::memset(dest, 0, this->_fsize);
+    uint32_t bucketChainCounts[2];
+    bucketChainCounts[0] = _buckets.size();
+    bucketChainCounts[1] = _chains.size();
+    std::memcpy(dest, (char *)bucketChainCounts, sizeof(bucketChainCounts));
+    dest += sizeof(bucketChainCounts);
+    // write bucket values
+    for (auto bi : _buckets) {
+      uint32_t val = (bi);
+      std::memcpy(dest, &val, sizeof(uint32_t));
+      dest += sizeof(uint32_t);
+    }
+    // write chain values
+    for (auto ci : _chains) {
+      uint32_t val = (ci);
+      std::memcpy(dest, &val, sizeof(uint32_t));
+      dest += sizeof(uint32_t);
+    }
   }
 
 private:
   std::vector<SymbolTableEntry> _entries;
+  std::vector<uint32_t> _buckets;
+  std::vector<uint32_t> _chains;
+  const DynamicSymbolTable<ELFT> *_symbolTable;
 };
 } // end namespace elf
 } // end namespace lld

Modified: lld/trunk/test/elf/Hexagon/dynlib-gotoff.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Hexagon/dynlib-gotoff.test?rev=178323&r1=178322&r2=178323&view=diff
==============================================================================
--- lld/trunk/test/elf/Hexagon/dynlib-gotoff.test (original)
+++ lld/trunk/test/elf/Hexagon/dynlib-gotoff.test Thu Mar 28 19:53:25 2013
@@ -2,10 +2,16 @@ RUN: lld -core -target hexagon %p/Inputs
 RUN: -output=%t -emit-yaml -noinhibit-exec -output-type=shared
 RUN: FileCheck -check-prefix=CHECKGOTPLT %s < %t
 
+              - name:            __got0
+CHECKGOTPLT:    type:            got
+CHECKGOTPLT:    content:         [ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 
+CHECKGOTPLT:                       00, 00, 00, 00 ]
+CHECKGOTPLT:    alignment:       2^3
+CHECKGOTPLT:    section-name:    .got.plt
               - name:            __got_c
 CHECKGOTPLT:    type:            got
 CHECKGOTPLT:    content:         [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-CHECKGOTPLT:    alignment:       2^3
+CHECKGOTPLT:    alignment:       2^2
 CHECKGOTPLT:    section-name:    .got
 CHECKGOTPLT:    permissions:     rw-
 CHECKGOTPLT:    references:      
@@ -15,7 +21,7 @@ CHECKGOTPLT:        target:          c
               - name:            __got_shankar
 CHECKGOTPLT:    type:            got
 CHECKGOTPLT:    content:         [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-CHECKGOTPLT:    alignment:       2^3
+CHECKGOTPLT:    alignment:       2^2
 CHECKGOTPLT:    section-name:    .got
 CHECKGOTPLT:    permissions:     rw-
 CHECKGOTPLT:    references:      

Added: lld/trunk/test/elf/Hexagon/dynlib-hash.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Hexagon/dynlib-hash.test?rev=178323&view=auto
==============================================================================
--- lld/trunk/test/elf/Hexagon/dynlib-hash.test (added)
+++ lld/trunk/test/elf/Hexagon/dynlib-hash.test Thu Mar 28 19:53:25 2013
@@ -0,0 +1,9 @@
+RUN: lld -core -target hexagon %p/Inputs/dynobj.o \
+RUN: -output=%t -output=%t -noinhibit-exec -output-type=shared
+RUN: llvm-objdump -s %t > %t1
+RUN: FileCheck -check-prefix=CHECKHASH %s < %t1
+
+CHECKHASH: Contents of section .hash:
+CHECKHASH: 00b4 03000000 06000000 05000000 01000000  ................
+CHECKHASH: 00c4 04000000 00000000 00000000 00000000  ................
+CHECKHASH: 00d4 00000000 03000000 02000000           ............

Added: lld/trunk/test/elf/Hexagon/dynlib-syms.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Hexagon/dynlib-syms.test?rev=178323&view=auto
==============================================================================
--- lld/trunk/test/elf/Hexagon/dynlib-syms.test (added)
+++ lld/trunk/test/elf/Hexagon/dynlib-syms.test Thu Mar 28 19:53:25 2013
@@ -0,0 +1,8 @@
+RUN: lld -core -target hexagon %p/Inputs/dynobj.o \
+RUN: -output=%t -output=%t -noinhibit-exec -output-type=shared
+RUN: llvm-nm -n -s %t > %t1
+RUN: FileCheck -check-prefix=CHECKSYMS %s < %t1
+
+CHECKSYMS: 00000288 A _DYNAMIC
+CHECKSYMS: 00001010 A _GLOBAL_OFFSET_TABLE_
+CHECKSYMS: 00002000 A _SDA_BASE_

Modified: lld/trunk/test/elf/dynamic.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/dynamic.test?rev=178323&r1=178322&r2=178323&view=diff
==============================================================================
--- lld/trunk/test/elf/dynamic.test (original)
+++ lld/trunk/test/elf/dynamic.test Thu Mar 28 19:53:25 2013
@@ -32,7 +32,7 @@ CHECK:   i FUNC {{[0-9a-f]+}} 0 {{[0-9a-
 CHECK:   Total: 2
 
 CHECK: Sections:
-CHECK:   .hash {{[0-9a-f]+}} 8 4 required,rodata
+CHECK:   .hash {{[0-9a-f]+}} 20 8 required,rodata
 
 CHECK: Dynamic section contains 14 entries
 CHECK:   Tag                Type                 Name/Value





More information about the llvm-commits mailing list