Create only one section for a name in LinkerScript.

Previously, we created two or more output sections if there are
input sections with the same name but with different attributes.
That is a wrong behavior. This patch fixes the issue.

One thing we need to do is to merge output section attributes.
Currently, we create an output section based on the first input
section's attributes. This may make a wrong output section
attributes. What we need to do is to bitwise-OR attributes.
We'll do it in a follow-up patch.

llvm-svn: 278461
This commit is contained in:
Rui Ueyama 2016-08-12 03:16:56 +00:00
parent 7b76d81bdf
commit 0b9ce6a48a
4 changed files with 69 additions and 84 deletions

View File

@ -155,27 +155,14 @@ private:
typename ELFT::Shdr Hdr;
};
// Helper class, which builds output section list, also
// creating symbol sections, when needed
namespace {
template <class ELFT> class OutputSectionBuilder {
public:
OutputSectionBuilder(OutputSectionFactory<ELFT> &F,
std::vector<OutputSectionBase<ELFT> *> *Out)
: Factory(F), OutputSections(Out) {}
void addSection(StringRef OutputName, InputSectionBase<ELFT> *I);
void addSymbol(LayoutInputSection<ELFT> *S) { PendingSymbols.push_back(S); }
void flushSymbols();
void flushSection();
private:
OutputSectionFactory<ELFT> &Factory;
std::vector<OutputSectionBase<ELFT> *> *OutputSections;
OutputSectionBase<ELFT> *Current = nullptr;
std::vector<LayoutInputSection<ELFT> *> PendingSymbols;
};
} // anonymous namespace
template <class ELFT>
static InputSectionBase<ELFT> *
getNonLayoutSection(std::vector<InputSectionBase<ELFT> *> &Vec) {
for (InputSectionBase<ELFT> *S : Vec)
if (!isa<LayoutInputSection<ELFT>>(S))
return S;
return nullptr;
}
template <class T> static T *zero(T *Val) {
memset(Val, 0, sizeof(*Val));
@ -196,38 +183,6 @@ bool LayoutInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
return S->SectionKind == InputSectionBase<ELFT>::Layout;
}
template <class ELFT>
void OutputSectionBuilder<ELFT>::addSection(StringRef OutputName,
InputSectionBase<ELFT> *C) {
bool IsNew;
std::tie(Current, IsNew) = Factory.create(C, OutputName);
if (IsNew)
OutputSections->push_back(Current);
flushSymbols();
Current->addSection(C);
}
template <class ELFT> void OutputSectionBuilder<ELFT>::flushSymbols() {
// Only regular output sections are supported.
if (dyn_cast_or_null<OutputSection<ELFT>>(Current)) {
for (LayoutInputSection<ELFT> *I : PendingSymbols) {
if (I->Cmd->Name == ".") {
Current->addSection(I);
} else if (shouldDefine<ELFT>(I->Cmd)) {
addSynthetic<ELFT>(I->Cmd, Current);
Current->addSection(I);
}
}
}
PendingSymbols.clear();
}
template <class ELFT> void OutputSectionBuilder<ELFT>::flushSection() {
flushSymbols();
Current = nullptr;
}
template <class ELFT>
static bool compareName(InputSectionBase<ELFT> *A, InputSectionBase<ELFT> *B) {
return A->getSectionName() < B->getSectionName();
@ -263,47 +218,76 @@ void LinkerScript<ELFT>::discard(OutputSectionCommand &Cmd) {
}
template <class ELFT>
void LinkerScript<ELFT>::createSections(
OutputSectionFactory<ELFT> &Factory) {
OutputSectionBuilder<ELFT> Builder(Factory, OutputSections);
std::vector<InputSectionBase<ELFT> *>
LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &Cmd) {
std::vector<InputSectionBase<ELFT> *> Ret;
for (const std::unique_ptr<BaseCommand> &Base : Cmd.Commands) {
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base.get())) {
Ret.push_back(new (LAlloc.Allocate()) LayoutInputSection<ELFT>(Cmd));
continue;
}
auto *Cmd = cast<InputSectionDescription>(Base.get());
std::vector<InputSectionBase<ELFT> *> V = getInputSections(Cmd);
if (Cmd->SortInner)
std::stable_sort(V.begin(), V.end(), getComparator<ELFT>(Cmd->SortInner));
if (Cmd->SortOuter)
std::stable_sort(V.begin(), V.end(), getComparator<ELFT>(Cmd->SortOuter));
Ret.insert(Ret.end(), V.begin(), V.end());
}
return Ret;
}
template <class ELFT>
void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
for (const std::unique_ptr<BaseCommand> &Base1 : Opt.Commands) {
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base1.get())) {
if (Cmd->Name == "/DISCARD/") {
discard(*Cmd);
continue;
}
for (const std::unique_ptr<BaseCommand> &Base2 : Cmd->Commands) {
if (auto *Cmd2 = dyn_cast<SymbolAssignment>(Base2.get())) {
Builder.addSymbol(new (LAlloc.Allocate())
LayoutInputSection<ELFT>(Cmd2));
continue;
}
auto *Cmd2 = cast<InputSectionDescription>(Base2.get());
std::vector<InputSectionBase<ELFT> *> Sections = getInputSections(Cmd2);
if (Cmd2->SortInner)
std::stable_sort(Sections.begin(), Sections.end(),
getComparator<ELFT>(Cmd2->SortInner));
if (Cmd2->SortOuter)
std::stable_sort(Sections.begin(), Sections.end(),
getComparator<ELFT>(Cmd2->SortOuter));
for (InputSectionBase<ELFT> *S : Sections)
Builder.addSection(Cmd->Name, S);
}
Builder.flushSection();
std::vector<InputSectionBase<ELFT> *> V = createInputSectionList(*Cmd);
InputSectionBase<ELFT> *Head = getNonLayoutSection<ELFT>(V);
if (!Head)
continue;
OutputSectionBase<ELFT> *OutSec;
bool IsNew;
std::tie(OutSec, IsNew) = Factory.create(Head, Cmd->Name);
if (IsNew)
OutputSections->push_back(OutSec);
for (InputSectionBase<ELFT> *Sec : V) {
if (auto *L = dyn_cast<LayoutInputSection<ELFT>>(Sec)) {
if (shouldDefine<ELFT>(L->Cmd))
addSynthetic<ELFT>(L->Cmd, OutSec);
else if (L->Cmd->Name != ".")
continue;
}
OutSec->addSection(Sec);
}
} else if (auto *Cmd2 = dyn_cast<SymbolAssignment>(Base1.get())) {
if (shouldDefine<ELFT>(Cmd2))
addRegular<ELFT>(Cmd2);
}
}
// Add all other input sections, which are not listed in script.
// Add orphan sections.
for (const std::unique_ptr<ObjectFile<ELFT>> &F :
Symtab<ELFT>::X->getObjectFiles())
for (InputSectionBase<ELFT> *S : F->getSections())
if (!isDiscarded(S) && !S->OutSec)
Builder.addSection(getOutputSectionName(S), S);
Symtab<ELFT>::X->getObjectFiles()) {
for (InputSectionBase<ELFT> *S : F->getSections()) {
if (!isDiscarded(S) && !S->OutSec) {
OutputSectionBase<ELFT> *OutSec;
bool IsNew;
std::tie(OutSec, IsNew) = Factory.create(S, getOutputSectionName(S));
if (IsNew)
OutputSections->push_back(OutSec);
OutSec->addSection(S);
}
}
}
// Remove from the output all the sections which did not meet
// the optional constraints.

View File

@ -161,6 +161,9 @@ private:
void discard(OutputSectionCommand &Cmd);
std::vector<InputSectionBase<ELFT> *>
createInputSectionList(OutputSectionCommand &Cmd);
// "ScriptConfig" is a bit too long, so define a short name for it.
ScriptConfiguration &Opt = *ScriptConfig;

View File

@ -17,9 +17,8 @@
# CHECK-NEXT: PhysicalAddress: 0x10000000
# CHECK-NEXT: FileSize: 521
# CHECK-NEXT: MemSize: 521
# CHECK-NEXT: Flags [ (0x7)
# CHECK-NEXT: Flags [ (0x5)
# CHECK-NEXT: PF_R (0x4)
# CHECK-NEXT: PF_W (0x2)
# CHECK-NEXT: PF_X (0x1)
# CHECK-NEXT: ]

View File

@ -7,9 +7,8 @@
# CHECK: Sections:
# CHECK-NEXT: Idx Name Size Address Type
# CHECK-NEXT: 0 00000000 0000000000000000
# CHECK-NEXT: 1 .foo 00000004 0000000000000158 DATA
# CHECK-NEXT: 2 .foo 00000004 000000000000015c DATA
# CHECK-NEXT: 3 .text 00000001 0000000000000160 TEXT DATA
# CHECK-NEXT: 1 .foo 00000008 0000000000000120 DATA
# CHECK-NEXT: 2 .text 00000001 0000000000000128 TEXT DATA
.global _start
_start: