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/Diagnostics/DiagVerbose.inc
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,7 @@ DIAG(verbose_loaded_plugin_config, DiagnosticEngine::Verbose,
"Initialized plugin config for %0")
DIAG(verbose_infer_target, DiagnosticEngine::Verbose,
"Inferred target : %0")
DIAG(verbose_performing_layout_iteration, DiagnosticEngine::Verbose,
"Performing layout iteration %0")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we --trace=layout and add the layout diagnostics in tracing layout iterations ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this sounds good to me. I think a lot of things can be covered under --trace=layout. Can we handle this as a separate task altogether that analysis what all diagnostics should fall under --trace=layout?

DIAG(verbose_eval_pending_assignments, DiagnosticEngine::Verbose,
"Evaluating pending assignments")
3 changes: 3 additions & 0 deletions include/eld/Diagnostics/DiagnosticPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class DiagnosticPrinter {
TraceMergeStrings = 0x8000,
TraceLinkerScript = 0x10000,
TraceSymDef = 0x100000,
TracePendingAssignments = 0x200000
};

enum Verbose : uint16_t { None = 0x0, Default = 0x1 };
Expand All @@ -68,6 +69,8 @@ class DiagnosticPrinter {

bool traceAssignments() { return Trace & TraceAssignments; }

bool tracePendingAssignments() { return Trace & TracePendingAssignments; }

bool traceFiles() { return Trace & TraceFiles; }

bool traceSymbols() { return Trace & TraceSymbols; }
Expand Down
3 changes: 2 additions & 1 deletion include/eld/Driver/GnuLinkerOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,8 @@ defm trace
"\t\t\t --trace=trampolines : trace trampolines\n"
"\t\t\t --trace=wrap-symbols : trace symbol wrap options\n"
"\t\t\t --trace=symdef : trace symbol resolution from symdef files\n"
"\t\t\t --trace=dynamic-linking : trace dynamic linking">,
"\t\t\t --trace=dynamic-linking : trace dynamic linking\n"
"\t\t\t --trace=pending-assignments : trace pending symbol assignments evaluation">,
MetaVarName<"<trace-type>">,
Group<grp_diagopts>;
defm trace_symbol : smDashTwoWithOpt<"y", "trace-symbol", "trace_symbol",
Expand Down
14 changes: 11 additions & 3 deletions include/eld/Script/Assignment.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,20 +73,26 @@ class Assignment : public ScriptCommand {

bool isDot() const;

// Does the assignment have any dot usage ?
// Does the assignment has any dot usage ?
bool hasDot() const;

static bool classof(const ScriptCommand *LinkerScriptCommand) {
return LinkerScriptCommand->getKind() == ScriptCommand::ASSIGNMENT;
}

/// Sets the expression context (location in the linker script)
/// and the assignment level.
eld::Expected<void> activate(Module &CurModule) override;

/// assign - evaluate the rhs and assign the result to lhs.
bool assign(Module &CurModule, const ELFSection *Section);
bool assign(Module &CurModule, const ELFSection *Section,
bool EvaluatePendingOnly);

LDSymbol *symbol() const { return ThisSymbol; }

/// Returns all the symbols that might be referenced by the rhs of this
/// assignment. No expression evaluation is performed. Hence, this may return
/// more symbols than what is actually referenced at runtime.
void getSymbols(std::vector<ResolveInfo *> &Symbols) const;

/// Query functions on Assignment Kinds.
Expand All @@ -113,7 +119,9 @@ class Assignment : public ScriptCommand {

bool isAssert() const { return ThisType == ASSERT; }

// Retrieve the symbol names referred by the assignment expression
/// Returns the symbol names that might be referenced by the rhs of this
/// assignment. No expression evaluation is performed. Hence, this may return
/// names of more symbols than what is actually referenced at runtime.
std::unordered_set<std::string> getSymbolNames() const;

// Add all undefined references from assignmnent expressions
Expand Down
137 changes: 90 additions & 47 deletions include/eld/Script/Expression.h

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions include/eld/SymbolResolver/NamePool.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@ class NamePool {

bool getSymbolTracingRequested() const;

// --------------------- Linker Script Symbols ----------------
// Record a symbol that originates from a linker script / defsym.
void addScriptSymbol(ResolveInfo *RI) { ScriptSymbols.push_back(RI); }

// Return all symbols that originates from linker script / defsym.
const std::vector<ResolveInfo *> &getScriptSymbols() const {
return ScriptSymbols;
}

/// --------------------- Symbol References and checks ----------------
bool canSymbolsBeResolved(const ResolveInfo *, const ResolveInfo *) const;
bool checkTLSTypes(const ResolveInfo *, const ResolveInfo *) const;
Expand Down Expand Up @@ -143,6 +152,9 @@ class NamePool {
SymbolResolutionInfo SymbolResInfo;
std::map<const ResolveInfo *, LDSymbol *> SharedLibsSymbols;
PluginManager &PM;

// Symbols defined via linker scripts / defsym.
std::vector<ResolveInfo *> ScriptSymbols;
};

} // namespace eld
Expand Down
36 changes: 36 additions & 0 deletions include/eld/Target/GNULDBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,28 @@ class GNULDBackend {

const ResolveInfo *findAbsolutePLT(ResolveInfo *I) const;

/// Returns true if the symbol is partially evaluated. That
/// is, the symbol assignment expression was partially evaluated.
bool isPartiallyEvaluated(const ResolveInfo *RI) const {
return PartiallyEvaluatedSymbols.count(RI);
}

void addPartiallyEvaluatedSymbol(const ResolveInfo *RI) {
PartiallyEvaluatedSymbols.insert(RI);
}

void removePartiallyEvaluatedSymbol(const ResolveInfo *RI) {
PartiallyEvaluatedSymbols.erase(RI);
}

void resetPartiallyEvalAssignmentsAndSymbols() {
PartiallyEvaluatedAssignments.clear();
PartiallyEvaluatedSymbols.clear();
}

/// Recursively evaluates the partially evaluated assignments.
void evaluatePendingAssignments();

protected:
virtual int numReservedSegments() const { return m_NumReservedSegments; }

Expand Down Expand Up @@ -1002,6 +1024,14 @@ class GNULDBackend {
// Setup TLS alignment and check for any layout issues
bool setupTLS();

/// Evaluates the assignment and tracks the partially evaluated assignments.
/// Partially evaluated assignments can be requested to be (recursively)
/// reevaluated using evaluatePendingAssignments.
void evaluateAssignmentAndTrackPartiallyEvalAssignments(Assignment &A,
const ELFSection *S);

void resetScriptSymbols();

protected:
Module &m_Module;

Expand Down Expand Up @@ -1132,6 +1162,12 @@ class GNULDBackend {
bool m_NeedEhdr = false;

bool m_NeedPhdr = false;

std::unordered_set<const ResolveInfo *> PartiallyEvaluatedSymbols;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be PartiallyEvaluatedAssignments instead ? because everything is an assignment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need both PartiallyEvaluatedAssignments and PartiallyEvaluatedSymbols. With just storing assignments, we cannot determine if a symbol was partially evaluated or not, as we do not maintain a mapping of symbol nodes to assignments.


/// Stores the assignments which needs to be reevaluated later.
std::vector<std::pair<Assignment *, const ELFSection *>>
PartiallyEvaluatedAssignments;
};

} // namespace eld
Expand Down
2 changes: 2 additions & 0 deletions lib/Config/GeneralOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ eld::Expected<void> GeneralOptions::setTrace(const char *PTraceType) {
DiagEngine->getPrinter()->TraceDynamicLinking)
.Case("linker-script", DiagEngine->getPrinter()->TraceLinkerScript)
.Case("symdef", DiagEngine->getPrinter()->TraceSymDef)
.Case("pending-assignments",
DiagEngine->getPrinter()->TracePendingAssignments)
.Default(std::nullopt);
}
// Warn if trace category is unknown.
Expand Down
12 changes: 6 additions & 6 deletions lib/Object/ObjectLinker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,10 @@ bool ObjectLinker::createOutputSection(ObjectBuilder &Builder,

// force input alignment from ldscript if any
if (Output->prolog().hasSubAlign()) {
Output->prolog().subAlign().eval();
// FIXME: eval() is an implementation function, it should not be
// used outside the component. Instead, evaluateAndReturnError and
// evaluateAndRaiseError should be used.
Output->prolog().subAlign().eval(/*EvaluatePendingOnly=*/false);
Output->prolog().subAlign().commit();
InAlign = Output->prolog().subAlign().result();
HasSubAlign = true;
Expand Down Expand Up @@ -1631,11 +1634,8 @@ bool ObjectLinker::addScriptSymbols() {
bool Ret = true;
// go through the entire symbol assignments
for (auto &AssignCmd : Script.assignments()) {
InputFile *ScriptInput = ThisModule->getInternalInput(eld::Module::Script);
// FIXME: Ideally, assignCmd should always have a context. We should perhaps
// add an internal error if the context is missing.
if (AssignCmd->hasInputFileInContext())
ScriptInput = AssignCmd->getInputFileInContext();
InputFile *ScriptInput = AssignCmd->getInputFileInContext();
ASSERT(ScriptInput, "Must always be non-null!");
llvm::StringRef SymName = AssignCmd->name();
ResolveInfo::Type Type = ResolveInfo::NoType;
ResolveInfo::Visibility Vis = ResolveInfo::Default;
Expand Down
23 changes: 19 additions & 4 deletions lib/Script/Assignment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "eld/Readers/Section.h"
#include "eld/Script/Expression.h"
#include "eld/SymbolResolver/LDSymbol.h"
#include "eld/Target/GNULDBackend.h"
#include "llvm/Support/Casting.h"
#include <cassert>

Expand Down Expand Up @@ -197,8 +198,8 @@ void Assignment::getSymbols(std::vector<ResolveInfo *> &Symbols) const {
ExpressionToEvaluate->getSymbols(Symbols);
}

bool Assignment::assign(Module &CurModule, const ELFSection *Section) {

bool Assignment::assign(Module &CurModule, const ELFSection *Section,
bool EvaluatePendingOnly) {
if (Section && !Section->isAlloc() && isDot()) {
CurModule.getConfig().raise(Diag::error_dot_lhs_in_non_alloc)
<< std::string(Section->name())
Expand All @@ -207,7 +208,11 @@ bool Assignment::assign(Module &CurModule, const ELFSection *Section) {
}

// evaluate, commit, then get the result of the expression
auto Result = ExpressionToEvaluate->evaluateAndRaiseError();
std::optional<uint64_t> Result;
if (EvaluatePendingOnly)
Result = ExpressionToEvaluate->evaluatePendingAndRaiseError();
else
Result = ExpressionToEvaluate->evaluateAndRaiseError();
if (!Result)
return false;
ExpressionValue = *Result;
Expand All @@ -216,13 +221,23 @@ bool Assignment::assign(Module &CurModule, const ELFSection *Section) {
return false;

LDSymbol *Sym = CurModule.getNamePool().findSymbol(Name);
// ASSERT(Sym, "Sym must exist!");
// FIXME: Why is it okay for the Sym to be nullptr?
if (Sym != nullptr) {
ThisSymbol = Sym;
ThisSymbol->setValue(ExpressionValue);
ThisSymbol->setScriptValueDefined();
GNULDBackend &Backend = CurModule.getBackend();
const ResolveInfo *RI = ThisSymbol->resolveInfo();
if (ExpressionToEvaluate->hasPendingEvaluation())
Backend.addPartiallyEvaluatedSymbol(RI);
else
Backend.removePartiallyEvaluatedSymbol(RI);
}

if (CurModule.getPrinter()->traceAssignments())
auto DP = CurModule.getPrinter();
if (DP->traceAssignments() ||
(EvaluatePendingOnly && DP->tracePendingAssignments()))
trace(llvm::outs());
return true;
}
Expand Down
Loading
Loading