summaryrefslogtreecommitdiff
path: root/gold/expression.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>2010-04-23 04:47:32 +0000
committerIan Lance Taylor <ian@airs.com>2010-04-23 04:47:32 +0000
commitc8cf97165d74ba9b3055ce5b02aca8e0dfc81819 (patch)
treecf991b21ef81d4a83eb879cb1ebaf119a5442f45 /gold/expression.cc
parent524b9b33c28905aa307836593d7557c4d4ea5da5 (diff)
downloadbinutils-redhat-c8cf97165d74ba9b3055ce5b02aca8e0dfc81819.tar.gz
* 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.
Diffstat (limited to 'gold/expression.cc')
-rw-r--r--gold/expression.cc118
1 files changed, 92 insertions, 26 deletions
diff --git a/gold/expression.cc b/gold/expression.cc
index 853a698d18..134b0fa2a2 100644
--- a/gold/expression.cc
+++ b/gold/expression.cc
@@ -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;