Index: lld/trunk/ELF/Config.h =================================================================== --- lld/trunk/ELF/Config.h +++ lld/trunk/ELF/Config.h @@ -104,6 +104,7 @@ std::vector SearchPaths; std::vector SymbolOrderingFile; std::vector Undefined; + std::vector DynamicList; std::vector VersionScriptGlobals; std::vector VersionScriptLocals; std::vector BuildIdVector; Index: lld/trunk/ELF/ScriptParser.cpp =================================================================== --- lld/trunk/ELF/ScriptParser.cpp +++ lld/trunk/ELF/ScriptParser.cpp @@ -175,9 +175,22 @@ void ScriptParser::readDynamicList() { expect("{"); - readAnonymousDeclaration(); - if (!atEOF()) + std::vector Locals; + std::vector Globals; + std::tie(Locals, Globals) = readSymbols(); + expect(";"); + + if (!atEOF()) { setError("EOF expected, but got " + next()); + return; + } + if (!Locals.empty()) { + setError("\"local:\" scope not supported in --dynamic-list"); + return; + } + + for (SymbolVersion V : Globals) + Config->DynamicList.push_back(V); } void ScriptParser::readVersionScript() { Index: lld/trunk/ELF/SymbolTable.h =================================================================== --- lld/trunk/ELF/SymbolTable.h +++ lld/trunk/ELF/SymbolTable.h @@ -90,6 +90,8 @@ void trace(StringRef Name); + void handleDynamicList(); + private: std::vector findByVersion(SymbolVersion Ver); std::vector findAllByVersion(SymbolVersion Ver); Index: lld/trunk/ELF/SymbolTable.cpp =================================================================== --- lld/trunk/ELF/SymbolTable.cpp +++ lld/trunk/ELF/SymbolTable.cpp @@ -680,6 +680,24 @@ assignWildcardVersion(Ver, VER_NDX_LOCAL); } +// Handles -dynamic-list. +void SymbolTable::handleDynamicList() { + for (SymbolVersion &Ver : Config->DynamicList) { + std::vector Syms; + if (Ver.HasWildcard) + Syms = findByVersion(Ver); + else + Syms = findAllByVersion(Ver); + + for (SymbolBody *B : Syms) { + if (!Config->Shared) + B->symbol()->VersionId = VER_NDX_GLOBAL; + else if (B->symbol()->includeInDynsym()) + B->IsPreemptible = true; + } + } +} + // Set symbol versions to symbols. This function handles patterns // containing no wildcard characters. void SymbolTable::assignExactVersion(SymbolVersion Ver, uint16_t VersionId, @@ -729,6 +747,7 @@ void SymbolTable::scanVersionScript() { // Handle edge cases first. handleAnonymousVersion(); + handleDynamicList(); // Now we have version definitions, so we need to set version ids to symbols. // Each version definition has a glob pattern, and all symbols that match Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -1219,8 +1219,9 @@ applySynthetic({In::EhFrame}, [](SyntheticSection *SS) { SS->finalizeContents(); }); - for (Symbol *S : Symtab->getSymbols()) - S->body()->IsPreemptible = computeIsPreemptible(*S->body()); + if (Config->DynamicList.empty()) + for (Symbol *S : Symtab->getSymbols()) + S->body()->IsPreemptible = computeIsPreemptible(*S->body()); // Scan relocations. This must be done after every symbol is declared so that // we can correctly decide if a dynamic relocation is needed. Index: lld/trunk/test/ELF/dynamic-list-preempt.s =================================================================== --- lld/trunk/test/ELF/dynamic-list-preempt.s +++ lld/trunk/test/ELF/dynamic-list-preempt.s @@ -0,0 +1,65 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "{ foo; zed; };" > %t.list +# RUN: echo "{ global: foo; bar; local: *; };" > %t.vers +# RUN: ld.lld -fatal-warnings -dynamic-list %t.list -version-script %t.vers -shared %t.o -o %t.so +# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=RELOCS %s +# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=DYNSYMS %s + +# RELOCS: Relocations [ +# RELOCS-NEXT: Section ({{.*}}) .rela.plt { +# RELOCS-NEXT: R_X86_64_JUMP_SLOT foo 0x0 +# RELOCS-NEXT: } +# RELOCS-NEXT: ] + +# DYNSYMS: DynamicSymbols [ +# DYNSYMS-NEXT: Symbol { +# DYNSYMS-NEXT: Name: @ (0) +# DYNSYMS-NEXT: Value: 0x0 +# DYNSYMS-NEXT: Size: 0 +# DYNSYMS-NEXT: Binding: Local +# DYNSYMS-NEXT: Type: None +# DYNSYMS-NEXT: Other: 0 +# DYNSYMS-NEXT: Section: Undefined +# DYNSYMS-NEXT: } +# DYNSYMS-NEXT: Symbol { +# DYNSYMS-NEXT: Name: bar@ +# DYNSYMS-NEXT: Value: +# DYNSYMS-NEXT: Size: +# DYNSYMS-NEXT: Binding: Global +# DYNSYMS-NEXT: Type: +# DYNSYMS-NEXT: Other: +# DYNSYMS-NEXT: Section: +# DYNSYMS-NEXT: } +# DYNSYMS-NEXT: Symbol { +# DYNSYMS-NEXT: Name: foo@ +# DYNSYMS-NEXT: Value: +# DYNSYMS-NEXT: Size: +# DYNSYMS-NEXT: Binding: Global +# DYNSYMS-NEXT: Type: +# DYNSYMS-NEXT: Other: +# DYNSYMS-NEXT: Section: +# DYNSYMS-NEXT: } +# DYNSYMS-NEXT: ] + + .globl foo +foo: + ret + + .globl bar +bar: + ret + + .globl baz +baz: + ret + + .globl zed +zed: + ret + + call foo@PLT + call bar@PLT + call baz@PLT + call zed@PLT