Merge addInputSec with OutputSection::addSection.

Previously, when we added an input section to an output section, we
called `OutputSectionFactory::addInputSec`. This isn't a good design
because, a factory class is intended to create a new object and
return it, but in this use case, it will never create a new object.
This patch fixes the design flaw.

llvm-svn: 315138
This commit is contained in:
Rui Ueyama 2017-10-07 00:43:31 +00:00
parent 850b554399
commit 0e2bfb1e3b
3 changed files with 51 additions and 66 deletions

View File

@ -416,7 +416,7 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) {
// Add input sections to an output section. // Add input sections to an output section.
for (InputSectionBase *S : V) for (InputSectionBase *S : V)
Factory.addInputSec(S, Sec); Sec->addSection(cast<InputSection>(S));
assert(Sec->SectionIndex == INT_MAX); assert(Sec->SectionIndex == INT_MAX);
Sec->SectionIndex = I; Sec->SectionIndex = I;
@ -466,7 +466,7 @@ void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
if (OutputSection *Sec = findByName( if (OutputSection *Sec = findByName(
makeArrayRef(Opt.Commands).slice(0, End), Name)) { makeArrayRef(Opt.Commands).slice(0, End), Name)) {
Factory.addInputSec(S, Sec); Sec->addSection(cast<InputSection>(S));
continue; continue;
} }

View File

@ -76,18 +76,54 @@ OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags)
Live = false; Live = false;
} }
void OutputSection::addSection(InputSection *S) { // We allow sections of types listed below to merged into a
assert(S->Live); // single progbits section. This is typically done by linker
// scripts. Merging nobits and progbits will force disk space
// to be allocated for nobits sections. Other ones don't require
// any special treatment on top of progbits, so there doesn't
// seem to be a harm in merging them.
static bool canMergeToProgbits(unsigned Type) {
return Type == SHT_NOBITS || Type == SHT_PROGBITS || Type == SHT_INIT_ARRAY ||
Type == SHT_PREINIT_ARRAY || Type == SHT_FINI_ARRAY ||
Type == SHT_NOTE;
}
void OutputSection::addSection(InputSection *IS) {
if (!IS->Live) {
reportDiscarded(IS);
return;
}
if (Live) {
if ((Flags & (SHF_ALLOC | SHF_TLS)) != (IS->Flags & (SHF_ALLOC | SHF_TLS)))
error("incompatible section flags for " + Name + "\n>>> " + toString(IS) +
": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Name +
": 0x" + utohexstr(Flags));
if (Type != IS->Type) {
if (!canMergeToProgbits(Type) || !canMergeToProgbits(IS->Type))
error("section type mismatch for " + IS->Name + "\n>>> " +
toString(IS) + ": " +
getELFSectionTypeName(Config->EMachine, IS->Type) +
"\n>>> output section " + Name + ": " +
getELFSectionTypeName(Config->EMachine, Type));
Type = SHT_PROGBITS;
}
} else {
Type = IS->Type;
}
Live = true; Live = true;
S->Parent = this; IS->Parent = this;
this->updateAlignment(S->Alignment); Flags |= IS->Flags;
this->updateAlignment(IS->Alignment);
// The actual offsets will be computed by assignAddresses. For now, use // The actual offsets will be computed by assignAddresses. For now, use
// crude approximation so that it is at least easy for other code to know the // crude approximation so that it is at least easy for other code to know the
// section order. It is also used to calculate the output section size early // section order. It is also used to calculate the output section size early
// for compressed debug sections. // for compressed debug sections.
S->OutSecOff = alignTo(Size, S->Alignment); IS->OutSecOff = alignTo(Size, IS->Alignment);
this->Size = S->OutSecOff + S->getSize(); this->Size = IS->OutSecOff + IS->getSize();
// If this section contains a table of fixed-size entries, sh_entsize // If this section contains a table of fixed-size entries, sh_entsize
// holds the element size. Consequently, if this contains two or more // holds the element size. Consequently, if this contains two or more
@ -96,14 +132,14 @@ void OutputSection::addSection(InputSection *S) {
// section by using linker scripts. I don't know what to do here. // section by using linker scripts. I don't know what to do here.
// Probably we sholuld handle that as an error. But for now we just // Probably we sholuld handle that as an error. But for now we just
// pick the largest sh_entsize. // pick the largest sh_entsize.
this->Entsize = std::max(this->Entsize, S->Entsize); this->Entsize = std::max(this->Entsize, IS->Entsize);
if (!S->Assigned) { if (!IS->Assigned) {
S->Assigned = true; IS->Assigned = true;
if (Commands.empty() || !isa<InputSectionDescription>(Commands.back())) if (Commands.empty() || !isa<InputSectionDescription>(Commands.back()))
Commands.push_back(make<InputSectionDescription>("")); Commands.push_back(make<InputSectionDescription>(""));
auto *ISD = cast<InputSectionDescription>(Commands.back()); auto *ISD = cast<InputSectionDescription>(Commands.back());
ISD->Sections.push_back(S); ISD->Sections.push_back(IS);
} }
} }
@ -164,22 +200,6 @@ static SectionKey createKey(InputSectionBase *IS, StringRef OutsecName) {
OutputSectionFactory::OutputSectionFactory() {} OutputSectionFactory::OutputSectionFactory() {}
static uint64_t getIncompatibleFlags(uint64_t Flags) {
return Flags & (SHF_ALLOC | SHF_TLS);
}
// We allow sections of types listed below to merged into a
// single progbits section. This is typically done by linker
// scripts. Merging nobits and progbits will force disk space
// to be allocated for nobits sections. Other ones don't require
// any special treatment on top of progbits, so there doesn't
// seem to be a harm in merging them.
static bool canMergeToProgbits(unsigned Type) {
return Type == SHT_NOBITS || Type == SHT_PROGBITS || Type == SHT_INIT_ARRAY ||
Type == SHT_PREINIT_ARRAY || Type == SHT_FINI_ARRAY ||
Type == SHT_NOTE;
}
void elf::sortByOrder(MutableArrayRef<InputSection *> In, void elf::sortByOrder(MutableArrayRef<InputSection *> In,
std::function<int(InputSectionBase *S)> Order) { std::function<int(InputSectionBase *S)> Order) {
typedef std::pair<int, InputSection *> Pair; typedef std::pair<int, InputSection *> Pair;
@ -209,40 +229,6 @@ static OutputSection *createSection(InputSectionBase *IS, StringRef OutsecName)
return Sec; return Sec;
} }
static void addSection(OutputSection *Sec, InputSectionBase *IS) {
if (Sec->Live) {
if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(IS->Flags))
error("incompatible section flags for " + Sec->Name + "\n>>> " +
toString(IS) + ": 0x" + utohexstr(IS->Flags) +
"\n>>> output section " + Sec->Name + ": 0x" +
utohexstr(Sec->Flags));
if (Sec->Type != IS->Type) {
if (canMergeToProgbits(Sec->Type) && canMergeToProgbits(IS->Type))
Sec->Type = SHT_PROGBITS;
else
error("section type mismatch for " + IS->Name + "\n>>> " +
toString(IS) + ": " +
getELFSectionTypeName(Config->EMachine, IS->Type) +
"\n>>> output section " + Sec->Name + ": " +
getELFSectionTypeName(Config->EMachine, Sec->Type));
}
} else {
Sec->Type = IS->Type;
}
Sec->Flags |= IS->Flags;
Sec->addSection(cast<InputSection>(IS));
}
void OutputSectionFactory::addInputSec(InputSectionBase *IS,
OutputSection *OS) {
if (IS->Live)
addSection(OS, IS);
else
reportDiscarded(IS);
}
OutputSection *OutputSectionFactory::addInputSec(InputSectionBase *IS, OutputSection *OutputSectionFactory::addInputSec(InputSectionBase *IS,
StringRef OutsecName) { StringRef OutsecName) {
if (!IS->Live) { if (!IS->Live) {
@ -272,7 +258,7 @@ OutputSection *OutputSectionFactory::addInputSec(InputSectionBase *IS,
OutputSection *Out = Sec->getRelocatedSection()->getOutputSection(); OutputSection *Out = Sec->getRelocatedSection()->getOutputSection();
if (Out->RelocationSection) { if (Out->RelocationSection) {
addSection(Out->RelocationSection, IS); Out->RelocationSection->addSection(Sec);
return nullptr; return nullptr;
} }
@ -283,7 +269,7 @@ OutputSection *OutputSectionFactory::addInputSec(InputSectionBase *IS,
SectionKey Key = createKey(IS, OutsecName); SectionKey Key = createKey(IS, OutsecName);
OutputSection *&Sec = Map[Key]; OutputSection *&Sec = Map[Key];
if (Sec) { if (Sec) {
addSection(Sec, IS); Sec->addSection(cast<InputSection>(IS));
return nullptr; return nullptr;
} }

View File

@ -82,7 +82,7 @@ public:
uint64_t Addr = 0; uint64_t Addr = 0;
uint32_t ShName = 0; uint32_t ShName = 0;
void addSection(InputSection *S); void addSection(InputSection *IS);
// Location in the output buffer. // Location in the output buffer.
uint8_t *Loc = nullptr; uint8_t *Loc = nullptr;
@ -165,7 +165,6 @@ public:
~OutputSectionFactory(); ~OutputSectionFactory();
OutputSection *addInputSec(InputSectionBase *IS, StringRef OutsecName); OutputSection *addInputSec(InputSectionBase *IS, StringRef OutsecName);
void addInputSec(InputSectionBase *IS, OutputSection *OS);
private: private:
llvm::SmallDenseMap<SectionKey, OutputSection *> Map; llvm::SmallDenseMap<SectionKey, OutputSection *> Map;