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.
This commit is contained in:
Cary Coutant 2011-10-31 22:51:03 +00:00
parent 9634ed06a6
commit 286adcf4f8
6 changed files with 108 additions and 44 deletions

View File

@ -1,3 +1,28 @@
2011-10-31 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.
2011-10-31 Cary Coutant <ccoutant@google.com>
* options.h (class General_options): Add --[no-]gnu-unique options.

View File

@ -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

View File

@ -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());

View File

@ -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,
&section, NULL);
&section, 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);
}

View File

@ -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

View File

@ -49,7 +49,7 @@ SECTIONS
/* This should match the remaining sections. */
*(.gold_test)
. = . + 4;
. = 60;
start_data = .;
BYTE(1)
SHORT(2)