aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
Diffstat (limited to 'ld')
-rw-r--r--ld/ChangeLog11
-rw-r--r--ld/ld.texinfo13
-rw-r--r--ld/ldexp.c97
-rw-r--r--ld/scripttempl/elfmicroblaze.sc4
-rw-r--r--ld/testsuite/ChangeLog20
-rw-r--r--ld/testsuite/ld-arm/arm-dyn.ld2
-rw-r--r--ld/testsuite/ld-arm/arm-lib.ld2
-rw-r--r--ld/testsuite/ld-arm/arm-no-rel-plt.ld1
-rw-r--r--ld/testsuite/ld-elfvsb/elf-offset.ld2
-rw-r--r--ld/testsuite/ld-mips-elf/mips-dyn.ld2
-rw-r--r--ld/testsuite/ld-mips-elf/mips-lib.ld2
-rw-r--r--ld/testsuite/ld-powerpc/vle-multiseg-1.ld3
-rw-r--r--ld/testsuite/ld-powerpc/vle-multiseg-2.ld3
-rw-r--r--ld/testsuite/ld-powerpc/vle-multiseg-3.ld3
-rw-r--r--ld/testsuite/ld-powerpc/vle-multiseg-4.ld3
-rw-r--r--ld/testsuite/ld-powerpc/vle-multiseg-6.ld3
-rw-r--r--ld/testsuite/ld-scripts/empty-aligned.d14
-rw-r--r--ld/testsuite/ld-scripts/empty-aligned.t8
-rw-r--r--ld/testsuite/ld-shared/elf-offset.ld2
19 files changed, 157 insertions, 38 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index b5071d9..3d73b06 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,14 @@
+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.
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index ae3d568..a8e5ea6 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -4406,9 +4406,9 @@ scripts.
@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
@@ -4416,7 +4416,12 @@ be present in any of the input files. For example:
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
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 9a529db..cc3be6d 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -790,6 +790,89 @@ fold_name (etree_type *tree)
}
}
+/* 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)
{
@@ -854,6 +937,20 @@ 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)
diff --git a/ld/scripttempl/elfmicroblaze.sc b/ld/scripttempl/elfmicroblaze.sc
index a54b891..8d2e6f2 100644
--- a/ld/scripttempl/elfmicroblaze.sc
+++ b/ld/scripttempl/elfmicroblaze.sc
@@ -183,7 +183,7 @@ SECTIONS
${RELOCATING+*(.bss.*)}
${RELOCATING+*(.gnu.linkonce.b.*)}
${RELOCATING+*(COMMON)}
- ${RELOCATING+. = ALIGN(4);}
+ ${RELOCATING+. = ALIGN(. != 0 ? 4 : 1);}
${RELOCATING+PROVIDE (__bss_end = .);}
@@ -203,7 +203,7 @@ SECTIONS
.stack : {
${RELOCATING+ _stack_end = .;}
${RELOCATING+ . += _STACK_SIZE;}
- ${RELOCATING+ . = ALIGN(8);}
+ ${RELOCATING+ . = ALIGN(. != 0 ? 8 : 1);}
${RELOCATING+ _stack = .;}
${RELOCATING+ _end = .;}
}
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index a092428..5fdf831 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,23 @@
+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
diff --git a/ld/testsuite/ld-arm/arm-dyn.ld b/ld/testsuite/ld-arm/arm-dyn.ld
index bef9a18..71cb4c9 100644
--- a/ld/testsuite/ld-arm/arm-dyn.ld
+++ b/ld/testsuite/ld-arm/arm-dyn.ld
@@ -149,7 +149,7 @@ 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 = .;
diff --git a/ld/testsuite/ld-arm/arm-lib.ld b/ld/testsuite/ld-arm/arm-lib.ld
index c9482c3..f158c23 100644
--- a/ld/testsuite/ld-arm/arm-lib.ld
+++ b/ld/testsuite/ld-arm/arm-lib.ld
@@ -141,7 +141,7 @@ 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 = .;
diff --git a/ld/testsuite/ld-arm/arm-no-rel-plt.ld b/ld/testsuite/ld-arm/arm-no-rel-plt.ld
index 439909c..d8e5c9d 100644
--- a/ld/testsuite/ld-arm/arm-no-rel-plt.ld
+++ b/ld/testsuite/ld-arm/arm-no-rel-plt.ld
@@ -181,7 +181,6 @@ SECTIONS
}
_bss_end__ = . ; __bss_end__ = . ;
. = ALIGN(32 / 8);
- . = ALIGN(32 / 8);
__end__ = . ;
_end = .; PROVIDE (end = .);
/* Stabs debugging sections. */
diff --git a/ld/testsuite/ld-elfvsb/elf-offset.ld b/ld/testsuite/ld-elfvsb/elf-offset.ld
index 7c64824..cd90bcc 100644
--- a/ld/testsuite/ld-elfvsb/elf-offset.ld
+++ b/ld/testsuite/ld-elfvsb/elf-offset.ld
@@ -131,7 +131,7 @@ 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 = . ;
diff --git a/ld/testsuite/ld-mips-elf/mips-dyn.ld b/ld/testsuite/ld-mips-elf/mips-dyn.ld
index e4f90d2..b931e1b 100644
--- a/ld/testsuite/ld-mips-elf/mips-dyn.ld
+++ b/ld/testsuite/ld-mips-elf/mips-dyn.ld
@@ -179,7 +179,7 @@ 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 = .;
diff --git a/ld/testsuite/ld-mips-elf/mips-lib.ld b/ld/testsuite/ld-mips-elf/mips-lib.ld
index 5073d9f..1d66c62 100644
--- a/ld/testsuite/ld-mips-elf/mips-lib.ld
+++ b/ld/testsuite/ld-mips-elf/mips-lib.ld
@@ -173,7 +173,7 @@ 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 = .;
diff --git a/ld/testsuite/ld-powerpc/vle-multiseg-1.ld b/ld/testsuite/ld-powerpc/vle-multiseg-1.ld
index f2ff319..3fe37b9 100644
--- a/ld/testsuite/ld-powerpc/vle-multiseg-1.ld
+++ b/ld/testsuite/ld-powerpc/vle-multiseg-1.ld
@@ -4,7 +4,6 @@ SECTIONS
{ *(.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)
@@ -12,6 +11,6 @@ SECTIONS
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) }
}
diff --git a/ld/testsuite/ld-powerpc/vle-multiseg-2.ld b/ld/testsuite/ld-powerpc/vle-multiseg-2.ld
index 2320b61..da9a79d 100644
--- a/ld/testsuite/ld-powerpc/vle-multiseg-2.ld
+++ b/ld/testsuite/ld-powerpc/vle-multiseg-2.ld
@@ -2,7 +2,6 @@ SECTIONS
{
.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)
@@ -12,6 +11,6 @@ SECTIONS
}
.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) }
}
diff --git a/ld/testsuite/ld-powerpc/vle-multiseg-3.ld b/ld/testsuite/ld-powerpc/vle-multiseg-3.ld
index 0ed2f44..cfb1d88 100644
--- a/ld/testsuite/ld-powerpc/vle-multiseg-3.ld
+++ b/ld/testsuite/ld-powerpc/vle-multiseg-3.ld
@@ -2,7 +2,6 @@ SECTIONS
{
.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)
@@ -10,7 +9,7 @@ SECTIONS
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) }
diff --git a/ld/testsuite/ld-powerpc/vle-multiseg-4.ld b/ld/testsuite/ld-powerpc/vle-multiseg-4.ld
index 503fe06..2130427 100644
--- a/ld/testsuite/ld-powerpc/vle-multiseg-4.ld
+++ b/ld/testsuite/ld-powerpc/vle-multiseg-4.ld
@@ -2,7 +2,6 @@ SECTIONS
{
.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)
@@ -10,7 +9,7 @@ SECTIONS
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) }
diff --git a/ld/testsuite/ld-powerpc/vle-multiseg-6.ld b/ld/testsuite/ld-powerpc/vle-multiseg-6.ld
index c8d88dd..2db76cc 100644
--- a/ld/testsuite/ld-powerpc/vle-multiseg-6.ld
+++ b/ld/testsuite/ld-powerpc/vle-multiseg-6.ld
@@ -16,7 +16,6 @@ SECTIONS
}
.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*)
@@ -24,14 +23,12 @@ SECTIONS
.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*)
}
}
diff --git a/ld/testsuite/ld-scripts/empty-aligned.d b/ld/testsuite/ld-scripts/empty-aligned.d
index d9916dd..ff131eb 100644
--- a/ld/testsuite/ld-scripts/empty-aligned.d
+++ b/ld/testsuite/ld-scripts/empty-aligned.d
@@ -1,14 +1,8 @@
#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
diff --git a/ld/testsuite/ld-scripts/empty-aligned.t b/ld/testsuite/ld-scripts/empty-aligned.t
index e59bc20..5f6a38d 100644
--- a/ld/testsuite/ld-scripts/empty-aligned.t
+++ b/ld/testsuite/ld-scripts/empty-aligned.t
@@ -6,14 +6,14 @@ SECTIONS
{
*(.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)
diff --git a/ld/testsuite/ld-shared/elf-offset.ld b/ld/testsuite/ld-shared/elf-offset.ld
index 125d879..ee587f9 100644
--- a/ld/testsuite/ld-shared/elf-offset.ld
+++ b/ld/testsuite/ld-shared/elf-offset.ld
@@ -128,7 +128,7 @@ 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 = . ;