diff options
Diffstat (limited to 'ld/ldexp.c')
-rw-r--r-- | ld/ldexp.c | 275 |
1 files changed, 137 insertions, 138 deletions
@@ -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; } } |