[lld] r274091 - [ELF] Support for wildcard in version scripts.

Davide Italiano via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 28 19:46:52 PDT 2016


Author: davide
Date: Tue Jun 28 21:46:51 2016
New Revision: 274091

URL: http://llvm.org/viewvc/llvm-project?rev=274091&view=rev
Log:
[ELF] Support for wildcard in version scripts.

Example:

VERSION_1.0 {
  global: foo*;
  local: *; }

now correctly matches all the symbols which name starts with
`foo`.

Differential Revision:  http://reviews.llvm.org/D21732

Added:
    lld/trunk/test/ELF/version-wildcard.test
Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/SymbolTable.h

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=274091&r1=274090&r2=274091&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Tue Jun 28 21:46:51 2016
@@ -35,8 +35,6 @@ using namespace lld::elf;
 
 ScriptConfiguration *elf::ScriptConfig;
 
-static bool matchStr(StringRef S, StringRef T);
-
 // This is an operator-precedence parser to parse and evaluate
 // a linker script expression. For each linker script arithmetic
 // expression (e.g. ". = . + 0x1000"), a new instance of ExprParser
@@ -291,7 +289,7 @@ int LinkerScript<ELFT>::compareSections(
 // Returns true if S matches T. S can contain glob meta-characters.
 // The asterisk ('*') matches zero or more characters, and the question
 // mark ('?') matches one character.
-static bool matchStr(StringRef S, StringRef T) {
+bool elf::matchStr(StringRef S, StringRef T) {
   for (;;) {
     if (S.empty())
       return T.empty();

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=274091&r1=274090&r2=274091&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Tue Jun 28 21:46:51 2016
@@ -19,6 +19,8 @@
 namespace lld {
 namespace elf {
 
+bool matchStr(StringRef S, StringRef T);
+
 // Parses a linker script. Calling this function updates
 // Config and ScriptConfig.
 void readLinkerScript(MemoryBufferRef MB);

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=274091&r1=274090&r2=274091&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Tue Jun 28 21:46:51 2016
@@ -17,6 +17,7 @@
 #include "SymbolTable.h"
 #include "Config.h"
 #include "Error.h"
+#include "LinkerScript.h"
 #include "Symbols.h"
 #include "llvm/Bitcode/ReaderWriter.h"
 #include "llvm/Support/StringSaver.h"
@@ -457,6 +458,21 @@ template <class ELFT> SymbolBody *Symbol
 }
 
 template <class ELFT>
+std::vector<SymbolBody *> SymbolTable<ELFT>::findAll(StringRef Pattern) {
+  // Fast-path. Fallback to find() if Pattern doesn't contain any wildcard
+  // characters.
+  bool HasWildcards = (Pattern.find_first_of("?*") != StringRef::npos);
+  if (!HasWildcards)
+    return {find(Pattern)};
+
+  std::vector<SymbolBody *> Result;
+  for (auto &It : Symtab)
+    if (matchStr(Pattern, It.first.Val))
+      Result.push_back(SymVector[It.second]->body());
+  return Result;
+}
+
+template <class ELFT>
 void SymbolTable<ELFT>::addLazyArchive(
     ArchiveFile *F, const llvm::object::Archive::Symbol Sym) {
   Symbol *S;
@@ -556,18 +572,19 @@ template <class ELFT> void SymbolTable<E
   size_t I = 2;
   for (Version &V : Config->SymbolVersions) {
     for (StringRef Name : V.Globals) {
-      SymbolBody *B = find(Name);
-      if (!B || B->isUndefined()) {
-        if (Config->NoUndefinedVersion)
-          error("version script assignment of " + V.Name + " to symbol " +
-                Name + " failed: symbol not defined");
-        continue;
+      for (SymbolBody *B : findAll(Name)) {
+        if (!B || B->isUndefined()) {
+          if (Config->NoUndefinedVersion)
+            error("version script assignment of " + V.Name + " to symbol " +
+                  Name + " failed: symbol not defined");
+          continue;
+        }
+
+        if (B->symbol()->VersionId != VER_NDX_GLOBAL &&
+            B->symbol()->VersionId != VER_NDX_LOCAL)
+          warning("duplicate symbol " + Name + " in version script");
+        B->symbol()->VersionId = I;
       }
-
-      if (B->symbol()->VersionId != VER_NDX_GLOBAL &&
-          B->symbol()->VersionId != VER_NDX_LOCAL)
-        warning("duplicate symbol " + Name + " in version script");
-      B->symbol()->VersionId = I;
     }
     ++I;
   }

Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=274091&r1=274090&r2=274091&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Tue Jun 28 21:46:51 2016
@@ -88,6 +88,7 @@ public:
   void wrap(StringRef Name);
 
 private:
+  std::vector<SymbolBody *> findAll(StringRef Pattern);
   std::pair<Symbol *, bool> insert(StringRef Name);
   std::pair<Symbol *, bool> insert(StringRef Name, uint8_t Type,
                                    uint8_t Visibility, bool CanOmitFromDynSym,

Added: lld/trunk/test/ELF/version-wildcard.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/version-wildcard.test?rev=274091&view=auto
==============================================================================
--- lld/trunk/test/ELF/version-wildcard.test (added)
+++ lld/trunk/test/ELF/version-wildcard.test Tue Jun 28 21:46:51 2016
@@ -0,0 +1,65 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: echo "VERSION_1.0{      \
+# RUN:          global: foo*;  \
+# RUN:          local: *; };" > %t.script
+# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
+# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s
+
+# CHECK: DynamicSymbols [
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name: @
+# CHECK-NEXT:     Value: 0x0
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Local
+# CHECK-NEXT:     Type: None
+# CHECK-NEXT:     Other: 0
+# CHECK-NEXT:     Section: Undefined
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name: foo1@@VERSION_1.0
+# CHECK-NEXT:     Value: 0x1000
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Global
+# CHECK-NEXT:     Type: None
+# CHECK-NEXT:     Other: 0
+# CHECK-NEXT:     Section: .text
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name: foo2@@VERSION_1.0
+# CHECK-NEXT:     Value: 0x1001
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Global
+# CHECK-NEXT:     Type: None
+# CHECK-NEXT:     Other: 0
+# CHECK-NEXT:     Section: .text
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name: foo3@@VERSION_1.0
+# CHECK-NEXT:     Value: 0x1007
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Global
+# CHECK-NEXT:     Type: None
+# CHECK-NEXT:     Other: 0
+# CHECK-NEXT:     Section: .text
+# CHECK-NEXT:   }
+# CHECK-NEXT: ]
+
+.globl foo1
+foo1:
+  ret
+
+.globl foo2
+foo2:
+  call foo1 at PLT
+  ret
+
+.globl foo3
+foo3:
+  call foo2 at PLT
+  ret
+
+.globl _start
+_start:
+  ret




More information about the llvm-commits mailing list