[lld] r246603 - Merge visibility from all symbols with the same name.
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 1 16:12:53 PDT 2015
Author: rafael
Date: Tue Sep 1 18:12:52 2015
New Revision: 246603
URL: http://llvm.org/viewvc/llvm-project?rev=246603&view=rev
Log:
Merge visibility from all symbols with the same name.
The ELF spec says:
... if any reference to or definition of a name is a symbol with a
non-default visibility attribute, the visibility attribute must be
propagated to the resolving symbol in the linked object. If different
visibility attributes are specified for distinct references to or
definitions of a symbol, the most constraining visibility attribute
must be propagated to the resolving symbol in the linked object. The
attributes, ordered from least to most constraining, are:
STV_PROTECTED, STV_HIDDEN and STV_INTERNAL.
Added:
lld/trunk/test/elf2/Inputs/visibility.s
lld/trunk/test/elf2/visibility.s
Modified:
lld/trunk/ELF/Symbols.cpp
lld/trunk/ELF/Symbols.h
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=246603&r1=246602&r2=246603&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Tue Sep 1 18:12:52 2015
@@ -13,10 +13,19 @@
#include "InputFiles.h"
using namespace llvm::object;
+using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf2;
+static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
+ if (VA == STV_DEFAULT)
+ return VB;
+ if (VB == STV_DEFAULT)
+ return VA;
+ return std::min(VA, VB);
+}
+
// Returns 1, 0 or -1 if this symbol should take precedence
// over the Other, tie or lose, respectively.
template <class ELFT> int SymbolBody::compare(SymbolBody *Other) {
@@ -27,6 +36,11 @@ template <class ELFT> int SymbolBody::co
if (L > R)
return -Other->compare<ELFT>(this);
+ uint8_t LV = getMostConstrainingVisibility();
+ uint8_t RV = Other->getMostConstrainingVisibility();
+ MostConstrainingVisibility = getMinVisibility(LV, RV);
+ Other->MostConstrainingVisibility = MostConstrainingVisibility;
+
if (L != R)
return -1;
Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=246603&r1=246602&r2=246603&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Tue Sep 1 18:12:52 2015
@@ -56,6 +56,10 @@ public:
// Returns the symbol name.
StringRef getName() const { return Name; }
+ uint8_t getMostConstrainingVisibility() const {
+ return MostConstrainingVisibility;
+ }
+
// A SymbolBody has a backreference to a Symbol. Originally they are
// doubly-linked. A backreference will never change. But the pointer
// in the Symbol may be mutated by the resolver. If you have a
@@ -71,12 +75,14 @@ public:
template <class ELFT> int compare(SymbolBody *Other);
protected:
- SymbolBody(Kind K, StringRef Name, bool IsWeak)
- : SymbolKind(K), IsWeak(IsWeak), Name(Name) {}
+ SymbolBody(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility)
+ : SymbolKind(K), IsWeak(IsWeak), MostConstrainingVisibility(Visibility),
+ Name(Name) {}
protected:
const unsigned SymbolKind : 8;
const unsigned IsWeak : 1;
+ unsigned MostConstrainingVisibility : 2;
StringRef Name;
Symbol *Backref = nullptr;
};
@@ -92,8 +98,9 @@ template <class ELFT> class ELFSymbolBod
protected:
typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
ELFSymbolBody(Kind K, StringRef Name, const Elf_Sym &Sym)
- : SymbolBody(K, Name, Sym.getBinding() == llvm::ELF::STB_WEAK), Sym(Sym) {
- }
+ : SymbolBody(K, Name, Sym.getBinding() == llvm::ELF::STB_WEAK,
+ Sym.getVisibility()),
+ Sym(Sym) {}
public:
const Elf_Sym &Sym;
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=246603&r1=246602&r2=246603&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue Sep 1 18:12:52 2015
@@ -304,7 +304,7 @@ template <class ELFT> void SymbolTableSe
SymbolBody *Body = Sym->Body;
const Elf_Sym &InputSym = cast<ELFSymbolBody<ELFT>>(Body)->Sym;
- uint8_t V = InputSym.getVisibility();
+ uint8_t V = Body->getMostConstrainingVisibility();
if (V != STV_DEFAULT && V != STV_PROTECTED)
continue;
@@ -331,7 +331,8 @@ template <class ELFT> void SymbolTableSe
uint8_t Binding = InputSym.getBinding();
ESym->setBindingAndType(Binding, Type);
ESym->st_size = InputSym.st_size;
- ESym->st_other = InputSym.st_other;
+ uint8_t Other = InputSym.st_other;
+ ESym->st_other = (Other & ~0x3) | Body->getMostConstrainingVisibility();
if (InputSym.isAbsolute()) {
ESym->st_shndx = SHN_ABS;
ESym->st_value = InputSym.st_value;
@@ -454,8 +455,7 @@ template <class ELFT> void Writer<ELFT>:
SymbolBody *Body = P.second->Body;
if (auto *C = dyn_cast<DefinedCommon<ELFT>>(Body))
CommonSymbols.push_back(C);
- auto *E = cast<ELFSymbolBody<ELFT>>(Body);
- uint8_t V = E->Sym.getVisibility();
+ uint8_t V = Body->getMostConstrainingVisibility();
if (V != STV_DEFAULT && V != STV_PROTECTED)
continue;
NumVisible++;
Added: lld/trunk/test/elf2/Inputs/visibility.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/visibility.s?rev=246603&view=auto
==============================================================================
--- lld/trunk/test/elf2/Inputs/visibility.s (added)
+++ lld/trunk/test/elf2/Inputs/visibility.s Tue Sep 1 18:12:52 2015
@@ -0,0 +1,13 @@
+.quad default
+
+.protected protected
+.quad protected
+
+.hidden hidden
+.quad hidden
+
+.internal internal
+.quad internal
+
+.hidden protected_with_hidden
+.quad protected_with_hidden
Added: lld/trunk/test/elf2/visibility.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/visibility.s?rev=246603&view=auto
==============================================================================
--- lld/trunk/test/elf2/visibility.s (added)
+++ lld/trunk/test/elf2/visibility.s Tue Sep 1 18:12:52 2015
@@ -0,0 +1,63 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/visibility.s -o %t2
+// RUN: lld -flavor gnu2 %t %t2 -o %t3
+// RUN: llvm-readobj -t %t3 | FileCheck %s
+// REQUIRES: x86
+
+// CHECK: Symbols [
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name:
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: _start
+// CHECK-NEXT: Value: 0x1000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: default
+// CHECK-NEXT: Value: 0x1000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: protected
+// CHECK-NEXT: Value: 0x1000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 3
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+.global _start
+_start:
+
+.global default
+default:
+
+.global protected
+protected:
+
+.global hidden
+hidden:
+
+.global internal
+internal:
+
+.global protected_with_hidden
+.protected
+protected_with_hidden:
More information about the llvm-commits
mailing list