diff --git a/include/eld/Object/OutputSectionEntry.h b/include/eld/Object/OutputSectionEntry.h index 2d560592f..eb7e752e9 100644 --- a/include/eld/Object/OutputSectionEntry.h +++ b/include/eld/Object/OutputSectionEntry.h @@ -98,17 +98,28 @@ class OutputSectionEntry { void append(RuleContainer *PInput) { Inputs.push_back(PInput); } - const SymbolAssignments §ionsEndAssignments() const { - return SectionEndAssignments; + const SymbolAssignments &getPostOutputSectionAssignments() const { + return postOutputSectionAssignments; + } + SymbolAssignments &getPostOutputSectionAssignments() { + return postOutputSectionAssignments; } - SymbolAssignments §ionEndAssignments() { return SectionEndAssignments; } - sym_iterator sectionendsymBegin() { return SectionEndAssignments.begin(); } - sym_iterator sectionendsymEnd() { return SectionEndAssignments.end(); } + sym_iterator postOutputSectionAssignmentsBegin() { + return postOutputSectionAssignments.begin(); + } + sym_iterator postOutputSectionAssignmentsEnd() { + return postOutputSectionAssignments.end(); + } + + void movePostOutputSectionAssignments(OutputSectionEntry *Out) { + postOutputSectionAssignments = Out->getPostOutputSectionAssignments(); + Out->getPostOutputSectionAssignments().clear(); + } - void moveSectionAssignments(OutputSectionEntry *Out) { - SectionEndAssignments = Out->sectionEndAssignments(); - Out->sectionEndAssignments().clear(); + template void forEachPostOutputSectionAssignment(Func F) { + for (auto *A : postOutputSectionAssignments) + F(A); } // A section may be part of multiple segments, this only returns the @@ -221,7 +232,7 @@ class OutputSectionEntry { size_t Order; bool IsDiscard; InputList Inputs; - SymbolAssignments SectionEndAssignments; + SymbolAssignments postOutputSectionAssignments; RuleContainer *FirstNonEmptyRule; RuleContainer *LastRule; std::vector BranchIslands; diff --git a/include/eld/Script/Assignment.h b/include/eld/Script/Assignment.h index 702803666..82656685a 100644 --- a/include/eld/Script/Assignment.h +++ b/include/eld/Script/Assignment.h @@ -35,10 +35,11 @@ class ELFSection; class Assignment : public ScriptCommand { public: enum Level { - BEFORE_SECTIONS, // Assignments before SECTIONS command - AFTER_SECTIONS, // Assignments after SECTIONS command - INPUT_SECTION, // related to an input section - SECTIONS_END + BeforeSections, // Assignments before any SECTIONS command + AfterInputSectDesc, // Assignments inside output section body (with input + // rules) + AfterOutputSection, // Assignments between output sections inside SECTIONS + AfterSections // Assignments after SECTIONS command }; enum Type { DEFAULT, HIDDEN, PROVIDE, PROVIDE_HIDDEN, FILL, ASSERT, PRINT }; @@ -47,8 +48,6 @@ class Assignment : public ScriptCommand { Assignment(Level AssignmentLevel, Type AssignmentType, std::string Symbol, Expression *ScriptExpression); - - Level level() const { return AssignmentLevel; } void setLevel(enum Level AssignmentLevel) { @@ -93,12 +92,12 @@ class Assignment : public ScriptCommand { /// Query functions on Assignment Kinds. bool isOutsideSections() const { - return AssignmentLevel == BEFORE_SECTIONS || - AssignmentLevel == AFTER_SECTIONS; + return AssignmentLevel == BeforeSections || + AssignmentLevel == AfterSections; } bool isInsideOutputSection() const { - return AssignmentLevel == INPUT_SECTION; + return AssignmentLevel == AfterInputSectDesc; } bool isHidden() const { return ThisType == HIDDEN; } diff --git a/include/eld/Target/GNULDBackend.h b/include/eld/Target/GNULDBackend.h index 5b0d81d9e..b5be50028 100644 --- a/include/eld/Target/GNULDBackend.h +++ b/include/eld/Target/GNULDBackend.h @@ -482,7 +482,7 @@ class GNULDBackend { void evaluateAssignments(OutputSectionEntry *output); - void evaluateAssignmentsAtEndOfOutputSection(OutputSectionEntry *output); + void evaluatePostOutputSectionAssignments(OutputSectionEntry *output); // Print padding between end and start fragments of adjacent rules std::vector @@ -962,7 +962,7 @@ class GNULDBackend { // Evaluate defsym assignments and script assignments that appear outside // sections. - void evaluateScriptAssignments(bool evaluateAsserts = true); + void evaluateBeforeSectionsAssignments(bool evaluateAsserts = true); bool isRelROSection(const ELFSection *sect) const; diff --git a/lib/LayoutMap/TextLayoutPrinter.cpp b/lib/LayoutMap/TextLayoutPrinter.cpp index a40443202..169ee0f5a 100644 --- a/lib/LayoutMap/TextLayoutPrinter.cpp +++ b/lib/LayoutMap/TextLayoutPrinter.cpp @@ -1303,7 +1303,8 @@ void TextLayoutPrinter::printMapFile(eld::Module &Module) { for (const auto *X : (Script.getScriptCommands())) { if (const Assignment *A = llvm::dyn_cast(X)) - printAssignment(*A, Module, UseColor); + if (A->level() == Assignment::Level::BeforeSections) + printAssignment(*A, Module, UseColor); } printLayout(Module); @@ -1405,12 +1406,8 @@ void TextLayoutPrinter::printLayout(eld::Module &Module) { } } - // Evaluate all assignments at the end of the output section. - for (OutputSectionEntry::sym_iterator It = (*Out)->sectionendsymBegin(), - Ie = (*Out)->sectionendsymEnd(); - It != Ie; ++It) { - printAssignment(**It, Module, UseColor); - } + (*Out)->forEachPostOutputSectionAssignment( + [&](Assignment *A) { printAssignment(*A, Module, UseColor); }); } } diff --git a/lib/LayoutMap/YamlLayoutPrinter.cpp b/lib/LayoutMap/YamlLayoutPrinter.cpp index 982a7a58d..7cf68baa1 100644 --- a/lib/LayoutMap/YamlLayoutPrinter.cpp +++ b/lib/LayoutMap/YamlLayoutPrinter.cpp @@ -383,20 +383,18 @@ eld::YamlLayoutPrinter::buildYaml(eld::Module &Module, } Result.OutputSections.emplace_back( std::make_shared(std::move(Value))); - for (OutputSectionEntry::sym_iterator It = I->sectionendsymBegin(), - Ie = I->sectionendsymEnd(); - It != Ie; ++It) { + I->forEachPostOutputSectionAssignment([&](Assignment *A) { eld::LDYAML::Assignment Assignment; - Assignment.Name = (*It)->name(); - Assignment.Value = (*It)->value(); + Assignment.Name = A->name(); + Assignment.Value = A->value(); { raw_string_ostream Stream(Assignment.Text); - (*It)->getExpression()->dump(Stream); + A->getExpression()->dump(Stream); Stream.flush(); } Result.OutputSections.emplace_back( std::make_shared(std::move(Assignment))); - } + }); } Module::const_obj_iterator Obj, ObjEnd = Module.objEnd(); for (Obj = Module.objBegin(); Obj != ObjEnd; ++Obj) { diff --git a/lib/LinkerWrapper/LinkerScript.cpp b/lib/LinkerWrapper/LinkerScript.cpp index 45818e961..91f599c38 100644 --- a/lib/LinkerWrapper/LinkerScript.cpp +++ b/lib/LinkerWrapper/LinkerScript.cpp @@ -471,10 +471,11 @@ bool plugin::Script::Assignment::isGlobal() const { return m_Assignment->isOutsideSections(); } -// FIXME: This should return true when the assignment level -// is SECTIONS_END or OUTSIDE_SECTIONS. bool plugin::Script::Assignment::isOutsideOutputSection() const { - return false; + auto Level = m_Assignment->level(); + return Level == eld::Assignment::BeforeSections || + Level == eld::Assignment::AfterSections || + Level == eld::Assignment::AfterOutputSection; } bool plugin::Script::Assignment::isInsideOutputSection() const { @@ -658,7 +659,6 @@ eld::ScriptCommand *plugin::Script::Output::getCommand() const { return m_Output; } - // // OUTPUT_ARCH // diff --git a/lib/Script/Assignment.cpp b/lib/Script/Assignment.cpp index bb37dd3a3..7cc320f34 100644 --- a/lib/Script/Assignment.cpp +++ b/lib/Script/Assignment.cpp @@ -34,8 +34,6 @@ Assignment::Assignment(Level AssignmentLevel, Type AssignmentType, ExpressionValue(0), Name(Symbol), ExpressionToEvaluate(ScriptExpression), ThisSymbol(nullptr) {} - - void Assignment::dump(llvm::raw_ostream &Outs) const { bool CloseParen = true; switch (type()) { @@ -75,16 +73,16 @@ void Assignment::dump(llvm::raw_ostream &Outs) const { void Assignment::trace(llvm::raw_ostream &Outs) const { switch (AssignmentLevel) { - case BEFORE_SECTIONS: + case BeforeSections: Outs << "BEFORE_SECTIONS >> "; break; - case AFTER_SECTIONS: + case AfterSections: Outs << "AFTER_SECTIONS >> "; break; - case INPUT_SECTION: + case AfterInputSectDesc: Outs << " INSIDE_OUTPUT_SECTION >> "; break; - case SECTIONS_END: + case AfterOutputSection: Outs << " OUTPUT_SECTION(EPILOGUE) >> "; break; } @@ -99,14 +97,14 @@ void Assignment::dumpMap(llvm::raw_ostream &Ostream, bool Color, bool UseNewLine, bool WithValues, bool AddIndent) const { switch (AssignmentLevel) { - case BEFORE_SECTIONS: - case AFTER_SECTIONS: { + case BeforeSections: + case AfterSections: { if (Color) Ostream.changeColor(llvm::raw_ostream::GREEN); break; } - case INPUT_SECTION: { + case AfterInputSectDesc: { if (Color) Ostream.changeColor(llvm::raw_ostream::YELLOW); if (AddIndent) @@ -114,7 +112,7 @@ void Assignment::dumpMap(llvm::raw_ostream &Ostream, bool Color, break; } - case SECTIONS_END: { + case AfterOutputSection: { if (Color) Ostream.changeColor(llvm::raw_ostream::MAGENTA); break; @@ -176,22 +174,22 @@ eld::Expected Assignment::activate(Module &CurModule) { ExpressionToEvaluate->setContext(getContext()); switch (AssignmentLevel) { - case BEFORE_SECTIONS: - case AFTER_SECTIONS: + case BeforeSections: break; - case INPUT_SECTION: { - OutputSectionEntry::reference In = Script.sectionMap().back()->back(); - In->symAssignments().push_back(this); + case AfterSections: + case AfterOutputSection: { + SectionMap::reference Out = Script.sectionMap().back(); + Out->getPostOutputSectionAssignments().push_back(this); break; } - case SECTIONS_END: { - SectionMap::reference Out = Script.sectionMap().back(); - Out->sectionEndAssignments().push_back(this); + case AfterInputSectDesc: { + OutputSectionEntry::reference In = Script.sectionMap().back()->back(); + In->symAssignments().push_back(this); break; } - } // end of switch + } return eld::Expected(); } diff --git a/lib/Script/ScriptFile.cpp b/lib/Script/ScriptFile.cpp index 25160b582..272a202b7 100644 --- a/lib/Script/ScriptFile.cpp +++ b/lib/Script/ScriptFile.cpp @@ -311,30 +311,26 @@ void ScriptFile::addAssignment(const std::string &SymbolName, if (ScriptStateInsideOutputSection) { assert(!Sections->empty()); NewAssignment = - make(Assignment::INPUT_SECTION, AssignmentType, + make(Assignment::AfterInputSectDesc, AssignmentType, SymbolName, ScriptExpression); NewAssignment->setInputFileInContext(getContext()); NewAssignment->setParent(getParent()); OutputSectionDescription->pushBack(NewAssignment); } else { NewAssignment = - make(Assignment::Level::SECTIONS_END, AssignmentType, + make(Assignment::AfterOutputSection, AssignmentType, SymbolName, ScriptExpression); NewAssignment->setInputFileInContext(getContext()); NewAssignment->setParent(getParent()); Sections->pushBack(NewAssignment); } } else { - // Assignments encountered when not inside SECTIONS are either BEFORE or - // AFTER SECTIONS. Mark as AFTER if we've already seen a SECTIONS block - // in this script file or any previously processed script. - // Global state is sufficient: it is set during parsing when any - // SECTIONS block is entered. - Assignment::Level Lvl = ThisModule.getScript().linkerScriptHasSectionsCommand() - ? Assignment::AFTER_SECTIONS - : Assignment::BEFORE_SECTIONS; - NewAssignment = make(Lvl, AssignmentType, SymbolName, - ScriptExpression); + Assignment::Level Lvl = + ThisModule.getScript().linkerScriptHasSectionsCommand() + ? Assignment::AfterSections + : Assignment::BeforeSections; + NewAssignment = + make(Lvl, AssignmentType, SymbolName, ScriptExpression); NewAssignment->setInputFileInContext(getContext()); NewAssignment->setParent(getParent()); LinkerScriptCommandQueue.push_back(NewAssignment); @@ -349,7 +345,7 @@ bool ScriptFile::linkerScriptHasSectionsCommand() const { void ScriptFile::enterSectionsCmd() { LinkerScriptHasSectionsCommand = true; // Also mark global script state so other scripts parsed later - // can correctly mark AFTER_SECTIONS assignments. + // can correctly set the level of assignments. ThisModule.getScript().setHasSectionsCmd(); ScriptStateInSectionsCommmand = true; auto *Cmd = make(); diff --git a/lib/Script/SectionsCmd.cpp b/lib/Script/SectionsCmd.cpp index e8dfa75be..bb2a7bd77 100644 --- a/lib/Script/SectionsCmd.cpp +++ b/lib/Script/SectionsCmd.cpp @@ -22,8 +22,6 @@ using namespace eld; //===----------------------------------------------------------------------===// SectionsCmd::SectionsCmd() : ScriptCommand(ScriptCommand::SECTIONS) {} - - void SectionsCmd::dump(llvm::raw_ostream &Outs) const { Outs << "SECTIONS\n{\n"; @@ -103,12 +101,9 @@ eld::Expected SectionsCmd::activate(Module &CurModule) { break; } } - // The assignment may be the last set too. if (!Assignments.empty()) { - iterator Assign, AssignEnd = Assignments.end(); - for (Assign = Assignments.begin(); Assign != AssignEnd; ++Assign) { - llvm::cast(*Assign)->setLevel(Assignment::SECTIONS_END); - eld::Expected E = (*Assign)->activate(CurModule); + for (auto *Assign : Assignments) { + eld::Expected E = Assign->activate(CurModule); ELDEXP_RETURN_DIAGENTRY_IF_ERROR(E); } Assignments.clear(); diff --git a/lib/Target/CreateProgramHeaders.hpp b/lib/Target/CreateProgramHeaders.hpp index ad47cb6bb..fc3c98550 100644 --- a/lib/Target/CreateProgramHeaders.hpp +++ b/lib/Target/CreateProgramHeaders.hpp @@ -177,7 +177,7 @@ bool GNULDBackend::createProgramHdrs() { { eld::RegisterTimer T("Evaluate Script Assignments", "Establish Layout", m_Module.getConfig().options().printTimingStats()); - evaluateScriptAssignments(/*evaluateAsserts=*/false); + evaluateBeforeSectionsAssignments(/*evaluateAsserts=*/false); } }; @@ -321,7 +321,7 @@ bool GNULDBackend::createProgramHdrs() { if (curIsDebugSection || (*out)->isDiscard()) { cur->setAddr(dotSymbol->value()); evaluateAssignments(*out); - evaluateAssignmentsAtEndOfOutputSection(*out); + evaluatePostOutputSectionAssignments(*out); cur->setWanted(cur->wantedInOutput() || cur->size()); ++out; cur->setAddr(0); @@ -585,7 +585,7 @@ bool GNULDBackend::createProgramHdrs() { } // Evaluate Assignments at end of output section. - evaluateAssignmentsAtEndOfOutputSection(*out); + evaluatePostOutputSectionAssignments(*out); cur->setWanted(cur->wantedInOutput() || cur->size()); if (!config().getDiagEngine()->diagnose()) { diff --git a/lib/Target/CreateScriptProgramHeaders.hpp b/lib/Target/CreateScriptProgramHeaders.hpp index 4f47069f8..fc33d151b 100644 --- a/lib/Target/CreateScriptProgramHeaders.hpp +++ b/lib/Target/CreateScriptProgramHeaders.hpp @@ -81,7 +81,7 @@ bool GNULDBackend::createScriptProgramHdrs() { { eld::RegisterTimer T("Evaluate Script Assignments", "Establish Layout", m_Module.getConfig().options().printTimingStats()); - evaluateScriptAssignments(/*evaluateAsserts=*/false); + evaluateBeforeSectionsAssignments(/*evaluateAsserts=*/false); } }; @@ -203,7 +203,7 @@ bool GNULDBackend::createScriptProgramHdrs() { if (curIsDebugSection || (*out)->isDiscard()) { cur->setAddr(dotSymbol->value()); evaluateAssignments(*out); - evaluateAssignmentsAtEndOfOutputSection(*out); + evaluatePostOutputSectionAssignments(*out); cur->setAddr(0); cur->setPaddr(0); ++out; @@ -329,7 +329,7 @@ bool GNULDBackend::createScriptProgramHdrs() { } // Evaluate Assignments at the end of the output section. - evaluateAssignmentsAtEndOfOutputSection(*out); + evaluatePostOutputSectionAssignments(*out); cur->setWanted(cur->wantedInOutput() || cur->size()); if (!config().getDiagEngine()->diagnose()) { return false; diff --git a/lib/Target/GNULDBackend.cpp b/lib/Target/GNULDBackend.cpp index 0dd419d59..968c4d1ea 100644 --- a/lib/Target/GNULDBackend.cpp +++ b/lib/Target/GNULDBackend.cpp @@ -2052,18 +2052,14 @@ void GNULDBackend::evaluateAssignments(OutputSectionEntry *out) { } } -void GNULDBackend::evaluateAssignmentsAtEndOfOutputSection( +void GNULDBackend::evaluatePostOutputSectionAssignments( OutputSectionEntry *out) { eld::RegisterTimer T("Evaluate Expressions", "Establish Layout", m_Module.getConfig().options().printTimingStats()); if (m_Module.getPrinter()->traceAssignments()) config().raise(Diag::output_section_eval) << (out->name().empty() ? "" : out->name()) << "\n"; - // Evaluate all assignments at the end of the output section. - for (OutputSectionEntry::sym_iterator it = out->sectionendsymBegin(), - ie = out->sectionendsymEnd(); - it != ie; ++it) { - Assignment *assign = (*it); + for (auto *assign : out->getPostOutputSectionAssignments()) { // We do not need to evaluate PROVIDE expressions for PROVIDE // symbols that are not being used in the link. if (assign->isProvideOrProvideHidden() && !isProvideSymBeingUsed(assign)) @@ -2078,7 +2074,7 @@ void GNULDBackend::evaluateAssignmentsAtEndOfOutputSection( } continue; } - (*it)->assign(m_Module, nullptr); + assign->assign(m_Module, nullptr); } } @@ -2555,6 +2551,7 @@ bool GNULDBackend::setOutputSectionOffset() { // Set initial dot symbol value. LDSymbol *dotSymbol = m_Module.getNamePool().findSymbol("."); + evaluateBeforeSectionsAssignments(); while (out != outEnd) { ELFSection *cur = (*out)->getSection(); @@ -2586,7 +2583,7 @@ bool GNULDBackend::setOutputSectionOffset() { if (isCurAlloc && cur->size()) changeSymbolsFromAbsoluteToGlobal(*out); prev = cur; - evaluateAssignmentsAtEndOfOutputSection(*out); + evaluatePostOutputSectionAssignments(*out); ++out; } return true; @@ -2952,7 +2949,7 @@ bool GNULDBackend::placeOutputSections() { // Behavior seen from GNU. if ((out != sectionMap.begin() && ((*cur)->getSection()->getFlags() == (*prev)->getSection()->getFlags()))) - (*cur)->moveSectionAssignments(*prev); + (*cur)->movePostOutputSectionAssignments(*prev); } } } @@ -3044,14 +3041,6 @@ bool GNULDBackend::layout() { return false; } - // Evaluate all assignments. - { - eld::RegisterTimer T("Evaluate Script Assignments and Asserts", - "Establish Layout", - m_Module.getConfig().options().printTimingStats()); - evaluateScriptAssignments(); - } - if (!config().getDiagEngine()->diagnose()) { if (m_Module.getPrinter()->isVerbose()) config().raise(Diag::function_has_error) << __PRETTY_FUNCTION__; @@ -4095,11 +4084,12 @@ MemoryRegion GNULDBackend::getFileOutputRegion(llvm::FileOutputBuffer &pBuffer, return MemoryRegion(pBuffer.getBufferStart() + pOffset, pLength); } -void GNULDBackend::evaluateScriptAssignments(bool evaluateAsserts) { +void GNULDBackend::evaluateBeforeSectionsAssignments(bool evaluateAsserts) { for (auto &assign : m_Module.getScript().assignments()) { - // Evaluate assignments outside SECTIONS both before and after layout. - if (!(assign->level() == Assignment::BEFORE_SECTIONS || - assign->level() == Assignment::AFTER_SECTIONS)) + // Only evaluate BeforeSections assignments here. + // AfterSections and AfterOutputSection assignments are evaluated + // per-OutputSectionEntry in evaluatePostOutputSectionAssignments(). + if (assign->level() != Assignment::BeforeSections) continue; if (shouldskipAssert(assign)) { if (m_Module.getPrinter()->isVerbose()) { diff --git a/test/Common/standalone/Map/OutsideSectionsAssignmentsContext/OutsideSectionsAssignmentsContext.test b/test/Common/standalone/Map/OutsideSectionsAssignmentsContext/OutsideSectionsAssignmentsContext.test index e1a551251..6c21d27fe 100644 --- a/test/Common/standalone/Map/OutsideSectionsAssignmentsContext/OutsideSectionsAssignmentsContext.test +++ b/test/Common/standalone/Map/OutsideSectionsAssignmentsContext/OutsideSectionsAssignmentsContext.test @@ -10,5 +10,5 @@ RUN: %filecheck %s < %t2.map #END_TEST CHECK: var_u(0x1) = 0x1; # var_u = 0x1; {{.*}}script.t -CHECK: var_w(0x5) = 0x5; # var_w = 0x5; {{.*}}script.t CHECK: var_v(0x3) = 0x3; # var_v = 0x3; {{.*}}script.t +CHECK: var_w(0x5) = 0x5; # var_w = 0x5; {{.*}}script.t diff --git a/test/Common/standalone/linkerscript/AssignmentOrderInSections/AssignmentOrderInSections.test b/test/Common/standalone/linkerscript/AssignmentOrderInSections/AssignmentOrderInSections.test new file mode 100644 index 000000000..bad38db4e --- /dev/null +++ b/test/Common/standalone/linkerscript/AssignmentOrderInSections/AssignmentOrderInSections.test @@ -0,0 +1,24 @@ +#---AssignmentOrderInSections.test--------------------- Executable,LS ----------------------# +#BEGIN_COMMENT +# This test verifies that assignments within SECTIONS are evaluated +# in sequential order. +# u = v should evaluate to 0xc (the value of v at that point), +# not 0xa (the value v is reassigned to later). +#END_COMMENT +#START_TEST +RUN: %clang %clangopts -o %t1.1.o %p/Inputs/1.c -c +RUN: %link %linkopts -o %t1.1.out %t1.1.o -T %p/Inputs/script.t -Map %t1.1.map.txt +RUN: %readelf -s %t1.1.out | %filecheck %s +RUN: %filecheck %s --check-prefix=MAP < %t1.1.map.txt +#END_TEST + +CHECK-DAG: {{0+}}c {{.*}} u +CHECK-DAG: {{0+}}a {{.*}} v + +MAP: Output Section and Layout +MAP: v(0xc) = 0xc; # v = 0xc; {{.*}}script.t +MAP: u(0xc) = v(0xc); # u = v; {{.*}}script.t +MAP: .text +MAP: *(.text*) +MAP: .text {{.*}}1.o +MAP: v(0xa) = 0xa; # v = 0xa; {{.*}}script.t \ No newline at end of file diff --git a/test/Common/standalone/linkerscript/AssignmentOrderInSections/Inputs/1.c b/test/Common/standalone/linkerscript/AssignmentOrderInSections/Inputs/1.c new file mode 100644 index 000000000..a60f28c10 --- /dev/null +++ b/test/Common/standalone/linkerscript/AssignmentOrderInSections/Inputs/1.c @@ -0,0 +1 @@ +int foo() { return 1; } diff --git a/test/Common/standalone/linkerscript/AssignmentOrderInSections/Inputs/script.t b/test/Common/standalone/linkerscript/AssignmentOrderInSections/Inputs/script.t new file mode 100644 index 000000000..66dbdc64e --- /dev/null +++ b/test/Common/standalone/linkerscript/AssignmentOrderInSections/Inputs/script.t @@ -0,0 +1,8 @@ +v = 0xc; +SECTIONS { + u = v; + .text : { + *(.text*) + } + v = 0xa; +} diff --git a/test/Common/standalone/linkerscript/IncorrectAssignmentInLayoutReiteration/IncorrectAssignmentInLayoutReiteration.test b/test/Common/standalone/linkerscript/IncorrectAssignmentInLayoutReiteration/IncorrectAssignmentInLayoutReiteration.test index 5741a680b..5fbb0849b 100644 --- a/test/Common/standalone/linkerscript/IncorrectAssignmentInLayoutReiteration/IncorrectAssignmentInLayoutReiteration.test +++ b/test/Common/standalone/linkerscript/IncorrectAssignmentInLayoutReiteration/IncorrectAssignmentInLayoutReiteration.test @@ -8,5 +8,5 @@ RUN: %link %linkopts -o %t1.1.out %t1.1.o -T %p/Inputs/script.t -Map %t1.1.map.t RUN: %readelf -s %t1.1.out | %filecheck %s #END_TEST +CHECK-DAG: {{0*300}} 0 NOTYPE GLOBAL DEFAULT ABS u CHECK-DAG: {{0*100}} 0 NOTYPE GLOBAL DEFAULT ABS v -CHECK-DAG: {{0*100}} 0 NOTYPE GLOBAL DEFAULT ABS u diff --git a/test/Common/standalone/linkerscript/IncorrectAssignmentInLayoutReiterationWithPHDRS/IncorrectAssignmentInLayoutReiterationWithPHDRS.test b/test/Common/standalone/linkerscript/IncorrectAssignmentInLayoutReiterationWithPHDRS/IncorrectAssignmentInLayoutReiterationWithPHDRS.test index cdb8e05c7..299307279 100644 --- a/test/Common/standalone/linkerscript/IncorrectAssignmentInLayoutReiterationWithPHDRS/IncorrectAssignmentInLayoutReiterationWithPHDRS.test +++ b/test/Common/standalone/linkerscript/IncorrectAssignmentInLayoutReiterationWithPHDRS/IncorrectAssignmentInLayoutReiterationWithPHDRS.test @@ -9,5 +9,5 @@ RUN: %link %linkopts -o %t1.1.out %t1.1.o -T %p/Inputs/script.t -Map %t1.1.map.t RUN: %readelf -s %t1.1.out | %filecheck %s #END_TEST +CHECK-DAG: {{0*300}} 0 NOTYPE GLOBAL DEFAULT ABS u CHECK-DAG: {{0*100}} 0 NOTYPE GLOBAL DEFAULT ABS v -CHECK-DAG: {{0*100}} 0 NOTYPE GLOBAL DEFAULT ABS u diff --git a/test/Common/standalone/linkerscript/MultipleSectionsAssignment/Inputs/1.c b/test/Common/standalone/linkerscript/MultipleSectionsAssignment/Inputs/1.c new file mode 100644 index 000000000..0bb1d6797 --- /dev/null +++ b/test/Common/standalone/linkerscript/MultipleSectionsAssignment/Inputs/1.c @@ -0,0 +1,2 @@ +int foo() { return 1; } +int bar = 42; diff --git a/test/Common/standalone/linkerscript/MultipleSectionsAssignment/Inputs/script.t b/test/Common/standalone/linkerscript/MultipleSectionsAssignment/Inputs/script.t new file mode 100644 index 000000000..4bb7954d6 --- /dev/null +++ b/test/Common/standalone/linkerscript/MultipleSectionsAssignment/Inputs/script.t @@ -0,0 +1,14 @@ +SECTIONS { + .text : { + *(.text*) + } + a = u; +} +u = 0x3; +SECTIONS { + .data : { + *(.data*) + } + b = u; +} +u = 0x7; diff --git a/test/Common/standalone/linkerscript/MultipleSectionsAssignment/MultipleSectionsAssignment.test b/test/Common/standalone/linkerscript/MultipleSectionsAssignment/MultipleSectionsAssignment.test new file mode 100644 index 000000000..4331da673 --- /dev/null +++ b/test/Common/standalone/linkerscript/MultipleSectionsAssignment/MultipleSectionsAssignment.test @@ -0,0 +1,26 @@ +#---MultipleSectionsAssignment.test--------------------- Executable,LS ----------------------# +#BEGIN_COMMENT +# This test verifies that assignments between multiple SECTIONS blocks +# are evaluated in the correct sequential order. +#END_COMMENT +#START_TEST +RUN: %clang %clangopts -o %t1.1.o %p/Inputs/1.c -c -ffunction-sections -fdata-sections +RUN: %link %linkopts -o %t1.1.out %t1.1.o -T %p/Inputs/script.t -Map %t1.1.map.txt +RUN: %readelf -s %t1.1.out | %filecheck %s +RUN: %filecheck %s --check-prefix=MAP < %t1.1.map.txt +#END_TEST + +CHECK-DAG: {{0+}}7 {{.*}} a +CHECK-DAG: {{0+}}3 {{.*}} b +CHECK-DAG: {{0+}}7 {{.*}} u + +MAP: Output Section and Layout +MAP: .text +MAP: *(.text*) #Rule 1 +MAP: .text.foo +MAP: a(0x7) = u(0x7); # a = u; +MAP: u(0x3) = 0x3; # u = 0x3; +MAP: .data +MAP: *(.data*) +MAP: b(0x3) = u(0x3); # b = u; +MAP: u(0x7) = 0x7; # u = 0x7; \ No newline at end of file