diff options
| author | Rui Ueyama <ruiu@google.com> | 2016-11-05 23:05:47 +0000 |
|---|---|---|
| committer | Rui Ueyama <ruiu@google.com> | 2016-11-05 23:05:47 +0000 |
| commit | e8a6102fa9ae49813b12871dc2bd48b8523948c2 (patch) | |
| tree | 5e95a3bceb018e22eb6e695f7f34f45ab42be6f3 | |
| parent | 9e0297b8bc1eafbd1eb845c740727abab44afa2f (diff) | |
| download | bcm5719-llvm-e8a6102fa9ae49813b12871dc2bd48b8523948c2.tar.gz bcm5719-llvm-e8a6102fa9ae49813b12871dc2bd48b8523948c2.zip | |
Rewrite CommonInputSection as a synthetic input section.
A CommonInputSection is a section containing all common symbols.
That was an input section but was abstracted in a different way
than the synthetic input sections because it was written before
the synthetic input section was invented.
This patch rewrites CommonInputSection as a synthetic input section
so that it behaves better with other sections.
llvm-svn: 286053
| -rw-r--r-- | lld/ELF/InputSection.cpp | 25 | ||||
| -rw-r--r-- | lld/ELF/InputSection.h | 11 | ||||
| -rw-r--r-- | lld/ELF/LinkerScript.cpp | 8 | ||||
| -rw-r--r-- | lld/ELF/OutputSections.cpp | 3 | ||||
| -rw-r--r-- | lld/ELF/Symbols.cpp | 4 | ||||
| -rw-r--r-- | lld/ELF/SyntheticSections.cpp | 43 | ||||
| -rw-r--r-- | lld/ELF/SyntheticSections.h | 12 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 51 | ||||
| -rw-r--r-- | lld/test/ELF/linkerscript/double-bss.s | 11 |
9 files changed, 87 insertions, 81 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index efff4b52973..d1c96fd0065 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -825,31 +825,6 @@ bool MipsAbiFlagsInputSection<ELFT>::classof(const InputSectionData *S) { return S->kind() == InputSectionBase<ELFT>::MipsAbiFlags; } -template <class ELFT> -InputSection<ELFT> InputSection<ELFT>::createCommonInputSection( - std::vector<DefinedCommon *> Syms) { - // Sort the common symbols by alignment as an heuristic to pack them better. - std::stable_sort(Syms.begin(), Syms.end(), - [](const DefinedCommon *A, const DefinedCommon *B) { - return A->Alignment > B->Alignment; - }); - - size_t Size = 0; - uintX_t Alignment = 1; - for (DefinedCommon *Sym : Syms) { - Alignment = std::max<uintX_t>(Alignment, Sym->Alignment); - Size = alignTo(Size, Sym->Alignment); - - // Compute symbol offset relative to beginning of input section. - Sym->Offset = Size; - Size += Sym->Size; - } - ArrayRef<uint8_t> Data = makeArrayRef<uint8_t>(nullptr, Size); - InputSection Ret(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, Alignment, Data, ""); - Ret.Live = true; - return Ret; -} - template class elf::InputSectionBase<ELF32LE>; template class elf::InputSectionBase<ELF32BE>; template class elf::InputSectionBase<ELF64LE>; diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index d54d019f596..62fc5e6a0f2 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -273,14 +273,6 @@ public: template <class RelTy> void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels); - // Common symbols don't belong to any section. But it is easier for us - // to handle them as if they belong to some input section. So we defined - // this section that "contains" all common symbols. - static InputSection<ELFT> *CommonInputSection; - - static InputSection<ELFT> - createCommonInputSection(std::vector<DefinedCommon *> Syms); - private: template <class RelTy> void copyRelocations(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels); @@ -294,9 +286,6 @@ private: llvm::TinyPtrVector<const Thunk<ELFT> *> Thunks; }; -template <class ELFT> -InputSection<ELFT> *InputSection<ELFT>::CommonInputSection; - // MIPS .reginfo section provides information on the registers used by the code // in the object file. Linker should collect this information and write a single // .reginfo section in the output file. The output section contains a union of diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index dd46faed586..53d2cc583c2 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -202,13 +202,9 @@ void LinkerScript<ELFT>::computeInputSections(InputSectionDescription *I) { if (elf::ObjectFile<ELFT> *F = S->getFile()) Filename = sys::path::filename(F->getName()); - if (!I->FilePat.match(Filename) || Pat.ExcludedFilePat.match(Filename)) - continue; - - if (Pat.SectionPat.match(S->Name)) + if (I->FilePat.match(Filename) && !Pat.ExcludedFilePat.match(Filename) && + Pat.SectionPat.match(S->Name)) I->Sections.push_back(S); - if (Pat.SectionPat.match("COMMON")) - I->Sections.push_back(InputSection<ELFT>::CommonInputSection); } // Sort sections as instructed by SORT-family commands and --sort-section diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 9179d197e7f..fa39213e2e9 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -15,6 +15,7 @@ #include "Memory.h" #include "Strings.h" #include "SymbolTable.h" +#include "SyntheticSections.h" #include "Target.h" #include "lld/Core/Parallel.h" #include "llvm/Support/Dwarf.h" @@ -1556,7 +1557,7 @@ SymbolTableSection<ELFT>::getOutputSection(SymbolBody *Sym) { break; } case SymbolBody::DefinedCommonKind: - return InputSection<ELFT>::CommonInputSection->OutSec; + return In<ELFT>::Common->OutSec; case SymbolBody::SharedKind: if (cast<SharedSymbol<ELFT>>(Sym)->needsCopy()) return Out<ELFT>::Bss; diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index f59132a6093..1c8c9a8b97a 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -12,6 +12,7 @@ #include "InputFiles.h" #include "InputSection.h" #include "OutputSections.h" +#include "SyntheticSections.h" #include "Target.h" #include "llvm/ADT/STLExtras.h" @@ -69,8 +70,7 @@ static typename ELFT::uint getSymVA(const SymbolBody &Body, return VA; } case SymbolBody::DefinedCommonKind: - return InputSection<ELFT>::CommonInputSection->OutSec->getVA() + - InputSection<ELFT>::CommonInputSection->OutSecOff + + return In<ELFT>::Common->OutSec->getVA() + In<ELFT>::Common->OutSecOff + cast<DefinedCommon>(Body).Offset; case SymbolBody::SharedKind: { auto &SS = cast<SharedSymbol<ELFT>>(Body); diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 002656617ee..09183d0b6f9 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -21,6 +21,7 @@ #include "Memory.h" #include "OutputSections.h" #include "Strings.h" +#include "SymbolTable.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MD5.h" @@ -37,6 +38,43 @@ using namespace llvm::support::endian; using namespace lld; using namespace lld::elf; +template <class ELFT> static std::vector<DefinedCommon *> getCommonSymbols() { + std::vector<DefinedCommon *> V; + for (Symbol *S : Symtab<ELFT>::X->getSymbols()) + if (auto *B = dyn_cast<DefinedCommon>(S->body())) + V.push_back(B); + return V; +} + +// Find all common symbols and allocate space for them. +template <class ELFT> +CommonSection<ELFT>::CommonSection() + : InputSection<ELFT>(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, 1, + ArrayRef<uint8_t>(), "COMMON") { + this->Live = true; + + // Sort the common symbols by alignment as an heuristic to pack them better. + std::vector<DefinedCommon *> Syms = getCommonSymbols<ELFT>(); + std::stable_sort(Syms.begin(), Syms.end(), + [](const DefinedCommon *A, const DefinedCommon *B) { + return A->Alignment > B->Alignment; + }); + + // Assign offsets to symbols. + size_t Size = 0; + size_t Alignment = 1; + for (DefinedCommon *Sym : Syms) { + Alignment = std::max(Alignment, Sym->Alignment); + Size = alignTo(Size, Sym->Alignment); + + // Compute symbol offset relative to beginning of input section. + Sym->Offset = Size; + Size += Sym->Size; + } + this->Alignment = Alignment; + this->Data = makeArrayRef<uint8_t>(nullptr, Size); +} + static ArrayRef<uint8_t> createInterp() { // StringSaver guarantees that the returned string ends with '\0'. StringRef S = Saver.save(Config->DynamicLinker); @@ -111,6 +149,11 @@ void BuildIdHexstring<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { Config->BuildIdVector.size()); } +template class elf::CommonSection<ELF32LE>; +template class elf::CommonSection<ELF32BE>; +template class elf::CommonSection<ELF64LE>; +template class elf::CommonSection<ELF64BE>; + template class elf::InterpSection<ELF32LE>; template class elf::InterpSection<ELF32BE>; template class elf::InterpSection<ELF64LE>; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index a98d94ee80b..5f122e54577 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -15,11 +15,19 @@ namespace lld { namespace elf { +// This class represents a BSS section containing all common symbols. +template <class ELFT> class CommonSection final : public InputSection<ELFT> { +public: + CommonSection(); +}; + +// .interp section. template <class ELFT> class InterpSection final : public InputSection<ELFT> { public: InterpSection(); }; +// .note.gnu.build-id section. template <class ELFT> class BuildIdSection : public InputSection<ELFT> { public: virtual void writeBuildId(llvm::MutableArrayRef<uint8_t> Buf) = 0; @@ -67,13 +75,13 @@ public: // Linker generated sections which can be used as inputs. template <class ELFT> struct In { static BuildIdSection<ELFT> *BuildId; + static CommonSection<ELFT> *Common; static InterpSection<ELFT> *Interp; - static std::vector<InputSection<ELFT> *> Sections; }; template <class ELFT> BuildIdSection<ELFT> *In<ELFT>::BuildId; +template <class ELFT> CommonSection<ELFT> *In<ELFT>::Common; template <class ELFT> InterpSection<ELFT> *In<ELFT>::Interp; -template <class ELFT> std::vector<InputSection<ELFT> *> In<ELFT>::Sections; } // namespace elf } // namespace lld diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 18dbccf269d..18d1c7d3c9c 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -105,6 +105,11 @@ StringRef elf::getOutputSectionName(StringRef Name) { return Prefix; } + // CommonSection is identified as "COMMON" in linker scripts. + // By default, it should go to .bss section. + if (Name == "COMMON") + return ".bss"; + // ".zdebug_" is a prefix for ZLIB-compressed sections. // Because we decompressed input sections, we want to remove 'z'. if (Name.startswith(".zdebug_")) @@ -130,14 +135,6 @@ template <class ELFT> void elf::writeResult() { Writer<ELFT>().run(); } -template <class ELFT> static std::vector<DefinedCommon *> getCommonSymbols() { - std::vector<DefinedCommon *> V; - for (Symbol *S : Symtab<ELFT>::X->getSymbols()) - if (auto *B = dyn_cast<DefinedCommon>(S->body())) - V.push_back(B); - return V; -} - // The main function of the writer. template <class ELFT> void Writer<ELFT>::run() { createSyntheticSections(); @@ -146,10 +143,6 @@ template <class ELFT> void Writer<ELFT>::run() { if (Target->NeedsThunks) forEachRelSec(createThunks<ELFT>); - InputSection<ELFT> Common = - InputSection<ELFT>::createCommonInputSection(getCommonSymbols<ELFT>()); - InputSection<ELFT>::CommonInputSection = &Common; - Script<ELFT>::X->OutputSections = &OutputSections; if (ScriptConfig->HasSections) { Script<ELFT>::X->createSections(Factory); @@ -234,8 +227,12 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { Out<ELFT>::ProgramHeaders = make<OutputSectionBase<ELFT>>("", 0, SHF_ALLOC); Out<ELFT>::ProgramHeaders->updateAlignment(sizeof(uintX_t)); - if (needsInterpSection<ELFT>()) + if (needsInterpSection<ELFT>()) { In<ELFT>::Interp = make<InterpSection<ELFT>>(); + Symtab<ELFT>::X->Sections.push_back(In<ELFT>::Interp); + } else { + In<ELFT>::Interp = nullptr; + } if (!Symtab<ELFT>::X->getSharedFiles().empty() || Config->Pic) { Out<ELFT>::DynSymTab = @@ -284,8 +281,17 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { In<ELFT>::BuildId = make<BuildIdUuid<ELFT>>(); else if (Config->BuildId == BuildIdKind::Hexstring) In<ELFT>::BuildId = make<BuildIdHexstring<ELFT>>(); + else + In<ELFT>::BuildId = nullptr; - In<ELFT>::Sections = {In<ELFT>::BuildId, In<ELFT>::Interp}; + if (In<ELFT>::BuildId) + Symtab<ELFT>::X->Sections.push_back(In<ELFT>::BuildId); + + CommonSection<ELFT> *Common = make<CommonSection<ELFT>>(); + if (!Common->Data.empty()) { + In<ELFT>::Common = Common; + Symtab<ELFT>::X->Sections.push_back(Common); + } } template <class ELFT> @@ -803,22 +809,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { if (HasError) return; - // If linker script processor hasn't added common symbol section yet, - // then add it to .bss now. - if (!InputSection<ELFT>::CommonInputSection->OutSec) { - Out<ELFT>::Bss->addSection(InputSection<ELFT>::CommonInputSection); - Out<ELFT>::Bss->assignOffsets(); - } - // So far we have added sections from input object files. // This function adds linker-created Out<ELFT>::* sections. addPredefinedSections(); - // Adds linker generated input sections to - // corresponding output sections. - for (InputSection<ELFT> *S : In<ELFT>::Sections) - addInputSec(S); - sortSections(); unsigned I = 1; @@ -827,11 +821,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { Sec->setSHName(Out<ELFT>::ShStrTab->addString(Sec->getName())); } - // Finalize linker generated sections. - for (InputSection<ELFT> *S : In<ELFT>::Sections) - if (S && S->OutSec) - S->OutSec->assignOffsets(); - // Finalizers fix each section's size. // .dynsym is finalized early since that may fill up .gnu.hash. if (Out<ELFT>::DynSymTab) diff --git a/lld/test/ELF/linkerscript/double-bss.s b/lld/test/ELF/linkerscript/double-bss.s index 9f047333ac6..c24332f5e5a 100644 --- a/lld/test/ELF/linkerscript/double-bss.s +++ b/lld/test/ELF/linkerscript/double-bss.s @@ -1,10 +1,15 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t -# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .text : { *(.text*) } }" > %t.script +# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; " > %t.script +# RUN: echo ".text : { *(.text*) }" >> %t.script +# RUN: echo ".bss1 : { *(.bss) }" >> %t.script +# RUN: echo ".bss2 : { *(COMMON) }" >> %t.script +# RUN: echo "}" >> %t.script + # RUN: ld.lld -o %t1 --script %t.script %t # RUN: llvm-objdump -section-headers %t1 | FileCheck %s -# CHECK: .bss 00000004 0000000000000122 BSS -# CHECK-NEXT: .bss 00000080 0000000000000128 BSS +# CHECK: .bss1 00000004 0000000000000122 BSS +# CHECK-NEXT: .bss2 00000080 0000000000000128 BSS .globl _start _start: |

