From aa8523e4b6de7e466456c92c0dbd69ae658b87eb Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Sat, 4 Nov 2017 23:54:25 +0000 Subject: [PATCH] Move OutputSectionFactory to LinkerScript.cpp. NFC. That class is used only by LinkerScript.cpp, so we should move it to that file. Also, it no longer has to be a "factory" class. It can just be a non-member function. llvm-svn: 317427 --- lld/ELF/LinkerScript.cpp | 102 ++++++++++++++++++++++++++++++++++++++++++++- lld/ELF/LinkerScript.h | 2 +- lld/ELF/OutputSections.cpp | 101 -------------------------------------------- lld/ELF/Writer.cpp | 4 +- 4 files changed, 102 insertions(+), 107 deletions(-) diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 6c32442..a59b1ef 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -434,9 +434,107 @@ static void reportOrphan(InputSectionBase *IS, StringRef Name) { warn(toString(IS) + " is being placed in '" + Name + "'"); } +static OutputSection *createSection(InputSectionBase *IS, + StringRef OutsecName) { + OutputSection *Sec = Script->createOutputSection(OutsecName, ""); + Sec->addSection(cast(IS)); + return Sec; +} + +static OutputSection *addInputSec(StringMap &Map, + InputSectionBase *IS, StringRef OutsecName) { + // Sections with SHT_GROUP or SHF_GROUP attributes reach here only when the -r + // option is given. A section with SHT_GROUP defines a "section group", and + // its members have SHF_GROUP attribute. Usually these flags have already been + // stripped by InputFiles.cpp as section groups are processed and uniquified. + // However, for the -r option, we want to pass through all section groups + // as-is because adding/removing members or merging them with other groups + // change their semantics. + if (IS->Type == SHT_GROUP || (IS->Flags & SHF_GROUP)) + return createSection(IS, OutsecName); + + // Imagine .zed : { *(.foo) *(.bar) } script. Both foo and bar may have + // relocation sections .rela.foo and .rela.bar for example. Most tools do + // not allow multiple REL[A] sections for output section. Hence we + // should combine these relocation sections into single output. + // We skip synthetic sections because it can be .rela.dyn/.rela.plt or any + // other REL[A] sections created by linker itself. + if (!isa(IS) && + (IS->Type == SHT_REL || IS->Type == SHT_RELA)) { + auto *Sec = cast(IS); + OutputSection *Out = Sec->getRelocatedSection()->getOutputSection(); + + if (Out->RelocationSection) { + Out->RelocationSection->addSection(Sec); + return nullptr; + } + + Out->RelocationSection = createSection(IS, OutsecName); + return Out->RelocationSection; + } + + // When control reaches here, mergeable sections have already been + // merged except the -r case. If that's the case, we do not combine them + // and let final link to handle this optimization. + if (Config->Relocatable && (IS->Flags & SHF_MERGE)) + return createSection(IS, OutsecName); + + // The ELF spec just says + // ---------------------------------------------------------------- + // In the first phase, input sections that match in name, type and + // attribute flags should be concatenated into single sections. + // ---------------------------------------------------------------- + // + // However, it is clear that at least some flags have to be ignored for + // section merging. At the very least SHF_GROUP and SHF_COMPRESSED have to be + // ignored. We should not have two output .text sections just because one was + // in a group and another was not for example. + // + // It also seems that that wording was a late addition and didn't get the + // necessary scrutiny. + // + // Merging sections with different flags is expected by some users. One + // reason is that if one file has + // + // int *const bar __attribute__((section(".foo"))) = (int *)0; + // + // gcc with -fPIC will produce a read only .foo section. But if another + // file has + // + // int zed; + // int *const bar __attribute__((section(".foo"))) = (int *)&zed; + // + // gcc with -fPIC will produce a read write section. + // + // Last but not least, when using linker script the merge rules are forced by + // the script. Unfortunately, linker scripts are name based. This means that + // expressions like *(.foo*) can refer to multiple input sections with + // different flags. We cannot put them in different output sections or we + // would produce wrong results for + // + // start = .; *(.foo.*) end = .; *(.bar) + // + // and a mapping of .foo1 and .bar1 to one section and .foo2 and .bar2 to + // another. The problem is that there is no way to layout those output + // sections such that the .foo sections are the only thing between the start + // and end symbols. + // + // Given the above issues, we instead merge sections by name and error on + // incompatible types and flags. + OutputSection *&Sec = Map[OutsecName]; + if (Sec) { + Sec->addSection(cast(IS)); + return nullptr; + } + + Sec = createSection(IS, OutsecName); + return Sec; +} + // Add sections that didn't match any sections command. -void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) { +void LinkerScript::addOrphanSections() { unsigned End = SectionCommands.size(); + StringMap Map; std::vector V; for (InputSectionBase *S : InputSections) { @@ -452,7 +550,7 @@ void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) { continue; } - if (OutputSection *OS = Factory.addInputSec(S, Name)) + if (OutputSection *OS = addInputSec(Map, S, Name)) V.push_back(OS); assert(S->getOutputSection()->SectionIndex == INT_MAX); } diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 6474da5..b937e7f 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -251,7 +251,7 @@ public: ExprValue getSymbolValue(StringRef Name, const Twine &Loc); - void addOrphanSections(OutputSectionFactory &Factory); + void addOrphanSections(); void removeEmptyCommands(); void adjustSectionsBeforeSorting(); void adjustSectionsAfterSorting(); diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index b4c1c80..357affe 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -142,8 +142,6 @@ void OutputSection::addSection(InputSection *IS) { } } -OutputSectionFactory::OutputSectionFactory() {} - void elf::sortByOrder(MutableArrayRef In, std::function Order) { typedef std::pair Pair; @@ -158,105 +156,6 @@ void elf::sortByOrder(MutableArrayRef In, In[I] = V[I].second; } -static OutputSection *createSection(InputSectionBase *IS, StringRef OutsecName) { - OutputSection *Sec = Script->createOutputSection(OutsecName, ""); - Sec->addSection(cast(IS)); - return Sec; -} - -OutputSection *OutputSectionFactory::addInputSec(InputSectionBase *IS, - StringRef OutsecName) { - - // Sections with SHT_GROUP or SHF_GROUP attributes reach here only when the -r - // option is given. A section with SHT_GROUP defines a "section group", and - // its members have SHF_GROUP attribute. Usually these flags have already been - // stripped by InputFiles.cpp as section groups are processed and uniquified. - // However, for the -r option, we want to pass through all section groups - // as-is because adding/removing members or merging them with other groups - // change their semantics. - if (IS->Type == SHT_GROUP || (IS->Flags & SHF_GROUP)) - return createSection(IS, OutsecName); - - // Imagine .zed : { *(.foo) *(.bar) } script. Both foo and bar may have - // relocation sections .rela.foo and .rela.bar for example. Most tools do - // not allow multiple REL[A] sections for output section. Hence we - // should combine these relocation sections into single output. - // We skip synthetic sections because it can be .rela.dyn/.rela.plt or any - // other REL[A] sections created by linker itself. - if (!isa(IS) && - (IS->Type == SHT_REL || IS->Type == SHT_RELA)) { - auto *Sec = cast(IS); - OutputSection *Out = Sec->getRelocatedSection()->getOutputSection(); - - if (Out->RelocationSection) { - Out->RelocationSection->addSection(Sec); - return nullptr; - } - - Out->RelocationSection = createSection(IS, OutsecName); - return Out->RelocationSection; - } - - // When control reaches here, mergeable sections have already been - // merged except the -r case. If that's the case, we do not combine them - // and let final link to handle this optimization. - if (Config->Relocatable && (IS->Flags & SHF_MERGE)) - return createSection(IS, OutsecName); - - // The ELF spec just says - // ---------------------------------------------------------------- - // In the first phase, input sections that match in name, type and - // attribute flags should be concatenated into single sections. - // ---------------------------------------------------------------- - // - // However, it is clear that at least some flags have to be ignored for - // section merging. At the very least SHF_GROUP and SHF_COMPRESSED have to be - // ignored. We should not have two output .text sections just because one was - // in a group and another was not for example. - // - // It also seems that that wording was a late addition and didn't get the - // necessary scrutiny. - // - // Merging sections with different flags is expected by some users. One - // reason is that if one file has - // - // int *const bar __attribute__((section(".foo"))) = (int *)0; - // - // gcc with -fPIC will produce a read only .foo section. But if another - // file has - // - // int zed; - // int *const bar __attribute__((section(".foo"))) = (int *)&zed; - // - // gcc with -fPIC will produce a read write section. - // - // Last but not least, when using linker script the merge rules are forced by - // the script. Unfortunately, linker scripts are name based. This means that - // expressions like *(.foo*) can refer to multiple input sections with - // different flags. We cannot put them in different output sections or we - // would produce wrong results for - // - // start = .; *(.foo.*) end = .; *(.bar) - // - // and a mapping of .foo1 and .bar1 to one section and .foo2 and .bar2 to - // another. The problem is that there is no way to layout those output - // sections such that the .foo sections are the only thing between the start - // and end symbols. - // - // Given the above issues, we instead merge sections by name and error on - // incompatible types and flags. - OutputSection *&Sec = Map[OutsecName]; - if (Sec) { - Sec->addSection(cast(IS)); - return nullptr; - } - - Sec = createSection(IS, OutsecName); - return Sec; -} - -OutputSectionFactory::~OutputSectionFactory() {} - uint64_t elf::getHeaderSize() { if (Config->OFormatBinary) return 0; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 56b8345..7bd7c2b 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -72,8 +72,6 @@ private: std::unique_ptr Buffer; - OutputSectionFactory Factory; - void addRelIpltSymbols(); void addStartEndSymbols(); void addStartStopSymbols(OutputSection *Sec); @@ -175,7 +173,7 @@ template void Writer::run() { // Linker scripts controls how input sections are assigned to output sections. // Input sections that were not handled by scripts are called "orphans", and // they are assigned to output sections by the default rule. Process that. - Script->addOrphanSections(Factory); + Script->addOrphanSections(); if (Config->Discard != DiscardPolicy::All) copyLocalSymbols(); -- 2.7.4