* 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.
This commit is contained in:
parent
496ddd4f6a
commit
f6973bdcb7
@ -1,3 +1,34 @@
|
||||
2010-04-22 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* 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 <nickc@redhat.com>
|
||||
|
||||
* po/gold.pot: Updated by the Translation project.
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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<true>(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<Output_section::Simple_input_section> 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
|
||||
|
@ -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_;
|
||||
|
@ -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<size>* ssym = symtab->get_sized_symbol<size>(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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -35,7 +35,7 @@ SECTIONS
|
||||
.tdata : { *(.tdata*) } :data :tls
|
||||
.tbss : { *(.tbss*) } :data :tls
|
||||
. += 0x100000;
|
||||
. = ALIGN(0x100);
|
||||
. = ALIGN(0x100000);
|
||||
.bss : { *(.bss) } :bss
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user