[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)
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
// and identical code folding.
if (Config->GcSections)

View File

@ -64,11 +64,6 @@ static void resolveReloc(InputSectionBase &Sec, RelT &Rel,
std::function<void(InputSectionBase *, uint64_t)> Fn) {
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 (!D->Section)
return;
@ -223,13 +218,9 @@ template <class ELFT> void elf::markLive() {
};
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))
Enqueue(IS, D->Value);
return;
}
if (auto *S = dyn_cast_or_null<DefinedCommon>(Sym))
S->Live = true;
};
// Add GC root symbols.

View File

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

View File

@ -167,11 +167,6 @@ public:
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.
uint32_t Alignment;

View File

@ -54,24 +54,28 @@ uint64_t SyntheticSection::getVA() const {
return 0;
}
std::vector<InputSection *> elf::createCommonSections() {
if (!Config->DefineCommon)
return {};
std::vector<InputSection *> Ret;
// Create a .bss section for each common section and replace the common symbol
// with a DefinedRegular symbol.
template <class ELFT> void elf::createCommonSections() {
for (Symbol *S : Symtab->getSymbols()) {
auto *Sym = dyn_cast<DefinedCommon>(S->body());
if (!Sym || !Sym->Live)
if (!Sym)
continue;
Sym->Section = make<BssSection>("COMMON");
size_t Pos = Sym->Section->reserveSpace(Sym->Size, Sym->Alignment);
assert(Pos == 0);
(void)Pos;
Sym->Section->File = Sym->getFile();
Ret.push_back(Sym->Section);
// Create a synthetic section for the common data.
auto *Section = make<BssSection>("COMMON");
Section->File = Sym->getFile();
Section->Live = !Config->GcSections;
Section->reserveSpace(Sym->Size, Sym->Alignment);
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.
@ -2378,6 +2382,11 @@ template void PltSection::addEntry<ELF32BE>(SymbolBody &Sym);
template void PltSection::addEntry<ELF64LE>(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<ELF32BE>();
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;
};
std::vector<InputSection *> createCommonSections();
template <class ELFT> void createCommonSections();
InputSection *createInterpSection();
template <class ELFT> MergeInputSection *createCommentSection();
void decompressAndMergeSections();

View File

@ -290,9 +290,6 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
Add(InX::BuildId);
}
for (InputSection *S : createCommonSections())
Add(S);
InX::Bss = make<BssSection>(".bss");
Add(InX::Bss);
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 (!S->getSectionPiece(D->Value)->Live)
return false;
return true;
}
if (auto *Sym = dyn_cast<DefinedCommon>(&B))
return Sym->Live;
return true;
}