diff options
-rw-r--r-- | lld/ELF/InputFiles.cpp | 4 | ||||
-rw-r--r-- | lld/ELF/OutputSections.cpp | 5 | ||||
-rw-r--r-- | lld/ELF/Symbols.cpp | 13 | ||||
-rw-r--r-- | lld/ELF/Symbols.h | 19 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 23 |
5 files changed, 35 insertions, 29 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 2edcb70023b..a68d83626d3 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -286,7 +286,9 @@ SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable, case SHN_UNDEF: return new (this->Alloc) UndefinedElf<ELFT>(Name, *Sym); case SHN_COMMON: - return new (this->Alloc) DefinedCommon<ELFT>(Name, *Sym); + return new (this->Alloc) DefinedCommon( + Name, Sym->st_size, Sym->st_value, + Sym->getBinding() == llvm::ELF::STB_WEAK, Sym->getVisibility()); } switch (Sym->getBinding()) { diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 3801629cfeb..613a2677cca 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -800,7 +800,7 @@ typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) { return SC->OutSec->getVA() + SC->getOffset(DR.Sym); } case SymbolBody::DefinedCommonKind: - return Out<ELFT>::Bss->getVA() + cast<DefinedCommon<ELFT>>(S).OffsetInBSS; + return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(S).OffsetInBSS; case SymbolBody::SharedKind: { auto &SS = cast<SharedSymbol<ELFT>>(S); if (SS.NeedsCopy) @@ -1370,6 +1370,9 @@ void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) { if (const Elf_Sym *InputSym = getElfSym<ELFT>(*Body)) { Type = InputSym->getType(); Size = InputSym->st_size; + } else if (auto *C = dyn_cast<DefinedCommon>(Body)) { + Type = STT_OBJECT; + Size = C->Size; } ESym->setBindingAndType(getSymbolBinding(Body), Type); diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index c3515d18ca6..44434177435 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -58,10 +58,10 @@ template <class ELFT> int SymbolBody::compare(SymbolBody *Other) { if (isCommon()) { if (!Other->isCommon()) return -1; - auto *ThisC = cast<DefinedCommon<ELFT>>(this); - auto *OtherC = cast<DefinedCommon<ELFT>>(Other); + auto *ThisC = cast<DefinedCommon>(this); + auto *OtherC = cast<DefinedCommon>(Other); uintX_t Align = std::max(ThisC->MaxAlignment, OtherC->MaxAlignment); - if (ThisC->Sym.st_size >= OtherC->Sym.st_size) { + if (ThisC->Size >= OtherC->Size) { ThisC->MaxAlignment = Align; return 1; } @@ -101,6 +101,13 @@ DefinedSynthetic<ELFT>::DefinedSynthetic(StringRef N, uintX_t Value, : Defined(SymbolBody::DefinedSyntheticKind, N, false, STV_DEFAULT, false), Value(Value), Section(Section) {} +DefinedCommon::DefinedCommon(StringRef N, uint64_t Size, uint64_t Alignment, + bool IsWeak, uint8_t Visibility) + : Defined(SymbolBody::DefinedCommonKind, N, IsWeak, Visibility, false) { + MaxAlignment = Alignment; + this->Size = Size; +} + std::unique_ptr<InputFile> Lazy::getMember() { MemoryBufferRef MBRef = File->getMember(&Sym); diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 0b70f5e2962..43e6a1196fc 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -57,9 +57,9 @@ public: enum Kind { DefinedFirst, DefinedRegularKind = DefinedFirst, - DefinedCommonKind, SharedKind, DefinedElfLast = SharedKind, + DefinedCommonKind, DefinedSyntheticKind, DefinedLast = DefinedSyntheticKind, UndefinedElfKind, @@ -154,15 +154,10 @@ public: } }; -template <class ELFT> class DefinedCommon : public DefinedElf<ELFT> { - typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym; - +class DefinedCommon : public Defined { public: - typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t; - DefinedCommon(StringRef N, const Elf_Sym &Sym) - : DefinedElf<ELFT>(SymbolBody::DefinedCommonKind, N, Sym) { - MaxAlignment = Sym.st_value; - } + DefinedCommon(StringRef N, uint64_t Size, uint64_t Alignment, bool IsWeak, + uint8_t Visibility); static bool classof(const SymbolBody *S) { return S->kind() == SymbolBody::DefinedCommonKind; @@ -170,10 +165,12 @@ public: // The output offset of this common symbol in the output bss. Computed by the // writer. - uintX_t OffsetInBSS; + uint64_t OffsetInBSS; // The maximum alignment we have seen for this symbol. - uintX_t MaxAlignment; + uint64_t MaxAlignment; + + uint64_t Size; }; // Regular defined symbols read from object file symbol tables. diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 2a258a81453..f2973d4c2d0 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -65,7 +65,7 @@ private: int getPhdrsNum() const; OutputSection<ELFT> *getBSS(); - void addCommonSymbols(std::vector<DefinedCommon<ELFT> *> &Syms); + void addCommonSymbols(std::vector<DefinedCommon *> &Syms); void addSharedCopySymbols(std::vector<SharedSymbol<ELFT> *> &Syms); std::unique_ptr<llvm::FileOutputBuffer> Buffer; @@ -472,27 +472,24 @@ template <class ELFT> OutputSection<ELFT> *Writer<ELFT>::getBSS() { // Until this function is called, common symbols do not belong to any section. // This function adds them to end of BSS section. template <class ELFT> -void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon<ELFT> *> &Syms) { +void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon *> &Syms) { typedef typename ELFFile<ELFT>::uintX_t uintX_t; - typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym; if (Syms.empty()) return; // Sort the common symbols by alignment as an heuristic to pack them better. - std::stable_sort( - Syms.begin(), Syms.end(), - [](const DefinedCommon<ELFT> *A, const DefinedCommon<ELFT> *B) { - return A->MaxAlignment > B->MaxAlignment; - }); + std::stable_sort(Syms.begin(), Syms.end(), + [](const DefinedCommon *A, const DefinedCommon *B) { + return A->MaxAlignment > B->MaxAlignment; + }); uintX_t Off = getBSS()->getSize(); - for (DefinedCommon<ELFT> *C : Syms) { - const Elf_Sym &Sym = C->Sym; + for (DefinedCommon *C : Syms) { uintX_t Align = C->MaxAlignment; Off = RoundUpToAlignment(Off, Align); C->OffsetInBSS = Off; - Off += Sym.st_size; + Off += C->Size; } Out<ELFT>::Bss->setSize(Off); @@ -751,7 +748,7 @@ template <class ELFT> void Writer<ELFT>::createSections() { addIRelocMarkers<ELFT>(Symtab, isOutputDynamic()); - std::vector<DefinedCommon<ELFT> *> CommonSymbols; + std::vector<DefinedCommon *> CommonSymbols; std::vector<SharedSymbol<ELFT> *> SharedCopySymbols; for (auto &P : Symtab.getSymbols()) { SymbolBody *Body = P.second->Body; @@ -759,7 +756,7 @@ template <class ELFT> void Writer<ELFT>::createSections() { if (!U->isWeak() && !U->canKeepUndefined()) reportUndefined<ELFT>(Symtab, *Body); - if (auto *C = dyn_cast<DefinedCommon<ELFT>>(Body)) + if (auto *C = dyn_cast<DefinedCommon>(Body)) CommonSymbols.push_back(C); if (auto *SC = dyn_cast<SharedSymbol<ELFT>>(Body)) if (SC->NeedsCopy) |