[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