Skip to content

Commit

Permalink
[ELF] Simpler scheme for handling common symbols
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bd1976bris committed Sep 29, 2017
1 parent 6150419 commit 73eabf2
Show file tree
Hide file tree
Showing 8 changed files with 2,486 additions and 45 deletions.
8 changes: 8 additions & 0 deletions lld/ELF/Driver.cpp
Expand Up @@ -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)
Expand Down
11 changes: 1 addition & 10 deletions lld/ELF/MarkLive.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down
12 changes: 3 additions & 9 deletions lld/ELF/Symbols.cpp
Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand Down
5 changes: 0 additions & 5 deletions lld/ELF/Symbols.h
Expand Up @@ -167,11 +167,6 @@ class DefinedCommon : public Defined {
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;

Expand Down
35 changes: 22 additions & 13 deletions lld/ELF/SyntheticSections.cpp
Expand Up @@ -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.
Expand Down Expand Up @@ -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>();
Expand Down

0 comments on commit 73eabf2

Please sign in to comment.