forked from OSchip/llvm-project
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:
parent
7b76d81bdf
commit
0b9ce6a48a
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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: ]
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue