[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