Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/eld/Core/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,14 @@ class Module {
enum LinkState : uint8_t {
Unknown,
Initializing,
ActBeforeRuleMatching,
BeforeLayout,
ActBeforeSectionMerging,
CreatingSections,
ActBeforePerformingLayout,
CreatingSegments,
AfterLayout,
ActBeforeWritingOutput
};

public:
Expand Down
10 changes: 9 additions & 1 deletion include/eld/PluginAPI/LinkerWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
1 change: 1 addition & 0 deletions lib/Core/Linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ bool Linker::resolve() {
}

PluginManager &PM = ThisModule->getPluginManager();
ThisModule->setLinkState(Module::LinkState::ActBeforeRuleMatching);
PM.callActBeforeRuleMatchingHook();

// Assign output sections.
Expand Down
29 changes: 16 additions & 13 deletions lib/Core/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -501,28 +501,31 @@ 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,
uint64_t Val,
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];
Expand Down
6 changes: 3 additions & 3 deletions lib/LayoutMap/TextLayoutPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ void TextLayoutPrinter::printFragInfo(Fragment *Frag, LayoutFragmentInfo *Info,

std::optional<uint64_t> AddressOrOffset;
bool HasFragInfo =
(M.isLinkStateCreatingSegments() || M.isLinkStateAfterLayout());
(M.getState() >= Module::LinkState::ActBeforePerformingLayout);
if (llvm::isa<MergeStringFragment>(Frag) && !M.isLinkStateBeforeLayout()) {
auto *Strings = llvm::cast<MergeStringFragment>(Frag);
for (MergeableString *S : Strings->getStrings()) {
Expand Down Expand Up @@ -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.
Expand Down
19 changes: 16 additions & 3 deletions lib/LinkerWrapper/CheckLinkState.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,33 @@ static inline bool
isValidLinkState(const eld::plugin::LinkerWrapper &LW,
std::initializer_list<std::string_view> 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;
}
Expand Down
57 changes: 44 additions & 13 deletions lib/LinkerWrapper/LinkerWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@ LinkerWrapper::getOutputSection(Section &S) const {

eld::Expected<std::unique_ptr<const uint8_t[]>>
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<DiagnosticEntry>(
Diag::error_nobits_unsupported, std::vector<std::string>{O.getName()});
Expand Down Expand Up @@ -218,7 +219,8 @@ eld::Expected<void> LinkerWrapper::reassignVirtualAddresses() {
}

eld::Expected<std::vector<Segment>> LinkerWrapper::getSegmentTable() const {
CHECK_LINK_STATE(*this, "CreatingSegments", "AfterLayout");
CHECK_LINK_STATE(*this, "CreatingSegments", "AfterLayout",
"ActBeforeWritingOutput");
std::vector<Segment> Segments;
for (auto *S : m_Module.getBackend().elfSegmentTable())
Segments.push_back(Segment(S));
Expand Down Expand Up @@ -263,7 +265,9 @@ eld::Expected<void> LinkerWrapper::doRelocation() {
}

eld::Expected<void> 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)
Expand All @@ -290,7 +294,8 @@ eld::Expected<void> LinkerWrapper::addChunkToOutput(Chunk C) {
}

eld::Expected<void> 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);
Expand All @@ -304,7 +309,9 @@ eld::Expected<void> LinkerWrapper::resetOffset(OutputSection O) {

eld::Expected<std::pair<OutputSection, LinkerScriptRule>>
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();

Expand Down Expand Up @@ -339,9 +346,10 @@ LinkerWrapper::getOutputSectionAndRule(Section S) {

eld::Expected<void> 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 {};
}

Expand Down Expand Up @@ -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!");
Expand All @@ -979,7 +991,9 @@ bool LinkerWrapper::isVerbose() const {

eld::Expected<std::vector<plugin::OutputSection>>
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<plugin::OutputSection> outputSects;
Expand All @@ -991,7 +1005,8 @@ LinkerWrapper::getAllOutputSections() const {

eld::Expected<std::vector<Segment>>
LinkerWrapper::getSegmentsForOutputSection(const OutputSection &O) const {
CHECK_LINK_STATE(*this, "CreatingSections", "CreatingSegments", "AfterLayout");
CHECK_LINK_STATE(*this, "CreatingSections", "ActBeforePerformingLayout",
"CreatingSegments", "AfterLayout", "ActBeforeWritingOutput");
std::vector<Segment> Segments;
for (auto *S :
m_Module.getBackend().getSegmentsForSection(O.getOutputSection()))
Expand Down Expand Up @@ -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;
}
8 changes: 1 addition & 7 deletions lib/LinkerWrapper/PluginADT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
#include "llvm/Support/Timer.h"
#include <memory>
#include <optional>

using namespace eld;
using namespace eld::plugin;

Expand Down Expand Up @@ -679,12 +678,7 @@ eld::Expected<void>
plugin::Section::overrideLinkerScriptRule(LinkerWrapper &LW,
plugin::LinkerScriptRule R,
const std::string &Annotation) {
if (!LW.isLinkStateInitializing()) {
return std::make_unique<plugin::DiagnosticEntry>(
Diag::error_invalid_link_state,
std::vector<std::string>{std::string(LW.getCurrentLinkStateAsStr()),
__FUNCTION__, ""});
}
CHECK_LINK_STATE(LW, "Initializing", "ActBeforeRuleMatching");
if (!m_Section)
return {};
ELFSection *S = llvm::dyn_cast<ELFSection>(m_Section);
Expand Down
4 changes: 4 additions & 0 deletions lib/Object/ObjectLinker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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.
Expand Down
1 change: 1 addition & 0 deletions lib/Writers/ELFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Original file line number Diff line number Diff line change
Expand Up @@ -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]
#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]
Loading