forked from OSchip/llvm-project
[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:
parent
6150419d71
commit
73eabf23a4
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue