aboutsummaryrefslogtreecommitdiff
path: root/ld/ldexp.c
diff options
context:
space:
mode:
Diffstat (limited to 'ld/ldexp.c')
-rw-r--r--ld/ldexp.c275
1 files changed, 137 insertions, 138 deletions
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 08664e6..e888c95 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -282,6 +282,7 @@ fold_unary (etree_type *tree)
static void
fold_binary (etree_type *tree)
{
+ etree_value_type lhs;
exp_fold_tree_1 (tree->binary.lhs);
/* The SEGMENT_START operator is special because its first
@@ -304,169 +305,167 @@ fold_binary (etree_type *tree)
expld.result.section = expld.section;
break;
}
+ return;
}
- else if (expld.result.valid_p)
- {
- etree_value_type lhs = expld.result;
- exp_fold_tree_1 (tree->binary.rhs);
- if (expld.result.valid_p)
+ lhs = expld.result;
+ exp_fold_tree_1 (tree->binary.rhs);
+ expld.result.valid_p &= lhs.valid_p;
+
+ if (expld.result.valid_p)
+ {
+ /* If the values are from different sections, or this is an
+ absolute expression, make both the source arguments
+ absolute. However, adding or subtracting an absolute
+ value from a relative value is meaningful, and is an
+ exception. */
+ if (expld.section != bfd_abs_section_ptr
+ && lhs.section == bfd_abs_section_ptr
+ && tree->type.node_code == '+')
{
- /* If the values are from different sections, or this is an
- absolute expression, make both the source arguments
- absolute. However, adding or subtracting an absolute
- value from a relative value is meaningful, and is an
- exception. */
- if (expld.section != bfd_abs_section_ptr
- && lhs.section == bfd_abs_section_ptr
- && tree->type.node_code == '+')
- {
- /* Keep the section of the rhs term. */
- expld.result.value = lhs.value + expld.result.value;
- return;
- }
- else if (expld.section != bfd_abs_section_ptr
- && expld.result.section == bfd_abs_section_ptr
- && (tree->type.node_code == '+'
- || tree->type.node_code == '-'))
- {
- /* Keep the section of the lhs term. */
- expld.result.section = lhs.section;
- }
- else if (expld.result.section != lhs.section
- || expld.section == bfd_abs_section_ptr)
- {
- make_abs ();
- lhs.value += lhs.section->vma;
- }
+ /* Keep the section of the rhs term. */
+ expld.result.value = lhs.value + expld.result.value;
+ return;
+ }
+ else if (expld.section != bfd_abs_section_ptr
+ && expld.result.section == bfd_abs_section_ptr
+ && (tree->type.node_code == '+'
+ || tree->type.node_code == '-'))
+ {
+ /* Keep the section of the lhs term. */
+ expld.result.section = lhs.section;
+ }
+ else if (expld.result.section != lhs.section
+ || expld.section == bfd_abs_section_ptr)
+ {
+ make_abs ();
+ lhs.value += lhs.section->vma;
+ }
- switch (tree->type.node_code)
- {
- case '%':
- if (expld.result.value != 0)
- expld.result.value = ((bfd_signed_vma) lhs.value
- % (bfd_signed_vma) expld.result.value);
- else if (expld.phase != lang_mark_phase_enum)
- einfo (_("%F%S %% by zero\n"));
- break;
+ switch (tree->type.node_code)
+ {
+ case '%':
+ if (expld.result.value != 0)
+ expld.result.value = ((bfd_signed_vma) lhs.value
+ % (bfd_signed_vma) expld.result.value);
+ else if (expld.phase != lang_mark_phase_enum)
+ einfo (_("%F%S %% by zero\n"));
+ break;
- case '/':
- if (expld.result.value != 0)
- expld.result.value = ((bfd_signed_vma) lhs.value
- / (bfd_signed_vma) expld.result.value);
- else if (expld.phase != lang_mark_phase_enum)
- einfo (_("%F%S / by zero\n"));
- break;
+ case '/':
+ if (expld.result.value != 0)
+ expld.result.value = ((bfd_signed_vma) lhs.value
+ / (bfd_signed_vma) expld.result.value);
+ else if (expld.phase != lang_mark_phase_enum)
+ einfo (_("%F%S / by zero\n"));
+ break;
#define BOP(x, y) \
case x: \
expld.result.value = lhs.value y expld.result.value; \
break;
- BOP ('+', +);
- BOP ('*', *);
- BOP ('-', -);
- BOP (LSHIFT, <<);
- BOP (RSHIFT, >>);
- BOP (EQ, ==);
- BOP (NE, !=);
- BOP ('<', <);
- BOP ('>', >);
- BOP (LE, <=);
- BOP (GE, >=);
- BOP ('&', &);
- BOP ('^', ^);
- BOP ('|', |);
- BOP (ANDAND, &&);
- BOP (OROR, ||);
-
- case MAX_K:
- if (lhs.value > expld.result.value)
- expld.result.value = lhs.value;
- break;
+ BOP ('+', +);
+ BOP ('*', *);
+ BOP ('-', -);
+ BOP (LSHIFT, <<);
+ BOP (RSHIFT, >>);
+ BOP (EQ, ==);
+ BOP (NE, !=);
+ BOP ('<', <);
+ BOP ('>', >);
+ BOP (LE, <=);
+ BOP (GE, >=);
+ BOP ('&', &);
+ BOP ('^', ^);
+ BOP ('|', |);
+ BOP (ANDAND, &&);
+ BOP (OROR, ||);
+
+ case MAX_K:
+ if (lhs.value > expld.result.value)
+ expld.result.value = lhs.value;
+ break;
- case MIN_K:
- if (lhs.value < expld.result.value)
- expld.result.value = lhs.value;
- break;
+ case MIN_K:
+ if (lhs.value < expld.result.value)
+ expld.result.value = lhs.value;
+ break;
- case ALIGN_K:
- expld.result.value = align_n (lhs.value, expld.result.value);
- break;
+ case ALIGN_K:
+ expld.result.value = align_n (lhs.value, expld.result.value);
+ break;
- case DATA_SEGMENT_ALIGN:
- expld.dataseg.relro = exp_dataseg_relro_start;
- if (expld.phase != lang_first_phase_enum
- && expld.section == bfd_abs_section_ptr
- && (expld.dataseg.phase == exp_dataseg_none
- || expld.dataseg.phase == exp_dataseg_adjust
- || expld.dataseg.phase == exp_dataseg_relro_adjust
- || expld.phase == lang_final_phase_enum))
- {
- bfd_vma maxpage = lhs.value;
- bfd_vma commonpage = expld.result.value;
+ case DATA_SEGMENT_ALIGN:
+ expld.dataseg.relro = exp_dataseg_relro_start;
+ if (expld.phase != lang_first_phase_enum
+ && expld.section == bfd_abs_section_ptr
+ && (expld.dataseg.phase == exp_dataseg_none
+ || expld.dataseg.phase == exp_dataseg_adjust
+ || expld.dataseg.phase == exp_dataseg_relro_adjust
+ || expld.phase == lang_final_phase_enum))
+ {
+ bfd_vma maxpage = lhs.value;
+ bfd_vma commonpage = expld.result.value;
- expld.result.value = align_n (expld.dot, maxpage);
- if (expld.dataseg.phase == exp_dataseg_relro_adjust)
- expld.result.value = expld.dataseg.base;
- else if (expld.dataseg.phase != exp_dataseg_adjust)
+ expld.result.value = align_n (expld.dot, maxpage);
+ if (expld.dataseg.phase == exp_dataseg_relro_adjust)
+ expld.result.value = expld.dataseg.base;
+ else if (expld.dataseg.phase != exp_dataseg_adjust)
+ {
+ expld.result.value += expld.dot & (maxpage - 1);
+ if (expld.phase == lang_allocating_phase_enum)
{
- expld.result.value += expld.dot & (maxpage - 1);
- if (expld.phase == lang_allocating_phase_enum)
- {
- expld.dataseg.phase = exp_dataseg_align_seen;
- expld.dataseg.min_base = expld.dot;
- expld.dataseg.base = expld.result.value;
- expld.dataseg.pagesize = commonpage;
- expld.dataseg.maxpagesize = maxpage;
- expld.dataseg.relro_end = 0;
- }
+ expld.dataseg.phase = exp_dataseg_align_seen;
+ expld.dataseg.min_base = expld.dot;
+ expld.dataseg.base = expld.result.value;
+ expld.dataseg.pagesize = commonpage;
+ expld.dataseg.maxpagesize = maxpage;
+ expld.dataseg.relro_end = 0;
}
- else if (commonpage < maxpage)
- expld.result.value += ((expld.dot + commonpage - 1)
- & (maxpage - commonpage));
}
- else
- expld.result.valid_p = FALSE;
- break;
-
- case DATA_SEGMENT_RELRO_END:
- expld.dataseg.relro = exp_dataseg_relro_end;
- if (expld.phase != lang_first_phase_enum
- && (expld.dataseg.phase == exp_dataseg_align_seen
- || expld.dataseg.phase == exp_dataseg_adjust
- || expld.dataseg.phase == exp_dataseg_relro_adjust
- || expld.phase == lang_final_phase_enum))
- {
- if (expld.dataseg.phase == exp_dataseg_align_seen
- || expld.dataseg.phase == exp_dataseg_relro_adjust)
- expld.dataseg.relro_end = lhs.value + expld.result.value;
+ else if (commonpage < maxpage)
+ expld.result.value += ((expld.dot + commonpage - 1)
+ & (maxpage - commonpage));
+ }
+ else
+ expld.result.valid_p = FALSE;
+ break;
- if (expld.dataseg.phase == exp_dataseg_relro_adjust
- && (expld.dataseg.relro_end
- & (expld.dataseg.pagesize - 1)))
- {
- expld.dataseg.relro_end += expld.dataseg.pagesize - 1;
- expld.dataseg.relro_end &= ~(expld.dataseg.pagesize - 1);
- expld.result.value = (expld.dataseg.relro_end
- - expld.result.value);
- }
- else
- expld.result.value = lhs.value;
+ case DATA_SEGMENT_RELRO_END:
+ expld.dataseg.relro = exp_dataseg_relro_end;
+ if (expld.phase != lang_first_phase_enum
+ && (expld.dataseg.phase == exp_dataseg_align_seen
+ || expld.dataseg.phase == exp_dataseg_adjust
+ || expld.dataseg.phase == exp_dataseg_relro_adjust
+ || expld.phase == lang_final_phase_enum))
+ {
+ if (expld.dataseg.phase == exp_dataseg_align_seen
+ || expld.dataseg.phase == exp_dataseg_relro_adjust)
+ expld.dataseg.relro_end = lhs.value + expld.result.value;
- if (expld.dataseg.phase == exp_dataseg_align_seen)
- expld.dataseg.phase = exp_dataseg_relro_seen;
+ if (expld.dataseg.phase == exp_dataseg_relro_adjust
+ && (expld.dataseg.relro_end
+ & (expld.dataseg.pagesize - 1)))
+ {
+ expld.dataseg.relro_end += expld.dataseg.pagesize - 1;
+ expld.dataseg.relro_end &= ~(expld.dataseg.pagesize - 1);
+ expld.result.value = (expld.dataseg.relro_end
+ - expld.result.value);
}
else
- expld.result.valid_p = FALSE;
- break;
+ expld.result.value = lhs.value;
- default:
- FAIL ();
+ if (expld.dataseg.phase == exp_dataseg_align_seen)
+ expld.dataseg.phase = exp_dataseg_relro_seen;
}
+ else
+ expld.result.valid_p = FALSE;
+ break;
+
+ default:
+ FAIL ();
}
- else
- expld.result.valid_p = FALSE;
}
}