[lld] r249406 - Handle strong undefined symbols fetching members after a weak undefined.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 6 07:33:59 PDT 2015


Author: rafael
Date: Tue Oct  6 09:33:58 2015
New Revision: 249406

URL: http://llvm.org/viewvc/llvm-project?rev=249406&view=rev
Log:
Handle strong undefined symbols fetching members after a weak undefined.

This is a case that requires --start-group --end-group with regular ELF
linkers. Fortunately it is still possible to handle it with lazy symbols without
taking a second look at archives.

Thanks to Michael Spencer for the bug report.

Added:
    lld/trunk/test/elf2/Inputs/archive3.s
    lld/trunk/test/elf2/Inputs/archive4.s
Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/Symbols.h
    lld/trunk/test/elf2/archive.s

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=249406&r1=249405&r2=249406&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Tue Oct  6 09:33:58 2015
@@ -49,8 +49,7 @@ void InputSection<ELFT>::relocate(
         continue;
       SymVA = getLocalSymVA(Sym, File);
     } else {
-      const auto &Body =
-          *cast<ELFSymbolBody<ELFT>>(File.getSymbolBody(SymIndex));
+      SymbolBody &Body = *File.getSymbolBody(SymIndex);
       SymVA = getSymVA<ELFT>(Body, BssSec);
       if (Target->relocNeedsPlt(Type, Body)) {
         SymVA = PltSec.getEntryAddr(Body);

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=249406&r1=249405&r2=249406&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Tue Oct  6 09:33:58 2015
@@ -349,13 +349,14 @@ void OutputSection<ELFT>::addSection(Inp
 
 template <class ELFT>
 typename ELFFile<ELFT>::uintX_t
-lld::elf2::getSymVA(const ELFSymbolBody<ELFT> &S,
-                    const OutputSection<ELFT> &BssSec) {
+lld::elf2::getSymVA(const SymbolBody &S, const OutputSection<ELFT> &BssSec) {
   switch (S.kind()) {
-  case SymbolBody::DefinedSyntheticKind:
-    return cast<DefinedSynthetic<ELFT>>(S).Section.getVA() + S.Sym.st_value;
+  case SymbolBody::DefinedSyntheticKind: {
+    auto &D = cast<DefinedSynthetic<ELFT>>(S);
+    return D.Section.getVA() + D.Sym.st_value;
+  }
   case SymbolBody::DefinedAbsoluteKind:
-    return S.Sym.st_value;
+    return cast<DefinedAbsolute<ELFT>>(S).Sym.st_value;
   case SymbolBody::DefinedRegularKind: {
     const auto &DR = cast<DefinedRegular<ELFT>>(S);
     const InputSection<ELFT> *SC = &DR.Section;
@@ -368,9 +369,9 @@ lld::elf2::getSymVA(const ELFSymbolBody<
   case SymbolBody::UndefinedKind:
     return 0;
   case SymbolBody::LazyKind:
-    break;
+    assert(S.isUsedInRegularObj() && "Lazy symbol reached writer");
+    return 0;
   }
-  llvm_unreachable("Lazy symbol reached writer");
 }
 
 template <class ELFT>
@@ -409,8 +410,6 @@ void StringTableSection<Is64Bits>::write
 }
 
 template <class ELFT> bool lld::elf2::includeInSymtab(const SymbolBody &B) {
-  if (B.isLazy())
-    return false;
   if (!B.isUsedInRegularObj())
     return false;
 
@@ -521,21 +520,20 @@ void SymbolTableSection<ELFT>::writeGlob
     if (StrTabSec.isDynamic() && !includeInDynamicSymtab(*Body))
       continue;
 
-    const auto &EBody = *cast<ELFSymbolBody<ELFT>>(Body);
-    const Elf_Sym &InputSym = EBody.Sym;
     auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
     Buf += sizeof(*ESym);
+
     ESym->st_name = StrTabSec.getFileOff(Name);
 
     const OutputSection<ELFT> *Out = nullptr;
     const InputSection<ELFT> *Section = nullptr;
 
-    switch (EBody.kind()) {
+    switch (Body->kind()) {
     case SymbolBody::DefinedSyntheticKind:
       Out = &cast<DefinedSynthetic<ELFT>>(Body)->Section;
       break;
     case SymbolBody::DefinedRegularKind:
-      Section = &cast<DefinedRegular<ELFT>>(EBody).Section;
+      Section = &cast<DefinedRegular<ELFT>>(Body)->Section;
       break;
     case SymbolBody::DefinedCommonKind:
       Out = &BssSec;
@@ -543,25 +541,33 @@ void SymbolTableSection<ELFT>::writeGlob
     case SymbolBody::UndefinedKind:
     case SymbolBody::DefinedAbsoluteKind:
     case SymbolBody::SharedKind:
-      break;
     case SymbolBody::LazyKind:
-      llvm_unreachable("Lazy symbol got to output symbol table!");
+      break;
     }
 
-    unsigned char Binding = InputSym.getBinding();
-    unsigned char Visibility = EBody.getMostConstrainingVisibility();
+    unsigned char Binding = Body->isWeak() ? STB_WEAK : STB_GLOBAL;
+    unsigned char Type = STT_NOTYPE;
+    uintX_t Size = 0;
+    if (const auto *EBody = dyn_cast<ELFSymbolBody<ELFT>>(Body)) {
+      const Elf_Sym &InputSym = EBody->Sym;
+      Binding = InputSym.getBinding();
+      Type = InputSym.getType();
+      Size = InputSym.st_size;
+    }
+
+    unsigned char Visibility = Body->getMostConstrainingVisibility();
     if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
       Binding = STB_LOCAL;
 
-    ESym->setBindingAndType(Binding, InputSym.getType());
-    ESym->st_size = InputSym.st_size;
+    ESym->setBindingAndType(Binding, Type);
+    ESym->st_size = Size;
     ESym->setVisibility(Visibility);
-    ESym->st_value = getSymVA(EBody, BssSec);
+    ESym->st_value = getSymVA(*Body, BssSec);
 
     if (Section)
       Out = Section->getOutputSection();
 
-    if (InputSym.isAbsolute())
+    if (isa<DefinedAbsolute<ELFT>>(Body))
       ESym->st_shndx = SHN_ABS;
     else if (Out)
       ESym->st_shndx = Out->getSectionIndex();
@@ -629,17 +635,14 @@ template class SymbolTableSection<ELF32B
 template class SymbolTableSection<ELF64LE>;
 template class SymbolTableSection<ELF64BE>;
 
-template ELFFile<ELF32LE>::uintX_t
-getSymVA(const ELFSymbolBody<ELF32LE> &, const OutputSection<ELF32LE> &);
-
-template ELFFile<ELF32BE>::uintX_t
-getSymVA(const ELFSymbolBody<ELF32BE> &, const OutputSection<ELF32BE> &);
-
-template ELFFile<ELF64LE>::uintX_t
-getSymVA(const ELFSymbolBody<ELF64LE> &, const OutputSection<ELF64LE> &);
-
-template ELFFile<ELF64BE>::uintX_t
-getSymVA(const ELFSymbolBody<ELF64BE> &, const OutputSection<ELF64BE> &);
+template ELFFile<ELF32LE>::uintX_t getSymVA(const SymbolBody &,
+                                            const OutputSection<ELF32LE> &);
+template ELFFile<ELF32BE>::uintX_t getSymVA(const SymbolBody &,
+                                            const OutputSection<ELF32BE> &);
+template ELFFile<ELF64LE>::uintX_t getSymVA(const SymbolBody &,
+                                            const OutputSection<ELF64LE> &);
+template ELFFile<ELF64BE>::uintX_t getSymVA(const SymbolBody &,
+                                            const OutputSection<ELF64BE> &);
 
 template ELFFile<ELF32LE>::uintX_t
 getLocalSymVA(const ELFFile<ELF32LE>::Elf_Sym *, const ObjectFile<ELF32LE> &);

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=249406&r1=249405&r2=249406&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Tue Oct  6 09:33:58 2015
@@ -34,7 +34,7 @@ template <class ELFT> class ELFSymbolBod
 
 template <class ELFT>
 typename llvm::object::ELFFile<ELFT>::uintX_t
-getSymVA(const ELFSymbolBody<ELFT> &S, const OutputSection<ELFT> &BssSec);
+getSymVA(const SymbolBody &S, const OutputSection<ELFT> &BssSec);
 
 template <class ELFT>
 typename llvm::object::ELFFile<ELFT>::uintX_t

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=249406&r1=249405&r2=249406&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Tue Oct  6 09:33:58 2015
@@ -256,10 +256,23 @@ void SymbolTable::addLazy(Lazy *New) {
   if (Sym->Body == New)
     return;
   SymbolBody *Existing = Sym->Body;
-  if (Existing->isDefined() || Existing->isLazy() || Existing->isWeak())
+  if (Existing->isDefined() || Existing->isLazy())
     return;
   Sym->Body = New;
   assert(Existing->isUndefined() && "Unexpected symbol kind.");
+
+  // Weak undefined symbols should not fetch members from archives.
+  // If we were to keep old symbol we would not know that an archive member was
+  // available if a strong undefined symbol shows up afterwards in the link.
+  // If a strong undefined symbol never shows up, this lazy symbol will
+  // get to the end of the link and must be treated as the weak undefined one.
+  // We set UsedInRegularObj in a similar way to what is done with shared
+  // symbols and mark it as weak to reduce how many special cases are needed.
+  if (Existing->isWeak()) {
+    New->setUsedInRegularObj();
+    New->setWeak();
+    return;
+  }
   addMemberFile(New);
 }
 

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=249406&r1=249405&r2=249406&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Tue Oct  6 09:33:58 2015
@@ -103,7 +103,7 @@ protected:
   }
 
   const unsigned SymbolKind : 8;
-  const unsigned IsWeak : 1;
+  unsigned IsWeak : 1;
   unsigned MostConstrainingVisibility : 2;
   unsigned IsUsedInRegularObj : 1;
   unsigned IsUsedInDynamicReloc : 1;
@@ -282,6 +282,9 @@ public:
   // was already returned.
   std::unique_ptr<InputFile> getMember();
 
+  void setWeak() { IsWeak = true; }
+  void setUsedInRegularObj() { IsUsedInRegularObj = true; }
+
 private:
   ArchiveFile *File;
   const llvm::object::Archive::Symbol Sym;

Added: lld/trunk/test/elf2/Inputs/archive3.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/archive3.s?rev=249406&view=auto
==============================================================================
--- lld/trunk/test/elf2/Inputs/archive3.s (added)
+++ lld/trunk/test/elf2/Inputs/archive3.s Tue Oct  6 09:33:58 2015
@@ -0,0 +1,2 @@
+.global bar
+bar:

Added: lld/trunk/test/elf2/Inputs/archive4.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/archive4.s?rev=249406&view=auto
==============================================================================
--- lld/trunk/test/elf2/Inputs/archive4.s (added)
+++ lld/trunk/test/elf2/Inputs/archive4.s Tue Oct  6 09:33:58 2015
@@ -0,0 +1 @@
+.quad bar

Modified: lld/trunk/test/elf2/archive.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/archive.s?rev=249406&r1=249405&r2=249406&view=diff
==============================================================================
--- lld/trunk/test/elf2/archive.s (original)
+++ lld/trunk/test/elf2/archive.s Tue Oct  6 09:33:58 2015
@@ -1,8 +1,10 @@
 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/archive.s -o %t2
 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/archive2.s -o %t3
-# RUN: llvm-ar rcs %tar %t2 %t3
-# RUN: lld -flavor gnu2 %t %tar -o %tout
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/archive3.s -o %t4
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/archive4.s -o %t5
+# RUN: llvm-ar rcs %tar %t2 %t3 %t4
+# RUN: lld -flavor gnu2 %t %tar %t5 -o %tout
 # RUN: llvm-nm %tout | FileCheck %s
 # REQUIRES: x86
 
@@ -13,6 +15,11 @@
 .weak foo
 .quad foo
 
-# CHECK: T _start
-# CHECK: T end
-# CHECK: w foo
+.weak bar
+.quad bar
+
+
+# CHECK:      T _start
+# CHECK-NEXT: T bar
+# CHECK-NEXT: T end
+# CHECK-NEXT: w foo




More information about the llvm-commits mailing list