[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