diff --git a/include/eld/Core/Module.h b/include/eld/Core/Module.h index 3343daa10..7e6562b64 100644 --- a/include/eld/Core/Module.h +++ b/include/eld/Core/Module.h @@ -159,10 +159,14 @@ class Module { enum LinkState : uint8_t { Unknown, Initializing, + ActBeforeRuleMatching, BeforeLayout, + ActBeforeSectionMerging, CreatingSections, + ActBeforePerformingLayout, CreatingSegments, AfterLayout, + ActBeforeWritingOutput }; public: diff --git a/include/eld/PluginAPI/LinkerWrapper.h b/include/eld/PluginAPI/LinkerWrapper.h index 2a2e24c07..39581b14c 100644 --- a/include/eld/PluginAPI/LinkerWrapper.h +++ b/include/eld/PluginAPI/LinkerWrapper.h @@ -805,14 +805,22 @@ class DLL_A_EXPORT LinkerWrapper { bool doNotUseRMName = false); bool isLinkStateInitializing() const; + bool isLinkStateActBeforeRuleMatching() const; + bool isLinkStateBeforeLayout() const; + bool isLinkStateActBeforeSectionMerging() const; + bool isLinkStateCreatingSections() const; - bool isLinkStateAfterLayout() const; + bool isLinkStateActBeforePerformingLayout() const; bool isLinkStateCreatingSegments() const; + bool isLinkStateAfterLayout() const; + + bool isLinkStateActBeforeWritingOutput() const; + private: uint8_t getLinkState() const; diff --git a/lib/Core/Linker.cpp b/lib/Core/Linker.cpp index bbaf23828..14c843cdb 100644 --- a/lib/Core/Linker.cpp +++ b/lib/Core/Linker.cpp @@ -468,6 +468,7 @@ bool Linker::resolve() { } PluginManager &PM = ThisModule->getPluginManager(); + ThisModule->setLinkState(Module::LinkState::ActBeforeRuleMatching); PM.callActBeforeRuleMatchingHook(); // Assign output sections. diff --git a/lib/Core/Module.cpp b/lib/Core/Module.cpp index 6b04ae941..e6f2728c8 100644 --- a/lib/Core/Module.cpp +++ b/lib/Core/Module.cpp @@ -501,20 +501,22 @@ bool Module::updateOutputSectionsWithPlugins() { } llvm::StringRef Module::getStateStr() const { +#define ADD_CASE(S) \ + case LinkState::S: \ + return #S; switch (getState()) { - case LinkState::Unknown: - return "Unknown"; - case LinkState::Initializing: - return "Initializing"; - case LinkState::BeforeLayout: - return "BeforeLayout"; - case LinkState::CreatingSections: - return "CreatingSections"; - case LinkState::AfterLayout: - return "AfterLayout"; - case LinkState::CreatingSegments: - return "CreatingSegments"; + ADD_CASE(Unknown) + ADD_CASE(Initializing) + ADD_CASE(ActBeforeRuleMatching) + ADD_CASE(BeforeLayout) + ADD_CASE(ActBeforeSectionMerging) + ADD_CASE(CreatingSections) + ADD_CASE(ActBeforePerformingLayout) + ADD_CASE(CreatingSegments) + ADD_CASE(AfterLayout) + ADD_CASE(ActBeforeWritingOutput) } +#undef ADD_CASE } void Module::addSymbolCreatedByPluginToFragment(Fragment *F, std::string Symbol, @@ -522,7 +524,8 @@ void Module::addSymbolCreatedByPluginToFragment(Fragment *F, std::string Symbol, const eld::Plugin *Plugin) { LayoutInfo *layoutInfo = getLayoutInfo(); LDSymbol *S = SymbolNamePool.createPluginSymbol( - getInternalInput(Module::InternalInputType::Plugin), Symbol, F, Val, layoutInfo); + getInternalInput(Module::InternalInputType::Plugin), Symbol, F, Val, + layoutInfo); if (S && layoutInfo && layoutInfo->showSymbolResolution()) SymbolNamePool.getSRI().recordPluginSymbol(S, Plugin); PluginFragmentToSymbols[F]; diff --git a/lib/LayoutMap/TextLayoutPrinter.cpp b/lib/LayoutMap/TextLayoutPrinter.cpp index 03e81c69d..d635fb720 100644 --- a/lib/LayoutMap/TextLayoutPrinter.cpp +++ b/lib/LayoutMap/TextLayoutPrinter.cpp @@ -693,7 +693,7 @@ void TextLayoutPrinter::printFragInfo(Fragment *Frag, LayoutFragmentInfo *Info, std::optional AddressOrOffset; bool HasFragInfo = - (M.isLinkStateCreatingSegments() || M.isLinkStateAfterLayout()); + (M.getState() >= Module::LinkState::ActBeforePerformingLayout); if (llvm::isa(Frag) && !M.isLinkStateBeforeLayout()) { auto *Strings = llvm::cast(Frag); for (MergeableString *S : Strings->getStrings()) { @@ -850,8 +850,8 @@ void TextLayoutPrinter::printFrag(eld::Module &CurModule, ELFSection *Section, const LayoutInfo::RemoveSymbolOpsMapT RemovedSymbols = ThisLayoutInfo->getRemovedSymbols(); - bool HasFragOffsets = (CurModule.isLinkStateCreatingSegments() || - CurModule.isLinkStateAfterLayout()); + bool HasFragOffsets = + (CurModule.getState() >= Module::LinkState::ActBeforePerformingLayout); for (Syms = FragmentInfo->Symbols.begin(); Syms != EndSymbols; ++Syms) { // Handle weak symbols. diff --git a/lib/LinkerWrapper/CheckLinkState.h b/lib/LinkerWrapper/CheckLinkState.h index f7282bc22..a35ad0fd5 100644 --- a/lib/LinkerWrapper/CheckLinkState.h +++ b/lib/LinkerWrapper/CheckLinkState.h @@ -26,20 +26,33 @@ static inline bool isValidLinkState(const eld::plugin::LinkerWrapper &LW, std::initializer_list ValidLinkStates) { for (const auto &S : ValidLinkStates) { - bool b = S == "Initializing" || S == "BeforeLayout" || - S == "CreatingSections" || S == "CreatingSegments" || - S == "AfterLayout"; + bool b = S == "Initializing" || S == "ActBeforeRuleMatching" || + S == "BeforeLayout" || S == "ActBeforeSectionMerging" || + S == "CreatingSections" || S == "ActBeforePerformingLayout" || + S == "CreatingSegments" || S == "AfterLayout" || + S == "ActBeforeWritingOutput"; ASSERT(b, "Invalid link state: " + std::string(S)); if (S == "Initializing" && LW.isLinkStateInitializing()) return true; + if (S == "ActBeforeRuleMatching" && LW.isLinkStateActBeforeRuleMatching()) + return true; if (S == "BeforeLayout" && LW.isLinkStateBeforeLayout()) return true; + if (S == "ActBeforeSectionMerging" && + LW.isLinkStateActBeforeSectionMerging()) + return true; if (S == "CreatingSections" && LW.isLinkStateCreatingSections()) return true; + if (S == "PerformingLayout" && LW.isLinkStateBeforeLayout()) + return true; if (S == "CreatingSegments" && LW.isLinkStateCreatingSegments()) return true; + if (S == "ActBeforePerformingLayout" && LW.isLinkStateActBeforePerformingLayout()) + return true; if (S == "AfterLayout" && LW.isLinkStateAfterLayout()) return true; + if (S == "ActBeforeWritingOutput" && LW.isLinkStateActBeforeWritingOutput()) + return true; } return false; } diff --git a/lib/LinkerWrapper/LinkerWrapper.cpp b/lib/LinkerWrapper/LinkerWrapper.cpp index 4bfeb69c3..ad38eae62 100644 --- a/lib/LinkerWrapper/LinkerWrapper.cpp +++ b/lib/LinkerWrapper/LinkerWrapper.cpp @@ -176,7 +176,8 @@ LinkerWrapper::getOutputSection(Section &S) const { eld::Expected> LinkerWrapper::getOutputSectionContents(OutputSection &O) const { - CHECK_LINK_STATE(*this, "CreatingSegments", "AfterLayout"); + CHECK_LINK_STATE(*this, "CreatingSegments", "AfterLayout", + "ActBeforeWritingOutput"); if (O.getOutputSection()->getSection()->isNoBits()) return std::make_unique( Diag::error_nobits_unsupported, std::vector{O.getName()}); @@ -218,7 +219,8 @@ eld::Expected LinkerWrapper::reassignVirtualAddresses() { } eld::Expected> LinkerWrapper::getSegmentTable() const { - CHECK_LINK_STATE(*this, "CreatingSegments", "AfterLayout"); + CHECK_LINK_STATE(*this, "CreatingSegments", "AfterLayout", + "ActBeforeWritingOutput"); std::vector Segments; for (auto *S : m_Module.getBackend().elfSegmentTable()) Segments.push_back(Segment(S)); @@ -263,7 +265,9 @@ eld::Expected LinkerWrapper::doRelocation() { } eld::Expected LinkerWrapper::addChunkToOutput(Chunk C) { - CHECK_LINK_STATE(*this, "CreatingSections", "CreatingSegments", "AfterLayout"); + CHECK_LINK_STATE(*this, "ActBeforeSectionMerging", "CreatingSections", + "ActBeforePerformingLayout", "CreatingSegments", + "AfterLayout"); auto ExpMapping = getOutputSectionAndRule(C.getSection()); if (!ExpMapping) @@ -290,7 +294,8 @@ eld::Expected LinkerWrapper::addChunkToOutput(Chunk C) { } eld::Expected LinkerWrapper::resetOffset(OutputSection O) { - CHECK_LINK_STATE(*this, "CreatingSegments", "AfterLayout"); + CHECK_LINK_STATE(*this, "ActBeforePerformingLayout", "CreatingSegments", + "AfterLayout"); if (auto *layoutInfo = m_Module.getLayoutInfo()) { auto OldOffset = O.getOffset(); ELDEXP_RETURN_DIAGENTRY_IF_ERROR(OldOffset); @@ -304,7 +309,9 @@ eld::Expected LinkerWrapper::resetOffset(OutputSection O) { eld::Expected> LinkerWrapper::getOutputSectionAndRule(Section S) { - CHECK_LINK_STATE(*this, "CreatingSections", "CreatingSegments", "AfterLayout"); + CHECK_LINK_STATE(*this, "ActBeforeSectionMerging", "CreatingSections", + "ActBeforePerformingLayout", "CreatingSegments", + "AfterLayout", "ActBeforeWritingOutput"); InputFile F = S.getInputFile(); @@ -339,9 +346,10 @@ LinkerWrapper::getOutputSectionAndRule(Section S) { eld::Expected LinkerWrapper::linkSections(OutputSection A, OutputSection B) const { - CHECK_LINK_STATE(*this, "CreatingSections", "CreatingSegments"); + CHECK_LINK_STATE(*this, "ActBeforeSectionMerging", "CreatingSections", + "ActBeforePerformingLayout", "CreatingSegments"); m_Module.getBackend().pluginLinkSections(A.getOutputSection(), - B.getOutputSection()); + B.getOutputSection()); return {}; } @@ -964,10 +972,14 @@ std::string_view LinkerWrapper::getCurrentLinkStateAsStr() const { return #linkerState; ADD_CASE(Unknown); ADD_CASE(Initializing); + ADD_CASE(ActBeforeRuleMatching); ADD_CASE(BeforeLayout); + ADD_CASE(ActBeforeSectionMerging); ADD_CASE(CreatingSections); - ADD_CASE(AfterLayout); + ADD_CASE(ActBeforePerformingLayout); ADD_CASE(CreatingSegments); + ADD_CASE(AfterLayout); + ADD_CASE(ActBeforeWritingOutput); #undef ADD_CASE } llvm_unreachable("Invalid link state!"); @@ -979,7 +991,9 @@ bool LinkerWrapper::isVerbose() const { eld::Expected> LinkerWrapper::getAllOutputSections() const { - CHECK_LINK_STATE(*this, "CreatingSections", "CreatingSegments", "AfterLayout"); + CHECK_LINK_STATE(*this, "ActBeforeSectionMerging", "CreatingSections", + "ActBeforePerformingLayout", "CreatingSegments", + "ActBeforeWritingOutput", "AfterLayout"); SectionMap sectMap = m_Module.getScript().sectionMap(); std::vector outputSects; @@ -991,7 +1005,8 @@ LinkerWrapper::getAllOutputSections() const { eld::Expected> LinkerWrapper::getSegmentsForOutputSection(const OutputSection &O) const { - CHECK_LINK_STATE(*this, "CreatingSections", "CreatingSegments", "AfterLayout"); + CHECK_LINK_STATE(*this, "CreatingSections", "ActBeforePerformingLayout", + "CreatingSegments", "AfterLayout", "ActBeforeWritingOutput"); std::vector Segments; for (auto *S : m_Module.getBackend().getSegmentsForSection(O.getOutputSection())) @@ -1171,18 +1186,34 @@ bool LinkerWrapper::isLinkStateInitializing() const { return m_Module.getState() == Module::LinkState::Initializing; } +bool LinkerWrapper::isLinkStateActBeforeRuleMatching() const { + return m_Module.getState() == Module::LinkState::ActBeforeRuleMatching; +} + bool LinkerWrapper::isLinkStateBeforeLayout() const { return m_Module.getState() == Module::LinkState::BeforeLayout; } +bool LinkerWrapper::isLinkStateActBeforeSectionMerging() const { + return m_Module.getState() == Module::LinkState::ActBeforeSectionMerging; +} + bool LinkerWrapper::isLinkStateCreatingSections() const { return m_Module.getState() == Module::LinkState::CreatingSections; } +bool LinkerWrapper::isLinkStateCreatingSegments() const { + return m_Module.getState() == Module::LinkState::CreatingSegments; +} + +bool LinkerWrapper::isLinkStateActBeforePerformingLayout() const { + return m_Module.getState() == Module::LinkState::ActBeforePerformingLayout; +} + bool LinkerWrapper::isLinkStateAfterLayout() const { return m_Module.getState() == Module::LinkState::AfterLayout; } -bool LinkerWrapper::isLinkStateCreatingSegments() const { - return m_Module.getState() == Module::LinkState::CreatingSegments; -} +bool LinkerWrapper::isLinkStateActBeforeWritingOutput() const { + return m_Module.getState() == Module::LinkState::ActBeforeWritingOutput; +} \ No newline at end of file diff --git a/lib/LinkerWrapper/PluginADT.cpp b/lib/LinkerWrapper/PluginADT.cpp index ce44f5856..61ea6b1aa 100644 --- a/lib/LinkerWrapper/PluginADT.cpp +++ b/lib/LinkerWrapper/PluginADT.cpp @@ -30,7 +30,6 @@ #include "llvm/Support/Timer.h" #include #include - using namespace eld; using namespace eld::plugin; @@ -679,12 +678,7 @@ eld::Expected plugin::Section::overrideLinkerScriptRule(LinkerWrapper &LW, plugin::LinkerScriptRule R, const std::string &Annotation) { - if (!LW.isLinkStateInitializing()) { - return std::make_unique( - Diag::error_invalid_link_state, - std::vector{std::string(LW.getCurrentLinkStateAsStr()), - __FUNCTION__, ""}); - } + CHECK_LINK_STATE(LW, "Initializing", "ActBeforeRuleMatching"); if (!m_Section) return {}; ELFSection *S = llvm::dyn_cast(m_Section); diff --git a/lib/Object/ObjectLinker.cpp b/lib/Object/ObjectLinker.cpp index dc1077ed5..a822d5632 100644 --- a/lib/Object/ObjectLinker.cpp +++ b/lib/Object/ObjectLinker.cpp @@ -1141,6 +1141,7 @@ bool ObjectLinker::mergeSections() { eld::RegisterTimer T("Universal Plugin", "Merge Sections", ThisConfig.options().printTimingStats()); auto &PM = ThisModule->getPluginManager(); + ThisModule->setLinkState(Module::LinkState::ActBeforeSectionMerging); if (!PM.callActBeforeSectionMergingHook()) return false; } @@ -1150,8 +1151,11 @@ bool ObjectLinker::mergeSections() { eld::RegisterTimer T("Plugin: Output Section Iterator Before Layout", "Merge Sections", ThisConfig.options().printTimingStats()); + // For backward compatibility + ThisModule->setLinkState(Module::LinkState::BeforeLayout); if (!runOutputSectionIteratorPlugin()) return false; + ThisModule->setLinkState(Module::LinkState::ActBeforeSectionMerging); } // Merge all the input sections. diff --git a/lib/Writers/ELFObjectWriter.cpp b/lib/Writers/ELFObjectWriter.cpp index 6c33f4de6..34cac6d17 100644 --- a/lib/Writers/ELFObjectWriter.cpp +++ b/lib/Writers/ELFObjectWriter.cpp @@ -195,6 +195,7 @@ ELFObjectWriter::writeObject(llvm::FileOutputBuffer &CurOutput) { { PluginManager &PM = ThisModule.getPluginManager(); + ThisModule.setLinkState(Module::LinkState::ActBeforePerformingLayout); if (!PM.callActBeforeWritingOutputHook()) { // Return generic error-code. Actual error is already reported! return make_error_code(std::errc::not_supported); diff --git a/test/Common/Plugin/InvalidStateOverrideLSRule/InvalidStateOverrideLSRule.test b/test/Common/Plugin/InvalidStateOverrideLSRule/InvalidStateOverrideLSRule.test index 51b5ba845..b650735f6 100644 --- a/test/Common/Plugin/InvalidStateOverrideLSRule/InvalidStateOverrideLSRule.test +++ b/test/Common/Plugin/InvalidStateOverrideLSRule/InvalidStateOverrideLSRule.test @@ -8,6 +8,6 @@ RUN: %clang %clangopts -c %p/Inputs/1.c -o %t1.1.o -ffunction-sections RUN: %not %link %linkopts %t1.1.o -T %p/Inputs/script.t -o %t2.out --plugin-config %p/Inputs/plugin.config 2>&1 | %filecheck %s -#CHECK: Error: Link state 'BeforeLayout' is invalid for the API '{{.*}}overrideLinkerScriptRule{{.*}}'. Valid link states: [] +#CHECK: Error: Link state 'ActBeforeSectionMerging' is invalid for the API '{{.*}}overrideLinkerScriptRule{{.*}}'. Valid link states: [Initializing, ActBeforeRuleMatching] #CHECK: Fatal: Linking had errors. diff --git a/test/Hexagon/Plugin/AllOutSectAddresses/AllOutSectAddresses.test b/test/Hexagon/Plugin/AllOutSectAddresses/AllOutSectAddresses.test index 7c812fd68..00282b72d 100644 --- a/test/Hexagon/Plugin/AllOutSectAddresses/AllOutSectAddresses.test +++ b/test/Hexagon/Plugin/AllOutSectAddresses/AllOutSectAddresses.test @@ -19,4 +19,4 @@ RUN: %not %link %linkopts -o %t1.1.out %t1.1.o -L%libsdir/test -T %p/Inputs/scri #CHECK: Virtual address: {{.*}} #CHECK: Physical address: 0 #INVALID_STATE: InvalidStateFindOutSectAddresses:Error: Link state 'BeforeLayout' is invalid for the API '{{.*}}getVirtualAddress{{.*}}'. Valid link states: [CreatingSegments, AfterLayout] -#INVALID_STATE: InvalidStateFindOutSectAddresses:Error: Link state 'BeforeLayout' is invalid for the API '{{.*}}eld::plugin::LinkerWrapper::getAllOutputSections({{.*}}) const'. Valid link states: [CreatingSections, CreatingSegments, AfterLayout] \ No newline at end of file +#INVALID_STATE: InvalidStateFindOutSectAddresses:Error: Link state 'BeforeLayout' is invalid for the API '{{.*}}eld::plugin::LinkerWrapper::getAllOutputSections({{.*}}) const'. Valid link states: [ActBeforeSectionMerging, CreatingSections, ActBeforePerformingLayout, CreatingSegments, ActBeforeWritingOutput, AfterLayout] \ No newline at end of file