[gold patch] PR gold/13023: Fix problem with assignments to dot in linker scripts
Cary Coutant
ccoutant@google.com
Fri Oct 28 21:13:00 GMT 2011
More information about the Binutils mailing list
Fri Oct 28 21:13:00 GMT 2011
- Previous message (by thread): PATCH COMMITTED: Fix readelf --debug=frames-interp with DW_CFA_restore
- Next message (by thread): [gold patch] PR gold/13023: Fix problem with assignments to dot in linker scripts
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
PR 13023 complains about gold not handling assignments to dot correctly. If an absolute value is assigned to dot within an output section, the value should be treated as an offset relative to the start of the section. This patch fixes that, and also fixes a related problem where a dot-relative assignment to a symbol (e.g., "L0 = .") would produce an absolute symbol rather than a symbol defined in that section. I've added a flag to eval_maybe_dot() so that it knows whether we're assigning to the dot symbol in an output section, and adjusts absolute values appropriately. I also had to pass in dot_section to set_if_absolute() so that we can set the values for dot-relative symbols during the set_section_addresses phase along with actual absolute symbols. I've updated script_test_2 to test this case, and also verified that the test attached to the PR now works. Tested on x86_64. OK to commit? -cary PR gold/13023 * expression.cc (Expression::eval_with_dot): Add is_section_dot_assignment parameter. (Expression::eval_maybe_dot): Likewise. Adjust value when rhs is absolute and assigning to dot within a section. * script-sections.cc (Output_section_element_assignment::set_section_addresses): Pass dot_section to set_if_absolute. (Output_section_element_dot_assignment::finalize_symbols): Pass TRUE as is_section_dot_assignment flag to eval_with_dot. (Output_section_element_dot_assignment::set_section_addresses): Likewise. * script.cc (Symbol_assignment::set_if_absolute): Add dot_section parameter. Also set value if relative to dot_section; set the symbol's output_section. * script.h (Expression::eval_with_dot): Add is_section_dot_assignment parameter. Adjust all callers. (Expression::eval_maybe_dot): Likewise. (Symbol_assignment::set_if_absolute): Add dot_section parameter. Adjust all callers. * testsuite/script_test_2.t: Test assignment of an absolute value to dot within an output section element. -------------- next part -------------- 2011-10-28 Cary Coutant <ccoutant@google.com> PR gold/13023 * expression.cc (Expression::eval_with_dot): Add is_section_dot_assignment parameter. (Expression::eval_maybe_dot): Likewise. Adjust value when rhs is absolute and assigning to dot within a section. * script-sections.cc (Output_section_element_assignment::set_section_addresses): Pass dot_section to set_if_absolute. (Output_section_element_dot_assignment::finalize_symbols): Pass TRUE as is_section_dot_assignment flag to eval_with_dot. (Output_section_element_dot_assignment::set_section_addresses): Likewise. * script.cc (Symbol_assignment::set_if_absolute): Add dot_section parameter. Also set value if relative to dot_section; set the symbol's output_section. * script.h (Expression::eval_with_dot): Add is_section_dot_assignment parameter. Adjust all callers. (Expression::eval_maybe_dot): Likewise. (Symbol_assignment::set_if_absolute): Add dot_section parameter. Adjust all callers. * testsuite/script_test_2.t: Test assignment of an absolute value to dot within an output section element. commit 65ff8bb95ef1657037a19a7c7c71222b065694c7 Author: Cary Coutant <ccoutant@google.com> Date: Fri Oct 28 13:47:25 2011 -0700 Fix assignment to dot in scripts (PR 13023). diff --git a/gold/expression.cc b/gold/expression.cc index e527b5e..b611a68 100644 --- a/gold/expression.cc +++ b/gold/expression.cc @@ -77,7 +77,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); + false, 0, NULL, NULL, NULL, false); } // Evaluate an expression which may refer to the dot symbol. @@ -87,11 +87,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, + is_section_dot_assignment); } // Evaluate an expression which may or may not refer to the dot @@ -102,7 +104,8 @@ 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, + bool is_section_dot_assignment) { Expression_eval_info eei; eei.symtab = symtab; @@ -113,14 +116,24 @@ 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. + // if we find a section-relative reference. if (result_section_pointer != NULL) *result_section_pointer = NULL; eei.result_section_pointer = result_section_pointer; eei.result_alignment_pointer = result_alignment_pointer; - return this->value(&eei); + uint64_t val = this->value(&eei); + + // 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. @@ -257,7 +270,8 @@ class Unary_expression : public Expression eei->dot_value, eei->dot_section, arg_section_pointer, - eei->result_alignment_pointer); + eei->result_alignment_pointer, + false); } void @@ -336,7 +350,8 @@ class Binary_expression : public Expression eei->dot_value, eei->dot_section, section_pointer, - alignment_pointer); + alignment_pointer, + false); } uint64_t @@ -350,7 +365,8 @@ class Binary_expression : public Expression eei->dot_value, eei->dot_section, section_pointer, - alignment_pointer); + alignment_pointer, + false); } void @@ -500,7 +516,8 @@ class Trinary_expression : public Expression eei->dot_value, eei->dot_section, section_pointer, - NULL); + NULL, + false); } uint64_t @@ -514,7 +531,8 @@ class Trinary_expression : public Expression eei->dot_value, eei->dot_section, section_pointer, - alignment_pointer); + alignment_pointer, + false); } uint64_t @@ -528,7 +546,8 @@ class Trinary_expression : public Expression eei->dot_value, eei->dot_section, section_pointer, - alignment_pointer); + alignment_pointer, + false); } void diff --git a/gold/script-sections.cc b/gold/script-sections.cc index eba6b9d..f90c0b3 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -680,7 +680,7 @@ class Sections_element_assignment : public Sections_element set_section_addresses(Symbol_table* symtab, Layout* layout, uint64_t* dot_value, uint64_t*, uint64_t*) { - this->assignment_.set_if_absolute(symtab, layout, true, *dot_value); + this->assignment_.set_if_absolute(symtab, layout, true, *dot_value, NULL); } // Print for debugging. @@ -714,7 +714,7 @@ class Sections_element_dot_assignment : public Sections_element // output section definition the dot symbol is always considered // to be absolute. *dot_value = this->val_->eval_with_dot(symtab, layout, true, *dot_value, - NULL, NULL, NULL); + NULL, NULL, NULL, false); } // Update the dot symbol while setting section addresses. @@ -724,7 +724,7 @@ class Sections_element_dot_assignment : public Sections_element uint64_t* load_address) { *dot_value = this->val_->eval_with_dot(symtab, layout, false, *dot_value, - NULL, NULL, dot_alignment); + NULL, NULL, dot_alignment, false); *load_address = *dot_value; } @@ -866,9 +866,11 @@ class Output_section_element_assignment : public Output_section_element void set_section_addresses(Symbol_table* symtab, Layout* layout, Output_section*, uint64_t, uint64_t* dot_value, uint64_t*, - Output_section**, std::string*, Input_section_list*) + Output_section** dot_section, std::string*, + Input_section_list*) { - this->assignment_.set_if_absolute(symtab, layout, true, *dot_value); + this->assignment_.set_if_absolute(symtab, layout, true, *dot_value, + *dot_section); } // Print for debugging. @@ -904,14 +906,16 @@ 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, NULL); + *dot_section, dot_section, NULL, + true); } // 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, uint64_t*, - Output_section**, std::string*, Input_section_list*); + Output_section** dot_section, std::string*, + Input_section_list*); // Print for debugging. void @@ -942,7 +946,8 @@ Output_section_element_dot_assignment::set_section_addresses( { uint64_t next_dot = this->val_->eval_with_dot(symtab, layout, false, *dot_value, *dot_section, - dot_section, dot_alignment); + dot_section, dot_alignment, + true); if (next_dot < *dot_value) gold_error(_("dot may not move backward")); if (next_dot > *dot_value && output_section != NULL) @@ -1043,7 +1048,8 @@ Output_data_expression::do_write_to_buffer(unsigned char* buf) { uint64_t val = this->val_->eval_with_dot(this->symtab_, this->layout_, true, this->dot_value_, - this->dot_section_, NULL, NULL); + this->dot_section_, NULL, NULL, + false); if (parameters->target().is_big_endian()) this->endian_write_to_buffer<true>(val, buf); @@ -1193,7 +1199,7 @@ class Output_section_element_fill : public Output_section_element Output_section* fill_section; uint64_t fill_val = this->val_->eval_with_dot(symtab, layout, false, *dot_value, *dot_section, - &fill_section, NULL); + &fill_section, NULL, false); if (fill_section != NULL) gold_warning(_("fill value is not absolute")); // FIXME: The GNU linker supports fill values of arbitrary length. @@ -2114,13 +2120,13 @@ Output_section_definition::finalize_symbols(Symbol_table* symtab, { address = this->address_->eval_with_dot(symtab, layout, true, *dot_value, NULL, - NULL, NULL); + NULL, NULL, false); } if (this->align_ != NULL) { uint64_t align = this->align_->eval_with_dot(symtab, layout, true, *dot_value, NULL, - NULL, NULL); + NULL, NULL, false); address = align_address(address, align); } *dot_value = address; @@ -2309,7 +2315,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, else address = this->address_->eval_with_dot(symtab, layout, true, *dot_value, NULL, NULL, - dot_alignment); + dot_alignment, false); uint64_t align; if (this->align_ == NULL) { @@ -2322,7 +2328,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); + NULL, &align_section, NULL, false); if (align_section != NULL) gold_warning(_("alignment of section %s is not absolute"), this->name_.c_str()); @@ -2407,7 +2413,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, laddr = this->load_address_->eval_with_dot(symtab, layout, true, *dot_value, this->output_section_, - NULL, NULL); + NULL, NULL, false); if (this->output_section_ != NULL) this->output_section_->set_load_address(laddr); } @@ -2422,7 +2428,8 @@ 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, NULL); + &subalign_section, NULL, + false); if (subalign_section != NULL) gold_warning(_("subalign of section %s is not absolute"), this->name_.c_str()); @@ -2437,7 +2444,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, uint64_t fill_val = this->fill_->eval_with_dot(symtab, layout, true, *dot_value, NULL, &fill_section, - NULL); + NULL, false); if (fill_section != NULL) gold_warning(_("fill of section %s is not absolute"), this->name_.c_str()); diff --git a/gold/script.cc b/gold/script.cc index 7df0c9e..b471cf9 100644 --- a/gold/script.cc +++ b/gold/script.cc @@ -983,18 +983,20 @@ 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, NULL); + §ion, NULL, false); Sized_symbol<size>* ssym = symtab->get_sized_symbol<size>(this->sym_); ssym->set_value(final_val); if (section != NULL) ssym->set_output_section(section); } -// Set the symbol value if the expression yields an absolute value. +// Set the symbol value if the expression yields an absolute value or +// a value relative to DOT_SECTION. void Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout, - bool is_dot_available, uint64_t dot_value) + bool is_dot_available, uint64_t dot_value, + Output_section* dot_section) { if (this->sym_ == NULL) return; @@ -1002,8 +1004,9 @@ 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); - if (val_section != NULL) + dot_section, &val_section, NULL, + false); + if (val_section != NULL && val_section != dot_section) return; if (parameters->target().get_size() == 32) @@ -1026,6 +1029,8 @@ Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout, } else gold_unreachable(); + if (val_section != NULL) + this->sym_->set_output_section(val_section); } // Print for debugging. @@ -1215,7 +1220,7 @@ Script_options::set_section_addresses(Symbol_table* symtab, Layout* layout) for (Symbol_assignments::iterator p = this->symbol_assignments_.begin(); p != this->symbol_assignments_.end(); ++p) - (*p)->set_if_absolute(symtab, layout, false, 0); + (*p)->set_if_absolute(symtab, layout, false, 0, NULL); return this->script_sections_.set_section_addresses(symtab, layout); } diff --git a/gold/script.h b/gold/script.h index 73079a4..f41f438 100644 --- a/gold/script.h +++ b/gold/script.h @@ -90,20 +90,28 @@ class Expression // 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. + // this is an ALIGN expression. If IS_SECTION_DOT_ASSIGMENT is true, + // we are evaluating an assignment to dot within an output section, + // and an absolute value should be interpreted as an offset within + // the section. 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, uint64_t* result_alignment); + Output_section** result_section, uint64_t* result_alignment, + bool is_section_dot_assignment); // Return the value of an expression which may or may not be // permitted to refer to the dot symbol, depending on - // is_dot_available. + // is_dot_available. If IS_SECTION_DOT_ASSIGMENT is true, + // we are evaluating an assignment to dot within an output section, + // and an absolute value should be interpreted as an offset within + // the section. uint64_t 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, uint64_t* result_alignment); + Output_section** result_section, uint64_t* result_alignment, + bool is_section_dot_assignment); // Print the expression to the FILE. This is for debugging. virtual void @@ -339,12 +347,12 @@ class Symbol_assignment finalize_with_dot(Symbol_table*, const Layout*, uint64_t dot_value, Output_section* dot_section); - // Set the symbol value, but only if the value is absolute. This is - // used while processing a SECTIONS clause. We assume that dot is - // an absolute value here. We do not check assertions. + // Set the symbol value, but only if the value is absolute or relative to + // DOT_SECTION. This is used while processing a SECTIONS clause. + // We assume that dot is an absolute value here. We do not check assertions. void set_if_absolute(Symbol_table*, const Layout*, bool is_dot_available, - uint64_t dot_value); + uint64_t dot_value, Output_section* dot_section); const std::string& name() const diff --git a/gold/testsuite/script_test_2.t b/gold/testsuite/script_test_2.t index 73d39df..6a0188f 100644 --- a/gold/testsuite/script_test_2.t +++ b/gold/testsuite/script_test_2.t @@ -49,7 +49,7 @@ SECTIONS /* This should match the remaining sections. */ *(.gold_test) - . = . + 4; + . = 60; start_data = .; BYTE(1) SHORT(2)
- Previous message (by thread): PATCH COMMITTED: Fix readelf --debug=frames-interp with DW_CFA_restore
- Next message (by thread): [gold patch] PR gold/13023: Fix problem with assignments to dot in linker scripts
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Binutils mailing list