[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:
parent
7035cbf8eb
commit
eea3114ff9
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.",
|
||||
|
|
Loading…
Reference in New Issue