diff --git a/gold/ChangeLog b/gold/ChangeLog index 5190e7e0d1..ebed52b2ee 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,17 @@ +2015-08-25 Cary Coutant + + PR gold/14746 + * expression.cc (Expression::Expression_eval_info): Add + is_valid_pointer field. + (Expression::eval_maybe_dot): Add is_valid_pointer parameter. + Adjust all callers. + (Addr_expression::value_from_output_section): Check whether address + is valid. + * script.cc (Symbol_assignment::set_if_absolute): Defer assignment + if evaluation failed due to address that is not yet valid. + * script.h: (Expression::eval_maybe_dot): Add is_valid_pointer + parameter. + 2015-08-25 Cary Coutant PR gold/18866 diff --git a/gold/expression.cc b/gold/expression.cc index a64fa42302..484a49341d 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 diff --git a/gold/script.cc b/gold/script.cc index 56f126c738..cfa3116e18 100644 --- a/gold/script.cc +++ b/gold/script.cc @@ -987,7 +987,7 @@ Symbol_assignment::sized_finalize(Symbol_table* symtab, const Layout* layout, is_dot_available, dot_value, dot_section, §ion, NULL, &type, - &vis, &nonvis, false); + &vis, &nonvis, false, NULL); Sized_symbol* ssym = symtab->get_sized_symbol(this->sym_); ssym->set_value(final_val); ssym->set_type(type); @@ -1009,11 +1009,12 @@ Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout, return; Output_section* val_section; + bool is_valid; uint64_t val = this->val_->eval_maybe_dot(symtab, layout, false, is_dot_available, dot_value, dot_section, &val_section, NULL, - NULL, NULL, NULL, false); - if (val_section != NULL && val_section != dot_section) + NULL, NULL, NULL, false, &is_valid); + if (!is_valid || (val_section != NULL && val_section != dot_section)) return; if (parameters->target().get_size() == 32) diff --git a/gold/script.h b/gold/script.h index 1731985d83..739baf16ed 100644 --- a/gold/script.h +++ b/gold/script.h @@ -113,7 +113,7 @@ class Expression Output_section* dot_section, Output_section** result_section, uint64_t* result_alignment, elfcpp::STT* type, elfcpp::STV* vis, unsigned char* nonvis, - bool is_section_dot_assignment); + bool is_section_dot_assignment, bool* is_valid_pointer); // Print the expression to the FILE. This is for debugging. virtual void