[lld] r287741 - Parse symbol versions in scanVersionScript() instead of insert().

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 22 21:48:40 PST 2016


Author: ruiu
Date: Tue Nov 22 23:48:40 2016
New Revision: 287741

URL: http://llvm.org/viewvc/llvm-project?rev=287741&view=rev
Log:
Parse symbol versions in scanVersionScript() instead of insert().

There are two ways to set symbol versions. One way is to use symbol
definition file, and the other is to embed version names to symbol
names. In the latter way, symbol name is in the form of `foo at version1`
where `foo` is a real name and `version1` is a version.

We were parsing symbol names in insert(). That seems unnecessarily
too early. We can do it later after we resolve all symbols. Doing it
lazily is a good thing because it makes code easier to read
(because now we have a separate pass to parse symbol names). Also
it could slightly improve performance because if two identical symbols
have versions, we now parse them only once.

Modified:
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/SymbolTable.h
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/Symbols.h

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=287741&r1=287740&r2=287741&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Tue Nov 22 23:48:40 2016
@@ -174,39 +174,9 @@ static uint8_t getMinVisibility(uint8_t
   return std::min(VA, VB);
 }
 
-// Parses a symbol in the form of <name>@<version> or <name>@@<version>.
-static std::pair<StringRef, uint16_t> getSymbolVersion(StringRef S) {
-  if (Config->VersionDefinitions.empty())
-    return {S, Config->DefaultSymbolVersion};
-
-  size_t Pos = S.find('@');
-  if (Pos == 0 || Pos == StringRef::npos)
-    return {S, Config->DefaultSymbolVersion};
-
-  StringRef Name = S.substr(0, Pos);
-  StringRef Verstr = S.substr(Pos + 1);
-  if (Verstr.empty())
-    return {S, Config->DefaultSymbolVersion};
-
-  // '@@' in a symbol name means the default version.
-  // It is usually the most recent one.
-  bool IsDefault = (Verstr[0] == '@');
-  if (IsDefault)
-    Verstr = Verstr.substr(1);
-
-  for (VersionDefinition &V : Config->VersionDefinitions) {
-    if (V.Name == Verstr)
-      return {Name, IsDefault ? V.Id : (V.Id | VERSYM_HIDDEN)};
-  }
-
-  // It is an error if the specified version was not defined.
-  error("symbol " + S + " has undefined version " + Verstr);
-  return {S, Config->DefaultSymbolVersion};
-}
-
 // Find an existing symbol or create and insert a new one.
 template <class ELFT>
-std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef &Name) {
+std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) {
   auto P = Symtab.insert(
       {CachedHashStringRef(Name), SymIndex((int)SymVector.size(), false)});
   SymIndex &V = P.first->second;
@@ -225,7 +195,7 @@ std::pair<Symbol *, bool> SymbolTable<EL
     Sym->IsUsedInRegularObj = false;
     Sym->ExportDynamic = false;
     Sym->Traced = V.Traced;
-    std::tie(Name, Sym->VersionId) = getSymbolVersion(Name);
+    Sym->VersionId = Config->DefaultSymbolVersion;
     SymVector.push_back(Sym);
   } else {
     Sym = SymVector[V.Idx];
@@ -244,7 +214,7 @@ static std::string conflictMsg(SymbolBod
 // attributes.
 template <class ELFT>
 std::pair<Symbol *, bool>
-SymbolTable<ELFT>::insert(StringRef &Name, uint8_t Type, uint8_t Visibility,
+SymbolTable<ELFT>::insert(StringRef Name, uint8_t Type, uint8_t Visibility,
                           bool CanOmitFromDynSym, InputFile *File) {
   bool IsUsedInRegularObj = !File || File->kind() == InputFile::ObjectKind;
   Symbol *S;
@@ -696,6 +666,13 @@ void SymbolTable<ELFT>::assignWildcardVe
 // This function processes version scripts by updating VersionId
 // member of symbols.
 template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() {
+  // Symbol themselves might know their versions because symbols
+  // can contain versions in the form of <name>@<version>.
+  // Let them parse their names.
+  if (!Config->VersionDefinitions.empty())
+    for (Symbol *Sym : SymVector)
+      Sym->body()->parseSymbolVersion();
+
   // Handle edge cases first.
   if (!Config->VersionScriptGlobals.empty()) {
     handleAnonymousVersion();

Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=287741&r1=287740&r2=287741&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Tue Nov 22 23:48:40 2016
@@ -93,8 +93,8 @@ public:
 
 private:
   std::vector<SymbolBody *> findAll(StringRef GlobPat);
-  std::pair<Symbol *, bool> insert(StringRef &Name);
-  std::pair<Symbol *, bool> insert(StringRef &Name, uint8_t Type,
+  std::pair<Symbol *, bool> insert(StringRef Name);
+  std::pair<Symbol *, bool> insert(StringRef Name, uint8_t Type,
                                    uint8_t Visibility, bool CanOmitFromDynSym,
                                    InputFile *File);
 

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=287741&r1=287740&r2=287741&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Tue Nov 22 23:48:40 2016
@@ -190,6 +190,41 @@ template <class ELFT> typename ELFT::uin
   return 0;
 }
 
+// If a symbol name contains '@', the characters after that is
+// a symbol version name. This function parses that.
+void SymbolBody::parseSymbolVersion() {
+  StringRef S = getName();
+  size_t Pos = S.find('@');
+  if (Pos == 0 || Pos == StringRef::npos)
+    return;
+  StringRef Verstr = S.substr(Pos + 1);
+  if (Verstr.empty())
+    return;
+
+  // Truncate the symbol name so that it doesn't include the version string.
+  NameLen = Pos;
+
+  // '@@' in a symbol name means the default version.
+  // It is usually the most recent one.
+  bool IsDefault = (Verstr[0] == '@');
+  if (IsDefault)
+    Verstr = Verstr.substr(1);
+
+  for (VersionDefinition &Ver : Config->VersionDefinitions) {
+    if (Ver.Name != Verstr)
+      continue;
+
+    if (IsDefault)
+      symbol()->VersionId = Ver.Id;
+    else
+      symbol()->VersionId = Ver.Id | VERSYM_HIDDEN;
+    return;
+  }
+
+  // It is an error if the specified version is not defined.
+  error("symbol " + S + " has undefined version " + Verstr);
+}
+
 Defined::Defined(Kind K, StringRef Name, uint8_t StOther, uint8_t Type)
     : SymbolBody(K, Name, StOther, Type) {}
 

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=287741&r1=287740&r2=287741&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Tue Nov 22 23:48:40 2016
@@ -69,10 +69,9 @@ public:
   bool isShared() const { return SymbolKind == SharedKind; }
   bool isLocal() const { return IsLocal; }
   bool isPreemptible() const;
-
   StringRef getName() const;
-
   uint8_t getVisibility() const { return StOther & 0x3; }
+  void parseSymbolVersion();
 
   bool isInGot() const { return GotIndex != -1U; }
   bool isInPlt() const { return PltIndex != -1U; }




More information about the llvm-commits mailing list