Create an OutputSection for each non-empty OutputSectionCommand.

We were already pretty close, the one exception was when a name was
reused in another SECTIONS directive:

SECTIONS {
  .text : { *(.text) }
  .data : { *(.data) }
}
SECTIONS {
  .data : { *(other) }
}

In this case we would create a single .data and magically output
"other" while looking at the first OutputSectionCommand.

We now create two .data sections. This matches what gold does. If we
really want to create a single one, we should change the parser so that
the above is parsed as if the user had written

SECTIONS {
  .text : { *(.text) }
  .data : { *(.data) *(other)}
}

That is, there should be only one OutputSectionCommand for .data and
it would have two InputSectionDescriptions.

By itself this patch makes the code a bit more complicated, but is an
important step in allowing assignAddresses to operate just on the
linker script.

llvm-svn: 301484
This commit is contained in:
Rafael Espindola 2017-04-26 22:30:15 +00:00
parent 8186cd43e2
commit 4f013bb3b2
4 changed files with 32 additions and 19 deletions

View File

@ -407,7 +407,7 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) {
// Add input sections to an output section.
for (InputSectionBase *S : V)
Factory.addInputSec(S, Cmd->Name);
Factory.addInputSec(S, Cmd->Name, Cmd->Sec);
}
}
CurOutSec = nullptr;
@ -465,9 +465,21 @@ void LinkerScript::fabricateDefaultCommands(bool AllocateHeader) {
// Add sections that didn't match any sections command.
void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
for (InputSectionBase *S : InputSections)
if (S->Live && !S->OutSec)
Factory.addInputSec(S, getOutputSectionName(S->Name));
for (InputSectionBase *S : InputSections) {
if (!S->Live || S->OutSec)
continue;
StringRef Name = getOutputSectionName(S->Name);
auto I = std::find_if(
Opt.Commands.begin(), Opt.Commands.end(), [&](BaseCommand *Base) {
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
return Cmd->Name == Name;
return false;
});
if (I == Opt.Commands.end())
Factory.addInputSec(S, Name);
else
Factory.addInputSec(S, Name, cast<OutputSectionCommand>(*I)->Sec);
}
}
static bool isTbss(OutputSection *Sec) {
@ -576,14 +588,6 @@ void LinkerScript::process(BaseCommand &Base) {
}
}
static OutputSection *
findSection(StringRef Name, const std::vector<OutputSection *> &Sections) {
for (OutputSection *Sec : Sections)
if (Sec->Name == Name)
return Sec;
return nullptr;
}
// This function searches for a memory region to place the given output
// section in. If found, a pointer to the appropriate memory region is
// returned. Otherwise, a nullptr is returned.
@ -663,7 +667,8 @@ void LinkerScript::removeEmptyCommands() {
auto Pos = std::remove_if(
Opt.Commands.begin(), Opt.Commands.end(), [&](BaseCommand *Base) {
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
return !Cmd->Sec;
return std::find(OutputSections->begin(), OutputSections->end(),
Cmd->Sec) == OutputSections->end();
return false;
});
Opt.Commands.erase(Pos, Opt.Commands.end());
@ -687,8 +692,7 @@ void LinkerScript::adjustSectionsBeforeSorting() {
auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
if (!Cmd)
continue;
if (OutputSection *Sec = findSection(Cmd->Name, *OutputSections)) {
Cmd->Sec = Sec;
if (OutputSection *Sec = Cmd->Sec) {
Flags = Sec->Flags;
Type = Sec->Type;
continue;

View File

@ -395,14 +395,20 @@ static void reportDiscarded(InputSectionBase *IS) {
void OutputSectionFactory::addInputSec(InputSectionBase *IS,
StringRef OutsecName) {
SectionKey Key = createKey(IS, OutsecName);
OutputSection *&Sec = Map[Key];
return addInputSec(IS, OutsecName, Sec);
}
void OutputSectionFactory::addInputSec(InputSectionBase *IS,
StringRef OutsecName,
OutputSection *&Sec) {
if (!IS->Live) {
reportDiscarded(IS);
return;
}
SectionKey Key = createKey(IS, OutsecName);
uint64_t Flags = getOutFlags(IS);
OutputSection *&Sec = Map[Key];
if (Sec) {
if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(IS->Flags))
error("incompatible section flags for " + Sec->Name +
@ -418,7 +424,7 @@ void OutputSectionFactory::addInputSec(InputSectionBase *IS,
}
Sec->Flags |= Flags;
} else {
Sec = make<OutputSection>(Key.Name, IS->Type, Flags);
Sec = make<OutputSection>(OutsecName, IS->Type, Flags);
OutputSections.push_back(Sec);
}

View File

@ -141,6 +141,8 @@ public:
~OutputSectionFactory();
void addInputSec(InputSectionBase *IS, StringRef OutsecName);
void addInputSec(InputSectionBase *IS, StringRef OutsecName,
OutputSection *&Sec);
private:
llvm::SmallDenseMap<SectionKey, OutputSection *> Map;

View File

@ -86,7 +86,8 @@
# Idx Name Size
# SEC-MULTI: 1 .text 0000000e {{[0-9a-f]*}} TEXT DATA
# SEC-MULTI-NEXT: .data 00000023 {{[0-9a-f]*}} DATA
# SEC-MULTI-NEXT: .data 00000020 {{[0-9a-f]*}} DATA
# SEC-MULTI-NEXT: .data 00000003 {{[0-9a-f]*}} DATA
# SEC-MULTI-NEXT: .bss 00000002 {{[0-9a-f]*}} BSS
# SEC-MULTI-NEXT: .comment 00000008 {{[0-9a-f]*}}
# SEC-MULTI-NEXT: .symtab 00000030 {{[0-9a-f]*}}