[lld] r273152 - [ELF] - Recommit r273143("[ELF] - Basic versioned symbols support implemented.")

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 20 04:55:13 PDT 2016


Author: grimar
Date: Mon Jun 20 06:55:12 2016
New Revision: 273152

URL: http://llvm.org/viewvc/llvm-project?rev=273152&view=rev
Log:
[ELF] - Recommit r273143("[ELF] - Basic versioned symbols support implemented.")

With fix:
-soname flag was not set in testcase. Hash calculated for base def was different on local
and bot machines because filename fos used for calculating.

Initial commit message:
Patch implements basic support of versioned symbols.
There is no wildcards patterns matching except local: *;
There is no support for hierarchies.
There is no support for symbols overrides (@ vs @@ not handled).

This patch allows programs that using simple scripts to link and run.

Differential revision: http://reviews.llvm.org/D21018

Added:
    lld/trunk/test/ELF/Inputs/verdef.s
      - copied unchanged from r273145, lld/trunk/test/ELF/Inputs/verdef.s
    lld/trunk/test/ELF/lto/version-script.ll
      - copied unchanged from r273145, lld/trunk/test/ELF/lto/version-script.ll
    lld/trunk/test/ELF/verdef.s
      - copied, changed from r273145, lld/trunk/test/ELF/verdef.s
Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/ELF/SymbolListFile.cpp
    lld/trunk/ELF/SymbolListFile.h
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/Symbols.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/ELF/version-script.s

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=273152&r1=273151&r2=273152&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Mon Jun 20 06:55:12 2016
@@ -32,6 +32,15 @@ enum ELFKind {
 
 enum class BuildIdKind { None, Fnv1, Md5, Sha1, Hexstring };
 
+// This struct contains symbols version definition that
+// can be found in version script if it is used for link.
+struct Version {
+  Version(llvm::StringRef Name) : Name(Name) {}
+  llvm::StringRef Name;
+  std::vector<llvm::StringRef> Globals;
+  size_t NameOff; // Offset in string table.
+};
+
 // This struct contains the global configuration for the linker.
 // Most fields are direct mapping from the command line options
 // and such fields have the same name as the corresponding options.
@@ -50,6 +59,7 @@ struct Configuration {
   llvm::StringRef SoName;
   llvm::StringRef Sysroot;
   std::string RPath;
+  std::vector<Version> SymbolVersions;
   std::vector<llvm::StringRef> DynamicList;
   std::vector<llvm::StringRef> SearchPaths;
   std::vector<llvm::StringRef> Undefined;

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=273152&r1=273151&r2=273152&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Mon Jun 20 06:55:12 2016
@@ -591,6 +591,11 @@ void GnuHashTableSection<ELFT>::addSymbo
     V.push_back({Sym.Body, Sym.STName});
 }
 
+// Returns the number of version definition entries. Because the first entry
+// is for the version definition itself, it is the number of versioned symbols
+// plus one. Note that we don't support multiple versions yet.
+static unsigned getVerDefNum() { return Config->SymbolVersions.size() + 1; }
+
 template <class ELFT>
 DynamicSection<ELFT>::DynamicSection()
     : OutputSectionBase<ELFT>(".dynamic", SHT_DYNAMIC, SHF_ALLOC | SHF_WRITE) {
@@ -693,10 +698,16 @@ template <class ELFT> void DynamicSectio
   if (!Config->Entry.empty())
     Add({DT_DEBUG, (uint64_t)0});
 
-  if (size_t NeedNum = Out<ELFT>::VerNeed->getNeedNum()) {
+  bool HasVerNeed = Out<ELFT>::VerNeed->getNeedNum() != 0;
+  if (HasVerNeed || Out<ELFT>::VerDef)
     Add({DT_VERSYM, Out<ELFT>::VerSym});
+  if (Out<ELFT>::VerDef) {
+    Add({DT_VERDEF, Out<ELFT>::VerDef});
+    Add({DT_VERDEFNUM, getVerDefNum()});
+  }
+  if (HasVerNeed) {
     Add({DT_VERNEED, Out<ELFT>::VerNeed});
-    Add({DT_VERNEEDNUM, NeedNum});
+    Add({DT_VERNEEDNUM, Out<ELFT>::VerNeed->getNeedNum()});
   }
 
   if (Config->EMachine == EM_MIPS) {
@@ -1435,6 +1446,68 @@ SymbolTableSection<ELFT>::getOutputSecti
 }
 
 template <class ELFT>
+VersionDefinitionSection<ELFT>::VersionDefinitionSection()
+    : OutputSectionBase<ELFT>(".gnu.version_d", SHT_GNU_verdef, SHF_ALLOC) {}
+
+static StringRef getFileDefName() {
+  if (!Config->SoName.empty())
+    return Config->SoName;
+  return Config->OutputFile;
+}
+
+template <class ELFT> void VersionDefinitionSection<ELFT>::finalize() {
+  FileDefNameOff = Out<ELFT>::DynStrTab->addString(getFileDefName());
+  for (Version &V : Config->SymbolVersions)
+    V.NameOff = Out<ELFT>::DynStrTab->addString(V.Name);
+
+  this->Header.sh_size =
+      (sizeof(Elf_Verdef) + sizeof(Elf_Verdaux)) * getVerDefNum();
+  this->Header.sh_link = Out<ELFT>::DynStrTab->SectionIndex;
+  this->Header.sh_addralign = sizeof(uint32_t);
+
+  // sh_info should be set to the number of definitions. This fact is missed in
+  // documentation, but confirmed by binutils community:
+  // https://sourceware.org/ml/binutils/2014-11/msg00355.html
+  this->Header.sh_info = getVerDefNum();
+}
+
+template <class Elf_Verdef, class Elf_Verdaux>
+static void writeDefinition(Elf_Verdef *&Verdef, Elf_Verdaux *&Verdaux,
+                            uint32_t Flags, uint32_t Index, StringRef Name,
+                            size_t StrTabOffset) {
+  Verdef->vd_version = 1;
+  Verdef->vd_cnt = 1;
+  Verdef->vd_aux =
+      reinterpret_cast<char *>(Verdaux) - reinterpret_cast<char *>(Verdef);
+  Verdef->vd_next = sizeof(Elf_Verdef);
+
+  Verdef->vd_flags = Flags;
+  Verdef->vd_ndx = Index;
+  Verdef->vd_hash = hashSysv(Name);
+  ++Verdef;
+
+  Verdaux->vda_name = StrTabOffset;
+  Verdaux->vda_next = 0;
+  ++Verdaux;
+}
+
+template <class ELFT>
+void VersionDefinitionSection<ELFT>::writeTo(uint8_t *Buf) {
+  Elf_Verdef *Verdef = reinterpret_cast<Elf_Verdef *>(Buf);
+  Elf_Verdaux *Verdaux =
+      reinterpret_cast<Elf_Verdaux *>(Verdef + getVerDefNum());
+
+  writeDefinition(Verdef, Verdaux, VER_FLG_BASE, 1, getFileDefName(),
+                  FileDefNameOff);
+
+  uint32_t I = 2;
+  for (Version &V : Config->SymbolVersions)
+    writeDefinition(Verdef, Verdaux, 0 /* Flags */, I++, V.Name, V.NameOff);
+
+  Verdef[-1].vd_next = 0;
+}
+
+template <class ELFT>
 VersionTableSection<ELFT>::VersionTableSection()
     : OutputSectionBase<ELFT>(".gnu.version", SHT_GNU_versym, SHF_ALLOC) {
   this->Header.sh_addralign = sizeof(uint16_t);
@@ -1453,10 +1526,7 @@ template <class ELFT> void VersionTableS
   auto *OutVersym = reinterpret_cast<Elf_Versym *>(Buf) + 1;
   for (const std::pair<SymbolBody *, size_t> &P :
        Out<ELFT>::DynSymTab->getSymbols()) {
-    if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(P.first))
-      OutVersym->vs_index = SS->VersionId;
-    else
-      OutVersym->vs_index = VER_NDX_GLOBAL;
+    OutVersym->vs_index = P.first->symbol()->VersionId;
     ++OutVersym;
   }
 }
@@ -1465,12 +1535,17 @@ template <class ELFT>
 VersionNeedSection<ELFT>::VersionNeedSection()
     : OutputSectionBase<ELFT>(".gnu.version_r", SHT_GNU_verneed, SHF_ALLOC) {
   this->Header.sh_addralign = sizeof(uint32_t);
+
+  // Identifiers in verneed section start at 2 because 0 and 1 are reserved
+  // for VER_NDX_LOCAL and VER_NDX_GLOBAL.
+  // First identifiers are reserved by verdef section if it exist.
+  NextIndex = getVerDefNum() + 1;
 }
 
 template <class ELFT>
 void VersionNeedSection<ELFT>::addSymbol(SharedSymbol<ELFT> *SS) {
   if (!SS->Verdef) {
-    SS->VersionId = VER_NDX_GLOBAL;
+    SS->symbol()->VersionId = VER_NDX_GLOBAL;
     return;
   }
   SharedFile<ELFT> *F = SS->File;
@@ -1488,7 +1563,7 @@ void VersionNeedSection<ELFT>::addSymbol
         SS->File->getStringTable().data() + SS->Verdef->getAux()->vda_name);
     NV.Index = NextIndex++;
   }
-  SS->VersionId = NV.Index;
+  SS->symbol()->VersionId = NV.Index;
 }
 
 template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) {
@@ -1744,6 +1819,11 @@ template class VersionNeedSection<ELF32B
 template class VersionNeedSection<ELF64LE>;
 template class VersionNeedSection<ELF64BE>;
 
+template class VersionDefinitionSection<ELF32LE>;
+template class VersionDefinitionSection<ELF32BE>;
+template class VersionDefinitionSection<ELF64LE>;
+template class VersionDefinitionSection<ELF64BE>;
+
 template class BuildIdSection<ELF32LE>;
 template class BuildIdSection<ELF32BE>;
 template class BuildIdSection<ELF64LE>;

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=273152&r1=273151&r2=273152&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Mon Jun 20 06:55:12 2016
@@ -25,6 +25,7 @@ namespace elf {
 
 class SymbolBody;
 struct SectionPiece;
+struct Version;
 template <class ELFT> class SymbolTable;
 template <class ELFT> class SymbolTableSection;
 template <class ELFT> class StringTableSection;
@@ -248,10 +249,30 @@ private:
 // For more information about .gnu.version and .gnu.version_r see:
 // https://www.akkadia.org/drepper/symbol-versioning
 
+// The .gnu.version_d section which has a section type of SHT_GNU_verdef shall
+// contain symbol version definitions. The number of entries in this section
+// shall be contained in the DT_VERDEFNUM entry of the .dynamic section.
+// The section shall contain an array of Elf_Verdef structures, optionally
+// followed by an array of Elf_Verdaux structures.
+template <class ELFT>
+class VersionDefinitionSection final : public OutputSectionBase<ELFT> {
+  typedef typename ELFT::Verdef Elf_Verdef;
+  typedef typename ELFT::Verdaux Elf_Verdaux;
+
+  unsigned FileDefNameOff;
+
+public:
+  VersionDefinitionSection();
+  void finalize() override;
+  void writeTo(uint8_t *Buf) override;
+};
+
 // The .gnu.version section specifies the required version of each symbol in the
 // dynamic symbol table. It contains one Elf_Versym for each dynamic symbol
 // table entry. An Elf_Versym is just a 16-bit integer that refers to a version
-// identifier defined in the .gnu.version_r section.
+// identifier defined in the either .gnu.version_r or .gnu.version_d section.
+// The values 0 and 1 are reserved. All other values are used for versions in
+// the own object or in any of the dependencies.
 template <class ELFT>
 class VersionTableSection final : public OutputSectionBase<ELFT> {
   typedef typename ELFT::Versym Elf_Versym;
@@ -276,9 +297,8 @@ class VersionNeedSection final : public
   // string table offsets of their sonames.
   std::vector<std::pair<SharedFile<ELFT> *, size_t>> Needed;
 
-  // The next available version identifier. Identifiers start at 2 because 0 and
-  // 1 are reserved.
-  unsigned NextIndex = 2;
+  // The next available version identifier.
+  unsigned NextIndex;
 
 public:
   VersionNeedSection();
@@ -630,6 +650,7 @@ template <class ELFT> struct Out {
   static StringTableSection<ELFT> *StrTab;
   static SymbolTableSection<ELFT> *DynSymTab;
   static SymbolTableSection<ELFT> *SymTab;
+  static VersionDefinitionSection<ELFT> *VerDef;
   static VersionTableSection<ELFT> *VerSym;
   static VersionNeedSection<ELFT> *VerNeed;
   static Elf_Phdr *TlsPhdr;
@@ -658,6 +679,7 @@ template <class ELFT> StringTableSection
 template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::StrTab;
 template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::DynSymTab;
 template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::SymTab;
+template <class ELFT> VersionDefinitionSection<ELFT> *Out<ELFT>::VerDef;
 template <class ELFT> VersionTableSection<ELFT> *Out<ELFT>::VerSym;
 template <class ELFT> VersionNeedSection<ELFT> *Out<ELFT>::VerNeed;
 template <class ELFT> typename ELFT::Phdr *Out<ELFT>::TlsPhdr;

Modified: lld/trunk/ELF/SymbolListFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolListFile.cpp?rev=273152&r1=273151&r2=273152&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolListFile.cpp (original)
+++ lld/trunk/ELF/SymbolListFile.cpp Mon Jun 20 06:55:12 2016
@@ -77,21 +77,21 @@ public:
   void run();
 
 private:
-  void parseVersion();
+  void parseVersion(StringRef Version);
   void parseLocal();
-  void parseVersionSymbols();
+  void parseVersionSymbols(StringRef Version);
 };
 
-void VersionScriptParser::parseVersion() {
+void VersionScriptParser::parseVersion(StringRef Version) {
   expect("{");
   if (peek() == "global:") {
     next();
-    parseVersionSymbols();
+    parseVersionSymbols(Version);
   }
   if (peek() == "local:")
     parseLocal();
   else
-    parseVersionSymbols();
+    parseVersionSymbols(Version);
 
   expect("}");
   expect(";");
@@ -104,13 +104,21 @@ void VersionScriptParser::parseLocal() {
   Config->VersionScriptGlobalByDefault = false;
 }
 
-void VersionScriptParser::parseVersionSymbols() {
+void VersionScriptParser::parseVersionSymbols(StringRef Version) {
+  std::vector<StringRef> *Globals;
+  if (Version.empty()) {
+    Globals = &Config->VersionScriptGlobals;
+  } else {
+    Config->SymbolVersions.push_back(elf::Version(Version));
+    Globals = &Config->SymbolVersions.back().Globals;
+  }
+
   for (;;) {
     StringRef Cur = peek();
     if (Cur == "}" || Cur == "local:")
       return;
     next();
-    Config->VersionScriptGlobals.push_back(Cur);
+    Globals->push_back(Cur);
     expect(";");
   }
 }
@@ -119,18 +127,18 @@ void VersionScriptParser::run() {
   StringRef Msg = "anonymous version definition is used in "
                   "combination with other version definitions";
   if (peek() == "{") {
-    parseVersion();
+    parseVersion("");
     if (!atEOF())
       setError(Msg);
     return;
   }
 
   while (!atEOF() && !Error) {
-    if (next() == "{") {
+    if (peek() == "{") {
       setError(Msg);
       return;
     }
-    parseVersion();
+    parseVersion(next());
   }
 }
 

Modified: lld/trunk/ELF/SymbolListFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolListFile.h?rev=273152&r1=273151&r2=273152&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolListFile.h (original)
+++ lld/trunk/ELF/SymbolListFile.h Mon Jun 20 06:55:12 2016
@@ -11,6 +11,7 @@
 #define LLD_ELF_SYMBOL_LIST_FILE_H
 
 #include "lld/Core/LLVM.h"
+#include "llvm/ADT/MapVector.h"
 #include "llvm/Support/MemoryBuffer.h"
 
 namespace lld {

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=273152&r1=273151&r2=273152&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Mon Jun 20 06:55:12 2016
@@ -175,7 +175,10 @@ std::pair<Symbol *, bool> SymbolTable<EL
     Sym->Visibility = STV_DEFAULT;
     Sym->IsUsedInRegularObj = false;
     Sym->ExportDynamic = false;
-    Sym->VersionScriptGlobal = Config->VersionScriptGlobalByDefault;
+    if (Config->VersionScriptGlobalByDefault)
+      Sym->VersionId = VER_NDX_GLOBAL;
+    else
+      Sym->VersionId = VER_NDX_LOCAL;
     SymVector.push_back(Sym);
   } else {
     Sym = SymVector[P.first->second];
@@ -514,9 +517,24 @@ template <class ELFT> void SymbolTable<E
 // symbols with the VersionScriptGlobal flag, which acts as a filter on the
 // dynamic symbol table.
 template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() {
-  for (StringRef S : Config->VersionScriptGlobals)
-    if (SymbolBody *B = find(S))
-      B->symbol()->VersionScriptGlobal = true;
+  // If version script does not contain versions declarations,
+  // we just should mark global symbols.
+  if (!Config->VersionScriptGlobals.empty()) {
+    for (StringRef S : Config->VersionScriptGlobals)
+      if (SymbolBody *B = find(S))
+        B->symbol()->VersionId = VER_NDX_GLOBAL;
+    return;
+  }
+
+  // If we have symbols version declarations, we should
+  // assign version references for each symbol.
+  size_t I = 2;
+  for (Version &V : Config->SymbolVersions) {
+    for (StringRef Name : V.Globals)
+      if (SymbolBody *B = find(Name))
+        B->symbol()->VersionId = I;
+    ++I;
+  }
 }
 
 template class elf::SymbolTable<ELF32LE>;

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=273152&r1=273151&r2=273152&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Mon Jun 20 06:55:12 2016
@@ -267,7 +267,7 @@ std::string elf::demangle(StringRef Name
 bool Symbol::includeInDynsym() const {
   if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
     return false;
-  return (ExportDynamic && VersionScriptGlobal) || body()->isShared() ||
+  return (ExportDynamic && VersionId != VER_NDX_LOCAL) || body()->isShared() ||
          (body()->isUndefined() && Config->Shared);
 }
 

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=273152&r1=273151&r2=273152&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Mon Jun 20 06:55:12 2016
@@ -30,6 +30,7 @@ class BitcodeFile;
 class InputFile;
 class LazyObjectFile;
 class SymbolBody;
+struct Version;
 template <class ELFT> class ObjectFile;
 template <class ELFT> class OutputSection;
 template <class ELFT> class OutputSectionBase;
@@ -302,13 +303,8 @@ public:
   SharedFile<ELFT> *File;
   const Elf_Sym &Sym;
 
-  // This field is initially a pointer to the symbol's version definition. As
-  // symbols are added to the version table, this field is replaced with the
-  // version identifier to be stored in .gnu.version in the output file.
-  union {
-    const Elf_Verdef *Verdef;
-    uint16_t VersionId;
-  };
+  // This field is a pointer to the symbol's version definition.
+  const Elf_Verdef *Verdef;
 
   // OffsetInBss is significant only when needsCopy() is true.
   uintX_t OffsetInBss = 0;
@@ -407,6 +403,9 @@ struct Symbol {
   // it is weak.
   uint8_t Binding;
 
+  // Version definition index.
+  uint16_t VersionId;
+
   // Symbol visibility. This is the computed minimum visibility of all
   // observed non-DSO symbols.
   unsigned Visibility : 2;
@@ -423,11 +422,6 @@ struct Symbol {
   // --export-dynamic, and by dynamic lists.
   unsigned ExportDynamic : 1;
 
-  // This flag acts as an additional filter on the dynamic symbol list. It is
-  // set if there is no version script, or if the symbol appears in the global
-  // section of the version script.
-  unsigned VersionScriptGlobal : 1;
-
   bool includeInDynsym() const;
   bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; }
 

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=273152&r1=273151&r2=273152&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Jun 20 06:55:12 2016
@@ -136,6 +136,7 @@ template <class ELFT> void elf::writeRes
   std::unique_ptr<StringTableSection<ELFT>> StrTab;
   std::unique_ptr<SymbolTableSection<ELFT>> SymTabSec;
   std::unique_ptr<OutputSection<ELFT>> MipsRldMap;
+  std::unique_ptr<VersionDefinitionSection<ELFT>> VerDef;
 
   if (Config->BuildId == BuildIdKind::Fnv1)
     BuildId.reset(new BuildIdFnv1<ELFT>);
@@ -170,6 +171,8 @@ template <class ELFT> void elf::writeRes
     MipsRldMap->setSize(sizeof(uintX_t));
     MipsRldMap->updateAlignment(sizeof(uintX_t));
   }
+  if (!Config->SymbolVersions.empty())
+    VerDef.reset(new VersionDefinitionSection<ELFT>());
 
   Out<ELFT>::Bss = &Bss;
   Out<ELFT>::BuildId = BuildId.get();
@@ -189,6 +192,7 @@ template <class ELFT> void elf::writeRes
   Out<ELFT>::ShStrTab = &ShStrTab;
   Out<ELFT>::StrTab = StrTab.get();
   Out<ELFT>::SymTab = SymTabSec.get();
+  Out<ELFT>::VerDef = VerDef.get();
   Out<ELFT>::VerSym = &VerSym;
   Out<ELFT>::VerNeed = &VerNeed;
   Out<ELFT>::MipsRldMap = MipsRldMap.get();
@@ -904,10 +908,15 @@ template <class ELFT> void Writer<ELFT>:
   Add(Out<ELFT>::StrTab);
   if (isOutputDynamic()) {
     Add(Out<ELFT>::DynSymTab);
-    if (Out<ELFT>::VerNeed->getNeedNum() != 0) {
+
+    bool HasVerNeed = Out<ELFT>::VerNeed->getNeedNum() != 0;
+    if (Out<ELFT>::VerDef || HasVerNeed)
       Add(Out<ELFT>::VerSym);
+    if (Out<ELFT>::VerDef)
+      Add(Out<ELFT>::VerDef);
+    if (HasVerNeed)
       Add(Out<ELFT>::VerNeed);
-    }
+
     Add(Out<ELFT>::GnuHashTab);
     Add(Out<ELFT>::HashTab);
     Add(Out<ELFT>::Dynamic);

Copied: lld/trunk/test/ELF/verdef.s (from r273145, lld/trunk/test/ELF/verdef.s)
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/verdef.s?p2=lld/trunk/test/ELF/verdef.s&p1=lld/trunk/test/ELF/verdef.s&r1=273145&r2=273152&rev=273152&view=diff
==============================================================================
--- lld/trunk/test/ELF/verdef.s (original)
+++ lld/trunk/test/ELF/verdef.s Mon Jun 20 06:55:12 2016
@@ -9,7 +9,7 @@
 # RUN:       LIBSAMPLE_3.0{  \
 # RUN:          global: c;   \
 # RUN:          local: *; };" > %t.script
-# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
+# RUN: ld.lld --version-script %t.script -shared -soname shared %t.o -o %t.so
 # RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s
 
 # DSO:        Version symbols {
@@ -48,7 +48,7 @@
 # DSO-NEXT:       Flags: 1
 # DSO-NEXT:       Index: 1
 # DSO-NEXT:       Cnt: 1
-# DSO-NEXT:       Hash: 146942095
+# DSO-NEXT:       Hash: 127830196
 # DSO-NEXT:       Name:
 # DSO-NEXT:     }
 # DSO-NEXT:     Entry {

Modified: lld/trunk/test/ELF/version-script.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/version-script.s?rev=273152&r1=273151&r2=273152&view=diff
==============================================================================
--- lld/trunk/test/ELF/version-script.s (original)
+++ lld/trunk/test/ELF/version-script.s Mon Jun 20 06:55:12 2016
@@ -26,7 +26,7 @@
 # RUN:          global: foo3;  \
 # RUN:          local: *; }; " > %t4.script
 # RUN: ld.lld --version-script %t4.script -shared %t.o %t2.so -o %t4.so
-# RUN: llvm-readobj -dyn-symbols %t4.so | FileCheck --check-prefix=DSO %s
+# RUN: llvm-readobj -dyn-symbols %t4.so | FileCheck --check-prefix=VERDSO %s
 
 # RUN: echo "VERSION_1.0{     \
 # RUN:          global: foo1; \
@@ -140,6 +140,44 @@
 # EXE-NEXT:   }
 # EXE-NEXT: ]
 
+# VERDSO:      DynamicSymbols [
+# VERDSO-NEXT:   Symbol {
+# VERDSO-NEXT:     Name: @
+# VERDSO-NEXT:     Value: 0x0
+# VERDSO-NEXT:     Size: 0
+# VERDSO-NEXT:     Binding: Local
+# VERDSO-NEXT:     Type: None
+# VERDSO-NEXT:     Other: 0
+# VERDSO-NEXT:     Section: Undefined
+# VERDSO-NEXT:   }
+# VERDSO-NEXT:   Symbol {
+# VERDSO-NEXT:     Name: bar@
+# VERDSO-NEXT:     Value: 0x0
+# VERDSO-NEXT:     Size: 0
+# VERDSO-NEXT:     Binding: Global
+# VERDSO-NEXT:     Type: Function
+# VERDSO-NEXT:     Other: 0
+# VERDSO-NEXT:     Section: Undefined
+# VERDSO-NEXT:   }
+# VERDSO-NEXT:   Symbol {
+# VERDSO-NEXT:     Name: foo1@@VERSION_1.0
+# VERDSO-NEXT:     Value: 0x1000
+# VERDSO-NEXT:     Size: 0
+# VERDSO-NEXT:     Binding: Global
+# VERDSO-NEXT:     Type: None
+# VERDSO-NEXT:     Other: 0
+# VERDSO-NEXT:     Section: .text
+# VERDSO-NEXT:   }
+# VERDSO-NEXT:   Symbol {
+# VERDSO-NEXT:     Name: foo3@@VERSION_2.0
+# VERDSO-NEXT:     Value: 0x1007
+# VERDSO-NEXT:     Size: 0
+# VERDSO-NEXT:     Binding: Global
+# VERDSO-NEXT:     Type: None
+# VERDSO-NEXT:     Other: 0
+# VERDSO-NEXT:     Section: .text
+# VERDSO-NEXT:   }
+# VERDSO-NEXT: ]
 
 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
 # RUN: ld.lld -shared %t.o %t2.so -o %t.so




More information about the llvm-commits mailing list