aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/ChangeLog25
-rw-r--r--gold/expression.cc43
-rw-r--r--gold/script-sections.cc41
-rw-r--r--gold/script.cc17
-rw-r--r--gold/script.h24
-rw-r--r--gold/testsuite/script_test_2.t2
6 files changed, 108 insertions, 44 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index cc8aae0..a21b217 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,5 +1,30 @@
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.
* symtab.cc (Symbol_table::sized_write_globals): Convert
STB_GNU_UNIQUE to STB_GLOBAL if --no-gnu-unique.
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,
- &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);
}
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)