Make assignments to dot keep an empty output section.

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.
This commit is contained in:
Alan Modra 2014-01-22 11:43:03 +10:30
parent 4584ec1207
commit 2edab91c10
19 changed files with 157 additions and 38 deletions

View 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.

View 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

View 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)

View 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 = .;}
}

View 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

View 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 = .;

View 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 = .;

View file

@ -181,7 +181,6 @@ SECTIONS
}
_bss_end__ = . ; __bss_end__ = . ;
. = ALIGN(32 / 8);
. = ALIGN(32 / 8);
__end__ = . ;
_end = .; PROVIDE (end = .);
/* Stabs debugging sections. */

View 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 = . ;

View 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 = .;

View 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 = .;

View 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) }
}

View 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) }
}

View 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) }

View 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) }

View 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*)
}
}

View 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

View 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)

View 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 = . ;