From c02bbaf81b69420eaae98908df7c9b99ce4f0f98 Mon Sep 17 00:00:00 2001 From: Alexey Karyakin Date: Thu, 24 Jul 2025 12:07:29 -0700 Subject: [PATCH] Suppress relaxations for incomplete script symbols A symbol may be defined in a script referencing a section address. Such symbols get their values after section layout is complete. At the relaxation time such symbols do not have the correct value. The current logic uses a value of zero as an indicator that the symbol value is unknown and prevents some relaxations with them. However, this logic produces both false positives and false negatives because 1) incomplete symbol values may be used in expressions that produce a nonzero value and 2) some symbols having a zero value are valid and can be relaxed. In this change, symbols that reference unknows section addresses are detected and the corresponding relaxations are not performed. --- include/eld/Readers/Relocation.h | 1 + include/eld/Script/Expression.h | 218 ++++++++++++++++++++------ include/eld/SymbolResolver/LDSymbol.h | 8 +- include/eld/Target/Relocator.h | 1 + lib/Readers/Relocation.cpp | 16 +- lib/Script/Assignment.cpp | 6 +- lib/Script/Expression.cpp | 163 ++++++++++--------- lib/SymbolResolver/LDSymbol.cpp | 2 +- lib/Target/RISCV/RISCVLDBackend.cpp | 74 +++++---- lib/Target/RISCV/RISCVLDBackend.h | 1 + lib/Target/Relocator.cpp | 13 +- 11 files changed, 338 insertions(+), 165 deletions(-) diff --git a/include/eld/Readers/Relocation.h b/include/eld/Readers/Relocation.h index a722b3e56..2963f131b 100644 --- a/include/eld/Readers/Relocation.h +++ b/include/eld/Readers/Relocation.h @@ -62,6 +62,7 @@ class Relocation { Type type() const { return m_Type; } /// symValue - S value - the symbol address + Address symValue(Module &M, bool &Uncertain) const; Address symValue(Module &M) const; /// symOffset - Offset of the symbol diff --git a/include/eld/Script/Expression.h b/include/eld/Script/Expression.h index ba014ae4c..49755a322 100644 --- a/include/eld/Script/Expression.h +++ b/include/eld/Script/Expression.h @@ -23,6 +23,128 @@ class Module; class GNULDBackend; class ScriptFile; +class UncertainValue { + uint64_t Value; + bool Uncertain; + +public: + uint64_t value() const { return Value; } + uint64_t &value() { return Value; } + bool isUncertain() const { return Uncertain; } + + UncertainValue(uint64_t Value, bool Uncertain = false) + : Value(Value), Uncertain(Uncertain) {} + + UncertainValue(uint64_t Value, const UncertainValue &Base) + : Value(Value), Uncertain(Base.isUncertain()) {} + + UncertainValue(uint64_t Value, const UncertainValue &BaseL, + const UncertainValue &BaseR) + : Value(Value), Uncertain(BaseL.isUncertain() || BaseR.isUncertain()) {} + + UncertainValue(uint64_t Value, const UncertainValue &Base, + const UncertainValue &BaseL, const UncertainValue &BaseR) + : Value(Value), Uncertain(Base.isUncertain() || BaseL.isUncertain() || + BaseR.isUncertain()) {} +}; + +inline UncertainValue operator+(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() + R.value(), L, R); +} + +inline UncertainValue operator-(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() - R.value(), L, R); +} + +inline UncertainValue operator*(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() * R.value(), L, R); +} + +inline UncertainValue operator/(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() / R.value(), L, R); +} + +inline UncertainValue operator%(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() % R.value(), L, R); +} + +inline UncertainValue operator>>(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() >> R.value(), L, R); +} + +inline UncertainValue operator<<(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() << R.value(), L, R); +} + +inline UncertainValue operator|(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() | R.value(), L, R); +} + +inline UncertainValue operator&(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() & R.value(), L, R); +} + +inline UncertainValue operator>(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() > R.value(), L, R); +} + +inline UncertainValue operator>=(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() >= R.value(), L, R); +} + +inline UncertainValue operator<(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() < R.value(), L, R); +} + +inline UncertainValue operator<=(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() <= R.value(), L, R); +} + +inline UncertainValue operator==(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() == R.value(), L, R); +} + +inline UncertainValue operator!=(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() != R.value(), L, R); +} + +inline UncertainValue operator~(const UncertainValue &E) { + return UncertainValue(~E.value(), E); +} + +inline UncertainValue operator-(const UncertainValue &E) { + return UncertainValue(-E.value(), E); +} + +inline UncertainValue operator!(const UncertainValue &E) { + return UncertainValue(!E.value(), E); +} + +inline UncertainValue operator&&(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() && R.value(), L, R); +} + +inline UncertainValue operator||(const UncertainValue &L, + const UncertainValue &R) { + return UncertainValue(L.value() || R.value(), L, R); +} + //===----------------------------------------------------------------------===// /** \class Expression * \brief This class defines the interfaces to an expression. @@ -192,6 +314,10 @@ class Expression { /// This method is intended to be called by Expression users. eld::Expected evaluateAndReturnError(); + /// evaluateUncertainAndRaiseError + /// \brief Same as evaluateAndReturnError, but return an UncertainValue. + std::optional evaluateUncertainAndRaiseError(); + /// evaluateAndRaiseError /// \brief Evaluate the expression and return the value when /// evaluation is successful. Raise an error if evaluation fails and @@ -206,7 +332,7 @@ class Expression { /// evaluation is successful or an error when failed. Commit is /// not called. This method is intended to be recursively called by /// parent expression nodes. - eld::Expected eval(); + eld::Expected eval(); private: /// eval @@ -214,7 +340,7 @@ class Expression { /// should be to verify and evaluate the expression. eval() should /// return the value if evaluation is successful or raise an error /// and return an empty object otherwise. - virtual eld::Expected evalImpl() = 0; + virtual eld::Expected evalImpl() = 0; static std::unique_ptr addContextToDiagEntry(std::unique_ptr, @@ -312,7 +438,7 @@ class Symbol : public Expression { private: bool hasDot() const override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; /// Returns a set of all the symbol names contained in the expression. void getSymbolNames(std::unordered_set &SymbolTokens) override; @@ -339,7 +465,7 @@ class Integer : public Expression { private: bool hasDot() const override { return false; } void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -366,7 +492,7 @@ class Add : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -394,7 +520,7 @@ class Subtract : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -422,7 +548,7 @@ class Modulo : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -450,7 +576,7 @@ class Multiply : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -478,7 +604,7 @@ class Divide : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -502,7 +628,7 @@ class SizeOf : public Expression { private: bool hasDot() const override { return false; } void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -525,7 +651,7 @@ class SizeOfHeaders : public Expression { private: bool hasDot() const override { return false; } void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -550,7 +676,7 @@ class OffsetOf : public Expression { private: bool hasDot() const override { return false; } void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -575,7 +701,7 @@ class Addr : public Expression { private: bool hasDot() const override { return false; } void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -598,7 +724,7 @@ class LoadAddr : public Expression { private: bool hasDot() const override { return false; } void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -627,7 +753,7 @@ class AlignExpr : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { @@ -661,7 +787,7 @@ class AlignOf : public Expression { private: bool hasDot() const override { return false; } void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -687,7 +813,7 @@ class Absolute : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -719,7 +845,7 @@ class Ternary : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -749,7 +875,7 @@ class ConditionGT : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -777,7 +903,7 @@ class ConditionLT : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -805,7 +931,7 @@ class ConditionEQ : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -835,7 +961,7 @@ class ConditionGTE : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -865,7 +991,7 @@ class ConditionLTE : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -893,7 +1019,7 @@ class ConditionNEQ : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -920,7 +1046,7 @@ class Complement : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -948,7 +1074,7 @@ class UnaryPlus : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -976,7 +1102,7 @@ class UnaryMinus : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -1004,7 +1130,7 @@ class UnaryNot : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -1031,7 +1157,7 @@ class Constant : public Expression { private: bool hasDot() const override { return false; } void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -1058,7 +1184,7 @@ class SegmentStart : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -1090,7 +1216,7 @@ class AssertCmd : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -1121,7 +1247,7 @@ class RightShift : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -1151,7 +1277,7 @@ class LeftShift : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -1179,7 +1305,7 @@ class BitwiseOr : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -1207,7 +1333,7 @@ class BitwiseAnd : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -1232,7 +1358,7 @@ class Defined : public Expression { private: bool hasDot() const override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -1260,7 +1386,7 @@ class DataSegmentAlign : public Expression { bool hasDot() const override { return false; } void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &MaxPageSize; } @@ -1294,7 +1420,7 @@ class DataSegmentRelRoEnd : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -1324,7 +1450,7 @@ class DataSegmentEnd : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -1354,7 +1480,7 @@ class Max : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -1382,7 +1508,7 @@ class Min : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -1408,7 +1534,7 @@ class Fill : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -1436,7 +1562,7 @@ class Log2Ceil : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -1467,7 +1593,7 @@ class LogicalOp : public Expression { bool hasDot() const override; void commit() override; void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return &LeftExpression; } @@ -1495,7 +1621,7 @@ class QueryMemory : public Expression { private: bool hasDot() const override { return false; } void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } @@ -1519,7 +1645,7 @@ class NullExpression : public Expression { private: bool hasDot() const override { return false; } void dump(llvm::raw_ostream &Outs, bool WithValues = true) const override; - eld::Expected evalImpl() override; + eld::Expected evalImpl() override; void getSymbols(std::vector &Symbols) override; void getSymbolNames(std::unordered_set &SymbolTokens) override; Expression *getLeftExpression() const override { return nullptr; } diff --git a/include/eld/SymbolResolver/LDSymbol.h b/include/eld/SymbolResolver/LDSymbol.h index 3244463a1..04015be17 100644 --- a/include/eld/SymbolResolver/LDSymbol.h +++ b/include/eld/SymbolResolver/LDSymbol.h @@ -112,10 +112,13 @@ class LDSymbol { bool scriptValueDefined() const { return ThisSymbolHasScriptValue; } - void setScriptValueDefined(bool Value = true) { - ThisSymbolHasScriptValue = Value; + void setScriptValueDefined(bool Uncertain) { + ThisSymbolHasScriptValue = true; + ThisSymbolHasUncertainValue = Uncertain; } + bool isUncertain() const { return ThisSymbolHasUncertainValue; } + const FragmentRef *fragRef() const { return ThisFragRef; } FragmentRef *fragRef() { return ThisFragRef; } @@ -166,6 +169,7 @@ class LDSymbol { uint32_t ThisSymIdx; bool ThisSymbolsIsScriptDefined; bool ThisSymbolHasScriptValue; + bool ThisSymbolHasUncertainValue; // used for ignore garbage collected Common symbols bool ThisSymbolGarbageCollected; }; diff --git a/include/eld/Target/Relocator.h b/include/eld/Target/Relocator.h index 00df613fc..0aff2d4e0 100644 --- a/include/eld/Target/Relocator.h +++ b/include/eld/Target/Relocator.h @@ -143,6 +143,7 @@ class Relocator { bool doDeMangle() const; // Get the address for a relocation + Relocation::Address getSymValue(Relocation *R, bool &Uncertain); Relocation::Address getSymValue(Relocation *R); private: diff --git a/lib/Readers/Relocation.cpp b/lib/Readers/Relocation.cpp index 499966835..1e8a70bf5 100644 --- a/lib/Readers/Relocation.cpp +++ b/lib/Readers/Relocation.cpp @@ -76,7 +76,7 @@ Relocation::Address Relocation::place(Module &M) const { return sect_addr + m_TargetAddress->getOutputOffset(M); } -Relocation::Address Relocation::symValue(Module &M) const { +Relocation::Address Relocation::symValue(Module &M, bool &Uncertain) const { const ELFSection *section = nullptr; const FragmentRef *fragRef = nullptr; ResolveInfo *info = m_pSymInfo; @@ -99,16 +99,26 @@ Relocation::Address Relocation::symValue(Module &M) const { bool isAllocSection = section ? section->isAlloc() : false; // If allocatable section, value => (address + offset) - if (isAllocSection) + if (isAllocSection) { + Uncertain = false; return section->addr() + fragRef->getOutputOffset(M); + } // If non allocatable section, value => (offset) - if (section && !isAllocSection) + if (section) { + Uncertain = false; return fragRef->getOutputOffset(M); + } + Uncertain = info->outSymbol()->isUncertain(); return info->outSymbol()->value(); } +Relocation::Address Relocation::symValue(Module &M) const { + bool Ignored; + return symValue(M, Ignored); +} + Relocation::Address Relocation::symOffset(Module &M) const { const ELFSection *section = nullptr; const FragmentRef *fragRef = nullptr; diff --git a/lib/Script/Assignment.cpp b/lib/Script/Assignment.cpp index e1991c142..5f9e59b78 100644 --- a/lib/Script/Assignment.cpp +++ b/lib/Script/Assignment.cpp @@ -211,10 +211,10 @@ bool Assignment::assign(Module &CurModule, const ELFSection *Section) { } // evaluate, commit, then get the result of the expression - auto Result = ExpressionToEvaluate->evaluateAndRaiseError(); + auto Result = ExpressionToEvaluate->evaluateUncertainAndRaiseError(); if (!Result) return false; - ExpressionValue = *Result; + ExpressionValue = Result->value(); if (!checkLinkerScript(CurModule)) return false; @@ -223,7 +223,7 @@ bool Assignment::assign(Module &CurModule, const ELFSection *Section) { if (Sym != nullptr) { ThisSymbol = Sym; ThisSymbol->setValue(ExpressionValue); - ThisSymbol->setScriptValueDefined(); + ThisSymbol->setScriptValueDefined(Result->isUncertain()); } if (CurModule.getPrinter()->traceAssignments()) diff --git a/lib/Script/Expression.cpp b/lib/Script/Expression.cpp index 0759322ca..bdb1f3a7e 100644 --- a/lib/Script/Expression.cpp +++ b/lib/Script/Expression.cpp @@ -68,10 +68,10 @@ eld::Expected Expression::evaluateAndReturnError() { if (!Result) return addContextToDiagEntry(std::move(Result.error()), MContext); commit(); - return Result; + return Result->value(); } -std::optional Expression::evaluateAndRaiseError() { +std::optional Expression::evaluateUncertainAndRaiseError() { ASSERT(!MContext.empty(), "Context not set for expression"); auto Result = eval(); if (!Result) { @@ -86,10 +86,17 @@ std::optional Expression::evaluateAndRaiseError() { return Result.value(); } -eld::Expected Expression::eval() { +std::optional Expression::evaluateAndRaiseError() { + auto Result = evaluateUncertainAndRaiseError(); + if (!Result) + return {}; + return Result->value(); +} + +eld::Expected Expression::eval() { auto V = evalImpl(); if (V) - EvaluatedValue = V.value(); + EvaluatedValue = V->value(); return V; } @@ -122,7 +129,7 @@ bool Symbol::hasDot() const { return ThisSymbol == ThisModule.getDotSymbol(); } -eld::Expected Symbol::evalImpl() { +eld::Expected Symbol::evalImpl() { if (!ThisSymbol) ThisSymbol = ThisModule.getNamePool().findSymbol(Name); @@ -174,7 +181,7 @@ void Integer::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected Integer::evalImpl() { return ExpressionValue; } +eld::Expected Integer::evalImpl() { return ExpressionValue; } void Integer::getSymbols(std::vector &Symbols) {} void Integer::getSymbolNames(std::unordered_set &SymbolTokens) {} @@ -198,7 +205,7 @@ void Add::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected Add::evalImpl() { +eld::Expected Add::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -251,7 +258,7 @@ void Subtract::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected Subtract::evalImpl() { +eld::Expected Subtract::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -291,7 +298,7 @@ void Modulo::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected Modulo::evalImpl() { +eld::Expected Modulo::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -299,7 +306,7 @@ eld::Expected Modulo::evalImpl() { auto Right = RightExpression.eval(); if (!Right) return Right; - if (Right.value() == 0) { + if (Right->value() == 0) { std::string ErrorString; llvm::raw_string_ostream ErrorStringStream(ErrorString); dump(ErrorStringStream); @@ -342,7 +349,7 @@ void Multiply::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected Multiply::evalImpl() { +eld::Expected Multiply::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -385,7 +392,7 @@ void Divide::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected Divide::evalImpl() { +eld::Expected Divide::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -393,7 +400,7 @@ eld::Expected Divide::evalImpl() { auto Right = RightExpression.eval(); if (!Right) return Right; - if (Right.value() == 0) { + if (Right->value() == 0) { std::string ErrorString; llvm::raw_string_ostream ErrorStringStream(ErrorString); dump(ErrorStringStream); @@ -430,7 +437,7 @@ void SizeOf::dump(llvm::raw_ostream &Outs, bool WithValues) const { } Outs << ")"; } -eld::Expected SizeOf::evalImpl() { +eld::Expected SizeOf::evalImpl() { if (Name.size() && Name[0] == ':') { // If the name is a segment and we don't have PHDR's. SIZEOF on segment will @@ -497,7 +504,7 @@ void SizeOfHeaders::dump(llvm::raw_ostream &Outs, bool WithValues) const { } } -eld::Expected SizeOfHeaders::evalImpl() { +eld::Expected SizeOfHeaders::evalImpl() { uint64_t Offset = 0; std::vector Sections; if (!ThisBackend.isEhdrNeeded()) @@ -527,7 +534,7 @@ void Addr::dump(llvm::raw_ostream &Outs, bool WithValues) const { } Outs << "\")"; } -eld::Expected Addr::evalImpl() { +eld::Expected Addr::evalImpl() { // As the section table is populated only during PostLayout, we have to // go the other way around to access the section. This is because size of // empty @@ -542,7 +549,7 @@ eld::Expected Addr::evalImpl() { ThisModule.getConfig().raise(Diag::warn_forward_reference) << MContext << Name; // evaluate sub expression - return ThisSection->addr(); + return UncertainValue(ThisSection->addr(), !ThisSection->hasVMA()); } void Addr::getSymbols(std::vector &Symbols) {} @@ -565,7 +572,7 @@ void LoadAddr::dump(llvm::raw_ostream &Outs, bool WithValues) const { } Outs << ")"; } -eld::Expected LoadAddr::evalImpl() { +eld::Expected LoadAddr::evalImpl() { // As the section table is populated only during PostLayout, we have to // go the other way around to access the section. This is because size of // empty @@ -594,7 +601,7 @@ void OffsetOf::dump(llvm::raw_ostream &Outs, bool WithValues) const { Outs.write_hex(*MResult); } } -eld::Expected OffsetOf::evalImpl() { +eld::Expected OffsetOf::evalImpl() { // As the section table is populated only during PostLayout, we have to // go the other way around to access the section. This is because size of // empty @@ -605,7 +612,7 @@ eld::Expected OffsetOf::evalImpl() { // evaluate sub expression if (ThisSection->hasOffset()) return ThisSection->offset(); - return 0; + return UncertainValue(0, true); } void OffsetOf::getSymbols(std::vector &Symbols) {} @@ -630,11 +637,14 @@ void Ternary::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected Ternary::evalImpl() { +eld::Expected Ternary::evalImpl() { auto Cond = ConditionExpression.eval(); if (!Cond) return Cond; - return Cond.value() ? LeftExpression.eval() : RightExpression.eval(); + auto Left = LeftExpression.eval(); + auto Right = RightExpression.eval(); + return UncertainValue(Cond->value() ? Left->value() : Right->value(), *Cond, + *Left, *Right); } void Ternary::getSymbols(std::vector &Symbols) { ConditionExpression.getSymbols(Symbols); @@ -676,7 +686,7 @@ void AlignExpr::dump(llvm::raw_ostream &Outs, bool WithValues) const { AlignmentExpression.dump(Outs, WithValues); Outs << ")"; } -eld::Expected AlignExpr::evalImpl() { +eld::Expected AlignExpr::evalImpl() { // evaluate sub expressions auto Expr = ExpressionToEvaluate.eval(); if (!Expr) @@ -684,8 +694,8 @@ eld::Expected AlignExpr::evalImpl() { auto Align = AlignmentExpression.eval(); if (!Align) return Align; - uint64_t Value = Expr.value(); - uint64_t AlignValue = Align.value(); + uint64_t Value = Expr->value(); + uint64_t AlignValue = Align->value(); if (!AlignValue) return Value; if (ThisModule.getConfig().showLinkerScriptWarnings() && @@ -693,7 +703,7 @@ eld::Expected AlignExpr::evalImpl() { ThisModule.getConfig().raise( Diag::warn_non_power_of_2_value_to_align_builtin) << getContext() << utility::toHex(AlignValue); - return llvm::alignTo(Value, AlignValue); + return UncertainValue(llvm::alignTo(Value, AlignValue), *Expr, *Align); } void AlignExpr::getSymbols(std::vector &Symbols) { @@ -719,7 +729,7 @@ void AlignOf::getSymbols(std::vector &Symbols) {} void AlignOf::getSymbolNames(std::unordered_set &SymbolTokens) {} -eld::Expected AlignOf::evalImpl() { +eld::Expected AlignOf::evalImpl() { // As the section table is populated only during PostLayout, we have to // go the other way around to access the section. This is because size of // empty @@ -743,7 +753,7 @@ void Absolute::dump(llvm::raw_ostream &Outs, bool WithValues) const { ExpressionToEvaluate.dump(Outs, WithValues); Outs << ")"; } -eld::Expected Absolute::evalImpl() { +eld::Expected Absolute::evalImpl() { return ExpressionToEvaluate.eval(); } void Absolute::getSymbols(std::vector &Symbols) { @@ -773,7 +783,7 @@ void ConditionGT::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected ConditionGT::evalImpl() { +eld::Expected ConditionGT::evalImpl() { auto Left = LeftExpression.eval(); if (!Left) return Left; @@ -814,7 +824,7 @@ void ConditionLT::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected ConditionLT::evalImpl() { +eld::Expected ConditionLT::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -856,7 +866,7 @@ void ConditionEQ::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected ConditionEQ::evalImpl() { +eld::Expected ConditionEQ::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -898,7 +908,7 @@ void ConditionGTE::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected ConditionGTE::evalImpl() { +eld::Expected ConditionGTE::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -940,7 +950,7 @@ void ConditionLTE::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected ConditionLTE::evalImpl() { +eld::Expected ConditionLTE::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -982,7 +992,7 @@ void ConditionNEQ::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected ConditionNEQ::evalImpl() { +eld::Expected ConditionNEQ::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -1018,7 +1028,7 @@ void Complement::dump(llvm::raw_ostream &Outs, bool WithValues) const { Outs << Name; ExpressionToEvaluate.dump(Outs, WithValues); } -eld::Expected Complement::evalImpl() { +eld::Expected Complement::evalImpl() { // evaluate sub expressions auto Expr = ExpressionToEvaluate.eval(); if (!Expr) @@ -1046,7 +1056,7 @@ void UnaryPlus::dump(llvm::raw_ostream &Outs, bool WithValues) const { Outs << Name; ExpressionToEvaluate.dump(Outs, WithValues); } -eld::Expected UnaryPlus::evalImpl() { +eld::Expected UnaryPlus::evalImpl() { return ExpressionToEvaluate.eval(); } void UnaryPlus::getSymbols(std::vector &Symbols) { @@ -1069,7 +1079,7 @@ void UnaryMinus::dump(llvm::raw_ostream &Outs, bool WithValues) const { Outs << "-"; ExpressionToEvaluate.dump(Outs, WithValues); } -eld::Expected UnaryMinus::evalImpl() { +eld::Expected UnaryMinus::evalImpl() { // evaluate sub expressions auto Expr = ExpressionToEvaluate.eval(); if (!Expr) @@ -1096,7 +1106,7 @@ void UnaryNot::dump(llvm::raw_ostream &Outs, bool WithValues) const { Outs << Name; ExpressionToEvaluate.dump(Outs, WithValues); } -eld::Expected UnaryNot::evalImpl() { +eld::Expected UnaryNot::evalImpl() { // evaluate sub expressions auto Expr = ExpressionToEvaluate.eval(); if (!Expr) @@ -1118,7 +1128,7 @@ void Constant::dump(llvm::raw_ostream &Outs, bool WithValues) const { // format output for operator Outs << "CONSTANT(" << Name << ")"; } -eld::Expected Constant::evalImpl() { +eld::Expected Constant::evalImpl() { // evaluate sub expressions switch (type()) { case Expression::MAXPAGESIZE: @@ -1128,7 +1138,7 @@ eld::Expected Constant::evalImpl() { default: // this can't happen because all constants are part of the syntax ASSERT(0, "Unexpected constant"); - return {}; + return 0; } } void Constant::getSymbols(std::vector &Symbols) {} @@ -1147,7 +1157,7 @@ void SegmentStart::dump(llvm::raw_ostream &Outs, bool WithValues) const { ExpressionToEvaluate.dump(Outs, WithValues); Outs << ")"; } -eld::Expected SegmentStart::evalImpl() { +eld::Expected SegmentStart::evalImpl() { GeneralOptions::AddressMapType &AddressMap = ThisModule.getConfig().options().addressMap(); GeneralOptions::AddressMapType::const_iterator Addr; @@ -1196,7 +1206,7 @@ void AssertCmd::dump(llvm::raw_ostream &Outs, bool WithValues) const { ExpressionToEvaluate.dump(Outs, WithValues); Outs << ", \"" << AssertionMessage << "\")"; } -eld::Expected AssertCmd::evalImpl() { +eld::Expected AssertCmd::evalImpl() { auto Expr = ExpressionToEvaluate.eval(); if (!Expr) return Expr; @@ -1231,7 +1241,7 @@ void RightShift::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected RightShift::evalImpl() { +eld::Expected RightShift::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -1275,7 +1285,7 @@ void LeftShift::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected LeftShift::evalImpl() { +eld::Expected LeftShift::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -1318,7 +1328,7 @@ void BitwiseOr::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected BitwiseOr::evalImpl() { +eld::Expected BitwiseOr::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -1361,7 +1371,7 @@ void BitwiseAnd::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected BitwiseAnd::evalImpl() { +eld::Expected BitwiseAnd::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -1391,7 +1401,7 @@ void Defined::dump(llvm::raw_ostream &Outs, bool WithValues) const { // format output for operator Outs << "DEFINED(" << Name << ")"; } -eld::Expected Defined::evalImpl() { +eld::Expected Defined::evalImpl() { const LDSymbol *Symbol = ThisModule.getNamePool().findSymbol(Name); if (Symbol == nullptr) return 0; @@ -1428,7 +1438,7 @@ void DataSegmentAlign::dump(llvm::raw_ostream &Outs, bool WithValues) const { CommonPageSize.dump(Outs, WithValues); Outs << ")"; } -eld::Expected DataSegmentAlign::evalImpl() { +eld::Expected DataSegmentAlign::evalImpl() { auto MaxPageSize = this->MaxPageSize.eval(); if (!MaxPageSize) return MaxPageSize; @@ -1436,18 +1446,13 @@ eld::Expected DataSegmentAlign::evalImpl() { if (!CommonPageSize) return CommonPageSize; uint64_t Dot = ThisModule.getDotSymbol()->value(); - uint64_t Form1 = 0, Form2 = 0; - uint64_t DotAligned = Dot; + alignAddress(DotAligned, MaxPageSize->value()); - alignAddress(DotAligned, MaxPageSize.value()); - - Form1 = DotAligned + (Dot & (MaxPageSize.value() - 1)); - Form2 = DotAligned + (Dot & (MaxPageSize.value() - CommonPageSize.value())); - - if (Form1 <= Form2) - return Form1; - return Form2; + uint64_t Form1 = DotAligned + (Dot & (MaxPageSize->value() - 1)); + uint64_t Form2 = + DotAligned + (Dot & (MaxPageSize->value() - CommonPageSize->value())); + return UncertainValue(std::min(Form1, Form2), *MaxPageSize, *CommonPageSize); } void DataSegmentAlign::getSymbols(std::vector &Symbols) {} @@ -1470,7 +1475,7 @@ void DataSegmentRelRoEnd::dump(llvm::raw_ostream &Outs, bool WithValues) const { RightExpression.dump(Outs, WithValues); Outs << ")"; } -eld::Expected DataSegmentRelRoEnd::evalImpl() { +eld::Expected DataSegmentRelRoEnd::evalImpl() { auto CommonPageSize = this->CommonPageSize.eval(); if (!CommonPageSize) return CommonPageSize; @@ -1480,8 +1485,8 @@ eld::Expected DataSegmentRelRoEnd::evalImpl() { auto Expr2 = RightExpression.eval(); if (!Expr2) return Expr2; - uint64_t Value = Expr1.value() + Expr2.value(); - alignAddress(Value, CommonPageSize.value()); + auto Value = Expr1.value() + Expr2.value(); + alignAddress(Value.value(), CommonPageSize->value()); return Value; } void DataSegmentRelRoEnd::getSymbols(std::vector &Symbols) { @@ -1511,7 +1516,7 @@ void DataSegmentEnd::dump(llvm::raw_ostream &Outs, bool WithValues) const { ExpressionToEvaluate.dump(Outs, WithValues); Outs << ")"; } -eld::Expected DataSegmentEnd::evalImpl() { +eld::Expected DataSegmentEnd::evalImpl() { // evaluate sub expressions auto Expr = ExpressionToEvaluate.eval(); if (!Expr) @@ -1548,7 +1553,7 @@ void Max::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected Max::evalImpl() { +eld::Expected Max::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -1557,7 +1562,9 @@ eld::Expected Max::evalImpl() { if (!Right) return Right; - return Left.value() > Right.value() ? Left.value() : Right.value(); + return UncertainValue(Left->value() > Right->value() ? Left->value() + : Right->value(), + *Left, *Right); } void Max::getSymbols(std::vector &Symbols) { LeftExpression.getSymbols(Symbols); @@ -1590,7 +1597,7 @@ void Min::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected Min::evalImpl() { +eld::Expected Min::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -1598,7 +1605,9 @@ eld::Expected Min::evalImpl() { auto Right = RightExpression.eval(); if (!Right) return Right; - return Left.value() < Right.value() ? Left.value() : Right.value(); + return UncertainValue(Left->value() < Right->value() ? Left->value() + : Right->value(), + *Left, *Right); } void Min::getSymbols(std::vector &Symbols) { LeftExpression.getSymbols(Symbols); @@ -1625,7 +1634,9 @@ void Fill::dump(llvm::raw_ostream &Outs, bool WithValues) const { ExpressionToEvaluate.dump(Outs, WithValues); Outs << ")"; } -eld::Expected Fill::evalImpl() { return ExpressionToEvaluate.eval(); } +eld::Expected Fill::evalImpl() { + return ExpressionToEvaluate.eval(); +} void Fill::getSymbols(std::vector &Symbols) { ExpressionToEvaluate.getSymbols(Symbols); @@ -1651,11 +1662,12 @@ void Log2Ceil::dump(llvm::raw_ostream &Outs, bool WithValues) const { Outs << ")"; } -eld::Expected Log2Ceil::evalImpl() { +eld::Expected Log2Ceil::evalImpl() { auto Val = ExpressionToEvaluate.eval(); if (!Val) return Val; - return llvm::Log2_64_Ceil(std::max(Val.value(), UINT64_C(1))); + return UncertainValue(llvm::Log2_64_Ceil(std::max(Val->value(), UINT64_C(1))), + *Val); } void Log2Ceil::getSymbols(std::vector &Symbols) { @@ -1695,7 +1707,7 @@ void LogicalOp::dump(llvm::raw_ostream &Outs, bool WithValues) const { if (ExpressionHasParenthesis) Outs << ")"; } -eld::Expected LogicalOp::evalImpl() { +eld::Expected LogicalOp::evalImpl() { // evaluate sub expressions auto Left = LeftExpression.eval(); if (!Left) @@ -1737,13 +1749,12 @@ void QueryMemory::dump(llvm::raw_ostream &Outs, bool WithValues) const { Outs << ")"; } -eld::Expected QueryMemory::evalImpl() { +eld::Expected QueryMemory::evalImpl() { auto Region = ThisModule.getScript().getMemoryRegion(Name); if (!Region) return std::move(Region.error()); - if (isOrigin()) - return Region.value()->getOrigin(); - return Region.value()->getLength(); + return UncertainValue(isOrigin() ? *Region.value()->getOrigin() + : *Region.value()->getLength()); } void QueryMemory::getSymbols(std::vector &Symbols) {} @@ -1761,7 +1772,7 @@ void NullExpression::dump(llvm::raw_ostream &Outs, bool WithValues) const { Outs << Name; } -eld::Expected NullExpression::evalImpl() { +eld::Expected NullExpression::evalImpl() { return std::make_unique( Diag::internal_error_null_expression, std::vector{}); } @@ -1769,4 +1780,4 @@ eld::Expected NullExpression::evalImpl() { void NullExpression::getSymbols(std::vector &Symbols) {} void NullExpression::getSymbolNames( - std::unordered_set &SymbolTokens) {} \ No newline at end of file + std::unordered_set &SymbolTokens) {} diff --git a/lib/SymbolResolver/LDSymbol.cpp b/lib/SymbolResolver/LDSymbol.cpp index b59fdb647..145d44ccf 100644 --- a/lib/SymbolResolver/LDSymbol.cpp +++ b/lib/SymbolResolver/LDSymbol.cpp @@ -32,7 +32,7 @@ static LDSymbol GNullSymbol; LDSymbol::LDSymbol(ResolveInfo *R, bool IsGc) : ThisResolveInfo(R), ThisFragRef(nullptr), ThisShndx(0), ThisSymIdx(0), ThisSymbolsIsScriptDefined(false), ThisSymbolHasScriptValue(false), - ThisSymbolGarbageCollected(IsGc) {} + ThisSymbolHasUncertainValue(false), ThisSymbolGarbageCollected(IsGc) {} LDSymbol::~LDSymbol() {} diff --git a/lib/Target/RISCV/RISCVLDBackend.cpp b/lib/Target/RISCV/RISCVLDBackend.cpp index 6a10e3efa..ee7ddce23 100644 --- a/lib/Target/RISCV/RISCVLDBackend.cpp +++ b/lib/Target/RISCV/RISCVLDBackend.cpp @@ -61,15 +61,25 @@ Relocator *RISCVLDBackend::getRelocator() const { return m_pRelocator; } -Relocation::Address RISCVLDBackend::getSymbolValuePLT(Relocation &R) { +Relocation::Address RISCVLDBackend::getSymbolValuePLT(Relocation &R, + bool &Uncertain) { ResolveInfo *rsym = R.symInfo(); if (rsym && (rsym->reserved() & Relocator::ReservePLT)) { - if (const Fragment *S = findEntryInPLT(rsym)) + if (const Fragment *S = findEntryInPLT(rsym)) { + Uncertain = false; return S->getAddr(config().getDiagEngine()); - if (const ResolveInfo *S = findAbsolutePLT(rsym)) + } + if (const ResolveInfo *S = findAbsolutePLT(rsym)) { + Uncertain = false; return S->value(); + } } - return getRelocator()->getSymValue(&R); + return getRelocator()->getSymValue(&R, Uncertain); +} + +Relocation::Address RISCVLDBackend::getSymbolValuePLT(Relocation &R) { + bool Ignored; + return getSymbolValuePLT(R, Ignored); } Relocation::Type RISCVLDBackend::getCopyRelType() const { @@ -241,11 +251,13 @@ bool RISCVLDBackend::doRelaxationCall(Relocation *reloc, bool DoCompressed) { bool canCompress = (rd == 0 || (rd == 1 && config().targets().is32Bits())); // test if it can fall into 21bits - Relocator::DWord S = getSymbolValuePLT(*reloc); + bool Uncertain; + Relocator::DWord S = getSymbolValuePLT(*reloc, Uncertain); Relocator::DWord A = reloc->addend(); Relocator::DWord P = reloc->place(m_Module); Relocator::DWord X = S + A - P; - bool canRelax = config().options().getRISCVRelax() && llvm::isInt<21>(X); + bool canRelax = + config().options().getRISCVRelax() && llvm::isInt<21>(X) && !Uncertain; if (!canRelax) { reportMissedRelaxation("RISCV_CALL", *region, offset, canCompress ? 6 : 4, @@ -313,15 +325,16 @@ bool RISCVLDBackend::doRelaxationQCCall(Relocation *reloc, bool DoCompressed) { uint64_t qc_e_jump = reloc->target() & 0xffffffffffff; bool isTailCall = (qc_e_jump & 0xf1f07f) == 0x00401f; - Relocator::DWord S = getSymbolValuePLT(*reloc); + bool Uncertain; + Relocator::DWord S = getSymbolValuePLT(*reloc, Uncertain); Relocator::DWord A = reloc->addend(); Relocator::DWord P = reloc->place(m_Module); Relocator::DWord X = S + A - P; - bool canRelaxXqci = - config().targets().is32Bits() && config().options().getRISCVRelaxXqci(); - bool canRelax = - config().options().getRISCVRelax() && canRelaxXqci && llvm::isInt<21>(X); + bool canRelax = config().options().getRISCVRelax() && + config().options().getRISCVRelaxXqci() && + config().targets().is32Bits() && llvm::isInt<21>(X) && + !Uncertain; bool canCompress = DoCompressed && llvm::isInt<12>(X); if (!canRelax) { @@ -382,20 +395,17 @@ bool RISCVLDBackend::doRelaxationLui(Relocation *reloc, Relocator::DWord G) { return false; size_t SymbolSize = reloc->symInfo()->outSymbol()->size(); - Relocator::DWord S = getSymbolValuePLT(*reloc); + bool Uncertain; + Relocator::DWord S = getSymbolValuePLT(*reloc, Uncertain); Relocator::DWord A = reloc->addend(); Relocator::DWord Value = S + A; uint64_t offset = reloc->targetRef()->offset(); Relocation::Type type = reloc->type(); - // Do not relax complete zeroes because they can be mistaken for - // not-yet-assigned values. This applies to both zero-page relaxation and GP - // relaxation when GP is close to zero. - // First, try zero-page relaxation. It's the cheapest and does not need GP. bool canRelaxZero = config().options().getRISCVRelax() && config().options().getRISCVZeroRelax() && - llvm::isInt<12>(Value) && S != 0; + llvm::isInt<12>(Value) && !Uncertain; // HI will be deleted, LO will be converted to use GP as base. // GP must be available and relocation must fit in 12 bits relative to GP. @@ -404,7 +414,7 @@ bool RISCVLDBackend::doRelaxationLui(Relocation *reloc, Relocator::DWord G) { config().options().getRISCVRelax() && config().options().getRISCVGPRelax() && !config().isCodeIndep() && G != 0 && fitsInGP(G, Value, frag, reloc->targetSection(), SymbolSize) && - S != 0; + !Uncertain; if (type == llvm::ELF::R_RISCV_HI20) { @@ -644,12 +654,7 @@ bool RISCVLDBackend::doRelaxationPC(Relocation *reloc, Relocator::DWord G) { if (!region) return false; - // Test if the symbol with size can fall in 12 bits. - size_t SymbolSize = reloc->symInfo()->outSymbol()->size(); - Relocator::DWord S = getSymbolValuePLT(*reloc); - Relocator::DWord A = reloc->addend(); - - Relocation::Type new_type = 0x0; + std::optional new_type; Relocation::Type type = reloc->type(); switch (type) { case llvm::ELF::R_RISCV_PCREL_LO12_I: @@ -662,6 +667,7 @@ bool RISCVLDBackend::doRelaxationPC(Relocation *reloc, Relocator::DWord G) { break; } + Relocation *SymbolReloc = reloc; if (new_type) { // Lookup reloc to get actual addend of HI. Relocation *HIReloc = m_PairedRelocs[reloc]; @@ -671,15 +677,21 @@ bool RISCVLDBackend::doRelaxationPC(Relocation *reloc, Relocator::DWord G) { return false; if (!HIReloc) ASSERT(0, "HIReloc not found! Internal Error!"); - S = getSymbolValuePLT(*HIReloc); - A = HIReloc->addend(); - SymbolSize = HIReloc->symInfo()->outSymbol()->size(); + SymbolReloc = HIReloc; } + // Test if the symbol with size can fall in 12 bits. + size_t SymbolSize = SymbolReloc->symInfo()->outSymbol()->size(); + bool Uncertain; + Relocator::DWord S = getSymbolValuePLT(*SymbolReloc, Uncertain); + Relocator::DWord A = SymbolReloc->addend(); + uint64_t offset = reloc->targetRef()->offset(); - bool canRelax = config().options().getRISCVRelax() && - config().options().getRISCVGPRelax() && G != 0 && - fitsInGP(G, S + A, frag, reloc->targetSection(), SymbolSize); + bool canRelax = + config().options().getRISCVRelax() && + config().options().getRISCVGPRelax() && G != 0 && + fitsInGP(G, S + A, frag, reloc->targetSection(), SymbolSize) && + !Uncertain; // HI will be deleted, Low will be converted to use gp as base. if (type == llvm::ELF::R_RISCV_PCREL_HI20) { @@ -701,7 +713,7 @@ bool RISCVLDBackend::doRelaxationPC(Relocation *reloc, Relocator::DWord G) { uint64_t instr = reloc->target(); uint64_t mask = 0x1F << 15; instr = (instr & ~mask) | (0x3 << 15); - reloc->setType(new_type); + reloc->setType(*new_type); reloc->setTargetData(instr); reloc->setAddend(A); return true; diff --git a/lib/Target/RISCV/RISCVLDBackend.h b/lib/Target/RISCV/RISCVLDBackend.h index da354d34b..54c34c7cf 100644 --- a/lib/Target/RISCV/RISCVLDBackend.h +++ b/lib/Target/RISCV/RISCVLDBackend.h @@ -176,6 +176,7 @@ class RISCVLDBackend : public GNULDBackend { } // Get the value of the symbol, using the PLT slot if one exists. + Relocation::Address getSymbolValuePLT(Relocation &R, bool &Uncertain); Relocation::Address getSymbolValuePLT(Relocation &R); private: diff --git a/lib/Target/Relocator.cpp b/lib/Target/Relocator.cpp index d12af0a48..111599ee7 100644 --- a/lib/Target/Relocator.cpp +++ b/lib/Target/Relocator.cpp @@ -289,8 +289,15 @@ bool Relocator::doDeMangle() const { return m_Config.options().shouldDemangle(); } -Relocation::Address Relocator::getSymValue(Relocation *R) { - if (R->symInfo() && R->symInfo()->isThreadLocal()) +Relocation::Address Relocator::getSymValue(Relocation *R, bool &Uncertain) { + if (R->symInfo() && R->symInfo()->isThreadLocal()) { + Uncertain = false; return getTarget().finalizeTLSSymbol(R->symInfo()->outSymbol()); - return R->symValue(m_Module); + } + return R->symValue(m_Module, Uncertain); +} + +Relocation::Address Relocator::getSymValue(Relocation *R) { + bool Ignored; + return getSymValue(R, Ignored); }