[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