forked from OSchip/llvm-project
[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 llvm-svn: 287124
This commit is contained in:
parent
7759e5b61b
commit
e0fc24210d
|
@ -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::readVersionDeclaration(StringRef VerStr) {
|
|||
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 VerStr) {
|
|||
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::vector<SymbolVersion> *Globals) {
|
|||
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::vector<SymbolVersion> *Globals) {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -586,7 +586,7 @@ static void setVersionId(SymbolBody *Body, StringRef VersionName,
|
|||
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<ELFT>::scanVersionScript() {
|
|||
// 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,
|
||||
|
|
|
@ -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,@function
|
||||
_Z3abbi:
|
||||
retq
|
||||
|
||||
.globl _Z3abci
|
||||
.type _Z3abci,@function
|
||||
_Z3abci:
|
||||
retq
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue