X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gold%2Fexpression.cc;h=b0bd875add2144c2b7eaa9bffc64d8c77521c866;hb=50838d1be72ddd30e0b5f081933482424ae5a6b0;hp=8bbcfaacea942713e0cadafaf6459dc835a44579;hpb=91d6fa6a035cc7d0b7be5c99c194a64cb80924b0;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/expression.cc b/gold/expression.cc index 8bbcfaacea..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, 2009 Free Software Foundation, Inc. +// Copyright (C) 2006-2020 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -66,6 +66,18 @@ struct Expression::Expression_eval_info Output_section* dot_section; // Points to where the section of the result should be stored. 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. @@ -74,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); + 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. @@ -85,10 +96,14 @@ uint64_t 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) + Output_section** result_section_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); + dot_value, dot_section, result_section_pointer, + result_alignment_pointer, NULL, NULL, NULL, + is_section_dot_assignment, NULL); } // Evaluate an expression which may or may not refer to the dot @@ -98,7 +113,13 @@ uint64_t 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) + Output_section** result_section_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; @@ -109,11 +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; - return this->value(&eei); + // 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; + + // 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. @@ -155,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()); } @@ -174,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(); @@ -210,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; } @@ -247,13 +313,23 @@ class Unary_expression : public Expression eei->is_dot_available, eei->dot_value, eei->dot_section, - arg_section_pointer); + arg_section_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_; }; @@ -317,26 +393,40 @@ class Binary_expression : public Expression protected: uint64_t left_value(const Expression_eval_info* eei, - Output_section** section_pointer) const + Output_section** section_pointer, + uint64_t* alignment_pointer) const { return this->left_->eval_maybe_dot(eei->symtab, eei->layout, eei->check_assertions, eei->is_dot_available, eei->dot_value, eei->dot_section, - section_pointer); + section_pointer, + alignment_pointer, + NULL, + NULL, + NULL, + false, + eei->is_valid_pointer); } uint64_t right_value(const Expression_eval_info* eei, - Output_section** section_pointer) const + Output_section** section_pointer, + uint64_t* alignment_pointer) const { return this->right_->eval_maybe_dot(eei->symtab, eei->layout, eei->check_assertions, eei->is_dot_available, eei->dot_value, eei->dot_section, - section_pointer); + section_pointer, + alignment_pointer, + NULL, + NULL, + NULL, + false, + eei->is_valid_pointer); } void @@ -350,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); @@ -359,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_; @@ -385,15 +482,31 @@ class Binary_expression : public Expression value(const Expression_eval_info* eei) \ { \ Output_section* left_section; \ - uint64_t left = this->left_value(eei, &left_section); \ + uint64_t left_alignment = 0; \ + uint64_t left = this->left_value(eei, &left_section, \ + &left_alignment); \ Output_section* right_section; \ - uint64_t right = this->right_value(eei, &right_section); \ + 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_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_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) \ && parameters->options().relocatable()) \ @@ -469,31 +582,51 @@ class Trinary_expression : public Expression eei->is_dot_available, eei->dot_value, eei->dot_section, - section_pointer); + section_pointer, + NULL, + NULL, + NULL, + NULL, + false, + eei->is_valid_pointer); } uint64_t arg2_value(const Expression_eval_info* eei, - Output_section** section_pointer) const + 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); + section_pointer, + alignment_pointer, + NULL, + NULL, + NULL, + false, + eei->is_valid_pointer); } uint64_t arg3_value(const Expression_eval_info* eei, - Output_section** section_pointer) const + 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); + section_pointer, + alignment_pointer, + NULL, + NULL, + NULL, + false, + eei->is_valid_pointer); } void @@ -508,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_; @@ -529,8 +670,10 @@ class Trinary_cond : public Trinary_expression Output_section* arg1_section; uint64_t arg1 = this->arg1_value(eei, &arg1_section); return (arg1 - ? this->arg2_value(eei, eei->result_section_pointer) - : this->arg3_value(eei, eei->result_section_pointer)); + ? this->arg2_value(eei, eei->result_section_pointer, + eei->result_alignment_pointer) + : this->arg3_value(eei, eei->result_section_pointer, + eei->result_alignment_pointer)); } void @@ -565,14 +708,30 @@ class Max_expression : public Binary_expression value(const Expression_eval_info* eei) { Output_section* left_section; - uint64_t left = this->left_value(eei, &left_section); + uint64_t left_alignment; + uint64_t left = this->left_value(eei, &left_section, &left_alignment); Output_section* right_section; - uint64_t right = this->right_value(eei, &right_section); + 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")); + if (eei->result_alignment_pointer != NULL) + { + uint64_t ra = *eei->result_alignment_pointer; + if (left > right) + ra = std::max(ra, left_alignment); + else if (right > left) + ra = std::max(ra, right_alignment); + else + ra = std::max(ra, std::max(left_alignment, right_alignment)); + *eei->result_alignment_pointer = ra; + } return std::max(left, right); } @@ -600,14 +759,30 @@ class Min_expression : public Binary_expression value(const Expression_eval_info* eei) { Output_section* left_section; - uint64_t left = this->left_value(eei, &left_section); + uint64_t left_alignment; + uint64_t left = this->left_value(eei, &left_section, &left_alignment); Output_section* right_section; - uint64_t right = this->right_value(eei, &right_section); + 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")); + if (eei->result_alignment_pointer != NULL) + { + uint64_t ra = *eei->result_alignment_pointer; + if (left < right) + ra = std::max(ra, left_alignment); + else if (right < left) + ra = std::max(ra, right_alignment); + else + ra = std::max(ra, std::max(left_alignment, right_alignment)); + *eei->result_alignment_pointer = ra; + } return std::min(left, right); } @@ -699,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; } @@ -734,15 +909,24 @@ class Align_expression : public Binary_expression value(const Expression_eval_info* eei) { Output_section* align_section; - uint64_t align = this->right_value(eei, &align_section); + uint64_t align = this->right_value(eei, &align_section, NULL); if (align_section != NULL && parameters->options().relocatable()) gold_warning(_("aligning to section relative value")); - uint64_t val = this->left_value(eei, eei->result_section_pointer); + if (eei->result_alignment_pointer != NULL + && align > *eei->result_alignment_pointer) + { + uint64_t a = align; + while ((a & (a - 1)) != 0) + a &= a - 1; + *eei->result_alignment_pointer = a; + } + + uint64_t value = this->left_value(eei, eei->result_section_pointer, NULL); if (align <= 1) - return val; - return ((val + align - 1) / align) * align; + return value; + return ((value + align - 1) / align) * align; } void @@ -768,10 +952,10 @@ class Assert_expression : public Unary_expression uint64_t value(const Expression_eval_info* eei) { - uint64_t val = this->arg_value(eei, eei->result_section_pointer); - if (!val && eei->check_assertions) + uint64_t value = this->arg_value(eei, eei->result_section_pointer); + if (!value && eei->check_assertions) gold_error("%s", this->message_.c_str()); - return val; + return value; } void @@ -807,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 @@ -1012,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(); } } @@ -1154,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; } } @@ -1171,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.