+2014-01-22 Alan Modra <amodra@gmail.com>
+
+ * ld.texinfo (Output Section Discarding): Mention assigning to dot
+ as a way of keeping otherwise empty sections.
+ * ldexp.c (is_dot, is_value, is_sym_value, is_dot_ne_0,
+ is_dot_plus_0, is_align_conditional): New predicates.
+ (exp_fold_tree_1): Set SEC_KEEP when assigning to dot inside an
+ output section, except for some special cases.
+ * scripttempl/elfmicroblaze.sc: Use canonical form to align at
+ end of .heap and .stack.
+
2014-01-20 Marcus Shawcroft <marcus.shawcroft@arm.com>
* emulparams/aarch64linuxb.sh (ELF_INTERPRETER_NAME): Define.
@cindex discarding sections
@cindex sections, discarding
@cindex removing sections
-The linker will not create output sections with no contents. This is
-for convenience when referring to input sections that may or may not
-be present in any of the input files. For example:
+The linker will not normally create output sections with no contents.
+This is for convenience when referring to input sections that may or
+may not be present in any of the input files. For example:
@smallexample
.foo : @{ *(.foo) @}
@end smallexample
will only create a @samp{.foo} section in the output file if there is a
@samp{.foo} section in at least one input file, and if the input
sections are not all empty. Other link script directives that allocate
-space in an output section will also create the output section.
+space in an output section will also create the output section. So
+too will assignments to dot even if the assignment does not create
+space, except for @samp{. = 0}, @samp{. = . + 0}, @samp{. = sym},
+@samp{. = . + sym} and @samp{. = ALIGN (. != 0, expr, 1)} when
+@samp{sym} is an absolute symbol of value 0 defined in the script.
+This allows you to force output of an empty section with @samp{. = .}.
The linker will ignore address assignments (@pxref{Output Section Address})
on discarded output sections, except when the linker script defines
}
}
+/* Return true if TREE is '.'. */
+
+static bfd_boolean
+is_dot (const etree_type *tree)
+{
+ return (tree->type.node_class == etree_name
+ && tree->type.node_code == NAME
+ && tree->name.name[0] == '.'
+ && tree->name.name[1] == 0);
+}
+
+/* Return true if TREE is a constant equal to VAL. */
+
+static bfd_boolean
+is_value (const etree_type *tree, bfd_vma val)
+{
+ return (tree->type.node_class == etree_value
+ && tree->value.value == val);
+}
+
+/* Return true if TREE is an absolute symbol equal to VAL defined in
+ a linker script. */
+
+static bfd_boolean
+is_sym_value (const etree_type *tree, bfd_vma val)
+{
+ struct bfd_link_hash_entry *h;
+ struct lang_definedness_hash_entry *def;
+
+ return (tree->type.node_class == etree_name
+ && tree->type.node_code == NAME
+ && (def = lang_symbol_defined (tree->name.name)) != NULL
+ && def->by_script
+ && def->iteration == (lang_statement_iteration & 1)
+ && (h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
+ &link_info,
+ tree->name.name,
+ FALSE, FALSE, TRUE)) != NULL
+ && h->type == bfd_link_hash_defined
+ && h->u.def.section == bfd_abs_section_ptr
+ && h->u.def.value == val);
+}
+
+/* Return true if TREE is ". != 0". */
+
+static bfd_boolean
+is_dot_ne_0 (const etree_type *tree)
+{
+ return (tree->type.node_class == etree_binary
+ && tree->type.node_code == NE
+ && is_dot (tree->binary.lhs)
+ && is_value (tree->binary.rhs, 0));
+}
+
+/* Return true if TREE is ". = . + 0" or ". = . + sym" where sym is an
+ absolute constant with value 0 defined in a linker script. */
+
+static bfd_boolean
+is_dot_plus_0 (const etree_type *tree)
+{
+ return (tree->type.node_class == etree_binary
+ && tree->type.node_code == '+'
+ && is_dot (tree->binary.lhs)
+ && (is_value (tree->binary.rhs, 0)
+ || is_sym_value (tree->binary.rhs, 0)));
+}
+
+/* Return true if TREE is "ALIGN (. != 0 ? some_expression : 1)". */
+
+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;
+}
+
static void
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)
${RELOCATING+*(.bss.*)}
${RELOCATING+*(.gnu.linkonce.b.*)}
${RELOCATING+*(COMMON)}
- ${RELOCATING+. = ALIGN(4);}
+ ${RELOCATING+. = ALIGN(. != 0 ? 4 : 1);}
${RELOCATING+PROVIDE (__bss_end = .);}
.stack : {
${RELOCATING+ _stack_end = .;}
${RELOCATING+ . += _STACK_SIZE;}
- ${RELOCATING+ . = ALIGN(8);}
+ ${RELOCATING+ . = ALIGN(. != 0 ? 8 : 1);}
${RELOCATING+ _stack = .;}
${RELOCATING+ _end = .;}
}
+2014-01-22 Alan Modra <amodra@gmail.com>
+
+ * ld-shared/elf-offset.ld: Align end of .bss with canonical form
+ of ALIGN that allows an empty .bss to be removed.
+ * ld-arm/arm-dyn.ld: Likewise.
+ * ld-arm/arm-lib.ld: Likewise.
+ * ld-elfvsb/elf-offset.ld: Likewise.
+ * ld-mips-elf/mips-dyn.ld: Likewise.
+ * ld-mips-elf/mips-lib.ld: Likewise.
+ * ld-arm/arm-no-rel-plt.ld: Remove duplicate ALIGN.
+ * ld-powerpc/vle-multiseg-1.ld: Remove ALIGN at start of section.
+ ALIGN address of section instead.
+ * ld-powerpc/vle-multiseg-2.ld: Likewise.
+ * ld-powerpc/vle-multiseg-3.ld: Likewise.
+ * ld-powerpc/vle-multiseg-4.ld: Likewise.
+ * ld-powerpc/vle-multiseg-6.ld: Likewise.
+ * ld-scripts/empty-aligned.d: Check section headers not program
+ headers. Remove xfail and notarget.
+ * ld-scripts/empty-aligned.t: Use canonical ALIGN for end of .text2.
+
2014-01-21 H.J. Lu <hongjiu.lu@intel.com>
PR ld/16467
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
- . = ALIGN(32 / 8);
+ . = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
_end = .;
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
- . = ALIGN(32 / 8);
+ . = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
_end = .;
}
_bss_end__ = . ; __bss_end__ = . ;
. = ALIGN(32 / 8);
- . = ALIGN(32 / 8);
__end__ = . ;
_end = .; PROVIDE (end = .);
/* Stabs debugging sections. */
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
- . = ALIGN(32 / 8);
+ . = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
_end = . ;
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
- . = ALIGN(32 / 8);
+ . = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
_end = .;
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
- . = ALIGN(32 / 8);
+ . = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
_end = .;
{ *(.data) *(.ctors) *(.dtors) *(.eh_frame) *(.jcr) }
.text_vle 0x00001000 :
{
- . = ALIGN(16);
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.text_vle)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.text)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.init)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.fini)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.fini_vle)
}
- .text_iv . : { . = ALIGN(16); *(.text_iv) }
+ .text_iv ALIGN(16) : { *(.text_iv) }
.iv_handlers 0x0001F000 : { *(.iv_handlers) }
}
{
.text_vle 0x00001000 :
{
- . = ALIGN(16);
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.text_vle)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.text)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.init)
}
.data 0x00001400 :
{ *(.data) *(.ctors) *(.dtors) *(.eh_frame) *(.jcr) }
- .text_iv . : { . = ALIGN(16); *(.text_iv) }
+ .text_iv ALIGN(16) : { *(.text_iv) }
.iv_handlers 0x0001F000 : { *(.iv_handlers) }
}
{
.text_vle 0x00001000 :
{
- . = ALIGN(16);
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.text_vle)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.text)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.init)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.fini)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.fini_vle)
}
- .text_iv . : { . = ALIGN(16); *(.text_iv) }
+ .text_iv ALIGN(16) : { *(.text_iv) }
.data 0x00001400 :
{ *(.data) *(.ctors) *(.dtors) *(.eh_frame) *(.jcr) }
.iv_handlers 0x0001F000 : { *(.iv_handlers) }
{
.text_vle 0x00001000 :
{
- . = ALIGN(16);
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.text_vle)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.text)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.init)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.fini)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.fini_vle)
}
- .text_iv . : { . = ALIGN(16); *(.text_iv) }
+ .text_iv ALIGN(16) : { *(.text_iv) }
.iv_handlers 0x0001F000 : { *(.iv_handlers) }
.data 0x00020400 :
{ *(.data) *(.ctors) *(.dtors) *(.eh_frame) *(.jcr) }
}
.text_vle 0x00001000 :
{
- . = ALIGN(16);
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.text*)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.init*)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.fini*)
.text_iv 0x100000 :
{
- . = ALIGN(16);
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.text_iv)
INPUT_SECTION_FLAGS (SHF_PPC_VLE) *(.iv_handlers)
} >vle_seg2
.text 0x101000 :
{
- . = ALIGN(16);
INPUT_SECTION_FLAGS (!SHF_PPC_VLE) *(.text*)
}
}
#source: empty-aligned.s
#ld: -T empty-aligned.t
-#readelf: -l --wide
-#xfail: "hppa64-*-*"
-#notarget: frv-*-*linux*
+#readelf: -S --wide
#...
-Program Headers:
- +Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg +Align
- +LOAD +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ [RWE ]+ +0x[0-9a-f]+
-! +LOAD .*
-#...
- +Segment Sections\.\.\.
- +00 +.text
+.* .text .*
+!.* .text[234] .*
+#pass
{
*(.text1)
}
- /* Same for alignment at beginning and end. */
+ /* Same for alignment at beginning and end, although we need to be
+ careful in the expression used to align. */
.text2 ALIGN (4096) :
{
*(.text2)
- . = ALIGN (4096);
+ . = ALIGN (. != 0 ? 4096 : 1);
}
- /* Same for alignment just at end, although we need to be careful in
- the expression used to align. */
+ /* Same for alignment just at end. */
.text3 :
{
*(.text3)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
- . = ALIGN(32 / 8);
+ . = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
_end = . ;