diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 30b994733094..16d593bbac65 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1121,14 +1121,6 @@ template void LinkerDriver::link(opt::InputArgList &Args) { if (!Config->Relocatable) InputSections.push_back(createCommentSection()); - // 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(); - // Do size optimizations: garbage collection, merging of SHF_MERGE sections // and identical code folding. markLive(); diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 3f16920d20c8..344943e6fbb8 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -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) {} }; diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 047af33b96e5..8dd300ef7700 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -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(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(S)) { + if (R->Section && isa(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("COMMON", Size, Alignment); + Bss->File = File; + Bss->Live = !Config->GcSections; + InputSections.push_back(Bss); + S->Binding = Binding; - replaceSymbol(S, File, N, Size, Alignment, StOther, Type); + replaceSymbol(S, File, N, /*IsLocal=*/false, StOther, Type, + 0, Size, Bss); } else if (Cmp == 0) { - auto *C = dyn_cast(S); - if (!C) { + auto *D = cast(S); + auto *Bss = dyn_cast_or_null(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(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; } diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index a398efef5501..504d3b6ff270 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -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(Sym); if (SS.CopyRelSec) @@ -182,8 +180,6 @@ uint64_t Symbol::getPltVA() const { } uint64_t Symbol::getSize() const { - if (const auto *C = dyn_cast(this)) - return C->Size; if (const auto *DR = dyn_cast(this)) return DR->Size; if (const auto *S = dyn_cast(this)) @@ -204,12 +200,6 @@ OutputSection *Symbol::getOutputSection() const { return nullptr; } - if (auto *S = dyn_cast(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(cast(Sym)->Section)) + S = ": common definition of "; else S = ": definition of "; diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 4f497af263cd..e1ff6c1e17d5 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -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)]; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index e99a45af3105..95ef5f520ffe 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -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 void elf::createCommonSections() { - for (Symbol *S : Symtab->getSymbols()) { - auto *Sym = dyn_cast(S); - - if (!Sym) - continue; - - // Create a synthetic section for the common data. - auto *Section = make("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( - S, Sym->getFile(), Sym->getName(), static_cast(Sym->isLocal()), - Sym->StOther, Sym->Type, 0, Sym->getSize(), Section); - } -} - // Returns an LLD version string. static ArrayRef 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 void SymbolTableSection::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(Sym)) + CommonSec = dyn_cast_or_null(D->Section); + if (CommonSec) + ESym->st_shndx = SHN_COMMON; + else if (const OutputSection *OutSec = Sym->getOutputSection()) ESym->st_shndx = OutSec->SectionIndex; else if (isa(Sym)) ESym->st_shndx = SHN_ABS; - else if (isa(Sym)) - ESym->st_shndx = SHN_COMMON; else ESym->st_shndx = SHN_UNDEF; @@ -1618,8 +1600,8 @@ template void SymbolTableSection::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(Sym)) - ESym->st_value = cast(Sym)->Alignment; + if (CommonSec) + ESym->st_value = CommonSec->Alignment; else ESym->st_value = Sym->getVA(); @@ -2642,11 +2624,6 @@ template void PltSection::addEntry(Symbol &Sym); template void PltSection::addEntry(Symbol &Sym); template void PltSection::addEntry(Symbol &Sym); -template void elf::createCommonSections(); -template void elf::createCommonSections(); -template void elf::createCommonSections(); -template void elf::createCommonSections(); - template MergeInputSection *elf::createCommentSection(); template MergeInputSection *elf::createCommentSection(); template MergeInputSection *elf::createCommentSection(); diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 042a98ea5197..c18be5b59f25 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -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 void createCommonSections(); InputSection *createInterpSection(); template MergeInputSection *createCommentSection(); void decompressSections(); diff --git a/lld/test/ELF/relocatable-common.s b/lld/test/ELF/relocatable-common.s index 3ead775492fc..89f08e23bf7b 100644 --- a/lld/test/ELF/relocatable-common.s +++ b/lld/test/ELF/relocatable-common.s @@ -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