diff options
Diffstat (limited to 'ld/ldexp.c')
-rw-r--r-- | ld/ldexp.c | 80 |
1 files changed, 31 insertions, 49 deletions
@@ -257,14 +257,6 @@ new_rel_from_abs (bfd_vma value) expld.result.section = s; } -static void -align_dot_val (bfd_vma align) -{ - bfd_vma base = expld.section->vma; - - new_rel_from_abs (base + align_n (expld.dot - base, align)); -} - /* New-function for the definedness hash table. */ static struct bfd_hash_entry * @@ -343,7 +335,7 @@ fold_unary (etree_type *tree) { case ALIGN_K: if (expld.phase != lang_first_phase_enum) - align_dot_val (expld.result.value); + new_rel_from_abs (align_n (expld.dot, expld.result.value)); else expld.result.valid_p = FALSE; break; @@ -373,7 +365,7 @@ fold_unary (etree_type *tree) if (expld.phase != lang_first_phase_enum) { make_abs (); - align_dot_val (expld.result.value); + expld.result.value = align_n (expld.dot, expld.result.value); } else expld.result.valid_p = FALSE; @@ -951,28 +943,20 @@ is_dot_plus_0 (const etree_type *tree) || is_sym_value (tree->binary.rhs, 0))); } -/* Return true if TREE is "ALIGN (. != 0 ? some_expression : 1)", - or equivalent binary ALIGN expressions. */ +/* Return true if TREE is "ALIGN (. != 0 ? some_expression : 1)". */ static bfd_boolean is_align_conditional (const etree_type *tree) { - if (tree->type.node_code != ALIGN_K) - return 0; - else if (tree->type.node_class == etree_unary) - tree = tree->unary.child; - else if (tree->type.node_class == etree_binary - && (is_dot (tree->binary.lhs) - || (tree->binary.lhs->type.node_class == etree_unary - && tree->binary.lhs->type.node_code == ABSOLUTE - && is_dot (tree->binary.lhs->unary.child)))) - tree = tree->binary.rhs; - else - return 0; - - return (tree->type.node_class == etree_trinary - && is_dot_ne_0 (tree->trinary.cond) - && is_value (tree->trinary.rhs, 1)); + if (tree->type.node_class == etree_unary + && tree->type.node_code == ALIGN_K) + { + tree = tree->unary.child; + return (tree->type.node_class == etree_trinary + && is_dot_ne_0 (tree->trinary.cond) + && is_value (tree->trinary.rhs, 1)); + } + return 0; } static void @@ -1039,13 +1023,30 @@ exp_fold_tree_1 (etree_type *tree) exp_fold_tree_1 (tree->assign.src); expld.assigning_to_dot = FALSE; + /* If we are assigning to dot inside an output section + arrange to keep the section, except for certain + expressions that evaluate to zero. We ignore . = 0, + . = . + 0, and . = ALIGN (. != 0 ? expr : 1). + We can't ignore all expressions that evaluate to zero + because an otherwise empty section might have padding + added by an alignment expression that changes with + relaxation. Such a section might have zero size + before relaxation and so be stripped incorrectly. */ + if (expld.phase == lang_mark_phase_enum + && expld.section != bfd_abs_section_ptr + && !(expld.result.valid_p + && expld.result.value == 0 + && (is_value (tree->assign.src, 0) + || is_sym_value (tree->assign.src, 0) + || is_dot_plus_0 (tree->assign.src) + || is_align_conditional (tree->assign.src)))) + expld.section->flags |= SEC_KEEP; + if (!expld.result.valid_p) { if (expld.phase != lang_mark_phase_enum) einfo (_("%F%S invalid assignment to" " location counter\n"), tree); - else if (expld.section != bfd_abs_section_ptr) - expld.section->flags |= SEC_KEEP; } else if (expld.dotp == NULL) einfo (_("%F%S assignment to location counter" @@ -1065,25 +1066,6 @@ exp_fold_tree_1 (etree_type *tree) nextdot += expld.result.section->vma; else nextdot += expld.section->vma; - - /* If we are assigning to dot inside an output - section arrange to keep the section, except for - certain expressions that evaluate to zero. We - can't ignore all expressions that evaluate to - zero because an otherwise empty section might - have padding added by an alignment expression - that changes with relaxation. Such a section - might have zero size before relaxation and so be - stripped incorrectly. */ - if (expld.phase == lang_mark_phase_enum - && expld.section != bfd_abs_section_ptr - && !(nextdot == expld.section->vma - && (is_value (tree->assign.src, 0) - || is_sym_value (tree->assign.src, 0) - || is_dot_plus_0 (tree->assign.src) - || is_align_conditional (tree->assign.src)))) - expld.section->flags |= SEC_KEEP; - if (nextdot < expld.dot && expld.section != bfd_abs_section_ptr) einfo (_("%F%S cannot move location counter backwards" |