Store the real binding of shared symbols.
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 28 Nov 2017 01:04:51 +0000 (01:04 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 28 Nov 2017 01:04:51 +0000 (01:04 +0000)
Currently we mark every shared symbol as STB_WEAK.

That is a hack to make it easy to decide when a .so is needed or not
because of a reference to a given symbol.

That hack leaks when we create copy relocations as shown by the update
to relocation-copy-alias.s.

This patch stores the original binding when we first read a shared
symbol. We still have to update the binding to weak if we see a weak
undef, but I find the logic easier to read where it is now.

llvm-svn: 319127

lld/ELF/SymbolTable.cpp
lld/ELF/Symbols.h
lld/test/ELF/relocation-copy-alias.s

index 711f46f..86c506a 100644 (file)
@@ -300,9 +300,9 @@ Symbol *SymbolTable::addUndefined(StringRef Name, uint8_t Binding,
     replaceSymbol<Undefined>(S, File, Name, Binding, StOther, Type);
     return S;
   }
+  if (S->isShared() || S->isLazy() || (S->isUndefined() && Binding != STB_WEAK))
+    S->Binding = Binding;
   if (Binding != STB_WEAK) {
-    if (!S->isDefined())
-      S->Binding = Binding;
     if (auto *SS = dyn_cast<SharedSymbol>(S))
       if (!Config->GcSections)
         SS->getFile<ELFT>()->IsNeeded = true;
@@ -310,12 +310,10 @@ Symbol *SymbolTable::addUndefined(StringRef Name, uint8_t Binding,
   if (auto *L = dyn_cast<Lazy>(S)) {
     // An undefined weak will not fetch archive members. See comment on Lazy in
     // Symbols.h for the details.
-    if (Binding == STB_WEAK) {
+    if (Binding == STB_WEAK)
       L->Type = Type;
-      L->Binding = STB_WEAK;
-    } else if (InputFile *F = L->fetch()) {
+    else if (InputFile *F = L->fetch())
       addFile<ELFT>(F);
-    }
   }
   return S;
 }
@@ -497,8 +495,9 @@ void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> *File,
   if (WasInserted || ((S->isUndefined() || S->isLazy()) &&
                       S->getVisibility() == STV_DEFAULT)) {
     uint8_t Binding = S->Binding;
-    replaceSymbol<SharedSymbol>(S, File, Name, Sym.st_other, Sym.getType(),
-                                Sym.st_value, Sym.st_size, Alignment, Verdef);
+    replaceSymbol<SharedSymbol>(S, File, Name, Sym.getBinding(), Sym.st_other,
+                                Sym.getType(), Sym.st_value, Sym.st_size,
+                                Alignment, Verdef);
     if (!WasInserted) {
       S->Binding = Binding;
       if (!S->isWeak() && !Config->GcSections)
index 533d43b..99fc61b 100644 (file)
@@ -209,10 +209,11 @@ class SharedSymbol : public Symbol {
 public:
   static bool classof(const Symbol *S) { return S->kind() == SharedKind; }
 
-  SharedSymbol(StringRef Name, uint8_t StOther, uint8_t Type, uint64_t Value,
-               uint64_t Size, uint32_t Alignment, const void *Verdef)
-      : Symbol(SharedKind, Name, llvm::ELF::STB_WEAK, StOther, Type),
-        Verdef(Verdef), Value(Value), Size(Size), Alignment(Alignment) {
+  SharedSymbol(StringRef Name, uint8_t Binding, uint8_t StOther, uint8_t Type,
+               uint64_t Value, uint64_t Size, uint32_t Alignment,
+               const void *Verdef)
+      : Symbol(SharedKind, Name, Binding, StOther, Type), Verdef(Verdef),
+        Value(Value), Size(Size), Alignment(Alignment) {
     // GNU ifunc is a mechanism to allow user-supplied functions to
     // resolve PLT slot values at load-time. This is contrary to the
     // regualr symbol resolution scheme in which symbols are resolved just
index edb1550..ee92047 100644 (file)
@@ -61,7 +61,7 @@ movl $5, b2
 // CHECK:      Name: b3
 // CHECK-NEXT: Value: [[B]]
 // CHECK-NEXT: Size: 1
-// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Binding: Global
 // CHECK-NEXT: Type: Object (0x1)
 // CHECK-NEXT: Other: 0
 // CHECK-NEXT: Section: .bss