[lld] r287124 - [ELF] - Added support for extern "c++" local symbols in version script.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 16 09:59:11 PST 2016


Author: grimar
Date: Wed Nov 16 11:59:10 2016
New Revision: 287124

URL: http://llvm.org/viewvc/llvm-project?rev=287124&view=rev
Log:
[ELF] - Added support for extern "c++" local symbols in version script.

Previously we did not support them,
patch implements this functionality

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

Added:
    lld/trunk/test/ELF/version-script-locals-extern.s
Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/test/ELF/version-script-locals.s
    lld/trunk/test/ELF/version-script-noundef.s

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=287124&r1=287123&r2=287124&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Wed Nov 16 11:59:10 2016
@@ -992,6 +992,7 @@ private:
   void readVersionDeclaration(StringRef VerStr);
   void readGlobal(StringRef VerStr);
   void readLocal(StringRef VerStr);
+  void readSymbols(std::vector<SymbolVersion> &V);
 
   ScriptConfiguration &Opt = *ScriptConfig;
   bool IsUnderSysroot;
@@ -1819,6 +1820,20 @@ void ScriptParser::readVersionDeclaratio
   expect(";");
 }
 
+void ScriptParser::readSymbols(std::vector<SymbolVersion> &V) {
+  for (;;) {
+    if (consume("extern"))
+      readVersionExtern(&V);
+
+    StringRef Cur = peek();
+    if (Cur == "}" || Cur == "local:" || Error)
+      return;
+    skip();
+    V.push_back({unquote(Cur), false, hasWildcard(Cur)});
+    expect(";");
+  }
+}
+
 void ScriptParser::readLocal(StringRef VerStr) {
   if (consume("*")) {
     Config->DefaultSymbolVersion = VER_NDX_LOCAL;
@@ -1829,15 +1844,10 @@ void ScriptParser::readLocal(StringRef V
   if (VerStr.empty())
     setError("locals list for anonymous version is not supported");
 
-  std::vector<SymbolVersion> &Locals = Config->VersionDefinitions.back().Locals;
-  while (!Error && peek() != "}") {
-    StringRef Tok = next();
-    Locals.push_back({unquote(Tok), false, hasWildcard(Tok)});
-    expect(";");
-  }
+  readSymbols(Config->VersionDefinitions.back().Locals);
 }
 
-void ScriptParser::readVersionExtern(std::vector<SymbolVersion> *Globals) {
+void ScriptParser::readVersionExtern(std::vector<SymbolVersion> *V) {
   expect("\"C++\"");
   expect("{");
 
@@ -1845,7 +1855,7 @@ void ScriptParser::readVersionExtern(std
     if (peek() == "}" || Error)
       break;
     bool HasWildcard = !peek().startswith("\"") && hasWildcard(peek());
-    Globals->push_back({unquote(next()), true, HasWildcard});
+    V->push_back({unquote(next()), true, HasWildcard});
     expect(";");
   }
 
@@ -1854,23 +1864,10 @@ void ScriptParser::readVersionExtern(std
 }
 
 void ScriptParser::readGlobal(StringRef VerStr) {
-  std::vector<SymbolVersion> *Globals;
   if (VerStr.empty())
-    Globals = &Config->VersionScriptGlobals;
+    readSymbols(Config->VersionScriptGlobals);
   else
-    Globals = &Config->VersionDefinitions.back().Globals;
-
-  for (;;) {
-    if (consume("extern"))
-      readVersionExtern(Globals);
-
-    StringRef Cur = peek();
-    if (Cur == "}" || Cur == "local:" || Error)
-      return;
-    skip();
-    Globals->push_back({unquote(Cur), false, hasWildcard(Cur)});
-    expect(";");
-  }
+    readSymbols(Config->VersionDefinitions.back().Globals);
 }
 
 static bool isUnderSysroot(StringRef Path) {

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=287124&r1=287123&r2=287124&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Wed Nov 16 11:59:10 2016
@@ -586,7 +586,7 @@ static void setVersionId(SymbolBody *Bod
                          StringRef Name, uint16_t Version) {
   if (!Body || Body->isUndefined()) {
     if (Config->NoUndefinedVersion)
-      error("version script assignment of " + VersionName + " to symbol " +
+      error("version script assignment of '" + VersionName + "' to symbol " +
             Name + " failed: symbol not defined");
     return;
   }
@@ -700,26 +700,26 @@ template <class ELFT> void SymbolTable<E
   // Each version definition has a glob pattern, and all symbols that match
   // with the pattern get that version.
 
+  auto assignVersion = [&](SymbolVersion &Ver, size_t Version,
+                           StringRef VerName) {
+    if (Ver.HasWildcards)
+      return;
+
+    if (Ver.IsExternCpp) {
+      for (SymbolBody *B : findDemangled(Ver.Name))
+        setVersionId(B, VerName, Ver.Name, Version);
+      return;
+    }
+    setVersionId(find(Ver.Name), VerName, Ver.Name, Version);
+  };
+
   // First, we assign versions to exact matching symbols,
   // i.e. version definitions not containing any glob meta-characters.
   for (VersionDefinition &V : Config->VersionDefinitions) {
-    for (SymbolVersion Ver : V.Globals) {
-      if (Ver.HasWildcards)
-        continue;
-
-      StringRef N = Ver.Name;
-      if (Ver.IsExternCpp) {
-        for (SymbolBody *B : findDemangled(N))
-          setVersionId(B, V.Name, N, V.Id);
-        continue;
-      }
-      setVersionId(find(N), V.Name, N, V.Id);
-    }
-    for (SymbolVersion Ver : V.Locals) {
-      if (Ver.HasWildcards)
-        continue;
-      setVersionId(find(Ver.Name), V.Name, Ver.Name, VER_NDX_LOCAL);
-    }
+    for (SymbolVersion Sym : V.Globals)
+      assignVersion(Sym, V.Id, V.Name);
+    for (SymbolVersion Sym : V.Locals)
+      assignVersion(Sym, VER_NDX_LOCAL, "local");
   }
 
   // Next, we assign versions to fuzzy matching symbols,

Added: lld/trunk/test/ELF/version-script-locals-extern.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/version-script-locals-extern.s?rev=287124&view=auto
==============================================================================
--- lld/trunk/test/ELF/version-script-locals-extern.s (added)
+++ lld/trunk/test/ELF/version-script-locals-extern.s Wed Nov 16 11:59:10 2016
@@ -0,0 +1,45 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: echo "FOO { local: extern \"C++\" { \"abb(int)\"; }; };" > %t.script
+# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
+# RUN: llvm-readobj -V %t.so | FileCheck %s --check-prefix=ABB
+# ABB:      Symbols [
+# ABB-NEXT:   Symbol {
+# ABB-NEXT:     Version: 0
+# ABB-NEXT:     Name: @
+# ABB-NEXT:   }
+# ABB-NEXT:   Symbol {
+# ABB-NEXT:     Version: 1
+# ABB-NEXT:     Name: _Z3abci@
+# ABB-NEXT:   }
+# ABB-NEXT: ]
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: echo "FOO { local: extern \"C++\" { abb*; }; };" > %t.script
+# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
+# RUN: llvm-readobj -V %t.so | FileCheck %s --check-prefix=ABB
+
+# RUN: echo "FOO { local: extern \"C++\" { abc*; }; };" > %t.script
+# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
+# RUN: llvm-readobj -V %t.so | FileCheck %s --check-prefix=ABC
+# ABC:      Symbols [
+# ABC-NEXT:   Symbol {
+# ABC-NEXT:     Version: 0
+# ABC-NEXT:     Name: @
+# ABC-NEXT:   }
+# ABC-NEXT:   Symbol {
+# ABC-NEXT:     Version: 1
+# ABC-NEXT:     Name: _Z3abbi@
+# ABC-NEXT:   }
+# ABC-NEXT: ]
+
+.globl _Z3abbi
+.type _Z3abbi, at function
+_Z3abbi:
+retq
+
+.globl _Z3abci
+.type _Z3abci, at function
+_Z3abci:
+retq

Modified: lld/trunk/test/ELF/version-script-locals.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/version-script-locals.s?rev=287124&r1=287123&r2=287124&view=diff
==============================================================================
--- lld/trunk/test/ELF/version-script-locals.s (original)
+++ lld/trunk/test/ELF/version-script-locals.s Wed Nov 16 11:59:10 2016
@@ -28,11 +28,6 @@
 # MIX-NOT:  foo2
 # MIX-NOT:  foo3
 
-# RUN: echo "VERSION_1.0 { global: *; local: extern \"C++\" { foo*; } };" > %t.script
-# RUN: not ld.lld --version-script %t.script -shared %t.o -o %t.so 2>&1 \
-# RUN:   | FileCheck --check-prefix=EXTERNERR %s
-# EXTERNERR: ; expected, but got "C++"
-
 .globl foo1
 foo1:
   ret

Modified: lld/trunk/test/ELF/version-script-noundef.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/version-script-noundef.s?rev=287124&r1=287123&r2=287124&view=diff
==============================================================================
--- lld/trunk/test/ELF/version-script-noundef.s (original)
+++ lld/trunk/test/ELF/version-script-noundef.s Wed Nov 16 11:59:10 2016
@@ -4,12 +4,17 @@
 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
 # RUN: not ld.lld --version-script %t.script -shared --no-undefined-version \
 # RUN:   %t.o -o %t.so 2>&1 | FileCheck -check-prefix=ERR1 %s
-# ERR1: version script assignment of VERSION_1.0 to symbol bar failed: symbol not defined
+# ERR1: version script assignment of 'VERSION_1.0' to symbol bar failed: symbol not defined
 
 # RUN: echo "VERSION_1.0 { global: und; };" > %t2.script
 # RUN: not ld.lld --version-script %t2.script -shared --no-undefined-version \
 # RUN:   %t.o -o %t.so 2>&1 | FileCheck -check-prefix=ERR2 %s
-# ERR2: version script assignment of VERSION_1.0 to symbol und failed: symbol not defined
+# ERR2: version script assignment of 'VERSION_1.0' to symbol und failed: symbol not defined
+
+# RUN: echo "VERSION_1.0 { local: und; };" > %t3.script
+# RUN: not ld.lld --version-script %t3.script -shared --no-undefined-version \
+# RUN:   %t.o -o %t.so 2>&1 | FileCheck -check-prefix=ERR3 %s
+# ERR3: version script assignment of 'local' to symbol und failed: symbol not defined
 
 .text
 .globl foo




More information about the llvm-commits mailing list