mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-24 02:24:46 +08:00
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:
parent
9634ed06a6
commit
286adcf4f8
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -49,7 +49,7 @@ SECTIONS
|
||||
/* This should match the remaining sections. */
|
||||
*(.gold_test)
|
||||
|
||||
. = . + 4;
|
||||
. = 60;
|
||||
start_data = .;
|
||||
BYTE(1)
|
||||
SHORT(2)
|
||||
|
Loading…
Reference in New Issue
Block a user