Make local: optional.

Doing that in an anonymous version is a bit silly, but this opens the
way for supporting it in general.

Since we don't support actual versions, for now we just disable the
version script if we detect that it is missing a local.

llvm-svn: 273000
This commit is contained in:
Rafael Espindola 2016-06-17 13:38:09 +00:00
parent 1d67ac5639
commit f70fb04e4f
5 changed files with 94 additions and 11 deletions

View File

@ -88,7 +88,7 @@ struct Configuration {
bool Threads;
bool Trace;
bool Verbose;
bool VersionScript = false;
bool VersionScriptGlobalByDefault = true;
bool WarnCommon;
bool ZCombreloc;
bool ZDefs;

View File

@ -414,7 +414,6 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
Config->DynamicList.push_back(Arg->getValue());
if (auto *Arg = Args.getLastArg(OPT_version_script)) {
Config->VersionScript = true;
if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
parseVersionScript(*Buffer);
}

View File

@ -78,24 +78,41 @@ public:
private:
void parseVersion();
void parseLocal();
void parseVersionSymbols();
};
void VersionScriptParser::parseVersion() {
expect("{");
if (peek() == "global:") {
next();
while (!Error) {
Config->VersionScriptGlobals.push_back(next());
expect(";");
if (peek() == "local:")
break;
}
parseVersionSymbols();
}
if (peek() == "local:")
parseLocal();
else
parseVersionSymbols();
expect("}");
expect(";");
}
void VersionScriptParser::parseLocal() {
expect("local:");
expect("*");
expect(";");
expect("}");
expect(";");
Config->VersionScriptGlobalByDefault = false;
}
void VersionScriptParser::parseVersionSymbols() {
for (;;) {
StringRef Cur = peek();
if (Cur == "}" || Cur == "local:")
return;
next();
Config->VersionScriptGlobals.push_back(Cur);
expect(";");
}
}
void VersionScriptParser::run() {

View File

@ -175,7 +175,7 @@ std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) {
Sym->Visibility = STV_DEFAULT;
Sym->IsUsedInRegularObj = false;
Sym->ExportDynamic = false;
Sym->VersionScriptGlobal = !Config->VersionScript;
Sym->VersionScriptGlobal = Config->VersionScriptGlobalByDefault;
SymVector.push_back(Sym);
} else {
Sym = SymVector[P.first->second];

View File

@ -140,6 +140,73 @@
# EXE-NEXT: }
# EXE-NEXT: ]
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
# RUN: ld.lld -shared %t.o %t2.so -o %t.so
# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=ALL %s
# RUN: echo "{ global: foo1; foo3; };" > %t2.script
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
# RUN: ld.lld --version-script %t2.script -shared %t.o %t2.so -o %t.so
# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=ALL %s
# ALL: DynamicSymbols [
# ALL-NEXT: Symbol {
# ALL-NEXT: Name: @
# ALL-NEXT: Value: 0x0
# ALL-NEXT: Size: 0
# ALL-NEXT: Binding: Local
# ALL-NEXT: Type: None
# ALL-NEXT: Other: 0
# ALL-NEXT: Section: Undefined
# ALL-NEXT: }
# ALL-NEXT: Symbol {
# ALL-NEXT: Name: _start@
# ALL-NEXT: Value:
# ALL-NEXT: Size: 0
# ALL-NEXT: Binding: Global
# ALL-NEXT: Type: None
# ALL-NEXT: Other: 0
# ALL-NEXT: Section: .text
# ALL-NEXT: }
# ALL-NEXT: Symbol {
# ALL-NEXT: Name: bar@
# ALL-NEXT: Value:
# ALL-NEXT: Size: 0
# ALL-NEXT: Binding: Global
# ALL-NEXT: Type: Function
# ALL-NEXT: Other: 0
# ALL-NEXT: Section: Undefined
# ALL-NEXT: }
# ALL-NEXT: Symbol {
# ALL-NEXT: Name: foo1@
# ALL-NEXT: Value:
# ALL-NEXT: Size: 0
# ALL-NEXT: Binding: Global
# ALL-NEXT: Type: None
# ALL-NEXT: Other: 0
# ALL-NEXT: Section: .text
# ALL-NEXT: }
# ALL-NEXT: Symbol {
# ALL-NEXT: Name: foo2@
# ALL-NEXT: Value:
# ALL-NEXT: Size: 0
# ALL-NEXT: Binding: Global
# ALL-NEXT: Type: None
# ALL-NEXT: Other: 0
# ALL-NEXT: Section: .text
# ALL-NEXT: }
# ALL-NEXT: Symbol {
# ALL-NEXT: Name: foo3@
# ALL-NEXT: Value:
# ALL-NEXT: Size: 0
# ALL-NEXT: Binding: Global
# ALL-NEXT: Type: None
# ALL-NEXT: Other: 0
# ALL-NEXT: Section: .text
# ALL-NEXT: }
# ALL-NEXT: ]
.globl foo1
foo1:
call bar@PLT