[lld] r308492 - Bring back r307364.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 19 09:45:05 PDT 2017


Author: rafael
Date: Wed Jul 19 09:45:05 2017
New Revision: 308492

URL: http://llvm.org/viewvc/llvm-project?rev=308492&view=rev
Log:
Bring back r307364.

In addition this includes a change to prefer symbols with a default
version @@ over unversioned symbols.

Original commit message:

[ELF] - Handle symbols with default version early.

This fixes last testcase provided in PR28414.
In short issue is next: when we had X@@Version symbol in object A,
we did not resolve it to X early. Then when in another object B
we had reference to undefined X, symbol X from archive was fetched.
Since both archive and object A contains another symbol Z, duplicate
symbol definition was triggered as a result.

Correct behavior is to use X@@Version from object A instead and do not fetch
any symbols from archive.

Differential revision: https://reviews.llvm.org/D35059

Added:
    lld/trunk/test/ELF/Inputs/symver-archive1.s
    lld/trunk/test/ELF/Inputs/symver-archive2.s
    lld/trunk/test/ELF/symver-archive.s
Modified:
    lld/trunk/ELF/SymbolTable.cpp

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=308492&r1=308491&r2=308492&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Wed Jul 19 09:45:05 2017
@@ -211,6 +211,12 @@ static uint8_t getMinVisibility(uint8_t
 // Find an existing symbol or create and insert a new one.
 template <class ELFT>
 std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) {
+  // <name>@@<version> means the symbol is the default version. In that
+  // case <name>@@<version> will be used to resolve references to <name>.
+  size_t Pos = Name.find("@@");
+  if (Pos != StringRef::npos)
+    Name = Name.take_front(Pos);
+
   auto P = Symtab.insert(
       {CachedHashStringRef(Name), SymIndex((int)SymVector.size(), false)});
   SymIndex &V = P.first->second;
@@ -312,15 +318,36 @@ Symbol *SymbolTable<ELFT>::addUndefined(
   return S;
 }
 
+// Using .symver foo,foo@@VER unfortunately creates two symbols: foo and
+// foo@@VER. We want to effectively ignore foo, so give precedence to
+// foo@@VER.
+// FIXME: If users can transition to using
+// .symver foo,foo@@@VER
+// we can delete this hack.
+static int compareVersion(Symbol *S, StringRef Name) {
+  if (Name.find("@@") != StringRef::npos &&
+      S->body()->getName().find("@@") == StringRef::npos)
+    return 1;
+  if (Name.find("@@") == StringRef::npos &&
+      S->body()->getName().find("@@") != StringRef::npos)
+    return -1;
+  return 0;
+}
+
 // We have a new defined symbol with the specified binding. Return 1 if the new
 // symbol should win, -1 if the new symbol should lose, or 0 if both symbols are
 // strong defined symbols.
-static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) {
+static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding,
+                          StringRef Name) {
   if (WasInserted)
     return 1;
   SymbolBody *Body = S->body();
   if (!Body->isInCurrentDSO())
     return 1;
+
+  if (int R = compareVersion(S, Name))
+    return R;
+
   if (Binding == STB_WEAK)
     return -1;
   if (S->isWeak())
@@ -333,8 +360,9 @@ static int compareDefined(Symbol *S, boo
 // is a conflict. If the new symbol wins, also update the binding.
 template <typename ELFT>
 static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding,
-                                   bool IsAbsolute, typename ELFT::uint Value) {
-  if (int Cmp = compareDefined(S, WasInserted, Binding)) {
+                                   bool IsAbsolute, typename ELFT::uint Value,
+                                   StringRef Name) {
+  if (int Cmp = compareDefined(S, WasInserted, Binding, Name)) {
     if (Cmp > 0)
       S->Binding = Binding;
     return Cmp;
@@ -362,7 +390,7 @@ Symbol *SymbolTable<ELFT>::addCommon(Str
   bool WasInserted;
   std::tie(S, WasInserted) = insert(N, Type, getVisibility(StOther),
                                     /*CanOmitFromDynSym*/ false, File);
-  int Cmp = compareDefined(S, WasInserted, Binding);
+  int Cmp = compareDefined(S, WasInserted, Binding, N);
   if (Cmp > 0) {
     S->Binding = Binding;
     replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File);
@@ -439,7 +467,7 @@ Symbol *SymbolTable<ELFT>::addRegular(St
   std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther),
                                     /*CanOmitFromDynSym*/ false, File);
   int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, Binding,
-                                          Section == nullptr, Value);
+                                          Section == nullptr, Value, Name);
   if (Cmp > 0)
     replaceBody<DefinedRegular>(S, Name, /*IsLocal=*/false, StOther, Type,
                                 Value, Size, Section, File);
@@ -485,7 +513,7 @@ Symbol *SymbolTable<ELFT>::addBitcode(St
   std::tie(S, WasInserted) =
       insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, F);
   int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, Binding,
-                                          /*IsAbs*/ false, /*Value*/ 0);
+                                          /*IsAbs*/ false, /*Value*/ 0, Name);
   if (Cmp > 0)
     replaceBody<DefinedRegular>(S, Name, /*IsLocal=*/false, StOther, Type, 0, 0,
                                 nullptr, F);
@@ -717,32 +745,9 @@ void SymbolTable<ELFT>::assignWildcardVe
       B->symbol()->VersionId = VersionId;
 }
 
-static bool isDefaultVersion(SymbolBody *B) {
-  return B->isInCurrentDSO() && B->getName().find("@@") != StringRef::npos;
-}
-
 // 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 and update their names to exclude version suffix.
-  for (Symbol *Sym : SymVector) {
-    SymbolBody *Body = Sym->body();
-    bool IsDefault = isDefaultVersion(Body);
-    Body->parseSymbolVersion();
-
-    if (!IsDefault)
-      continue;
-
-    // <name>@@<version> means the symbol is the default version. If that's the
-    // case, the symbol is not used only to resolve <name> of version <version>
-    // but also undefined unversioned symbols with name <name>.
-    SymbolBody *S = find(Body->getName());
-    if (S && S->isUndefined())
-      S->copy(Body);
-  }
-
   // Handle edge cases first.
   handleAnonymousVersion();
 

Added: lld/trunk/test/ELF/Inputs/symver-archive1.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/symver-archive1.s?rev=308492&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/symver-archive1.s (added)
+++ lld/trunk/test/ELF/Inputs/symver-archive1.s Wed Jul 19 09:45:05 2017
@@ -0,0 +1,6 @@
+.text
+.globl x
+.type x, @function
+x:
+
+.symver x, xx@@VER

Added: lld/trunk/test/ELF/Inputs/symver-archive2.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/symver-archive2.s?rev=308492&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/symver-archive2.s (added)
+++ lld/trunk/test/ELF/Inputs/symver-archive2.s Wed Jul 19 09:45:05 2017
@@ -0,0 +1 @@
+call xx at PLT

Added: lld/trunk/test/ELF/symver-archive.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/symver-archive.s?rev=308492&view=auto
==============================================================================
--- lld/trunk/test/ELF/symver-archive.s (added)
+++ lld/trunk/test/ELF/symver-archive.s Wed Jul 19 09:45:05 2017
@@ -0,0 +1,15 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1
+# RUN: rm -f %t.a
+# RUN: llvm-ar rcs %t.a %t1
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/symver-archive1.s -o %t2.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/symver-archive2.s -o %t3.o
+# RUN: ld.lld -o %t.out %t2.o %t3.o %t.a
+
+.text
+.globl x
+.type x, @function
+x:
+
+.globl xx
+xx = x




More information about the llvm-commits mailing list