* ldexp.c (fold_binary): Evaluate rhs when lhs not valid.
This commit is contained in:
parent
121a04390c
commit
4ac0c89885
2 changed files with 145 additions and 142 deletions
|
@ -1,3 +1,7 @@
|
|||
2008-09-25 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* ldexp.c (fold_binary): Evaluate rhs when lhs not valid.
|
||||
|
||||
2008-09-11 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* configure.in: Call AC_SYS_LARGEFILE.
|
||||
|
|
283
ld/ldexp.c
283
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)
|
||||
|
||||
lhs = expld.result;
|
||||
exp_fold_tree_1 (tree->binary.rhs);
|
||||
expld.result.valid_p &= lhs.valid_p;
|
||||
|
||||
if (expld.result.valid_p)
|
||||
{
|
||||
etree_value_type lhs = expld.result;
|
||||
|
||||
exp_fold_tree_1 (tree->binary.rhs);
|
||||
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, ||);
|
||||
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 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))
|
||||
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)
|
||||
{
|
||||
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 += 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;
|
||||
|
||||
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;
|
||||
|
||||
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 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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue