Make assignments to dot keep an empty output section.
authorAlan Modra <amodra@gmail.com>
Wed, 22 Jan 2014 01:13:03 +0000 (11:43 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 22 Jan 2014 01:28:29 +0000 (11:58 +1030)
An assignment to dot in an output section that allocates space of
course keeps the output section.  Here, I'm changing the behaviour for
assignments that don't allocate space.  The idea is not so much to
allow people to force output of an empty section with ". = .", but
to fix cases where an otherwise empty section has padding added by an
alignment expression that changes with relaxation or .eh_frame
editing.  Such a section might have zero size before relaxation and so
be stripped incorrectly.

ld/
* 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.
ld/testsuite/
* 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.

19 files changed:
ld/ChangeLog
ld/ld.texinfo
ld/ldexp.c
ld/scripttempl/elfmicroblaze.sc
ld/testsuite/ChangeLog
ld/testsuite/ld-arm/arm-dyn.ld
ld/testsuite/ld-arm/arm-lib.ld
ld/testsuite/ld-arm/arm-no-rel-plt.ld
ld/testsuite/ld-elfvsb/elf-offset.ld
ld/testsuite/ld-mips-elf/mips-dyn.ld
ld/testsuite/ld-mips-elf/mips-lib.ld
ld/testsuite/ld-powerpc/vle-multiseg-1.ld
ld/testsuite/ld-powerpc/vle-multiseg-2.ld
ld/testsuite/ld-powerpc/vle-multiseg-3.ld
ld/testsuite/ld-powerpc/vle-multiseg-4.ld
ld/testsuite/ld-powerpc/vle-multiseg-6.ld
ld/testsuite/ld-scripts/empty-aligned.d
ld/testsuite/ld-scripts/empty-aligned.t
ld/testsuite/ld-shared/elf-offset.ld

index b5071d9c01cef3fe6651db775b317ac827b01053..3d73b06c6aab6c8c31afce351e540d0fb21f7202 100644 (file)
@@ -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.
index ae3d568721d522865a2564ae717c3ebbcf5f5f89..a8e5ea69a7aa3b51169a354e7b2eba948eb88deb 100644 (file)
@@ -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
index 9a529dbb6516df1e2f416b44c131e412e28ad5b0..cc3be6d235091032dce234c9b5649425b43b91f8 100644 (file)
@@ -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)
index a54b89193c212a028330fa22b2406ea9297cfe84..8d2e6f220f4b1ee547530bc4c1b2b3a053dc1202 100644 (file)
@@ -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 = .;}
   }
index a09242852d36a96dcb59d6a356061f57e4fa976b..5fdf831d9ef177cb395917fc971d0817b1bb92ba 100644 (file)
@@ -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
index bef9a182d3a3eb159da0880498aa9a78cb581b91..71cb4c9e18a6214bcbe40af1747ff270d0eeb912 100644 (file)
@@ -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 = .;
index c9482c352b7b47b111e49667413610dea3581547..f158c230f48c92ece9ca2558f16603ece6b95db2 100644 (file)
@@ -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 = .;
index 439909c84403ca072e39dd4a12429bc4076e72a0..d8e5c9d2dedb7c684927d823911e479e52b3d3ee 100644 (file)
@@ -181,7 +181,6 @@ SECTIONS
   }
   _bss_end__ = . ; __bss_end__ = . ;
   . = ALIGN(32 / 8);
-  . = ALIGN(32 / 8);
   __end__ = . ;
   _end = .; PROVIDE (end = .);
   /* Stabs debugging sections.  */
index 7c648247e7d8d428ce4d5ebc2d30ee30cdd707f8..cd90bcc906386684c1a435576fda63ec62b30789 100644 (file)
@@ -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 = . ;
index e4f90d27393fac317373eb36c53c2282c24174fd..b931e1b63e8c295a5b986bdfb6c1a77fcd5d5ab0 100644 (file)
@@ -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 = .;
index 5073d9f51cc42fb00c66e602fd4900c9a9bd372c..1d66c62e3363714ab094221d29a91b69b0f9e16d 100644 (file)
@@ -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 = .;
index f2ff319fdaa5454a5357a8e33136306296edac13..3fe37b989212a3a2020559fe181b26da1074a30b 100644 (file)
@@ -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) }
 }
index 2320b61c2ad7442d8bd3f8e5cdc3d71d95260348..da9a79d6c4afb68ba309f2a2edfa64d9c16988b3 100644 (file)
@@ -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) }
 }
index 0ed2f44c54784bfb7cd7bd4aeb99c008864344d4..cfb1d88911a628791633f730175bb1619bf81a3d 100644 (file)
@@ -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) }
index 503fe06eafbf69c0c170e7840063564041ad85ff..21304271eb12692a93caf63a60fea7abcb4da65c 100644 (file)
@@ -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) }
index c8d88dd8319e7a786d060f8a18086864fc360c7a..2db76cc7c31647c9770ebbc3629451b06a93cebd 100644 (file)
@@ -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*)
   }
 }
index d9916ddca9069f1d110dec4c314dd828d151285b..ff131ebd3bcefe3d90c35dfa15c386eb8ecd78bd 100644 (file)
@@ -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
index e59bc2036080bb1fde229fb25ffc890e131b6d82..5f6a38d8889b15d09868bb093c0d2ba4e98c17af 100644 (file)
@@ -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)
index 125d879ab1e5a0fcebafd5ccb618bae0c0095c40..ee587f9fdd1a38f5ba19626db58c99abf125c35a 100644 (file)
@@ -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 = . ;