[ELF] Simpler scheme for handling common symbols

Convert all common symbols to regular symbols after scan.
This means that the downstream code does not to handle common symbols as a special case.

Differential Revision: https://reviews.llvm.org/D38137

llvm-svn: 314495
This commit is contained in:
Ben Dunbobbin 2017-09-29 09:08:26 +00:00
parent 6150419d71
commit 73eabf23a4
8 changed files with 2486 additions and 45 deletions

View File

@ -1086,6 +1086,14 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
if (!Config->Relocatable) if (!Config->Relocatable)
InputSections.push_back(createCommentSection<ELFT>()); InputSections.push_back(createCommentSection<ELFT>());
// Create a .bss section for each common symbol and then replace the common
// symbol with a DefinedRegular symbol. As a result, all common symbols are
// "instantiated" as regular defined symbols, so that we don't need to care
// about common symbols beyond this point. Note that if -r is given, we just
// need to pass through common symbols as-is.
if (Config->DefineCommon)
createCommonSections<ELFT>();
// Do size optimizations: garbage collection, merging of SHF_MERGE sections // Do size optimizations: garbage collection, merging of SHF_MERGE sections
// and identical code folding. // and identical code folding.
if (Config->GcSections) if (Config->GcSections)

View File

@ -64,11 +64,6 @@ static void resolveReloc(InputSectionBase &Sec, RelT &Rel,
std::function<void(InputSectionBase *, uint64_t)> Fn) { std::function<void(InputSectionBase *, uint64_t)> Fn) {
SymbolBody &B = Sec.getFile<ELFT>()->getRelocTargetSym(Rel); SymbolBody &B = Sec.getFile<ELFT>()->getRelocTargetSym(Rel);
if (auto *Sym = dyn_cast<DefinedCommon>(&B)) {
Sym->Live = true;
return;
}
if (auto *D = dyn_cast<DefinedRegular>(&B)) { if (auto *D = dyn_cast<DefinedRegular>(&B)) {
if (!D->Section) if (!D->Section)
return; return;
@ -223,13 +218,9 @@ template <class ELFT> void elf::markLive() {
}; };
auto MarkSymbol = [&](SymbolBody *Sym) { auto MarkSymbol = [&](SymbolBody *Sym) {
if (auto *D = dyn_cast_or_null<DefinedRegular>(Sym)) { if (auto *D = dyn_cast_or_null<DefinedRegular>(Sym))
if (auto *IS = cast_or_null<InputSectionBase>(D->Section)) if (auto *IS = cast_or_null<InputSectionBase>(D->Section))
Enqueue(IS, D->Value); Enqueue(IS, D->Value);
return;
}
if (auto *S = dyn_cast_or_null<DefinedCommon>(Sym))
S->Live = true;
}; };
// Add GC root symbols. // Add GC root symbols.

View File

@ -99,14 +99,8 @@ static uint64_t getSymVA(const SymbolBody &Body, int64_t &Addend) {
} }
return VA; return VA;
} }
case SymbolBody::DefinedCommonKind: { case SymbolBody::DefinedCommonKind:
if (!Config->DefineCommon) llvm_unreachable("common are converted to bss");
return 0;
auto DC = cast<DefinedCommon>(Body);
if (!DC.Live)
return 0;
return DC.Section->getParent()->Addr + DC.Section->OutSecOff;
}
case SymbolBody::SharedKind: { case SymbolBody::SharedKind: {
auto &SS = cast<SharedSymbol>(Body); auto &SS = cast<SharedSymbol>(Body);
if (SS.CopyRelSec) if (SS.CopyRelSec)
@ -286,7 +280,7 @@ DefinedCommon::DefinedCommon(StringRef Name, uint64_t Size, uint32_t Alignment,
uint8_t StOther, uint8_t Type) uint8_t StOther, uint8_t Type)
: Defined(SymbolBody::DefinedCommonKind, Name, /*IsLocal=*/false, StOther, : Defined(SymbolBody::DefinedCommonKind, Name, /*IsLocal=*/false, StOther,
Type), Type),
Live(!Config->GcSections), Alignment(Alignment), Size(Size) {} Alignment(Alignment), Size(Size) {}
// If a shared symbol is referred via a copy relocation, its alignment // If a shared symbol is referred via a copy relocation, its alignment
// becomes part of the ABI. This function returns a symbol alignment. // becomes part of the ABI. This function returns a symbol alignment.

View File

@ -167,11 +167,6 @@ public:
return S->kind() == SymbolBody::DefinedCommonKind; return S->kind() == SymbolBody::DefinedCommonKind;
} }
// True if this symbol is not GC'ed. Liveness is usually a notion of
// input sections and not of symbols, but since common symbols don't
// belong to any input section, their liveness is managed by this bit.
bool Live;
// The maximum alignment we have seen for this symbol. // The maximum alignment we have seen for this symbol.
uint32_t Alignment; uint32_t Alignment;

View File

@ -54,24 +54,28 @@ uint64_t SyntheticSection::getVA() const {
return 0; return 0;
} }
std::vector<InputSection *> elf::createCommonSections() { // Create a .bss section for each common section and replace the common symbol
if (!Config->DefineCommon) // with a DefinedRegular symbol.
return {}; template <class ELFT> void elf::createCommonSections() {
std::vector<InputSection *> Ret;
for (Symbol *S : Symtab->getSymbols()) { for (Symbol *S : Symtab->getSymbols()) {
auto *Sym = dyn_cast<DefinedCommon>(S->body()); auto *Sym = dyn_cast<DefinedCommon>(S->body());
if (!Sym || !Sym->Live)
if (!Sym)
continue; continue;
Sym->Section = make<BssSection>("COMMON"); // Create a synthetic section for the common data.
size_t Pos = Sym->Section->reserveSpace(Sym->Size, Sym->Alignment); auto *Section = make<BssSection>("COMMON");
assert(Pos == 0); Section->File = Sym->getFile();
(void)Pos; Section->Live = !Config->GcSections;
Sym->Section->File = Sym->getFile(); Section->reserveSpace(Sym->Size, Sym->Alignment);
Ret.push_back(Sym->Section); InputSections.push_back(Section);
// Replace all DefinedCommon symbols with DefinedRegular symbols so that we
// don't have to care about DefinedCommon symbols beyond this point.
replaceBody<DefinedRegular>(S, Sym->getFile(), Sym->getName(),
static_cast<bool>(Sym->IsLocal), Sym->StOther,
Sym->Type, 0, Sym->getSize<ELFT>(), Section);
} }
return Ret;
} }
// Returns an LLD version string. // Returns an LLD version string.
@ -2378,6 +2382,11 @@ template void PltSection::addEntry<ELF32BE>(SymbolBody &Sym);
template void PltSection::addEntry<ELF64LE>(SymbolBody &Sym); template void PltSection::addEntry<ELF64LE>(SymbolBody &Sym);
template void PltSection::addEntry<ELF64BE>(SymbolBody &Sym); template void PltSection::addEntry<ELF64BE>(SymbolBody &Sym);
template void elf::createCommonSections<ELF32LE>();
template void elf::createCommonSections<ELF32BE>();
template void elf::createCommonSections<ELF64LE>();
template void elf::createCommonSections<ELF64BE>();
template MergeInputSection *elf::createCommentSection<ELF32LE>(); template MergeInputSection *elf::createCommentSection<ELF32LE>();
template MergeInputSection *elf::createCommentSection<ELF32BE>(); template MergeInputSection *elf::createCommentSection<ELF32BE>();
template MergeInputSection *elf::createCommentSection<ELF64LE>(); template MergeInputSection *elf::createCommentSection<ELF64LE>();

File diff suppressed because it is too large Load Diff

View File

@ -786,7 +786,7 @@ private:
size_t Size = 0; size_t Size = 0;
}; };
std::vector<InputSection *> createCommonSections(); template <class ELFT> void createCommonSections();
InputSection *createInterpSection(); InputSection *createInterpSection();
template <class ELFT> MergeInputSection *createCommentSection(); template <class ELFT> MergeInputSection *createCommentSection();
void decompressAndMergeSections(); void decompressAndMergeSections();

View File

@ -290,9 +290,6 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
Add(InX::BuildId); Add(InX::BuildId);
} }
for (InputSection *S : createCommonSections())
Add(S);
InX::Bss = make<BssSection>(".bss"); InX::Bss = make<BssSection>(".bss");
Add(InX::Bss); Add(InX::Bss);
InX::BssRelRo = make<BssSection>(".bss.rel.ro"); InX::BssRelRo = make<BssSection>(".bss.rel.ro");
@ -441,11 +438,7 @@ static bool includeInSymtab(const SymbolBody &B) {
if (auto *S = dyn_cast<MergeInputSection>(Sec)) if (auto *S = dyn_cast<MergeInputSection>(Sec))
if (!S->getSectionPiece(D->Value)->Live) if (!S->getSectionPiece(D->Value)->Live)
return false; return false;
return true;
} }
if (auto *Sym = dyn_cast<DefinedCommon>(&B))
return Sym->Live;
return true; return true;
} }