From f6973bdcb778ca7a54817a696cb0c6457f4ae96f Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 23 Apr 2010 04:47:33 +0000 Subject: [PATCH] * expression.cc (Expression::Expression_eval_info): Add result_alignment_pointer field. (Expression::eval_with_dot): Add result_alignment_pointer parameter. Change all callers. (Expression::eval_maybe_dot): Likewise. (class Binary_expression): Add alignment_pointer parameter to left_value and right_value. Change all callers. (BINARY_EXPRESSION): Set result alignment. (class Trinary_expression): Add alignment_pointer parameter to arg2_value and arg3_value. Change all callers. (Trinary_cond::value): Set result alignment. (Max_expression::value, Min_expression::value): Likewise. (Align_expression::value): Likewise. * script-sections.cc (class Sections_element): Add dot_alignment parameter to set_section_addresses virtual function. Update instantiations. (class Output_section_element): Likewise. (Script_sections::create_segments): Add dot_alignment parameter. Change all callers. (Script_sections::create_segments_from_phdrs_clause): Likewise. (Script_sections::set_phdrs_clause_addresses): Likewise. * script-sections.h: Update declarations. * script.h: Update declarations. * output.h (Output_segment::set_minimum_p_align): Don't decrease min_p_align. * testsuite/script_test_3.t: Set large alignment. * testsuite/script_test_3.sh: Make sure that at least one LOAD segment has expected alignment. --- gold/ChangeLog | 31 +++++++++ gold/expression.cc | 118 +++++++++++++++++++++++++------- gold/output.h | 5 +- gold/script-sections.cc | 92 +++++++++++++++---------- gold/script-sections.h | 6 +- gold/script.cc | 4 +- gold/script.h | 9 ++- gold/testsuite/script_test_3.sh | 14 ++++ gold/testsuite/script_test_3.t | 2 +- 9 files changed, 208 insertions(+), 73 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index f3fabd00a6c..54e775dd0dc 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,34 @@ +2010-04-22 Ian Lance Taylor + + * expression.cc (Expression::Expression_eval_info): Add + result_alignment_pointer field. + (Expression::eval_with_dot): Add result_alignment_pointer + parameter. Change all callers. + (Expression::eval_maybe_dot): Likewise. + (class Binary_expression): Add alignment_pointer parameter to + left_value and right_value. Change all callers. + (BINARY_EXPRESSION): Set result alignment. + (class Trinary_expression): Add alignment_pointer parameter to + arg2_value and arg3_value. Change all callers. + (Trinary_cond::value): Set result alignment. + (Max_expression::value, Min_expression::value): Likewise. + (Align_expression::value): Likewise. + * script-sections.cc (class Sections_element): Add dot_alignment + parameter to set_section_addresses virtual function. Update + instantiations. + (class Output_section_element): Likewise. + (Script_sections::create_segments): Add dot_alignment parameter. + Change all callers. + (Script_sections::create_segments_from_phdrs_clause): Likewise. + (Script_sections::set_phdrs_clause_addresses): Likewise. + * script-sections.h: Update declarations. + * script.h: Update declarations. + * output.h (Output_segment::set_minimum_p_align): Don't decrease + min_p_align. + * testsuite/script_test_3.t: Set large alignment. + * testsuite/script_test_3.sh: Make sure that at least one LOAD + segment has expected alignment. + 2010-04-22 Nick Clifton * po/gold.pot: Updated by the Translation project. diff --git a/gold/expression.cc b/gold/expression.cc index 853a698d187..134b0fa2a22 100644 --- a/gold/expression.cc +++ b/gold/expression.cc @@ -66,6 +66,8 @@ 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; }; // Evaluate an expression. @@ -76,7 +78,7 @@ Expression::eval(const Symbol_table* symtab, const Layout* layout, { Output_section* dummy; return this->eval_maybe_dot(symtab, layout, check_assertions, - false, 0, NULL, &dummy); + false, 0, NULL, &dummy, NULL); } // Evaluate an expression which may refer to the dot symbol. @@ -85,10 +87,12 @@ 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) { 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); } // Evaluate an expression which may or may not refer to the dot @@ -98,7 +102,8 @@ 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) { Expression_eval_info eei; eei.symtab = symtab; @@ -113,6 +118,8 @@ Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout, *result_section_pointer = NULL; eei.result_section_pointer = result_section_pointer; + eei.result_alignment_pointer = result_alignment_pointer; + return this->value(&eei); } @@ -247,7 +254,8 @@ 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); } void @@ -317,26 +325,30 @@ 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); } 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); } void @@ -385,15 +397,27 @@ 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; \ + 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 (KEEP_RIGHT && left_section == NULL && right_section != NULL) \ - *eei->result_section_pointer = right_section; \ + { \ + *eei->result_section_pointer = right_section; \ + if (eei->result_alignment_pointer != NULL) \ + *eei->result_alignment_pointer = right_alignment; \ + } \ else if (KEEP_LEFT \ && left_section != NULL \ && right_section == NULL) \ - *eei->result_section_pointer = left_section; \ + { \ + *eei->result_section_pointer = left_section; \ + if (eei->result_alignment_pointer != NULL) \ + *eei->result_alignment_pointer = right_alignment; \ + } \ else if ((WARN || left_section != right_section) \ && (left_section != NULL || right_section != NULL) \ && parameters->options().relocatable()) \ @@ -469,31 +493,36 @@ class Trinary_expression : public Expression eei->is_dot_available, eei->dot_value, eei->dot_section, - section_pointer); + section_pointer, + NULL); } 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, eei->check_assertions, eei->is_dot_available, eei->dot_value, eei->dot_section, - section_pointer); + section_pointer, + alignment_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, eei->check_assertions, eei->is_dot_available, eei->dot_value, eei->dot_section, - section_pointer); + section_pointer, + alignment_pointer); } void @@ -529,8 +558,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 +596,27 @@ 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; 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 +644,27 @@ 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; 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); } @@ -734,12 +791,21 @@ 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 value = 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 value; return ((value + align - 1) / align) * align; diff --git a/gold/output.h b/gold/output.h index 80885653492..410ec2c39e6 100644 --- a/gold/output.h +++ b/gold/output.h @@ -3833,7 +3833,10 @@ class Output_segment // upward based on the section alignments. void set_minimum_p_align(uint64_t align) - { this->min_p_align_ = align; } + { + if (align > this->min_p_align_) + this->min_p_align_ = align; + } // Set the offset of this segment based on the section. This should // only be called for a non-PT_LOAD segment. diff --git a/gold/script-sections.cc b/gold/script-sections.cc index 24b9103f921..b4cbb401149 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -369,7 +369,8 @@ class Sections_element // Set section addresses. This includes applying assignments if the // the expression is an absolute value. virtual void - set_section_addresses(Symbol_table*, Layout*, uint64_t*, uint64_t*) + set_section_addresses(Symbol_table*, Layout*, uint64_t*, uint64_t*, + uint64_t*) { } // Check a constraint (ONLY_IF_RO, etc.) on an output section. If @@ -447,7 +448,7 @@ class Sections_element_assignment : public Sections_element // absolute symbols when setting dot. void set_section_addresses(Symbol_table* symtab, Layout* layout, - uint64_t* dot_value, uint64_t*) + uint64_t* dot_value, uint64_t*, uint64_t*) { this->assignment_.set_if_absolute(symtab, layout, true, *dot_value); } @@ -484,17 +485,18 @@ class Sections_element_dot_assignment : public Sections_element // to be absolute. Output_section* dummy; *dot_value = this->val_->eval_with_dot(symtab, layout, true, *dot_value, - NULL, &dummy); + NULL, &dummy, NULL); } // Update the dot symbol while setting section addresses. void set_section_addresses(Symbol_table* symtab, Layout* layout, - uint64_t* dot_value, uint64_t* load_address) + uint64_t* dot_value, uint64_t* dot_alignment, + uint64_t* load_address) { Output_section* dummy; *dot_value = this->val_->eval_with_dot(symtab, layout, false, *dot_value, - NULL, &dummy); + NULL, &dummy, dot_alignment); *load_address = *dot_value; } @@ -577,7 +579,7 @@ class Output_section_element // the expression is an absolute value. virtual void set_section_addresses(Symbol_table*, Layout*, Output_section*, uint64_t, - uint64_t*, Output_section**, std::string*, + uint64_t*, uint64_t*, Output_section**, std::string*, Input_section_list*) { } @@ -635,8 +637,8 @@ class Output_section_element_assignment : public Output_section_element // absolute symbols when setting dot. void set_section_addresses(Symbol_table* symtab, Layout* layout, Output_section*, - uint64_t, uint64_t* dot_value, Output_section**, - std::string*, Input_section_list*) + uint64_t, uint64_t* dot_value, uint64_t*, + Output_section**, std::string*, Input_section_list*) { this->assignment_.set_if_absolute(symtab, layout, true, *dot_value); } @@ -668,14 +670,14 @@ class Output_section_element_dot_assignment : public Output_section_element uint64_t* dot_value, Output_section** dot_section) { *dot_value = this->val_->eval_with_dot(symtab, layout, true, *dot_value, - *dot_section, dot_section); + *dot_section, dot_section, NULL); } // Update the dot symbol while setting section addresses. void set_section_addresses(Symbol_table* symtab, Layout* layout, Output_section*, - uint64_t, uint64_t* dot_value, Output_section**, - std::string*, Input_section_list*); + uint64_t, uint64_t* dot_value, uint64_t*, + Output_section**, std::string*, Input_section_list*); // Print for debugging. void @@ -699,13 +701,14 @@ Output_section_element_dot_assignment::set_section_addresses( Output_section* output_section, uint64_t, uint64_t* dot_value, + uint64_t* dot_alignment, Output_section** dot_section, std::string* fill, Input_section_list*) { uint64_t next_dot = this->val_->eval_with_dot(symtab, layout, false, *dot_value, *dot_section, - dot_section); + dot_section, dot_alignment); if (next_dot < *dot_value) gold_error(_("dot may not move backward")); if (next_dot > *dot_value && output_section != NULL) @@ -807,7 +810,7 @@ Output_data_expression::do_write_to_buffer(unsigned char* buf) Output_section* dummy; uint64_t val = this->val_->eval_with_dot(this->symtab_, this->layout_, true, this->dot_value_, - this->dot_section_, &dummy); + this->dot_section_, &dummy, NULL); if (parameters->target().is_big_endian()) this->endian_write_to_buffer(val, buf); @@ -868,8 +871,8 @@ class Output_section_element_data : public Output_section_element // Store the value in the section. void set_section_addresses(Symbol_table*, Layout*, Output_section*, uint64_t, - uint64_t* dot_value, Output_section**, std::string*, - Input_section_list*); + uint64_t* dot_value, uint64_t*, Output_section**, + std::string*, Input_section_list*); // Print for debugging. void @@ -893,6 +896,7 @@ Output_section_element_data::set_section_addresses( Output_section* os, uint64_t, uint64_t* dot_value, + uint64_t*, Output_section** dot_section, std::string*, Input_section_list*) @@ -949,14 +953,14 @@ class Output_section_element_fill : public Output_section_element // Update the fill value while setting section addresses. void set_section_addresses(Symbol_table* symtab, Layout* layout, Output_section*, - uint64_t, uint64_t* dot_value, + uint64_t, uint64_t* dot_value, uint64_t*, Output_section** dot_section, std::string* fill, Input_section_list*) { Output_section* fill_section; uint64_t fill_val = this->val_->eval_with_dot(symtab, layout, false, *dot_value, *dot_section, - &fill_section); + &fill_section, NULL); if (fill_section != NULL) gold_warning(_("fill value is not absolute")); // FIXME: The GNU linker supports fill values of arbitrary length. @@ -1012,7 +1016,7 @@ class Output_section_element_input : public Output_section_element // Set the section address. void set_section_addresses(Symbol_table* symtab, Layout* layout, Output_section*, - uint64_t subalign, uint64_t* dot_value, + uint64_t subalign, uint64_t* dot_value, uint64_t*, Output_section**, std::string* fill, Input_section_list*); @@ -1309,6 +1313,7 @@ Output_section_element_input::set_section_addresses( Output_section* output_section, uint64_t subalign, uint64_t* dot_value, + uint64_t*, Output_section** dot_section, std::string* fill, Input_section_list* input_sections) @@ -1629,7 +1634,8 @@ class Output_section_definition : public Sections_element // Set the section address. void set_section_addresses(Symbol_table* symtab, Layout* layout, - uint64_t* dot_value, uint64_t* load_address); + uint64_t* dot_value, uint64_t*, + uint64_t* load_address); // Check a constraint (ONLY_IF_RO, etc.) on an output section. If // this section is constrained, and the input sections do not match, @@ -1861,7 +1867,7 @@ Output_section_definition::finalize_symbols(Symbol_table* symtab, Output_section* dummy; address = this->address_->eval_with_dot(symtab, layout, true, *dot_value, NULL, - &dummy); + &dummy, NULL); } if (this->align_ != NULL) { @@ -1869,7 +1875,7 @@ Output_section_definition::finalize_symbols(Symbol_table* symtab, uint64_t align = this->align_->eval_with_dot(symtab, layout, true, *dot_value, NULL, - &dummy); + &dummy, NULL); address = align_address(address, align); } *dot_value = address; @@ -1918,6 +1924,7 @@ void Output_section_definition::set_section_addresses(Symbol_table* symtab, Layout* layout, uint64_t* dot_value, + uint64_t* dot_alignment, uint64_t* load_address) { uint64_t address; @@ -1930,7 +1937,8 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, { Output_section* dummy; address = this->address_->eval_with_dot(symtab, layout, true, - *dot_value, NULL, &dummy); + *dot_value, NULL, &dummy, + dot_alignment); } uint64_t align; @@ -1945,7 +1953,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, { Output_section* align_section; align = this->align_->eval_with_dot(symtab, layout, true, *dot_value, - NULL, &align_section); + NULL, &align_section, NULL); if (align_section != NULL) gold_warning(_("alignment of section %s is not absolute"), this->name_.c_str()); @@ -1976,7 +1984,8 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, Output_section* dummy; uint64_t laddr = this->load_address_->eval_with_dot(symtab, layout, true, *dot_value, - this->output_section_, &dummy); + this->output_section_, &dummy, + NULL); if (this->output_section_ != NULL) this->output_section_->set_load_address(laddr); this->evaluated_load_address_ = laddr; @@ -1990,7 +1999,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, Output_section* subalign_section; subalign = this->subalign_->eval_with_dot(symtab, layout, true, *dot_value, NULL, - &subalign_section); + &subalign_section, NULL); if (subalign_section != NULL) gold_warning(_("subalign of section %s is not absolute"), this->name_.c_str()); @@ -2004,8 +2013,8 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, Output_section* fill_section; uint64_t fill_val = this->fill_->eval_with_dot(symtab, layout, true, *dot_value, - NULL, - &fill_section); + NULL, &fill_section, + NULL); if (fill_section != NULL) gold_warning(_("fill of section %s is not absolute"), this->name_.c_str()); @@ -2031,8 +2040,8 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, p != this->elements_.end(); ++p) (*p)->set_section_addresses(symtab, layout, this->output_section_, - subalign, dot_value, &dot_section, &fill, - &input_sections); + subalign, dot_value, dot_alignment, + &dot_section, &fill, &input_sections); gold_assert(input_sections.empty()); @@ -2339,7 +2348,8 @@ class Orphan_output_section : public Sections_element // Set section addresses. void - set_section_addresses(Symbol_table*, Layout*, uint64_t*, uint64_t*); + set_section_addresses(Symbol_table*, Layout*, uint64_t*, uint64_t*, + uint64_t*); // Get the list of segments to use for an allocated section when // using a PHDRS clause. @@ -2368,6 +2378,7 @@ class Orphan_output_section : public Sections_element void Orphan_output_section::set_section_addresses(Symbol_table*, Layout*, uint64_t* dot_value, + uint64_t*, uint64_t* load_address) { typedef std::list Input_section_list; @@ -2950,6 +2961,7 @@ Script_sections::set_section_addresses(Symbol_table* symtab, Layout* layout) // For a relocatable link, we implicitly set dot to zero. uint64_t dot_value = 0; + uint64_t dot_alignment = 0; uint64_t load_address = 0; // Check to see if we want to use any of -Ttext, -Tdata and -Tbss options @@ -2995,7 +3007,8 @@ Script_sections::set_section_addresses(Symbol_table* symtab, Layout* layout) } } - (*p)->set_section_addresses(symtab, layout, &dot_value, &load_address); + (*p)->set_section_addresses(symtab, layout, &dot_value, &dot_alignment, + &load_address); } if (this->phdrs_elements_ != NULL) @@ -3006,7 +3019,7 @@ Script_sections::set_section_addresses(Symbol_table* symtab, Layout* layout) (*p)->eval_load_address(symtab, layout); } - return this->create_segments(layout); + return this->create_segments(layout, dot_alignment); } // Sort the sections in order to put them into segments. @@ -3114,7 +3127,7 @@ Script_sections::header_size_adjustment(uint64_t lma, // if any. Output_segment* -Script_sections::create_segments(Layout* layout) +Script_sections::create_segments(Layout* layout, uint64_t dot_alignment) { gold_assert(this->saw_sections_clause_); @@ -3122,7 +3135,7 @@ Script_sections::create_segments(Layout* layout) return NULL; if (this->saw_phdrs_clause()) - return create_segments_from_phdrs_clause(layout); + return create_segments_from_phdrs_clause(layout, dot_alignment); Layout::Section_list sections; layout->get_allocated_sections(§ions); @@ -3195,6 +3208,7 @@ Script_sections::create_segments(Layout* layout) current_seg = layout->make_output_segment(elfcpp::PT_LOAD, seg_flags); current_seg->set_addresses(vma, lma); + current_seg->set_minimum_p_align(dot_alignment); if (first_seg == NULL) first_seg = current_seg; is_current_seg_readonly = true; @@ -3388,10 +3402,11 @@ Script_sections::expected_segment_count(const Layout* layout) const // should hold the file header and program headers, if any. Output_segment* -Script_sections::create_segments_from_phdrs_clause(Layout* layout) +Script_sections::create_segments_from_phdrs_clause(Layout* layout, + uint64_t dot_alignment) { this->attach_sections_using_phdrs_clause(layout); - return this->set_phdrs_clause_addresses(layout); + return this->set_phdrs_clause_addresses(layout, dot_alignment); } // Create the segments from the PHDRS clause, and put the output @@ -3485,7 +3500,8 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout) // if any. Output_segment* -Script_sections::set_phdrs_clause_addresses(Layout* layout) +Script_sections::set_phdrs_clause_addresses(Layout* layout, + uint64_t dot_alignment) { Output_segment* load_seg = NULL; for (Phdrs_elements::const_iterator p = this->phdrs_elements_->begin(); @@ -3508,6 +3524,8 @@ Script_sections::set_phdrs_clause_addresses(Layout* layout) continue; } + oseg->set_minimum_p_align(dot_alignment); + // The output sections should have addresses from the SECTIONS // clause. The addresses don't have to be in order, so find the // one with the lowest load address. Use that to set the diff --git a/gold/script-sections.h b/gold/script-sections.h index 725d1a2ecca..f18b06c7d13 100644 --- a/gold/script-sections.h +++ b/gold/script-sections.h @@ -232,7 +232,7 @@ class Script_sections // Create segments. Output_segment* - create_segments(Layout*); + create_segments(Layout*, uint64_t); // Create PT_NOTE and PT_TLS segments. void @@ -253,7 +253,7 @@ class Script_sections // Create the segments from a PHDRS clause. Output_segment* - create_segments_from_phdrs_clause(Layout* layout); + create_segments_from_phdrs_clause(Layout* layout, uint64_t); // Attach sections to segments from a PHDRS clause. void @@ -261,7 +261,7 @@ class Script_sections // Set addresses of segments from a PHDRS clause. Output_segment* - set_phdrs_clause_addresses(Layout*); + set_phdrs_clause_addresses(Layout*, uint64_t); // True if we ever saw a SECTIONS clause. bool saw_sections_clause_; diff --git a/gold/script.cc b/gold/script.cc index 11e4612905c..a68fb3865a0 100644 --- a/gold/script.cc +++ b/gold/script.cc @@ -955,7 +955,7 @@ Symbol_assignment::sized_finalize(Symbol_table* symtab, const Layout* layout, uint64_t final_val = this->val_->eval_maybe_dot(symtab, layout, true, is_dot_available, dot_value, dot_section, - §ion); + §ion, NULL); Sized_symbol* ssym = symtab->get_sized_symbol(this->sym_); ssym->set_value(final_val); if (section != NULL) @@ -974,7 +974,7 @@ Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout, Output_section* val_section; uint64_t val = this->val_->eval_maybe_dot(symtab, layout, false, is_dot_available, dot_value, - NULL, &val_section); + NULL, &val_section, NULL); if (val_section != NULL) return; diff --git a/gold/script.h b/gold/script.h index f4c3f22620b..3b8cb92f1c8 100644 --- a/gold/script.h +++ b/gold/script.h @@ -86,11 +86,14 @@ class Expression // value is defined. If the value is absolute *RESULT_SECTION will // be NULL. Note that the returned value is still an absolute // value; to get a section relative value the caller must subtract - // the section address. + // the section address. If RESULT_ALIGNMENT is not NULL, this sets + // *RESULT_ALIGNMENT to the alignment of the value of that alignment + // is larger than *RESULT_ALIGNMENT; this will only be non-zero if + // this is an ALIGN expression. uint64_t eval_with_dot(const Symbol_table*, const Layout*, bool check_assertions, uint64_t dot_value, Output_section* dot_section, - Output_section** result_section); + Output_section** result_section, uint64_t* result_alignment); // Return the value of an expression which may or may not be // permitted to refer to the dot symbol, depending on @@ -99,7 +102,7 @@ class Expression eval_maybe_dot(const Symbol_table*, const Layout*, bool check_assertions, bool is_dot_available, uint64_t dot_value, Output_section* dot_section, - Output_section** result_section); + Output_section** result_section, uint64_t* result_alignment); // Print the expression to the FILE. This is for debugging. virtual void diff --git a/gold/testsuite/script_test_3.sh b/gold/testsuite/script_test_3.sh index cddb69accfd..d114edd1807 100755 --- a/gold/testsuite/script_test_3.sh +++ b/gold/testsuite/script_test_3.sh @@ -85,4 +85,18 @@ if test "$section_size" != "$segment_size"; then exit 1 fi +# At least one PT_LOAD segment should have an alignment >= 0x100000. +found=no +for a in `grep LOAD script_test_3.stdout | sed -e 's/^.* 0x/0x/'`; do + script="BEGIN { if ($a >= 0x100000) { print \"true\" } else { print \"false\" } }" + x=`awk "$script" < /dev/null` + if test "$x" = "true"; then + found=yes + fi +done +if test "$found" = "no"; then + echo "no LOAD segment has required alignment" + exit 1 +fi + exit 0 diff --git a/gold/testsuite/script_test_3.t b/gold/testsuite/script_test_3.t index a6a655f7e72..75d81305101 100644 --- a/gold/testsuite/script_test_3.t +++ b/gold/testsuite/script_test_3.t @@ -35,7 +35,7 @@ SECTIONS .tdata : { *(.tdata*) } :data :tls .tbss : { *(.tbss*) } :data :tls . += 0x100000; - . = ALIGN(0x100); + . = ALIGN(0x100000); .bss : { *(.bss) } :bss } -- 2.30.2