X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gold%2Fexpression.cc;h=b0bd875add2144c2b7eaa9bffc64d8c77521c866;hb=de54374205650be71237ce51ef7981d30ddd78dc;hp=134b0fa2a22a4c10a1b283c63629a36b58357376;hpb=f6973bdcb778ca7a54817a696cb0c6457f4ae96f;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/expression.cc b/gold/expression.cc index 134b0fa2a2..b0bd875add 100644 --- a/gold/expression.cc +++ b/gold/expression.cc @@ -1,6 +1,6 @@ // expression.cc -- expressions in linker scripts for gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright (C) 2006-2020 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -68,6 +68,16 @@ struct Expression::Expression_eval_info Output_section** result_section_pointer; // Pointer to where the alignment of the result should be stored. uint64_t* result_alignment_pointer; + // Pointer to where the type of the symbol on the RHS should be stored. + elfcpp::STT* type_pointer; + // Pointer to where the visibility of the symbol on the RHS should be stored. + 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. @@ -76,9 +86,8 @@ uint64_t Expression::eval(const Symbol_table* symtab, const Layout* layout, bool check_assertions) { - Output_section* dummy; - return this->eval_maybe_dot(symtab, layout, check_assertions, - false, 0, NULL, &dummy, NULL); + return this->eval_maybe_dot(symtab, layout, check_assertions, false, 0, + NULL, NULL, NULL, NULL, NULL, NULL, false, NULL); } // Evaluate an expression which may refer to the dot symbol. @@ -88,11 +97,13 @@ Expression::eval_with_dot(const Symbol_table* symtab, const Layout* layout, bool check_assertions, uint64_t dot_value, Output_section* dot_section, Output_section** result_section_pointer, - uint64_t* result_alignment_pointer) + uint64_t* result_alignment_pointer, + bool is_section_dot_assignment) { return this->eval_maybe_dot(symtab, layout, check_assertions, true, dot_value, dot_section, result_section_pointer, - result_alignment_pointer); + result_alignment_pointer, NULL, NULL, NULL, + is_section_dot_assignment, NULL); } // Evaluate an expression which may or may not refer to the dot @@ -103,7 +114,12 @@ Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout, bool check_assertions, bool is_dot_available, uint64_t dot_value, Output_section* dot_section, Output_section** result_section_pointer, - uint64_t* result_alignment_pointer) + uint64_t* result_alignment_pointer, + elfcpp::STT* type_pointer, + elfcpp::STV* vis_pointer, + unsigned char* nonvis_pointer, + bool is_section_dot_assignment, + bool* is_valid_pointer) { Expression_eval_info eei; eei.symtab = symtab; @@ -114,13 +130,40 @@ Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout, eei.dot_section = dot_section; // We assume the value is absolute, and only set this to a section - // if we find a section relative reference. - *result_section_pointer = NULL; + // if we find a section-relative reference. + if (result_section_pointer != NULL) + *result_section_pointer = NULL; eei.result_section_pointer = result_section_pointer; + // For symbol=symbol assignments, we need to track the type, visibility, + // and remaining st_other bits. + eei.type_pointer = type_pointer; + eei.vis_pointer = vis_pointer; + eei.nonvis_pointer = nonvis_pointer; + eei.result_alignment_pointer = result_alignment_pointer; - return this->value(&eei); + // 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) + { + gold_assert(dot_section != NULL); + val += dot_section->address(); + *result_section_pointer = dot_section; + } + return val; } // A number. @@ -162,6 +205,14 @@ class Symbol_expression : public Expression uint64_t value(const Expression_eval_info*); + void + set_expr_sym_in_real_elf(Symbol_table* symtab) const + { + Symbol* sym = symtab->lookup(this->name_.c_str()); + if (sym != NULL) + sym->set_in_real_elf(); + } + void print(FILE* f) const { fprintf(f, "%s", this->name_.c_str()); } @@ -181,7 +232,14 @@ Symbol_expression::value(const Expression_eval_info* eei) return 0; } - *eei->result_section_pointer = sym->output_section(); + if (eei->result_section_pointer != NULL) + *eei->result_section_pointer = sym->output_section(); + if (eei->type_pointer != NULL) + *eei->type_pointer = sym->type(); + if (eei->vis_pointer != NULL) + *eei->vis_pointer = sym->visibility(); + if (eei->nonvis_pointer != NULL) + *eei->nonvis_pointer = sym->nonvis(); if (parameters->target().get_size() == 32) return eei->symtab->get_sized_symbol<32>(sym)->value(); @@ -217,7 +275,8 @@ Dot_expression::value(const Expression_eval_info* eei) "SECTIONS clause")); return 0; } - *eei->result_section_pointer = eei->dot_section; + if (eei->result_section_pointer != NULL) + *eei->result_section_pointer = eei->dot_section; return eei->dot_value; } @@ -255,13 +314,22 @@ class Unary_expression : public Expression eei->dot_value, eei->dot_section, arg_section_pointer, - eei->result_alignment_pointer); + eei->result_alignment_pointer, + NULL, + NULL, + NULL, + false, + eei->is_valid_pointer); } void arg_print(FILE* f) const { this->arg_->print(f); } + void + set_expr_sym_in_real_elf(Symbol_table* symtab) const + { return this->arg_->set_expr_sym_in_real_elf(symtab); } + private: Expression* arg_; }; @@ -334,7 +402,12 @@ class Binary_expression : public Expression eei->dot_value, eei->dot_section, section_pointer, - alignment_pointer); + alignment_pointer, + NULL, + NULL, + NULL, + false, + eei->is_valid_pointer); } uint64_t @@ -348,7 +421,12 @@ class Binary_expression : public Expression eei->dot_value, eei->dot_section, section_pointer, - alignment_pointer); + alignment_pointer, + NULL, + NULL, + NULL, + false, + eei->is_valid_pointer); } void @@ -362,7 +440,7 @@ class Binary_expression : public Expression // This is a call to function FUNCTION_NAME. Print it. This is for // debugging. void - print_function(FILE* f, const char *function_name) const + print_function(FILE* f, const char* function_name) const { fprintf(f, "%s(", function_name); this->left_print(f); @@ -371,6 +449,13 @@ class Binary_expression : public Expression fprintf(f, ")"); } + void + set_expr_sym_in_real_elf(Symbol_table* symtab) const + { + this->left_->set_expr_sym_in_real_elf(symtab); + this->right_->set_expr_sym_in_real_elf(symtab); + } + private: Expression* left_; Expression* right_; @@ -397,26 +482,30 @@ class Binary_expression : public Expression value(const Expression_eval_info* eei) \ { \ Output_section* left_section; \ - uint64_t left_alignment; \ + uint64_t left_alignment = 0; \ uint64_t left = this->left_value(eei, &left_section, \ &left_alignment); \ Output_section* right_section; \ - uint64_t right_alignment; \ + uint64_t right_alignment = 0; \ uint64_t right = this->right_value(eei, &right_section, \ &right_alignment); \ if (KEEP_RIGHT && left_section == NULL && right_section != NULL) \ { \ - *eei->result_section_pointer = right_section; \ - if (eei->result_alignment_pointer != NULL) \ + if (eei->result_section_pointer != NULL) \ + *eei->result_section_pointer = right_section; \ + if (eei->result_alignment_pointer != NULL \ + && right_alignment > *eei->result_alignment_pointer) \ *eei->result_alignment_pointer = right_alignment; \ } \ else if (KEEP_LEFT \ && left_section != NULL \ && right_section == NULL) \ { \ - *eei->result_section_pointer = left_section; \ - if (eei->result_alignment_pointer != NULL) \ - *eei->result_alignment_pointer = right_alignment; \ + if (eei->result_section_pointer != NULL) \ + *eei->result_section_pointer = left_section; \ + if (eei->result_alignment_pointer != NULL \ + && left_alignment > *eei->result_alignment_pointer) \ + *eei->result_alignment_pointer = left_alignment; \ } \ else if ((WARN || left_section != right_section) \ && (left_section != NULL || right_section != NULL) \ @@ -494,7 +583,12 @@ class Trinary_expression : public Expression eei->dot_value, eei->dot_section, section_pointer, - NULL); + NULL, + NULL, + NULL, + NULL, + false, + eei->is_valid_pointer); } uint64_t @@ -502,13 +596,18 @@ class Trinary_expression : public Expression Output_section** section_pointer, uint64_t* alignment_pointer) const { - return this->arg1_->eval_maybe_dot(eei->symtab, eei->layout, + return this->arg2_->eval_maybe_dot(eei->symtab, eei->layout, eei->check_assertions, eei->is_dot_available, eei->dot_value, eei->dot_section, section_pointer, - alignment_pointer); + alignment_pointer, + NULL, + NULL, + NULL, + false, + eei->is_valid_pointer); } uint64_t @@ -516,13 +615,18 @@ class Trinary_expression : public Expression Output_section** section_pointer, uint64_t* alignment_pointer) const { - return this->arg1_->eval_maybe_dot(eei->symtab, eei->layout, + return this->arg3_->eval_maybe_dot(eei->symtab, eei->layout, eei->check_assertions, eei->is_dot_available, eei->dot_value, eei->dot_section, section_pointer, - alignment_pointer); + alignment_pointer, + NULL, + NULL, + NULL, + false, + eei->is_valid_pointer); } void @@ -537,6 +641,14 @@ class Trinary_expression : public Expression arg3_print(FILE* f) const { this->arg3_->print(f); } + void + set_expr_sym_in_real_elf(Symbol_table* symtab) const + { + this->arg1_->set_expr_sym_in_real_elf(symtab); + this->arg2_->set_expr_sym_in_real_elf(symtab); + this->arg3_->set_expr_sym_in_real_elf(symtab); + } + private: Expression* arg1_; Expression* arg2_; @@ -602,7 +714,10 @@ class Max_expression : public Binary_expression uint64_t right_alignment; uint64_t right = this->right_value(eei, &right_section, &right_alignment); if (left_section == right_section) - *eei->result_section_pointer = left_section; + { + if (eei->result_section_pointer != NULL) + *eei->result_section_pointer = left_section; + } else if ((left_section != NULL || right_section != NULL) && parameters->options().relocatable()) gold_warning(_("max applied to section relative value")); @@ -650,7 +765,10 @@ class Min_expression : public Binary_expression uint64_t right_alignment; uint64_t right = this->right_value(eei, &right_section, &right_alignment); if (left_section == right_section) - *eei->result_section_pointer = left_section; + { + if (eei->result_section_pointer != NULL) + *eei->result_section_pointer = left_section; + } else if ((left_section != NULL || right_section != NULL) && parameters->options().relocatable()) gold_warning(_("min applied to section relative value")); @@ -756,10 +874,10 @@ class Absolute_expression : public Unary_expression uint64_t value(const Expression_eval_info* eei) { - Output_section* dummy; - uint64_t ret = this->arg_value(eei, &dummy); + uint64_t ret = this->arg_value(eei, NULL); // Force the value to be absolute. - *eei->result_section_pointer = NULL; + if (eei->result_section_pointer != NULL) + *eei->result_section_pointer = NULL; return ret; } @@ -873,8 +991,12 @@ class Addr_expression : public Section_expression value_from_output_section(const Expression_eval_info* eei, Output_section* os) { - *eei->result_section_pointer = os; - return os->address(); + if (eei->result_section_pointer != NULL) + *eei->result_section_pointer = os; + if (os->is_address_valid()) + return os->address(); + *eei->is_valid_pointer = false; + return 0; } uint64_t @@ -1078,7 +1200,8 @@ class Loadaddr_expression : public Section_expression return os->load_address(); else { - *eei->result_section_pointer = os; + if (eei->result_section_pointer != NULL) + *eei->result_section_pointer = os; return os->address(); } } @@ -1220,10 +1343,10 @@ Segment_start_expression::value(const Expression_eval_info* eei) return parameters->options().Tbss(); else { - Output_section* dummy; - uint64_t ret = this->arg_value(eei, &dummy); + uint64_t ret = this->arg_value(eei, NULL); // Force the value to be absolute. - *eei->result_section_pointer = NULL; + if (eei->result_section_pointer != NULL) + *eei->result_section_pointer = NULL; return ret; } } @@ -1237,19 +1360,4 @@ script_exp_function_segment_start(const char* segment_name, default_value); } -// Functions for memory regions. These can not be implemented unless -// and until we implement memory regions. - -extern "C" Expression* -script_exp_function_origin(const char*, size_t) -{ - gold_fatal(_("ORIGIN not implemented")); -} - -extern "C" Expression* -script_exp_function_length(const char*, size_t) -{ - gold_fatal(_("LENGTH not implemented")); -} - } // End namespace gold.