[ELF] - Linkerscript: add InputSectionDescription command to LS parser.

This adds InputSectionDescription command to represent
the input section declaration.

This leads to next cleanup:
SectionRule removed.
ScriptConfiguration::Sections mamber removed.
LinkerScript<ELFT>::getOutputSection() removed.

Differential revision: https://reviews.llvm.org/D22617

llvm-svn: 276283
This commit is contained in:
George Rimar 2016-07-21 14:26:59 +00:00
parent 7035cbf8eb
commit eea3114ff9
3 changed files with 59 additions and 49 deletions

View File

@ -47,6 +47,10 @@ bool OutputSectionCommand::classof(const BaseCommand *C) {
return C->Kind == OutputSectionKind;
}
bool InputSectionDescription::classof(const BaseCommand *C) {
return C->Kind == InputSectionKind;
}
// This is an operator-precedence parser to parse and evaluate
// a linker script expression. For each linker script arithmetic
// expression (e.g. ". = . + 0x1000"), a new instance of ExprParser
@ -194,17 +198,9 @@ uint64_t ExprParser::parseExpr1(uint64_t Lhs, int MinPrec) {
// Reads and evaluates an arithmetic expression.
uint64_t ExprParser::parseExpr() { return parseExpr1(parsePrimary(), 0); }
template <class ELFT>
StringRef LinkerScript<ELFT>::getOutputSection(InputSectionBase<ELFT> *S) {
for (SectionRule &R : Opt.Sections)
if (globMatch(R.SectionPattern, S->getSectionName()))
return R.Dest;
return "";
}
template <class ELFT>
bool LinkerScript<ELFT>::isDiscarded(InputSectionBase<ELFT> *S) {
return !S || !S->Live || getOutputSection(S) == "/DISCARD/";
return !S || !S->Live;
}
template <class ELFT>
@ -215,9 +211,17 @@ bool LinkerScript<ELFT>::shouldKeep(InputSectionBase<ELFT> *S) {
return false;
}
static bool match(StringRef Pattern, ArrayRef<StringRef> Arr) {
for (StringRef S : Arr)
if (globMatch(S, Pattern))
return true;
return false;
}
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;
// Add input section to output section. If there is no output section yet,
@ -234,18 +238,34 @@ LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
// 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 (SectionRule &R : Opt.Sections)
for (const std::unique_ptr<ObjectFile<ELFT>> &F :
Symtab<ELFT>::X->getObjectFiles())
for (InputSectionBase<ELFT> *S : F->getSections())
if (!isDiscarded(S) && !S->OutSec &&
globMatch(R.SectionPattern, S->getSectionName()))
// Add single input section to output section.
AddInputSec(S, R.Dest);
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)
continue;
for (ObjectFile &F : Symtab<ELFT>::X->getObjectFiles()) {
for (InputSectionBase<ELFT> *S : F->getSections()) {
if (isDiscarded(S) || S->OutSec)
continue;
if (match(S->getSectionName(), InCmd->Patterns)) {
if (OutCmd->Name == "/DISCARD/")
S->Live = false;
else
AddInputSec(S, OutCmd->Name);
}
}
}
}
}
// Add all other input sections, which are not listed in script.
for (const std::unique_ptr<ObjectFile<ELFT>> &F :
Symtab<ELFT>::X->getObjectFiles())
for (ObjectFile &F : Symtab<ELFT>::X->getObjectFiles())
for (InputSectionBase<ELFT> *S : F->getSections())
if (!isDiscarded(S)) {
if (!S->OutSec)
@ -735,17 +755,20 @@ void ScriptParser::readOutputSectionDescription(StringRef OutSec) {
while (!Error && !skip("}")) {
StringRef Tok = next();
if (Tok == "*") {
auto *InCmd = new InputSectionDescription();
Cmd->Commands.emplace_back(InCmd);
expect("(");
while (!Error && !skip(")"))
Opt.Sections.emplace_back(OutSec, next());
InCmd->Patterns.push_back(next());
} else if (Tok == "KEEP") {
expect("(");
expect("*");
expect("(");
auto *InCmd = new InputSectionDescription();
Cmd->Commands.emplace_back(InCmd);
while (!Error && !skip(")")) {
StringRef Sec = next();
Opt.Sections.emplace_back(OutSec, Sec);
Opt.KeptSections.push_back(Sec);
Opt.KeptSections.push_back(peek());
InCmd->Patterns.push_back(next());
}
expect(")");
} else {

View File

@ -31,26 +31,14 @@ class ScriptParser;
template <class ELFT> class InputSectionBase;
template <class ELFT> class OutputSectionBase;
// This class represents each rule in SECTIONS command.
struct SectionRule {
SectionRule(StringRef D, StringRef S)
: Dest(D), SectionPattern(S) {}
StringRef Dest;
StringRef SectionPattern;
// This enum is used to implement linker script SECTIONS command.
// https://sourceware.org/binutils/docs/ld/SECTIONS.html#SECTIONS
enum SectionsCommandKind {
AssignmentKind,
OutputSectionKind,
InputSectionKind
};
// This enum represents what we can observe in SECTIONS tag of script.
// Each sections-command may of be one of the following:
// (https://sourceware.org/binutils/docs/ld/SECTIONS.html#SECTIONS)
// * An ENTRY command.
// * A symbol assignment.
// * An output section description.
// * An overlay description.
// We support only AssignmentKind and OutputSectionKind for now.
enum SectionsCommandKind { AssignmentKind, OutputSectionKind };
struct BaseCommand {
BaseCommand(int K) : Kind(K) {}
virtual ~BaseCommand() {}
@ -70,10 +58,17 @@ struct OutputSectionCommand : BaseCommand {
: BaseCommand(OutputSectionKind), Name(Name) {}
static bool classof(const BaseCommand *C);
StringRef Name;
std::vector<std::unique_ptr<BaseCommand>> Commands;
std::vector<StringRef> Phdrs;
std::vector<uint8_t> Filler;
};
struct InputSectionDescription : BaseCommand {
InputSectionDescription() : BaseCommand(InputSectionKind) {}
static bool classof(const BaseCommand *C);
std::vector<StringRef> Patterns;
};
struct PhdrsCommand {
StringRef Name;
unsigned Type;
@ -84,9 +79,6 @@ struct PhdrsCommand {
// ScriptConfiguration holds linker script parse results.
struct ScriptConfiguration {
// SECTIONS commands.
std::vector<SectionRule> Sections;
// Used to assign addresses to sections.
std::vector<std::unique_ptr<BaseCommand>> Commands;
@ -114,7 +106,6 @@ public:
std::vector<OutputSectionBase<ELFT> *>
createSections(OutputSectionFactory<ELFT> &Factory);
StringRef getOutputSection(InputSectionBase<ELFT> *S);
ArrayRef<uint8_t> getFiller(StringRef Name);
bool isDiscarded(InputSectionBase<ELFT> *S);
bool shouldKeep(InputSectionBase<ELFT> *S);

View File

@ -90,10 +90,6 @@ private:
template <class ELFT>
StringRef elf::getOutputSectionName(InputSectionBase<ELFT> *S) {
StringRef Dest = Script<ELFT>::X->getOutputSection(S);
if (!Dest.empty())
return Dest;
StringRef Name = S->getSectionName();
for (StringRef V : {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.",
".init_array.", ".fini_array.", ".ctors.", ".dtors.",