Split LinkerScript::createSections into small functions.
createSections function is getting longer, so it is time to split it into small functions. The reason why the function is long is because it has deeply nested for-loops. This patch constructs temporary data to reduce nesting level. Differential Revision: https://reviews.llvm.org/D22786 llvm-svn: 276706
This commit is contained in:
parent
63dc650938
commit
6b2748104b
|
@ -74,65 +74,76 @@ static bool match(ArrayRef<StringRef> Patterns, StringRef S) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Create a vector of (<output section name>, <input section name patterns>).
|
||||
// For example, if a returned vector contains (".text" (".foo.*" ".bar.*")),
|
||||
// input sections start with ".foo." or ".bar." should be added to
|
||||
// ".text" section.
|
||||
template <class ELFT>
|
||||
std::vector<std::pair<StringRef, ArrayRef<StringRef>>>
|
||||
LinkerScript<ELFT>::getSectionMap() {
|
||||
std::vector<std::pair<StringRef, ArrayRef<StringRef>>> Ret;
|
||||
|
||||
for (const std::unique_ptr<BaseCommand> &Base1 : Opt.Commands)
|
||||
if (auto *Cmd1 = dyn_cast<OutputSectionCommand>(Base1.get()))
|
||||
for (const std::unique_ptr<BaseCommand> &Base2 : Cmd1->Commands)
|
||||
if (auto *Cmd2 = dyn_cast<InputSectionDescription>(Base2.get()))
|
||||
Ret.emplace_back(Cmd1->Name, Cmd2->Patterns);
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
// Returns input sections filtered by given glob patterns.
|
||||
template <class ELFT>
|
||||
std::vector<InputSectionBase<ELFT> *>
|
||||
LinkerScript<ELFT>::getInputSections(ArrayRef<StringRef> Patterns) {
|
||||
std::vector<InputSectionBase<ELFT> *> Ret;
|
||||
for (const std::unique_ptr<ObjectFile<ELFT>> &F :
|
||||
Symtab<ELFT>::X->getObjectFiles())
|
||||
for (InputSectionBase<ELFT> *S : F->getSections())
|
||||
if (!isDiscarded(S) && !S->OutSec && match(Patterns, S->getSectionName()))
|
||||
Ret.push_back(S);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
std::vector<OutputSectionBase<ELFT> *>
|
||||
LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
|
||||
typedef const std::unique_ptr<ObjectFile<ELFT>> ObjectFile;
|
||||
std::vector<OutputSectionBase<ELFT> *> Result;
|
||||
std::vector<OutputSectionBase<ELFT> *> Ret;
|
||||
|
||||
// Add input section to output section. If there is no output section yet,
|
||||
// then create it and add to output section list.
|
||||
auto AddInputSec = [&](InputSectionBase<ELFT> *C, StringRef Name) {
|
||||
auto Add = [&](InputSectionBase<ELFT> *C, StringRef Name) {
|
||||
OutputSectionBase<ELFT> *Sec;
|
||||
bool IsNew;
|
||||
std::tie(Sec, IsNew) = Factory.create(C, Name);
|
||||
if (IsNew)
|
||||
Result.push_back(Sec);
|
||||
Ret.push_back(Sec);
|
||||
Sec->addSection(C);
|
||||
};
|
||||
|
||||
// Select input sections matching rule and add them to corresponding
|
||||
// output section. Section rules are processed in order they're listed
|
||||
// in script, so correct input section order is maintained by design.
|
||||
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
|
||||
auto *OutCmd = dyn_cast<OutputSectionCommand>(Base.get());
|
||||
if (!OutCmd)
|
||||
continue;
|
||||
|
||||
for (const std::unique_ptr<BaseCommand> &Cmd : OutCmd->Commands) {
|
||||
auto *InCmd = dyn_cast<InputSectionDescription>(Cmd.get());
|
||||
if (!InCmd)
|
||||
for (auto &P : getSectionMap()) {
|
||||
StringRef OutputName = P.first;
|
||||
ArrayRef<StringRef> InputPatterns = P.second;
|
||||
for (InputSectionBase<ELFT> *S : getInputSections(InputPatterns)) {
|
||||
if (OutputName == "/DISCARD/") {
|
||||
S->Live = false;
|
||||
reportDiscarded(S);
|
||||
continue;
|
||||
|
||||
for (ObjectFile &F : Symtab<ELFT>::X->getObjectFiles()) {
|
||||
for (InputSectionBase<ELFT> *S : F->getSections()) {
|
||||
if (isDiscarded(S) || S->OutSec)
|
||||
continue;
|
||||
|
||||
if (match(InCmd->Patterns, S->getSectionName())) {
|
||||
if (OutCmd->Name == "/DISCARD/")
|
||||
S->Live = false;
|
||||
else
|
||||
AddInputSec(S, OutCmd->Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
Add(S, OutputName);
|
||||
}
|
||||
}
|
||||
|
||||
// Add all other input sections, which are not listed in script.
|
||||
for (ObjectFile &F : Symtab<ELFT>::X->getObjectFiles())
|
||||
for (InputSectionBase<ELFT> *S : F->getSections()) {
|
||||
if (!isDiscarded(S)) {
|
||||
if (!S->OutSec)
|
||||
AddInputSec(S, getOutputSectionName(S));
|
||||
} else
|
||||
reportDiscarded(S);
|
||||
}
|
||||
for (const std::unique_ptr<ObjectFile<ELFT>> &F :
|
||||
Symtab<ELFT>::X->getObjectFiles())
|
||||
for (InputSectionBase<ELFT> *S : F->getSections())
|
||||
if (!isDiscarded(S) && !S->OutSec)
|
||||
Add(S, getOutputSectionName(S));
|
||||
|
||||
// Remove from the output all the sections which did not meet
|
||||
// the optional constraints.
|
||||
return filter(Result);
|
||||
return filter(Ret);
|
||||
}
|
||||
|
||||
// Process ONLY_IF_RO and ONLY_IF_RW.
|
||||
|
|
|
@ -131,6 +131,11 @@ public:
|
|||
bool hasPhdrsCommands();
|
||||
|
||||
private:
|
||||
std::vector<std::pair<StringRef, ArrayRef<StringRef>>> getSectionMap();
|
||||
|
||||
std::vector<InputSectionBase<ELFT> *>
|
||||
getInputSections(ArrayRef<StringRef> Patterns);
|
||||
|
||||
// "ScriptConfig" is a bit too long, so define a short name for it.
|
||||
ScriptConfiguration &Opt = *ScriptConfig;
|
||||
|
||||
|
|
Loading…
Reference in New Issue