aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog7
-rw-r--r--ld/ldexp.c63
-rw-r--r--ld/scripttempl/elf.sc4
3 files changed, 48 insertions, 26 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 3dd0a6f..ba6eded 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,10 @@
+2015-07-20 Alan Modra <amodra@gmail.com>
+
+ * scripttempl/elf.sc (.ldata, .bss): Align absolute value of dot.
+ * ldexp.c (is_align_conditional): Handle binary ALIGN.
+ (exp_fold_tree_1): Move code setting SEC_KEEP for assignments to
+ dot inside output sections. Handle absolute expressions.
+
2015-07-14 H.J. Lu <hongjiu.lu@intel.com>
* emultempl/elf32.em (gld${EMULATION_NAME}_handle_option): Make
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 2c0fe5a..f02f576 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -951,20 +951,28 @@ 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)". */
+/* Return true if TREE is "ALIGN (. != 0 ? some_expression : 1)",
+ or equivalent binary ALIGN expressions. */
static bfd_boolean
is_align_conditional (const etree_type *tree)
{
- 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;
+ 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));
}
static void
@@ -1031,25 +1039,13 @@ 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). */
- 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"
@@ -1069,6 +1065,25 @@ 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"
diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc
index c6dfe5d..5a15a68 100644
--- a/ld/scripttempl/elf.sc
+++ b/ld/scripttempl/elf.sc
@@ -240,7 +240,7 @@ test "${LARGE_SECTIONS}" = "yes" && LARGE_SECTIONS="
.ldata ${RELOCATING-0} ${RELOCATING+ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1))} :
{
*(.ldata${RELOCATING+ .ldata.* .gnu.linkonce.l.*})
- ${RELOCATING+. = ALIGN(. != 0 ? ${ALIGNMENT} : 1);}
+ ${RELOCATING+. = ALIGN (ABSOLUTE (.), . != 0 ? ${ALIGNMENT} : 1);}
}"
if test "${ENABLE_INITFINI_ARRAY}" = "yes"; then
SORT_INIT_ARRAY="KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))"
@@ -628,7 +628,7 @@ cat <<EOF
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we don't
pad the .data section. */
- ${RELOCATING+. = ALIGN(. != 0 ? ${ALIGNMENT} : 1);}
+ ${RELOCATING+. = ALIGN (ABSOLUTE (.), . != 0 ? ${ALIGNMENT} : 1);}
}
${OTHER_BSS_SECTIONS}
${LARGE_BSS_AFTER_BSS+${LARGE_BSS}}