ELF: Remove DefinedCommon.

Common symbols are now represented with a DefinedRegular that points
to a BssSection, even during symbol resolution.

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

llvm-svn: 317447
This commit is contained in:
Peter Collingbourne 2017-11-06 04:33:58 +00:00
parent 32665f702e
commit 6c55a70838
8 changed files with 42 additions and 96 deletions

View File

@ -1121,14 +1121,6 @@ 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.
markLive<ELFT>();

View File

@ -24,7 +24,6 @@
namespace lld {
namespace elf {
class DefinedCommon;
class Symbol;
struct SectionPiece;
@ -55,6 +54,8 @@ public:
// If GC is disabled, all sections are considered live by default.
unsigned Live : 1;
unsigned Bss : 1;
// These corresponds to the fields in Elf_Shdr.
uint32_t Alignment;
uint64_t Flags;
@ -78,7 +79,7 @@ protected:
SectionBase(Kind SectionKind, StringRef Name, uint64_t Flags,
uint64_t Entsize, uint64_t Alignment, uint32_t Type,
uint32_t Info, uint32_t Link)
: Name(Name), SectionKind(SectionKind), Live(false),
: Name(Name), SectionKind(SectionKind), Live(false), Bss(false),
Alignment(Alignment), Flags(Flags), Entsize(Entsize), Type(Type),
Link(Link), Info(Info) {}
};

View File

@ -19,6 +19,7 @@
#include "LinkerScript.h"
#include "Memory.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/STLExtras.h"
@ -365,13 +366,13 @@ static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding,
S->Binding = Binding;
return Cmp;
}
if (isa<DefinedCommon>(S)) {
// Non-common symbols take precedence over common symbols.
if (Config->WarnCommon)
warn("common " + S->getName() + " is overridden");
return 1;
}
if (auto *R = dyn_cast<DefinedRegular>(S)) {
if (R->Section && isa<BssSection>(R->Section)) {
// Non-common symbols take precedence over common symbols.
if (Config->WarnCommon)
warn("common " + S->getName() + " is overridden");
return 1;
}
if (R->Section == nullptr && Binding == STB_GLOBAL && IsAbsolute &&
R->Value == Value)
return -1;
@ -388,11 +389,18 @@ Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment,
/*CanOmitFromDynSym*/ false, File);
int Cmp = compareDefined(S, WasInserted, Binding, N);
if (Cmp > 0) {
auto *Bss = make<BssSection>("COMMON", Size, Alignment);
Bss->File = File;
Bss->Live = !Config->GcSections;
InputSections.push_back(Bss);
S->Binding = Binding;
replaceSymbol<DefinedCommon>(S, File, N, Size, Alignment, StOther, Type);
replaceSymbol<DefinedRegular>(S, File, N, /*IsLocal=*/false, StOther, Type,
0, Size, Bss);
} else if (Cmp == 0) {
auto *C = dyn_cast<DefinedCommon>(S);
if (!C) {
auto *D = cast<DefinedRegular>(S);
auto *Bss = dyn_cast_or_null<BssSection>(D->Section);
if (!Bss) {
// Non-common symbols take precedence over common symbols.
if (Config->WarnCommon)
warn("common " + S->getName() + " is overridden");
@ -400,11 +408,13 @@ Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment,
}
if (Config->WarnCommon)
warn("multiple common of " + S->getName());
warn("multiple common of " + D->getName());
Alignment = C->Alignment = std::max(C->Alignment, Alignment);
if (Size > C->Size)
replaceSymbol<DefinedCommon>(S, File, N, Size, Alignment, StOther, Type);
Bss->Alignment = std::max(Bss->Alignment, Alignment);
if (Size > Bss->Size) {
D->File = Bss->File = File;
D->Size = Bss->Size = Size;
}
}
return S;
}

View File

@ -99,8 +99,6 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
}
return VA;
}
case Symbol::DefinedCommonKind:
llvm_unreachable("common are converted to bss");
case Symbol::SharedKind: {
auto &SS = cast<SharedSymbol>(Sym);
if (SS.CopyRelSec)
@ -182,8 +180,6 @@ uint64_t Symbol::getPltVA() const {
}
uint64_t Symbol::getSize() const {
if (const auto *C = dyn_cast<DefinedCommon>(this))
return C->Size;
if (const auto *DR = dyn_cast<DefinedRegular>(this))
return DR->Size;
if (const auto *S = dyn_cast<SharedSymbol>(this))
@ -204,12 +200,6 @@ OutputSection *Symbol::getOutputSection() const {
return nullptr;
}
if (auto *S = dyn_cast<DefinedCommon>(this)) {
if (Config->DefineCommon)
return S->Section->getParent();
return nullptr;
}
return nullptr;
}
@ -321,12 +311,12 @@ void elf::printTraceSymbol(Symbol *Sym) {
std::string S;
if (Sym->isUndefined())
S = ": reference to ";
else if (Sym->isCommon())
S = ": common definition of ";
else if (Sym->isLazy())
S = ": lazy definition of ";
else if (Sym->isShared())
S = ": shared definition of ";
else if (dyn_cast_or_null<BssSection>(cast<DefinedRegular>(Sym)->Section))
S = ": common definition of ";
else
S = ": definition of ";

View File

@ -40,8 +40,7 @@ public:
enum Kind {
DefinedFirst,
DefinedRegularKind = DefinedFirst,
DefinedCommonKind,
DefinedLast = DefinedCommonKind,
DefinedLast = DefinedRegularKind,
SharedKind,
UndefinedKind,
LazyArchiveKind,
@ -97,7 +96,6 @@ public:
bool isUndefined() const { return SymbolKind == UndefinedKind; }
bool isDefined() const { return SymbolKind <= DefinedLast; }
bool isCommon() const { return SymbolKind == DefinedCommonKind; }
bool isShared() const { return SymbolKind == SharedKind; }
bool isLocal() const { return IsLocal; }
@ -106,7 +104,7 @@ public:
}
bool isInCurrentOutput() const {
return SymbolKind == DefinedRegularKind || SymbolKind == DefinedCommonKind;
return SymbolKind == DefinedRegularKind;
}
// True is this is an undefined weak symbol. This only works once
@ -199,26 +197,6 @@ public:
static bool classof(const Symbol *S) { return S->isDefined(); }
};
class DefinedCommon : public Defined {
public:
DefinedCommon(StringRef Name, uint64_t Size, uint32_t Alignment,
uint8_t StOther, uint8_t Type)
: Defined(DefinedCommonKind, Name, /*IsLocal=*/false, StOther, Type),
Alignment(Alignment), Size(Size) {}
static bool classof(const Symbol *S) {
return S->kind() == DefinedCommonKind;
}
// The maximum alignment we have seen for this symbol.
uint32_t Alignment;
// The output offset of this common symbol in the output bss.
// Computed by the writer.
uint64_t Size;
BssSection *Section = nullptr;
};
// Regular defined symbols read from object file symbol tables.
class DefinedRegular : public Defined {
public:
@ -378,7 +356,6 @@ struct ElfSym {
// using the placement new.
union SymbolUnion {
alignas(DefinedRegular) char A[sizeof(DefinedRegular)];
alignas(DefinedCommon) char B[sizeof(DefinedCommon)];
alignas(Undefined) char C[sizeof(Undefined)];
alignas(SharedSymbol) char D[sizeof(SharedSymbol)];
alignas(LazyArchive) char E[sizeof(LazyArchive)];

View File

@ -63,29 +63,6 @@ uint64_t SyntheticSection::getVA() const {
return 0;
}
// Create a .bss section for each common symbol 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);
if (!Sym)
continue;
// Create a synthetic section for the common data.
auto *Section = make<BssSection>("COMMON", Sym->Size, Sym->Alignment);
Section->File = Sym->getFile();
Section->Live = !Config->GcSections;
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.
replaceSymbol<DefinedRegular>(
S, Sym->getFile(), Sym->getName(), static_cast<bool>(Sym->isLocal()),
Sym->StOther, Sym->Type, 0, Sym->getSize(), Section);
}
}
// Returns an LLD version string.
static ArrayRef<uint8_t> getVersion() {
// Check LLD_VERSION first for ease of testing.
@ -367,6 +344,7 @@ void BuildIdSection::computeHash(
BssSection::BssSection(StringRef Name, uint64_t Size, uint32_t Alignment)
: SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, Alignment, Name) {
this->Bss = true;
if (OutputSection *Sec = getParent())
Sec->Alignment = std::max(Sec->Alignment, Alignment);
this->Size = Size;
@ -1596,12 +1574,16 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
ESym->st_name = Ent.StrTabOffset;
// Set a section index.
if (const OutputSection *OutSec = Sym->getOutputSection())
BssSection *CommonSec = nullptr;
if (!Config->DefineCommon)
if (auto *D = dyn_cast<DefinedRegular>(Sym))
CommonSec = dyn_cast_or_null<BssSection>(D->Section);
if (CommonSec)
ESym->st_shndx = SHN_COMMON;
else if (const OutputSection *OutSec = Sym->getOutputSection())
ESym->st_shndx = OutSec->SectionIndex;
else if (isa<DefinedRegular>(Sym))
ESym->st_shndx = SHN_ABS;
else if (isa<DefinedCommon>(Sym))
ESym->st_shndx = SHN_COMMON;
else
ESym->st_shndx = SHN_UNDEF;
@ -1618,8 +1600,8 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
// st_value is usually an address of a symbol, but that has a
// special meaining for uninstantiated common symbols (this can
// occur if -r is given).
if (!Config->DefineCommon && isa<DefinedCommon>(Sym))
ESym->st_value = cast<DefinedCommon>(Sym)->Alignment;
if (CommonSec)
ESym->st_value = CommonSec->Alignment;
else
ESym->st_value = Sym->getVA();
@ -2642,11 +2624,6 @@ template void PltSection::addEntry<ELF32BE>(Symbol &Sym);
template void PltSection::addEntry<ELF64LE>(Symbol &Sym);
template void PltSection::addEntry<ELF64BE>(Symbol &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>();

View File

@ -159,7 +159,7 @@ public:
bool empty() const override { return getSize() == 0; }
size_t getSize() const override { return Size; }
private:
static bool classof(const SectionBase *S) { return S->Bss; }
uint64_t Size;
};
@ -821,7 +821,6 @@ private:
size_t Size = 0;
};
template <class ELFT> void createCommonSections();
InputSection *createInterpSection();
template <class ELFT> MergeInputSection *createCommentSection();
void decompressSections();

View File

@ -30,7 +30,7 @@
# DEFCOMM-NEXT: Binding: Global
# DEFCOMM-NEXT: Type: Object
# DEFCOMM-NEXT: Other: 0
# DEFCOMM-NEXT: Section: COMMON (0x2)
# DEFCOMM-NEXT: Section: COMMON
# DEFCOMM-NEXT: }
.comm common,4,4