diff options
Diffstat (limited to 'gold/expression.cc')
-rw-r--r-- | gold/expression.cc | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/gold/expression.cc b/gold/expression.cc index a64fa42..484a493 100644 --- a/gold/expression.cc +++ b/gold/expression.cc @@ -74,6 +74,10 @@ struct Expression::Expression_eval_info elfcpp::STV* vis_pointer; // Pointer to where the rest of the symbol's st_other field should be stored. unsigned char* nonvis_pointer; + // Whether the value is valid. In Symbol_assignment::set_if_absolute, we + // may be trying to evaluate the address of a section whose address is not + // yet finalized, and we need to fail the evaluation gracefully. + bool *is_valid_pointer; }; // Evaluate an expression. @@ -83,7 +87,7 @@ Expression::eval(const Symbol_table* symtab, const Layout* layout, bool check_assertions) { return this->eval_maybe_dot(symtab, layout, check_assertions, false, 0, - NULL, NULL, NULL, NULL, NULL, NULL, false); + NULL, NULL, NULL, NULL, NULL, NULL, false, NULL); } // Evaluate an expression which may refer to the dot symbol. @@ -99,7 +103,7 @@ Expression::eval_with_dot(const Symbol_table* symtab, const Layout* layout, return this->eval_maybe_dot(symtab, layout, check_assertions, true, dot_value, dot_section, result_section_pointer, result_alignment_pointer, NULL, NULL, NULL, - is_section_dot_assignment); + is_section_dot_assignment, NULL); } // Evaluate an expression which may or may not refer to the dot @@ -114,7 +118,8 @@ Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout, elfcpp::STT* type_pointer, elfcpp::STV* vis_pointer, unsigned char* nonvis_pointer, - bool is_section_dot_assignment) + bool is_section_dot_assignment, + bool* is_valid_pointer) { Expression_eval_info eei; eei.symtab = symtab; @@ -138,8 +143,18 @@ Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout, eei.result_alignment_pointer = result_alignment_pointer; + // Assume the value is valid until we try to evaluate an expression + // that can't be evaluated yet. + bool is_valid = true; + eei.is_valid_pointer = &is_valid; + uint64_t val = this->value(&eei); + if (is_valid_pointer != NULL) + *is_valid_pointer = is_valid; + else + gold_assert(is_valid); + // If this is an assignment to dot within a section, and the value // is absolute, treat it as a section-relative offset. if (is_section_dot_assignment && *result_section_pointer == NULL) @@ -295,7 +310,8 @@ class Unary_expression : public Expression NULL, NULL, NULL, - false); + false, + eei->is_valid_pointer); } void @@ -378,7 +394,8 @@ class Binary_expression : public Expression NULL, NULL, NULL, - false); + false, + eei->is_valid_pointer); } uint64_t @@ -396,7 +413,8 @@ class Binary_expression : public Expression NULL, NULL, NULL, - false); + false, + eei->is_valid_pointer); } void @@ -550,7 +568,8 @@ class Trinary_expression : public Expression NULL, NULL, NULL, - false); + false, + eei->is_valid_pointer); } uint64_t @@ -568,7 +587,8 @@ class Trinary_expression : public Expression NULL, NULL, NULL, - false); + false, + eei->is_valid_pointer); } uint64_t @@ -586,7 +606,8 @@ class Trinary_expression : public Expression NULL, NULL, NULL, - false); + false, + eei->is_valid_pointer); } void @@ -945,7 +966,10 @@ class Addr_expression : public Section_expression { if (eei->result_section_pointer != NULL) *eei->result_section_pointer = os; - return os->address(); + if (os->is_address_valid()) + return os->address(); + *eei->is_valid_pointer = false; + return 0; } uint64_t |