[lld] r274002 - [ELF] - Implemented support of default/non-default symbols versions
George Rimar via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 28 01:21:11 PDT 2016
Author: grimar
Date: Tue Jun 28 03:21:10 2016
New Revision: 274002
URL: http://llvm.org/viewvc/llvm-project?rev=274002&view=rev
Log:
[ELF] - Implemented support of default/non-default symbols versions
t is possible to create new version of symbol instead of depricated one
using combination of version script and asm commands. For example:
__asm__(".symver b_1,b at LIBSAMPLE_1.0");
int b_1() { return 10; }
__asm__(".symver b_2,b@@LIBSAMPLE_2.0");
int b_2() { return 20; }
This code makes b_2() to be default implementation for b().
b_1() is used for compatibility with binaries compiled against
library of older version LIBSAMPLE_1.0.
This patch implements support for above functionality in lld.
Differential revision: http://reviews.llvm.org/D21681
Added:
lld/trunk/test/ELF/Inputs/verdef-defaultver.s
lld/trunk/test/ELF/verdef-defaultver.s
Modified:
lld/trunk/ELF/SymbolTable.cpp
lld/trunk/ELF/Symbols.cpp
lld/trunk/ELF/Symbols.h
Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=274002&r1=274001&r2=274002&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Tue Jun 28 03:21:10 2016
@@ -163,6 +163,32 @@ static uint8_t getMinVisibility(uint8_t
return std::min(VA, VB);
}
+// A symbol version may be included in a symbol name as a prefix after '@'.
+// This function parses that part and returns a version ID number.
+static uint16_t getVersionId(Symbol *Sym, StringRef Name) {
+ size_t VersionBegin = Name.find('@');
+ if (VersionBegin == StringRef::npos)
+ return Config->VersionScriptGlobalByDefault ? VER_NDX_GLOBAL
+ : VER_NDX_LOCAL;
+
+ // If symbol name contains '@' or '@@' we can assign its version id right
+ // here. '@@' means version by default. It is usually the most recent one.
+ // VERSYM_HIDDEN flag should be set for all non-default versions.
+ StringRef Version = Name.drop_front(VersionBegin + 1);
+ bool Default = Version.startswith("@");
+ if (Default)
+ Version = Version.drop_front();
+
+ size_t I = 2;
+ for (elf::Version &V : Config->SymbolVersions) {
+ if (V.Name == Version)
+ return Default ? I : (I | VERSYM_HIDDEN);
+ ++I;
+ }
+ error("symbol " + Name + " has undefined version " + Version);
+ return 0;
+}
+
// Find an existing symbol or create and insert a new one.
template <class ELFT>
std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) {
@@ -175,10 +201,9 @@ std::pair<Symbol *, bool> SymbolTable<EL
Sym->Visibility = STV_DEFAULT;
Sym->IsUsedInRegularObj = false;
Sym->ExportDynamic = false;
- if (Config->VersionScriptGlobalByDefault)
- Sym->VersionId = VER_NDX_GLOBAL;
- else
- Sym->VersionId = VER_NDX_LOCAL;
+ Sym->VersionId = getVersionId(Sym, Name);
+ Sym->VersionedName =
+ Sym->VersionId != VER_NDX_LOCAL && Sym->VersionId != VER_NDX_GLOBAL;
SymVector.push_back(Sym);
} else {
Sym = SymVector[P.first->second];
Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=274002&r1=274001&r2=274002&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Tue Jun 28 03:21:10 2016
@@ -101,6 +101,14 @@ SymbolBody::SymbolBody(Kind K, StringRef
IsInGlobalMipsGot(false), Type(Type), StOther(StOther),
Name({Name.data(), Name.size()}) {}
+StringRef SymbolBody::getName() const {
+ assert(!isLocal());
+ StringRef S = StringRef(Name.S, Name.Len);
+ if (!symbol()->VersionedName)
+ return S;
+ return S.substr(0, S.find('@'));
+}
+
// Returns true if a symbol can be replaced at load-time by a symbol
// with the same name defined in other ELF executable or DSO.
bool SymbolBody::isPreemptible() const {
Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=274002&r1=274001&r2=274002&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Tue Jun 28 03:21:10 2016
@@ -77,10 +77,7 @@ public:
bool isPreemptible() const;
// Returns the symbol name.
- StringRef getName() const {
- assert(!isLocal());
- return StringRef(Name.S, Name.Len);
- }
+ StringRef getName() const;
uint32_t getNameOffset() const {
assert(isLocal());
return NameOffset;
@@ -422,6 +419,11 @@ struct Symbol {
// --export-dynamic, and by dynamic lists.
unsigned ExportDynamic : 1;
+ // If this flag is true then symbol name also contains version name. Such
+ // name can have single or double symbol @. Double means that version is
+ // used as default. Single signals about depricated symbol version.
+ unsigned VersionedName : 1;
+
bool includeInDynsym() const;
bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; }
Added: lld/trunk/test/ELF/Inputs/verdef-defaultver.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/verdef-defaultver.s?rev=274002&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/verdef-defaultver.s (added)
+++ lld/trunk/test/ELF/Inputs/verdef-defaultver.s Tue Jun 28 03:21:10 2016
@@ -0,0 +1,22 @@
+b at LIBSAMPLE_1.0 = b_1
+b@@LIBSAMPLE_2.0 = b_2
+
+.globl a
+.type a, at function
+a:
+retq
+
+.globl b_1
+.type b_1, at function
+b_1:
+retq
+
+.globl b_2
+.type b_2, at function
+b_2:
+retq
+
+.globl c
+.type c, at function
+c:
+retq
Added: lld/trunk/test/ELF/verdef-defaultver.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/verdef-defaultver.s?rev=274002&view=auto
==============================================================================
--- lld/trunk/test/ELF/verdef-defaultver.s (added)
+++ lld/trunk/test/ELF/verdef-defaultver.s Tue Jun 28 03:21:10 2016
@@ -0,0 +1,210 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/verdef-defaultver.s -o %t1
+# RUN: echo "LIBSAMPLE_1.0{ \
+# RUN: global: a; \
+# RUN: local: *; }; \
+# RUN: LIBSAMPLE_2.0{ \
+# RUN: global: b; c; \
+# RUN: }LIBSAMPLE_1.0;" > %t.script
+# RUN: ld.lld -shared -soname shared %t1 --version-script %t.script -o %t.so
+# RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s
+
+# DSO: DynamicSymbols [
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: @
+# DSO-NEXT: Value: 0x0
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Local
+# DSO-NEXT: Type: None
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: Undefined
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: a@@LIBSAMPLE_1.0
+# DSO-NEXT: Value: 0x1000
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Global
+# DSO-NEXT: Type: Function
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: .text
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: b@@LIBSAMPLE_2.0
+# DSO-NEXT: Value: 0x1002
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Global
+# DSO-NEXT: Type: Function
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: .text
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: b at LIBSAMPLE_1.0
+# DSO-NEXT: Value: 0x1001
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Global
+# DSO-NEXT: Type: Function
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: .text
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: c@@LIBSAMPLE_2.0
+# DSO-NEXT: Value: 0x1003
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Global
+# DSO-NEXT: Type: Function
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: .text
+# DSO-NEXT: }
+# DSO-NEXT: ]
+# DSO-NEXT: Version symbols {
+# DSO-NEXT: Section Name: .gnu.version
+# DSO-NEXT: Address: 0x240
+# DSO-NEXT: Offset: 0x240
+# DSO-NEXT: Link: 1
+# DSO-NEXT: Symbols [
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 0
+# DSO-NEXT: Name: @
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 2
+# DSO-NEXT: Name: a@@LIBSAMPLE_1.0
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 3
+# DSO-NEXT: Name: b@@LIBSAMPLE_2.0
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 2
+# DSO-NEXT: Name: b at LIBSAMPLE_1.0
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 3
+# DSO-NEXT: Name: c@@LIBSAMPLE_2.0
+# DSO-NEXT: }
+# DSO-NEXT: ]
+# DSO-NEXT: }
+# DSO-NEXT: SHT_GNU_verdef {
+# DSO-NEXT: Definition {
+# DSO-NEXT: Version: 1
+# DSO-NEXT: Flags: Base
+# DSO-NEXT: Index: 1
+# DSO-NEXT: Hash: 127830196
+# DSO-NEXT: Name: shared
+# DSO-NEXT: }
+# DSO-NEXT: Definition {
+# DSO-NEXT: Version: 1
+# DSO-NEXT: Flags: 0x0
+# DSO-NEXT: Index: 2
+# DSO-NEXT: Hash: 98457184
+# DSO-NEXT: Name: LIBSAMPLE_1.0
+# DSO-NEXT: }
+# DSO-NEXT: Definition {
+# DSO-NEXT: Version: 1
+# DSO-NEXT: Flags: 0x0
+# DSO-NEXT: Index: 3
+# DSO-NEXT: Hash: 98456416
+# DSO-NEXT: Name: LIBSAMPLE_2.0
+# DSO-NEXT: Predecessor: LIBSAMPLE_1.0
+# DSO-NEXT: }
+# DSO-NEXT: }
+
+## Check that we can link against DSO produced.
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2
+# RUN: ld.lld %t2 %t.so -o %t3
+# RUN: llvm-readobj -V -dyn-symbols %t3 | FileCheck --check-prefix=EXE %s
+
+# EXE: DynamicSymbols [
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Name: @
+# EXE-NEXT: Value: 0x0
+# EXE-NEXT: Size: 0
+# EXE-NEXT: Binding: Local
+# EXE-NEXT: Type: None
+# EXE-NEXT: Other: 0
+# EXE-NEXT: Section: Undefined
+# EXE-NEXT: }
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Name: a at LIBSAMPLE_1.0
+# EXE-NEXT: Value: 0x11020
+# EXE-NEXT: Size: 0
+# EXE-NEXT: Binding: Global
+# EXE-NEXT: Type: Function
+# EXE-NEXT: Other: 0
+# EXE-NEXT: Section: Undefined
+# EXE-NEXT: }
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Name: b at LIBSAMPLE_2.0
+# EXE-NEXT: Value: 0x11030
+# EXE-NEXT: Size: 0
+# EXE-NEXT: Binding: Global
+# EXE-NEXT: Type: Function
+# EXE-NEXT: Other: 0
+# EXE-NEXT: Section: Undefined
+# EXE-NEXT: }
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Name: c at LIBSAMPLE_2.0
+# EXE-NEXT: Value: 0x11040
+# EXE-NEXT: Size: 0
+# EXE-NEXT: Binding: Global
+# EXE-NEXT: Type: Function
+# EXE-NEXT: Other: 0
+# EXE-NEXT: Section: Undefined
+# EXE-NEXT: }
+# EXE-NEXT: ]
+# EXE-NEXT: Version symbols {
+# EXE-NEXT: Section Name: .gnu.version
+# EXE-NEXT: Address: 0x10228
+# EXE-NEXT: Offset: 0x228
+# EXE-NEXT: Link: 1
+# EXE-NEXT: Symbols [
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Version: 0
+# EXE-NEXT: Name: @
+# EXE-NEXT: }
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Version: 2
+# EXE-NEXT: Name: a at LIBSAMPLE_1.0
+# EXE-NEXT: }
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Version: 3
+# EXE-NEXT: Name: b at LIBSAMPLE_2.0
+# EXE-NEXT: }
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Version: 3
+# EXE-NEXT: Name: c at LIBSAMPLE_2.0
+# EXE-NEXT: }
+# EXE-NEXT: ]
+# EXE-NEXT: }
+# EXE-NEXT: SHT_GNU_verdef {
+# EXE-NEXT: }
+# EXE-NEXT: SHT_GNU_verneed {
+# EXE-NEXT: Dependency {
+# EXE-NEXT: Version: 1
+# EXE-NEXT: Count: 2
+# EXE-NEXT: FileName: shared
+# EXE-NEXT: Entry {
+# EXE-NEXT: Hash: 98457184
+# EXE-NEXT: Flags: 0x0
+# EXE-NEXT: Index: 2
+# EXE-NEXT: Name: LIBSAMPLE_1.0
+# EXE-NEXT: }
+# EXE-NEXT: Entry {
+# EXE-NEXT: Hash: 98456416
+# EXE-NEXT: Flags: 0x0
+# EXE-NEXT: Index: 3
+# EXE-NEXT: Name: LIBSAMPLE_2.0
+# EXE-NEXT: }
+# EXE-NEXT: }
+# EXE-NEXT: }
+
+# RUN: not ld.lld -shared %t1 -o %terr.so 2>&1 | \
+# RUN: FileCheck -check-prefix=ERR1 %s
+# ERR1: symbol b@@LIBSAMPLE_2.0 has undefined version LIBSAMPLE_2.0
+
+.globl _start
+_start:
+ callq a
+ callq b
+ callq c
More information about the llvm-commits
mailing list