Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -44,13 +44,42 @@ // This enum represents what we can observe in SECTIONS tag of script: // ExprKind is a location counter change, like ". = . + 0x1000" // SectionKind is a description of output section, like ".data :..." -enum SectionsCommandKind { SectionKind, AssignmentKind }; +enum CommandKind { AssignmentKind, SectionKind }; -struct SectionsCommand { - SectionsCommandKind Kind; +enum SectionsCommandKind { + AssignmentKind, + OutputSectionKind, + InputSectionKind, +}; + +struct BaseCommand { + enum { AssignmentKind, SectionKind }; + BaseCommand(int K) : Kind(K) {} + virtual ~BaseCommand() {} + int Kind; +}; + +struct SymbolAssignment : BaseCommand { + SymbolAssignment() : BaseCommand(AssignmentKind) {} + static bool classof(const CommandBase *C); + StringRef Name; std::vector Expr; +}; + +struct OutputSectionDescription : BaseCommand { + OutputSectionDescription() : BaseCommand(OutputSectionKind) {} + static bool classof(const CommandBase *C); StringRef Name; + std::vector Commands; std::vector Phdrs; + std::vector Filler; +}; + +struct InputSectionDescription : BaseCommand { + InputSectionDescription() : BaseCommand(InputSectionKind) {} + static bool classof(const CommandBase *C); + std::vector Patterns; + bool Keep = false; }; struct PhdrsCommand { @@ -69,7 +98,7 @@ llvm::StringMap> Filler; // Used to assign addresses to sections. - std::vector Commands; + std::vector Commands; // Used to assign sections to headers. std::vector PhdrsCommands; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -39,6 +39,18 @@ ScriptConfiguration *elf::ScriptConfig; +bool SymbolAssignment::classof(const CommandBase *C) { + return C->Kind == AssignmentKind; +}; + +bool OutputSectionDescription::classof(const CommandBase *C) { + return C->Kind == OutputSectionKind; +}; + +bool InputSectionDescription::classof(const CommandBase *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 @@ -267,14 +279,13 @@ uintX_t MinVA = std::numeric_limits::max(); uintX_t ThreadBssOffset = 0; - for (SectionsCommand &Cmd : Opt.Commands) { - if (Cmd.Kind == AssignmentKind) { - uint64_t Val = evalExpr(Cmd.Expr, Dot); - - if (Cmd.Name == ".") { + for (BaseCommand &Base : Opt.Commands) { + if (auto *Cmd = dyn_cast(&Base)) { + uint64_t Val = evalExpr(Cmd->Expr, Dot); + if (Cmd->Name == ".") { Dot = Val; } else { - auto *D = cast>(Symtab::X->find(Cmd.Name)); + auto *D = cast>(Symtab::X->find(Cmd->Name)); D->Value = Val; } continue; @@ -283,9 +294,9 @@ // Find all the sections with required name. There can be more than // one section with such name, if the alignment, flags or type // attribute differs. - assert(Cmd.Kind == SectionKind); + auto *Cmd = cast(&Base); for (OutputSectionBase *Sec : Sections) { - if (Sec->getName() != Cmd.Name) + if (Sec->getName() != Cmd->Name) continue; if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) { @@ -416,8 +427,11 @@ int LinkerScript::getSectionIndex(StringRef Name) { auto Begin = Opt.Commands.begin(); auto End = Opt.Commands.end(); - auto I = std::find_if(Begin, End, [&](SectionsCommand &N) { - return N.Kind == SectionKind && N.Name == Name; + auto I = std::find_if(Begin, End, [&](CommandBase &Base) { + if (auto *Cmd = dyn_cast(&Base) + if (Cmd->Name == Name) + return true; + return false; }); return I == End ? INT_MAX : (I - Begin); } @@ -435,10 +449,10 @@ template void LinkerScript::addScriptedSymbols() { - for (SectionsCommand &Cmd : Opt.Commands) - if (Cmd.Kind == AssignmentKind) - if (Cmd.Name != "." && Symtab::X->find(Cmd.Name) == nullptr) - Symtab::X->addAbsolute(Cmd.Name, STV_DEFAULT); + for (BaseCommand &Base : Opt.Commands) + if (auto *Cmd = dyn_cast(&Base)) + if (Cmd->Name != "." && Symtab::X->find(Cmd->Name) == nullptr) + Symtab::X->addAbsolute(Cmd->Name, STV_DEFAULT); } template bool LinkerScript::hasPhdrsCommands() { @@ -451,15 +465,16 @@ template std::vector LinkerScript::getPhdrIndicesForSection(StringRef Name) { - for (SectionsCommand &Cmd : Opt.Commands) { - if (Cmd.Kind != SectionKind || Cmd.Name != Name) + for (BaseCommand &Base : Opt.Commands) { + auto *Cmd = dyn_cast(&Base); + if (!Cmd || Cmd->Name != Name) continue; std::vector Indices; - for (StringRef PhdrName : Cmd.Phdrs) { + for (StringRef PhdrName : Cmd->Phdrs) { auto ItPhdr = std::find_if(Opt.PhdrsCommands.rbegin(), Opt.PhdrsCommands.rend(), - [&](PhdrsCommand &Cmd) { return Cmd.Name == PhdrName; }); + [&](PhdrsCommand &Cmd) { return Cmd->Name == PhdrName; }); if (ItPhdr == Opt.PhdrsCommands.rend()) error("section header '" + PhdrName + "' is not listed in PHDRS"); else