public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* PATCH: PR 797: Alignment in empty section changes the output layout
@ 2005-03-24 11:45 H. J. Lu
  2005-03-25  2:22 ` H. J. Lu
  0 siblings, 1 reply; 17+ messages in thread
From: H. J. Lu @ 2005-03-24 11:45 UTC (permalink / raw)
  To: binutils

This patch tries to undo the damange caused by the unused output
sections in linker script by removing them and resizing the remaining
sections.


H.J.
----
2005-03-23  H.J. Lu  <hongjiu.lu@intel.com>

	PR 797
	* emultempl/elf32.em (gld${EMULATION_NAME}_finish): Remove
	the unused output sections without input sections and the empty
	unused output sections created by linker, if they don't have
	any contents. Resize sections.

	* ldlang.c (lang_output_section_statement_lookup_1): Set the
	ignored field to FALSE.
	(lang_size_sections_1): Skip an output section if it should
	be ignored.

	* ldlang.h (lang_output_section_statement_type): Add ignored.

--- ld/emultempl/elf32.em.empty	2005-03-23 11:05:04.000000000 -0800
+++ ld/emultempl/elf32.em	2005-03-23 16:27:44.511115226 -0800
@@ -1472,20 +1472,76 @@ gld${EMULATION_NAME}_finish (void)
   if (!link_info.relocatable)
     {
       lang_output_section_statement_type *os;
+      asection *s, **p;
+      bfd_boolean resize = FALSE;
+
+      /* We want to remove unused output sections and resize the
+	 remaining sections so that any alignment changes caused by
+	 those removed output sections are reverted. Possible unused
+	 output sections are those without input sections or empty.
+	 We can't remove all unused output sections without input
+	 sections since they may be created by linker scripts. We can't
+	 remove all empty unused output sections since they may have
+	 empty input sections whose alignments may affect the memory
+	 layout of output sections which we don't want to change.
+	 
+	 So we remove the unused output sections without input sections
+	 and the empty unused output sections created by linker, if
+	 they don't have any contents.  */
 
       for (os = &lang_output_section_statement.head->output_section_statement;
 	   os != NULL;
 	   os = os->next)
 	{
-	  asection *s;
+	  if (os == abs_output_section || os->constraint == -1)
+	    continue;
+	  s = os->bfd_section;
+	  if (s != NULL
+	      && (s->linker_has_input == 0
+		  || (s->size == 0
+		      && (s->flags & SEC_LINKER_CREATED) != 0))
+	      && (s->flags & (SEC_KEEP | SEC_HAS_CONTENTS)) == 0)
+	    {
+	      os->ignored = TRUE;
+	      resize = TRUE;
+
+	      for (p = &output_bfd->sections; *p; p = &(*p)->next)
+		if (*p == s)
+		  {
+		    bfd_section_list_remove (output_bfd, p);
+		    output_bfd->section_count--;
+		    break;
+		  }
+	    }
+	}
+
+      /* Resize to revert the changes from those removed sections.  */
+      if (resize)
+	{
+	  lang_reset_memory_regions ();
+
+	  /* Resize the sections.  */
+	  lang_size_sections (stat_ptr->head, abs_output_section,
+			      &stat_ptr->head, 0, (bfd_vma) 0,
+			      NULL, TRUE);
+
+	  /* Redo special stuff.  */
+	  ldemul_after_allocation ();
+
+	  /* Do the assignments again.  */
+	  lang_do_assignments (stat_ptr->head, abs_output_section,
+			       (fill_type *) 0, (bfd_vma) 0);
+	}
 
+      for (os = &lang_output_section_statement.head->output_section_statement;
+	   os != NULL;
+	   os = os->next)
+	{
 	  if (os == abs_output_section || os->constraint == -1)
 	    continue;
 	  s = os->bfd_section;
 	  if (s != NULL && s->size == 0 && (s->flags & SEC_KEEP) == 0)
 	    {
-	      asection **p;
-
 	      for (p = &output_bfd->sections; *p; p = &(*p)->next)
 		if (*p == s)
 		  {
--- ld/ldlang.c.empty	2005-03-18 06:23:45.000000000 -0800
+++ ld/ldlang.c	2005-03-23 16:03:11.799216976 -0800
@@ -637,6 +637,7 @@ lang_output_section_statement_lookup_1 (
       lookup->bfd_section = NULL;
       lookup->processed = 0;
       lookup->constraint = constraint;
+      lookup->ignored = FALSE;
       lookup->sectype = normal_section;
       lookup->addr_tree = NULL;
       lang_list_init (&lookup->children);
@@ -3418,8 +3419,8 @@ lang_size_sections_1
 	    lang_output_section_statement_type *os;
 
 	    os = &s->output_section_statement;
-	    if (os->bfd_section == NULL)
-	      /* This section was never actually created.  */
+	    if (os->bfd_section == NULL || os->ignored)
+	      /* This section was removed or never actually created.  */
 	      break;
 
 	    /* If this is a COFF shared library section, use the size and
--- ld/ldlang.h.empty	2005-03-03 08:56:33.000000000 -0800
+++ ld/ldlang.h	2005-03-23 14:11:11.000000000 -0800
@@ -148,6 +148,7 @@ typedef struct lang_output_section_state
   int section_alignment;	/* Alignment of start of section.  */
   int constraint;
   bfd_boolean all_input_readonly;
+  bfd_boolean ignored; 
 
   union etree_union *load_base;
 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR 797: Alignment in empty section changes the output layout
  2005-03-24 11:45 PATCH: PR 797: Alignment in empty section changes the output layout H. J. Lu
@ 2005-03-25  2:22 ` H. J. Lu
  2005-03-29  4:21   ` Alan Modra
  0 siblings, 1 reply; 17+ messages in thread
From: H. J. Lu @ 2005-03-25  2:22 UTC (permalink / raw)
  To: binutils

On Wed, Mar 23, 2005 at 04:36:53PM -0800, H. J. Lu wrote:
> This patch tries to undo the damange caused by the unused output
> sections in linker script by removing them and resizing the remaining
> sections.
> 
> 
> H.J.
> ----
> 2005-03-23  H.J. Lu  <hongjiu.lu@intel.com>
> 
> 	PR 797
> 	* emultempl/elf32.em (gld${EMULATION_NAME}_finish): Remove
> 	the unused output sections without input sections and the empty
> 	unused output sections created by linker, if they don't have
> 	any contents. Resize sections.
> 
> 	* ldlang.c (lang_output_section_statement_lookup_1): Set the
> 	ignored field to FALSE.
> 	(lang_size_sections_1): Skip an output section if it should
> 	be ignored.
> 
> 	* ldlang.h (lang_output_section_statement_type): Add ignored.
> 

I missed one place in lang_do_assignments_1. We need to skip the
ignored output section when we assign values to symbols. Otherwise,
their values will be incorrect.


H.J.
----
2005-03-24  H.J. Lu  <hongjiu.lu@intel.com>

	PR 797
	* emultempl/elf32.em (gld${EMULATION_NAME}_finish): Remove
	the unused output sections without input sections and the empty
	unused output sections created by linker, if they don't have
	any contents. Resize sections.

	* ldlang.c (lang_output_section_statement_lookup_1): Set the
	ignored field to FALSE.
	(lang_size_sections_1): Skip an output section if it should
	be ignored.
	(lang_do_assignments_1): Likewise.

	* ldlang.h (lang_output_section_statement_type): Add ignored.

--- ld/emultempl/elf32.em.empty	2005-03-23 11:05:04.000000000 -0800
+++ ld/emultempl/elf32.em	2005-03-24 08:58:05.000000000 -0800
@@ -1472,20 +1472,76 @@ gld${EMULATION_NAME}_finish (void)
   if (!link_info.relocatable)
     {
       lang_output_section_statement_type *os;
+      asection *s, **p;
+      bfd_boolean resize = FALSE;
+
+      /* We want to remove unused output sections and resize the
+	 remaining sections so that any alignment changes caused by
+	 those removed output sections are reverted. Possible unused
+	 output sections are those without input sections or empty.
+	 We can't remove all unused output sections without input
+	 sections since they may be created by linker scripts. We can't
+	 remove all empty unused output sections since they may have
+	 empty input sections whose alignments may affect the memory
+	 layout of output sections which we don't want to change.
+	 
+	 So we remove the unused output sections without input sections
+	 and the empty unused output sections created by linker, if
+	 they don't have any contents.  */
 
       for (os = &lang_output_section_statement.head->output_section_statement;
 	   os != NULL;
 	   os = os->next)
 	{
-	  asection *s;
+	  if (os == abs_output_section || os->constraint == -1)
+	    continue;
+	  s = os->bfd_section;
+	  if (s != NULL
+	      && (s->linker_has_input == 0
+		  || (s->size == 0
+		      && (s->flags & SEC_LINKER_CREATED) != 0))
+	      && (s->flags & (SEC_KEEP | SEC_HAS_CONTENTS)) == 0)
+	    {
+	      os->ignored = TRUE;
+	      resize = TRUE;
+
+	      for (p = &output_bfd->sections; *p; p = &(*p)->next)
+		if (*p == s)
+		  {
+		    bfd_section_list_remove (output_bfd, p);
+		    output_bfd->section_count--;
+		    break;
+		  }
+	    }
+	}
+
+      /* Resize to revert the changes from those removed sections.  */
+      if (resize)
+	{
+	  lang_reset_memory_regions ();
+
+	  /* Resize the sections.  */
+	  lang_size_sections (stat_ptr->head, abs_output_section,
+			      &stat_ptr->head, 0, (bfd_vma) 0,
+			      NULL, TRUE);
+
+	  /* Redo special stuff.  */
+	  ldemul_after_allocation ();
+
+	  /* Do the assignments again.  */
+	  lang_do_assignments (stat_ptr->head, abs_output_section,
+			       (fill_type *) 0, (bfd_vma) 0);
+	}
 
+      for (os = &lang_output_section_statement.head->output_section_statement;
+	   os != NULL;
+	   os = os->next)
+	{
 	  if (os == abs_output_section || os->constraint == -1)
 	    continue;
 	  s = os->bfd_section;
 	  if (s != NULL && s->size == 0 && (s->flags & SEC_KEEP) == 0)
 	    {
-	      asection **p;
-
 	      for (p = &output_bfd->sections; *p; p = &(*p)->next)
 		if (*p == s)
 		  {
--- ld/ldlang.c.empty	2005-03-24 11:13:06.000000000 -0800
+++ ld/ldlang.c	2005-03-24 12:37:30.431168331 -0800
@@ -637,6 +637,7 @@ lang_output_section_statement_lookup_1 (
       lookup->bfd_section = NULL;
       lookup->processed = 0;
       lookup->constraint = constraint;
+      lookup->ignored = FALSE;
       lookup->sectype = normal_section;
       lookup->addr_tree = NULL;
       lang_list_init (&lookup->children);
@@ -3418,8 +3419,8 @@ lang_size_sections_1
 	    lang_output_section_statement_type *os;
 
 	    os = &s->output_section_statement;
-	    if (os->bfd_section == NULL)
-	      /* This section was never actually created.  */
+	    if (os->bfd_section == NULL || os->ignored)
+	      /* This section was removed or never actually created.  */
 	      break;
 
 	    /* If this is a COFF shared library section, use the size and
@@ -3914,7 +3915,7 @@ lang_do_assignments_1
 	    lang_output_section_statement_type *os;
 
 	    os = &(s->output_section_statement);
-	    if (os->bfd_section != NULL)
+	    if (os->bfd_section != NULL && !os->ignored)
 	      {
 		dot = os->bfd_section->vma;
 		lang_do_assignments_1 (os->children.head, os, os->fill, dot);
@@ -3928,7 +3929,7 @@ lang_do_assignments_1
 	      {
 		/* If nothing has been placed into the output section then
 		   it won't have a bfd_section.  */
-		if (os->bfd_section)
+		if (os->bfd_section && !os->ignored)
 		  {
 		    os->bfd_section->lma
 		      = exp_get_abs_int (os->load_base, 0, "load base",
--- ld/ldlang.h.empty	2005-03-03 08:56:33.000000000 -0800
+++ ld/ldlang.h	2005-03-24 08:58:05.000000000 -0800
@@ -148,6 +148,7 @@ typedef struct lang_output_section_state
   int section_alignment;	/* Alignment of start of section.  */
   int constraint;
   bfd_boolean all_input_readonly;
+  bfd_boolean ignored; 
 
   union etree_union *load_base;
 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR 797: Alignment in empty section changes the output layout
  2005-03-25  2:22 ` H. J. Lu
@ 2005-03-29  4:21   ` Alan Modra
  2005-03-29  7:13     ` H. J. Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Alan Modra @ 2005-03-29  4:21 UTC (permalink / raw)
  To: H. J. Lu; +Cc: binutils

On Thu, Mar 24, 2005 at 02:05:56PM -0800, H. J. Lu wrote:
> +	 So we remove the unused output sections without input sections
> +	 and the empty unused output sections created by linker, if
> +	 they don't have any contents.  */

Is it possible to do this in strip_excluded_output_sections?  You won't
have sizes set at that stage, but linker_has_input will be set, as will
SEC_HAS_CONTENTS from link script data statements.  So I think most of
what you're trying to achieve can be done there.  SEC_LINKER_CREATED
sections ought to be handled by the backend size_dynamic_sections
function calling _bfd_strip_section_from_output.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR 797: Alignment in empty section changes the output layout
  2005-03-29  4:21   ` Alan Modra
@ 2005-03-29  7:13     ` H. J. Lu
  2005-03-29  8:12       ` Alan Modra
  0 siblings, 1 reply; 17+ messages in thread
From: H. J. Lu @ 2005-03-29  7:13 UTC (permalink / raw)
  To: binutils

On Tue, Mar 29, 2005 at 08:12:31AM +0930, Alan Modra wrote:
> On Thu, Mar 24, 2005 at 02:05:56PM -0800, H. J. Lu wrote:
> > +	 So we remove the unused output sections without input sections
> > +	 and the empty unused output sections created by linker, if
> > +	 they don't have any contents.  */
> 
> Is it possible to do this in strip_excluded_output_sections?  You won't
> have sizes set at that stage, but linker_has_input will be set, as will
> SEC_HAS_CONTENTS from link script data statements.  So I think most of

But SEC_KEEP may not be set before lang_mark_used_section.

> what you're trying to achieve can be done there.  SEC_LINKER_CREATED
> sections ought to be handled by the backend size_dynamic_sections
> function calling _bfd_strip_section_from_output.

Or I can check every output section and call _bfd_strip_section_from_output
at the end of bfd_elf_size_dynamic_sections so that I don't have to
change every backend. But _bfd_strip_section_from_output will check
every input section. It may be expensive. If I have to do it in
gld${EMULATION_NAME}_finish for other sections anyway, why not
to remove empty unused linker created sections in a same place.


H.J.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR 797: Alignment in empty section changes the output layout
  2005-03-29  7:13     ` H. J. Lu
@ 2005-03-29  8:12       ` Alan Modra
  2005-03-30 16:30         ` H. J. Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Alan Modra @ 2005-03-29  8:12 UTC (permalink / raw)
  To: H. J. Lu; +Cc: binutils

On Mon, Mar 28, 2005 at 06:06:31PM -0800, H. J. Lu wrote:
> On Tue, Mar 29, 2005 at 08:12:31AM +0930, Alan Modra wrote:
> > On Thu, Mar 24, 2005 at 02:05:56PM -0800, H. J. Lu wrote:
> > > +	 So we remove the unused output sections without input sections
> > > +	 and the empty unused output sections created by linker, if
> > > +	 they don't have any contents.  */
> > 
> > Is it possible to do this in strip_excluded_output_sections?  You won't
> > have sizes set at that stage, but linker_has_input will be set, as will
> > SEC_HAS_CONTENTS from link script data statements.  So I think most of
> 
> But SEC_KEEP may not be set before lang_mark_used_section.
> 
> > what you're trying to achieve can be done there.  SEC_LINKER_CREATED
> > sections ought to be handled by the backend size_dynamic_sections
> > function calling _bfd_strip_section_from_output.
> 
> Or I can check every output section and call _bfd_strip_section_from_output
> at the end of bfd_elf_size_dynamic_sections so that I don't have to
> change every backend.

No, I think that would be a bad idea.  Most SEC_LINKER_CREATED sections
are created by the backend code, so the backend code should manage them.
Otherwise you run the risk of removing sections that some backend wants
to keep.

> But _bfd_strip_section_from_output will check
> every input section. It may be expensive.

Sure.  Let's fix it.  Perhaps by creating bfd_link_order lists earlier,
after placing orphans.

> If I have to do it in
> gld${EMULATION_NAME}_finish for other sections anyway, why not
> to remove empty unused linker created sections in a same place.

I don't really like the idea of removing sections so late in the link
process.  It's a hack that I allowed because removing excess symbols and
output sections was desirable, but now you're adding hacks upon hacks. 
As evidenced by the need for yet another section flag.

The proper place to remove sections is after the backend
size_dynamic_sections has run and before space for dynamic symbols is
allocated.  If you do it that way you'll avoid some unnecessary dynamic
syms too.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR 797: Alignment in empty section changes the output layout
  2005-03-29  8:12       ` Alan Modra
@ 2005-03-30 16:30         ` H. J. Lu
  0 siblings, 0 replies; 17+ messages in thread
From: H. J. Lu @ 2005-03-30 16:30 UTC (permalink / raw)
  To: binutils

On Tue, Mar 29, 2005 at 12:29:59PM +0930, Alan Modra wrote:
> On Mon, Mar 28, 2005 at 06:06:31PM -0800, H. J. Lu wrote:
> > On Tue, Mar 29, 2005 at 08:12:31AM +0930, Alan Modra wrote:
> > > On Thu, Mar 24, 2005 at 02:05:56PM -0800, H. J. Lu wrote:
> > > > +	 So we remove the unused output sections without input sections
> > > > +	 and the empty unused output sections created by linker, if
> > > > +	 they don't have any contents.  */
> > > 
> > > Is it possible to do this in strip_excluded_output_sections?  You won't
> > > have sizes set at that stage, but linker_has_input will be set, as will
> > > SEC_HAS_CONTENTS from link script data statements.  So I think most of
> > 
> > But SEC_KEEP may not be set before lang_mark_used_section.
> > 
> > > what you're trying to achieve can be done there.  SEC_LINKER_CREATED
> > > sections ought to be handled by the backend size_dynamic_sections
> > > function calling _bfd_strip_section_from_output.
> > 
> > Or I can check every output section and call _bfd_strip_section_from_output
> > at the end of bfd_elf_size_dynamic_sections so that I don't have to
> > change every backend.
> 
> No, I think that would be a bad idea.  Most SEC_LINKER_CREATED sections
> are created by the backend code, so the backend code should manage them.
> Otherwise you run the risk of removing sections that some backend wants
> to keep.
> 
> > But _bfd_strip_section_from_output will check
> > every input section. It may be expensive.
> 
> Sure.  Let's fix it.  Perhaps by creating bfd_link_order lists earlier,
> after placing orphans.
> 
> > If I have to do it in
> > gld${EMULATION_NAME}_finish for other sections anyway, why not
> > to remove empty unused linker created sections in a same place.
> 
> I don't really like the idea of removing sections so late in the link
> process.  It's a hack that I allowed because removing excess symbols and
> output sections was desirable, but now you're adding hacks upon hacks. 
> As evidenced by the need for yet another section flag.
> 
> The proper place to remove sections is after the backend
> size_dynamic_sections has run and before space for dynamic symbols is
> allocated.  If you do it that way you'll avoid some unnecessary dynamic
> syms too.
> 

This is an updated patch. The new section flag is needed since I
can't set bfd_section to NULL if it is ever created.


H.J.
---
bfd/

2005-03-29  H.J. Lu  <hongjiu.lu@intel.com>

	PR 797
	* elf32-i386.c (elf_i386_size_dynamic_sections): Also remove
	empty sdynbss section.
	* elf64-x86-64.c (elf64_x86_64_size_dynamic_sections): Likewise.

ld/

2005-03-29  H.J. Lu  <hongjiu.lu@intel.com>

	PR 797
	* ldlang.c (lang_output_section_statement_lookup_1): Set the
	ignored field to FALSE.
	(strip_excluded_output_sections): Renamed to ...
	(strip_excluded_or_unused_output_sections): This. Accept an
	argument to check for unused sections.
	(lang_size_sections_1): Skip an output section if it should
	be ignored.
	(lang_do_assignments_1): Likewise.
	(lang_process): Call strip_excluded_or_unused_output_sections
	to remove unused output sections after lang_mark_used_section.

	* ldlang.h (lang_output_section_statement_type): Change
	all_input_readonly to bitfield. Add ignored.

--- binutils/bfd/elf32-i386.c.empty	2005-02-11 09:28:10.000000000 -0800
+++ binutils/bfd/elf32-i386.c	2005-03-29 12:13:09.000000000 -0800
@@ -1830,7 +1830,8 @@ elf_i386_size_dynamic_sections (bfd *out
 
       if (s == htab->splt
 	  || s == htab->sgot
-	  || s == htab->sgotplt)
+	  || s == htab->sgotplt
+	  || s == htab->sdynbss)
 	{
 	  /* Strip this section if we don't need it; see the
 	     comment below.  */
--- binutils/bfd/elf64-x86-64.c.empty	2005-03-21 13:13:36.000000000 -0800
+++ binutils/bfd/elf64-x86-64.c	2005-03-29 12:13:09.000000000 -0800
@@ -1622,7 +1622,8 @@ elf64_x86_64_size_dynamic_sections (bfd 
 
       if (s == htab->splt
 	  || s == htab->sgot
-	  || s == htab->sgotplt)
+	  || s == htab->sgotplt
+	  || s == htab->sdynbss)
 	{
 	  /* Strip this section if we don't need it; see the
 	     comment below.  */
--- binutils/ld/ldlang.c.empty	2005-03-24 11:13:06.000000000 -0800
+++ binutils/ld/ldlang.c	2005-03-29 13:50:42.351403473 -0800
@@ -637,6 +637,7 @@ lang_output_section_statement_lookup_1 (
       lookup->bfd_section = NULL;
       lookup->processed = 0;
       lookup->constraint = constraint;
+      lookup->ignored = FALSE;
       lookup->sectype = normal_section;
       lookup->addr_tree = NULL;
       lang_list_init (&lookup->children);
@@ -2643,7 +2644,7 @@ map_input_to_output_sections
    sections if they turn out to be not needed.  Clean them up here.  */
 
 static void
-strip_excluded_output_sections (void)
+strip_excluded_or_unused_output_sections (bfd_boolean unused)
 {
   lang_output_section_statement_type *os;
 
@@ -2656,11 +2657,20 @@ strip_excluded_output_sections (void)
       if (os->constraint == -1)
 	continue;
       s = os->bfd_section;
-      if (s != NULL && (s->flags & SEC_EXCLUDE) != 0)
+      if (s != NULL
+	  && ((!unused && (s->flags & SEC_EXCLUDE) != 0)
+	      || (unused
+		  && s->linker_has_input == 0
+		  && (s->flags & (SEC_KEEP | SEC_HAS_CONTENTS)) == 0)))
 	{
 	  asection **p;
 
-	  os->bfd_section = NULL;
+	  /* We don't set bfd_section to NULL since bfd_section of 
+	     the used output section may still be used.  */
+	  if (unused)
+	    os->ignored = TRUE;
+	  else
+	    os->bfd_section = NULL;
 
 	  for (p = &output_bfd->sections; *p; p = &(*p)->next)
 	    if (*p == s)
@@ -3418,8 +3428,8 @@ lang_size_sections_1
 	    lang_output_section_statement_type *os;
 
 	    os = &s->output_section_statement;
-	    if (os->bfd_section == NULL)
-	      /* This section was never actually created.  */
+	    if (os->bfd_section == NULL || os->ignored)
+	      /* This section was removed or never actually created.  */
 	      break;
 
 	    /* If this is a COFF shared library section, use the size and
@@ -3914,7 +3924,7 @@ lang_do_assignments_1
 	    lang_output_section_statement_type *os;
 
 	    os = &(s->output_section_statement);
-	    if (os->bfd_section != NULL)
+	    if (os->bfd_section != NULL && !os->ignored)
 	      {
 		dot = os->bfd_section->vma;
 		lang_do_assignments_1 (os->children.head, os, os->fill, dot);
@@ -3928,7 +3938,7 @@ lang_do_assignments_1
 	      {
 		/* If nothing has been placed into the output section then
 		   it won't have a bfd_section.  */
-		if (os->bfd_section)
+		if (os->bfd_section && !os->ignored)
 		  {
 		    os->bfd_section->lma
 		      = exp_get_abs_int (os->load_base, 0, "load base",
@@ -4819,7 +4829,7 @@ lang_process (void)
   ldemul_before_allocation ();
 
   if (!link_info.relocatable)
-    strip_excluded_output_sections ();
+    strip_excluded_or_unused_output_sections (FALSE);
 
   /* We must record the program headers before we try to fix the
      section positions, since they will affect SIZEOF_HEADERS.  */
@@ -4867,9 +4877,19 @@ lang_process (void)
 	    }
 	}
       while (relax_again);
+    }
 
+  if (command_line.relax || !link_info.relocatable)
+    {
       /* Final extra sizing to report errors.  */
       lang_do_assignments (statement_list.head, abs_output_section, NULL, 0);
+      if (!link_info.relocatable)
+	{
+	  lang_mark_used_section ();
+	  /* Do it here so that the unused output_sections won't affect
+	     memory layout.  */ 
+	  strip_excluded_or_unused_output_sections (TRUE);
+	}
       lang_reset_memory_regions ();
       lang_size_sections (statement_list.head, abs_output_section,
 			  &statement_list.head, 0, 0, NULL, TRUE);
@@ -4893,7 +4913,7 @@ lang_process (void)
     lang_check_section_addresses ();
 
   /* Final stuffs.  */
-  lang_mark_used_section ();
+
   ldemul_finish ();
   lang_finish ();
 }
--- binutils/ld/ldlang.h.empty	2005-03-03 08:56:33.000000000 -0800
+++ binutils/ld/ldlang.h	2005-03-29 12:13:09.000000000 -0800
@@ -147,7 +147,8 @@ typedef struct lang_output_section_state
   int subsection_alignment;	/* Alignment of components.  */
   int section_alignment;	/* Alignment of start of section.  */
   int constraint;
-  bfd_boolean all_input_readonly;
+  unsigned int all_input_readonly : 1;
+  unsigned int ignored : 1; 
 
   union etree_union *load_base;
 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR 797: Alignment in empty section changes the output layout
  2005-05-07 20:08                 ` H. J. Lu
@ 2005-05-17 15:13                   ` Nick Clifton
  0 siblings, 0 replies; 17+ messages in thread
From: Nick Clifton @ 2005-05-17 15:13 UTC (permalink / raw)
  To: H. J. Lu; +Cc: binutils

Hi H. J.

> bfd/
> 2005-05-07  H.J. Lu  <hongjiu.lu@intel.com>
> 
> 	PR 797
> 	* elf32-i386.c (elf_i386_size_dynamic_sections): Also remove
> 	empty sdynbss section.
> 	* elf64-x86-64.c (elf64_x86_64_size_dynamic_sections): Likewise.
> 
> ld/
> 2005-05-07  H.J. Lu  <hongjiu.lu@intel.com>
> 
> 	PR 797
> 	* ldexp.c (exp_fold_tree_1): Renamed from exp_fold_tree and
> 	take take a bfd_boolean, mark_used. Ignore assert failure if
> 	mark_used is TRUE.
> 	(exp_fold_tree) Call exp_fold_tree_1 with mark_used == FALSE.
> 	(exp_fold_tree_no_dot): Updated to take a bfd_boolean,
> 	mark_used and pass down.
> 	(fold_unary): Likewise.
> 	(fold_binary): Likewise.
> 	(fold_trinary): Likewise.
> 	(exp_binop): Add FALSE to call to exp_fold_tree_no_dot.
> 	(exp_trinop): Likewise.
> 	(exp_unop): Likewise.
> 	(exp_nameop): Likewise.
> 	(exp_get_vma): Likewise.
> 	(exp_get_fill): Likewise.
> 	(exp_get_abs_int): Likewise.
> 	(fold_name): Likewise. Set SEC_KEEP in output section flags.
> 	(exp_mark_used_section): New.
> 
> 	* ldexp.h (exp_mark_used_section): New.
> 
> 	* ldlang.c (lang_output_section_statement_lookup_1): Set the
> 	ignored field to FALSE.
> 	(lang_mark_used_section_1): New.
> 	(lang_mark_used_section): Call lang_mark_used_section_1.
> 	(strip_excluded_output_sections): Call lang_mark_used_section
> 	and check for unused sections.
> 	(lang_size_sections_1): Skip an output section if it should
> 	be ignored.
> 	(lang_do_assignments_1): Likewise.
> 	(lang_process): Don't call lang_mark_used_section here.
> 
> 	* ldlang.h (lang_output_section_statement_type): Change
> 	all_input_readonly to bitfield. Add ignored.

Approved - please apply - but could also generate a test case to make 
sure that this problem does not reoccur.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR 797: Alignment in empty section changes the output layout
  2005-05-07 19:16               ` H. J. Lu
@ 2005-05-07 20:08                 ` H. J. Lu
  2005-05-17 15:13                   ` Nick Clifton
  0 siblings, 1 reply; 17+ messages in thread
From: H. J. Lu @ 2005-05-07 20:08 UTC (permalink / raw)
  To: binutils

On Sat, May 07, 2005 at 10:34:32AM -0700, H. J. Lu wrote:
> On Fri, May 06, 2005 at 03:47:17PM +0930, Alan Modra wrote:
> > On Thu, May 05, 2005 at 09:02:23AM -0700, H. J. Lu wrote:
> > > With
> > > 
> > >   lang_size_sections (statement_list.head, abs_output_section,
> > >                       &statement_list.head, 0, 0, NULL,
> > >                       command_line.relax ? FALSE : TRUE);
> > >   lang_do_assignments (statement_list.head, abs_output_section, NULL,
> > > 0);
> > >   lang_reset_memory_regions ();
> > >   lang_mark_used_section ();
> > >   strip_unused_output_sections ();
> > > 
> > > at the end of strip_excluded_output_sections, I got
> > > failed: Bad value FAIL: PHDRS
> > > FAIL: PHDRS2
> > 
> > You need this from ppc64elf.em.
> > 
> > 	  /* We must not cache anything from the preliminary sizing.  */
> > 	  elf_tdata (output_bfd)->program_header_size = 0;
> > 
> > Perhaps a better approach would be to run a cut-down lang_do_assignments
> > that just keeps track of output section and symbol assignments other
> > than "." within output sections.  If it finds such an assignment, mark
> > the section as needed.
> > 
> 
> This patch implements it.
> 
> 

We should ignore assert failure if mark_used is TRUE, not skip it.


H.J.
---
bfd/

2005-05-07  H.J. Lu  <hongjiu.lu@intel.com>

	PR 797
	* elf32-i386.c (elf_i386_size_dynamic_sections): Also remove
	empty sdynbss section.
	* elf64-x86-64.c (elf64_x86_64_size_dynamic_sections): Likewise.

ld/

2005-05-07  H.J. Lu  <hongjiu.lu@intel.com>

	PR 797
	* ldexp.c (exp_fold_tree_1): Renamed from exp_fold_tree and
	take take a bfd_boolean, mark_used. Ignore assert failure if
	mark_used is TRUE.
	(exp_fold_tree) Call exp_fold_tree_1 with mark_used == FALSE.
	(exp_fold_tree_no_dot): Updated to take a bfd_boolean,
	mark_used and pass down.
	(fold_unary): Likewise.
	(fold_binary): Likewise.
	(fold_trinary): Likewise.
	(exp_binop): Add FALSE to call to exp_fold_tree_no_dot.
	(exp_trinop): Likewise.
	(exp_unop): Likewise.
	(exp_nameop): Likewise.
	(exp_get_vma): Likewise.
	(exp_get_fill): Likewise.
	(exp_get_abs_int): Likewise.
	(fold_name): Likewise. Set SEC_KEEP in output section flags.
	(exp_mark_used_section): New.

	* ldexp.h (exp_mark_used_section): New.

	* ldlang.c (lang_output_section_statement_lookup_1): Set the
	ignored field to FALSE.
	(lang_mark_used_section_1): New.
	(lang_mark_used_section): Call lang_mark_used_section_1.
	(strip_excluded_output_sections): Call lang_mark_used_section
	and check for unused sections.
	(lang_size_sections_1): Skip an output section if it should
	be ignored.
	(lang_do_assignments_1): Likewise.
	(lang_process): Don't call lang_mark_used_section here.

	* ldlang.h (lang_output_section_statement_type): Change
	all_input_readonly to bitfield. Add ignored.

--- binutils/bfd/elf32-i386.c.empty	2005-05-05 07:44:37.000000000 -0700
+++ binutils/bfd/elf32-i386.c	2005-05-07 06:58:49.000000000 -0700
@@ -1914,7 +1914,8 @@ elf_i386_size_dynamic_sections (bfd *out
 
       if (s == htab->splt
 	  || s == htab->sgot
-	  || s == htab->sgotplt)
+	  || s == htab->sgotplt
+	  || s == htab->sdynbss)
 	{
 	  /* Strip this section if we don't need it; see the
 	     comment below.  */
--- binutils/bfd/elf64-x86-64.c.empty	2005-05-05 07:44:41.000000000 -0700
+++ binutils/bfd/elf64-x86-64.c	2005-05-07 06:58:49.000000000 -0700
@@ -1624,7 +1624,8 @@ elf64_x86_64_size_dynamic_sections (bfd 
 
       if (s == htab->splt
 	  || s == htab->sgot
-	  || s == htab->sgotplt)
+	  || s == htab->sgotplt
+	  || s == htab->sdynbss)
 	{
 	  /* Strip this section if we don't need it; see the
 	     comment below.  */
--- binutils/ld/ldexp.c.empty	2005-03-15 09:35:19.000000000 -0800
+++ binutils/ld/ldexp.c	2005-05-07 12:11:09.000000000 -0700
@@ -41,8 +41,12 @@
 #include "libiberty.h"
 #include "safe-ctype.h"
 
+static etree_value_type exp_fold_tree_1
+  (etree_type *, lang_output_section_statement_type *,
+   lang_phase_type, bfd_vma, bfd_vma *, bfd_boolean);
 static etree_value_type exp_fold_tree_no_dot
-  (etree_type *, lang_output_section_statement_type *, lang_phase_type);
+  (etree_type *, lang_output_section_statement_type *, lang_phase_type,
+   bfd_boolean);
 static bfd_vma align_n
   (bfd_vma, bfd_vma);
 
@@ -219,13 +223,14 @@ fold_unary (etree_type *tree,
 	    lang_output_section_statement_type *current_section,
 	    lang_phase_type allocation_done,
 	    bfd_vma dot,
-	    bfd_vma *dotp)
+	    bfd_vma *dotp,
+	    bfd_boolean mark_used)
 {
   etree_value_type result;
 
-  result = exp_fold_tree (tree->unary.child,
-			  current_section,
-			  allocation_done, dot, dotp);
+  result = exp_fold_tree_1 (tree->unary.child,
+			    current_section,
+			    allocation_done, dot, dotp, mark_used);
   if (result.valid_p)
     {
       switch (tree->type.node_code)
@@ -308,12 +313,13 @@ fold_binary (etree_type *tree,
 	     lang_output_section_statement_type *current_section,
 	     lang_phase_type allocation_done,
 	     bfd_vma dot,
-	     bfd_vma *dotp)
+	     bfd_vma *dotp,
+	     bfd_boolean mark_used)
 {
   etree_value_type result;
 
-  result = exp_fold_tree (tree->binary.lhs, current_section,
-			  allocation_done, dot, dotp);
+  result = exp_fold_tree_1 (tree->binary.lhs, current_section,
+			    allocation_done, dot, dotp, mark_used);
 
   /* The SEGMENT_START operator is special because its first
      operand is a string, not the name of a symbol.  */
@@ -338,9 +344,10 @@ fold_binary (etree_type *tree,
     {
       etree_value_type other;
 
-      other = exp_fold_tree (tree->binary.rhs,
-			     current_section,
-			     allocation_done, dot, dotp);
+      other = exp_fold_tree_1 (tree->binary.rhs,
+			       current_section,
+			       allocation_done,
+			       dot, dotp, mark_used);
       if (other.valid_p)
 	{
 	  /* If the values are from different sections, or this is an
@@ -498,18 +505,20 @@ fold_trinary (etree_type *tree,
 	      lang_output_section_statement_type *current_section,
 	      lang_phase_type allocation_done,
 	      bfd_vma dot,
-	      bfd_vma *dotp)
+	      bfd_vma *dotp,
+	      bfd_boolean mark_used)
 {
   etree_value_type result;
 
-  result = exp_fold_tree (tree->trinary.cond, current_section,
-			  allocation_done, dot, dotp);
+  result = exp_fold_tree_1 (tree->trinary.cond, current_section,
+			    allocation_done, dot, dotp, mark_used);
   if (result.valid_p)
-    result = exp_fold_tree ((result.value
-			     ? tree->trinary.lhs
-			     : tree->trinary.rhs),
-			    current_section,
-			    allocation_done, dot, dotp);
+    result = exp_fold_tree_1 ((result.value
+			       ? tree->trinary.lhs
+			       : tree->trinary.rhs),
+			      current_section,
+			      allocation_done,
+			      dot, dotp, mark_used);
 
   return result;
 }
@@ -518,7 +527,8 @@ static etree_value_type
 fold_name (etree_type *tree,
 	   lang_output_section_statement_type *current_section,
 	   lang_phase_type allocation_done,
-	   bfd_vma dot)
+	   bfd_vma dot,
+	   bfd_boolean mark_used)
 {
   etree_value_type result;
 
@@ -596,6 +606,7 @@ fold_name (etree_type *tree,
 					 + h->u.def.section->output_offset),
 					NULL,
 					os);
+		      os->bfd_section->flags |= SEC_KEEP;
 		    }
 		}
 	    }
@@ -619,8 +630,12 @@ fold_name (etree_type *tree,
 	  lang_output_section_statement_type *os;
 
 	  os = lang_output_section_find (tree->name.name);
-	  if (os && os->processed > 0)
-	    result = new_rel (0, NULL, os);
+	  if (os)
+	    {
+	      os->bfd_section->flags |= SEC_KEEP;
+	      if (os->processed > 0)
+		result = new_rel (0, NULL, os);
+	    }
 	}
       break;
 
@@ -630,14 +645,19 @@ fold_name (etree_type *tree,
 	  lang_output_section_statement_type *os;
 
 	  os = lang_output_section_find (tree->name.name);
-	  if (os && os->processed != 0)
+	  if (os)
 	    {
-	      if (os->load_base == NULL)
-		result = new_rel (0, NULL, os);
-	      else
-		result = exp_fold_tree_no_dot (os->load_base,
-					       abs_output_section,
-					       allocation_done);
+	      os->bfd_section->flags |= SEC_KEEP;
+	      if (os->processed != 0)
+		{
+		  if (os->load_base == NULL)
+		    result = new_rel (0, NULL, os);
+		  else
+		    result = exp_fold_tree_no_dot (os->load_base,
+						   abs_output_section,
+						   allocation_done,
+						   mark_used);
+		}
 	    }
 	}
       break;
@@ -649,8 +669,12 @@ fold_name (etree_type *tree,
 	  lang_output_section_statement_type *os;
 
 	  os = lang_output_section_find (tree->name.name);
-	  if (os && os->processed > 0)
-	    result = new_abs (os->bfd_section->size / opb);
+	  if (os)
+	    {
+	      os->bfd_section->flags |= SEC_KEEP;
+	      if (os->processed > 0)
+		result = new_abs (os->bfd_section->size / opb);
+	    }
 	}
       break;
 
@@ -688,12 +712,13 @@ fold_name (etree_type *tree,
   return result;
 }
 
-etree_value_type
-exp_fold_tree (etree_type *tree,
-	       lang_output_section_statement_type *current_section,
-	       lang_phase_type allocation_done,
-	       bfd_vma dot,
-	       bfd_vma *dotp)
+static etree_value_type
+exp_fold_tree_1 (etree_type *tree,
+		 lang_output_section_statement_type *current_section,
+		 lang_phase_type allocation_done,
+		 bfd_vma dot,
+		 bfd_vma *dotp,
+		 bfd_boolean mark_used)
 {
   etree_value_type result;
 
@@ -721,26 +746,34 @@ exp_fold_tree (etree_type *tree,
       break;
 
     case etree_assert:
-      result = exp_fold_tree (tree->assert_s.child,
-			      current_section,
-			      allocation_done, dot, dotp);
-      if (result.valid_p && !result.value)
-	einfo ("%X%P: %s\n", tree->assert_s.message);
+      result = exp_fold_tree_1 (tree->assert_s.child,
+				current_section,
+				allocation_done, dot, dotp,
+				mark_used);
+      if (result.valid_p)
+	{
+	  if (mark_used)
+	    /* We don't care if assert fails or not when we are just
+	       marking if a section is used or not.  */
+	    result.value = 1;
+	  else if (!result.value)
+	    einfo ("%X%P: %s\n", tree->assert_s.message);
+	}
       break;
 
     case etree_unary:
       result = fold_unary (tree, current_section, allocation_done,
-			   dot, dotp);
+			   dot, dotp, mark_used);
       break;
 
     case etree_binary:
       result = fold_binary (tree, current_section, allocation_done,
-			    dot, dotp);
+			    dot, dotp, mark_used);
       break;
 
     case etree_trinary:
       result = fold_trinary (tree, current_section, allocation_done,
-			     dot, dotp);
+			     dot, dotp, mark_used);
       break;
 
     case etree_assign:
@@ -757,9 +790,10 @@ exp_fold_tree (etree_type *tree,
 	    {
 	      /* Notify the folder that this is an assignment to dot.  */
 	      assigning_to_dot = TRUE;
-	      result = exp_fold_tree (tree->assign.src,
-				      current_section,
-				      allocation_done, dot, dotp);
+	      result = exp_fold_tree_1 (tree->assign.src,
+					current_section,
+					allocation_done,
+					dot, dotp, mark_used);
 	      assigning_to_dot = FALSE;
 
 	      if (! result.valid_p)
@@ -788,9 +822,9 @@ exp_fold_tree (etree_type *tree,
 	}
       else
 	{
-	  result = exp_fold_tree (tree->assign.src,
-				  current_section, allocation_done,
-				  dot, dotp);
+	  result = exp_fold_tree_1 (tree->assign.src,
+				    current_section, allocation_done,
+				    dot, dotp, mark_used);
 	  if (result.valid_p)
 	    {
 	      bfd_boolean create;
@@ -832,7 +866,8 @@ exp_fold_tree (etree_type *tree,
       break;
 
     case etree_name:
-      result = fold_name (tree, current_section, allocation_done, dot);
+      result = fold_name (tree, current_section, allocation_done, dot,
+			  mark_used);
       break;
 
     default:
@@ -844,12 +879,25 @@ exp_fold_tree (etree_type *tree,
   return result;
 }
 
+etree_value_type
+exp_fold_tree (etree_type *tree,
+	       lang_output_section_statement_type *current_section,
+	       lang_phase_type allocation_done,
+	       bfd_vma dot,
+	       bfd_vma *dotp)
+{
+  return exp_fold_tree_1 (tree, current_section, allocation_done,
+			  dot, dotp, FALSE);
+}
+
 static etree_value_type
 exp_fold_tree_no_dot (etree_type *tree,
 		      lang_output_section_statement_type *current_section,
-		      lang_phase_type allocation_done)
+		      lang_phase_type allocation_done,
+		      bfd_boolean mark_used)
 {
-  return exp_fold_tree (tree, current_section, allocation_done, 0, NULL);
+  return exp_fold_tree_1 (tree, current_section, allocation_done, 0,
+			  NULL, mark_used);
 }
 
 etree_type *
@@ -864,7 +912,7 @@ exp_binop (int code, etree_type *lhs, et
   value.type.node_class = etree_binary;
   r = exp_fold_tree_no_dot (&value,
 			    abs_output_section,
-			    lang_first_phase_enum);
+			    lang_first_phase_enum, FALSE);
   if (r.valid_p)
     {
       return exp_intop (r.value);
@@ -884,7 +932,7 @@ exp_trinop (int code, etree_type *cond, 
   value.trinary.cond = cond;
   value.trinary.rhs = rhs;
   value.type.node_class = etree_trinary;
-  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum);
+  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum, FALSE);
   if (r.valid_p)
     return exp_intop (r.value);
 
@@ -903,7 +951,7 @@ exp_unop (int code, etree_type *child)
   value.unary.child = child;
   value.unary.type.node_class = etree_unary;
   r = exp_fold_tree_no_dot (&value, abs_output_section,
-			    lang_first_phase_enum);
+			    lang_first_phase_enum, FALSE);
   if (r.valid_p)
     return exp_intop (r.value);
 
@@ -921,7 +969,7 @@ exp_nameop (int code, const char *name)
   value.name.name = name;
   value.name.type.node_class = etree_name;
 
-  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum);
+  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum, FALSE);
   if (r.valid_p)
     return exp_intop (r.value);
 
@@ -1071,7 +1119,8 @@ exp_get_vma (etree_type *tree,
 
   if (tree != NULL)
     {
-      r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+      r = exp_fold_tree_no_dot (tree, abs_output_section,
+				allocation_done, FALSE);
       if (! r.valid_p && name != NULL)
 	einfo (_("%F%S nonconstant expression for %s\n"), name);
       return r.value;
@@ -1103,7 +1152,8 @@ exp_get_fill (etree_type *tree,
   if (tree == NULL)
     return def;
 
-  r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+  r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done,
+			    FALSE);
   if (! r.valid_p && name != NULL)
     einfo (_("%F%S nonconstant expression for %s\n"), name);
 
@@ -1154,7 +1204,8 @@ exp_get_abs_int (etree_type *tree,
 		 lang_phase_type allocation_done)
 {
   etree_value_type res;
-  res = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+  res = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done,
+			      FALSE);
 
   if (res.valid_p)
     res.value += res.section->bfd_section->vma;
@@ -1173,3 +1224,91 @@ align_n (bfd_vma value, bfd_vma align)
   value = (value + align - 1) / align;
   return value * align;
 }
+
+void
+exp_mark_used_section
+  (etree_type *tree,
+   lang_output_section_statement_type *current_section)
+{
+  switch (tree->type.node_class)
+    {
+    case etree_value:
+      break;
+
+    case etree_rel:
+      break;
+
+    case etree_assert:
+      break;
+
+    case etree_unary:
+      break;
+
+    case etree_binary:
+      break;
+
+    case etree_trinary:
+      break;
+
+    case etree_assign:
+    case etree_provide:
+    case etree_provided:
+      if (tree->assign.dst[0] != '.' || tree->assign.dst[1] != 0)
+	{
+	  etree_value_type result;
+	  bfd_vma dot = 0;
+
+	  result = exp_fold_tree_1 (tree->assign.src,
+				    current_section,
+				    lang_allocating_phase_enum,
+				    dot, &dot, TRUE);
+	  if (result.valid_p)
+	    {
+	      bfd_boolean create;
+	      struct bfd_link_hash_entry *h;
+
+	      if (tree->type.node_class == etree_assign)
+		create = TRUE;
+	      else
+		create = FALSE;
+	      h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
+					create, FALSE, TRUE);
+	      if (h == NULL)
+		{
+		  if (create)
+		    einfo (_("%P%F:%s: hash creation failed\n"),
+			   tree->assign.dst);
+		}
+	      else if (tree->type.node_class == etree_provide
+		       && h->type != bfd_link_hash_new
+		       && h->type != bfd_link_hash_undefined
+		       && h->type != bfd_link_hash_common)
+		{
+		  /* Do nothing.  The symbol was defined by some
+		     object.  */
+		}
+	      else
+		{
+		  /* FIXME: Should we worry if the symbol is already
+		     defined?  */
+		  lang_update_definedness (tree->assign.dst, h);
+		  h->type = bfd_link_hash_defined;
+		  h->u.def.value = result.value;
+		  h->u.def.section = result.section->bfd_section;
+		  if (tree->type.node_class == etree_provide)
+		    tree->type.node_class = etree_provided;
+		}
+	    }
+	}
+      break;
+
+    case etree_name:
+      fold_name (tree, current_section, lang_allocating_phase_enum, 0,
+		 TRUE);
+      break;
+
+    default:
+      abort ();
+      break;
+    }
+}
--- binutils/ld/ldexp.h.empty	2004-12-22 09:30:57.000000000 -0800
+++ binutils/ld/ldexp.h	2005-05-07 09:34:05.000000000 -0700
@@ -156,5 +156,7 @@ fill_type *exp_get_fill
   (etree_type *, fill_type *, char *, lang_phase_type);
 bfd_vma exp_get_abs_int
   (etree_type *, int, char *, lang_phase_type);
+void exp_mark_used_section
+  (etree_type *, struct lang_output_section_statement_struct *);
 
 #endif
--- binutils/ld/ldlang.c.empty	2005-05-07 06:58:49.000000000 -0700
+++ binutils/ld/ldlang.c	2005-05-07 10:13:04.000000000 -0700
@@ -1083,6 +1083,7 @@ lang_output_section_statement_lookup_1 (
       lookup->bfd_section = NULL;
       lookup->processed = 0;
       lookup->constraint = constraint;
+      lookup->ignored = FALSE;
       lookup->sectype = normal_section;
       lookup->addr_tree = NULL;
       lang_list_init (&lookup->children);
@@ -3109,6 +3110,90 @@ map_input_to_output_sections
     }
 }
 
+/* Worker function for lang_mark_used_section.  Recursiveness goes
+   here.  */
+
+static void
+lang_mark_used_section_1
+  (lang_statement_union_type *s,
+   lang_output_section_statement_type *output_section_statement)
+{
+  for (; s != NULL; s = s->header.next)
+    {
+      switch (s->header.type)
+	{
+	case lang_constructors_statement_enum:
+	  break;
+
+	case lang_output_section_statement_enum:
+	  {
+	    lang_output_section_statement_type *os;
+
+	    os = &(s->output_section_statement);
+	    if (os->bfd_section != NULL)
+	      lang_mark_used_section_1 (os->children.head, os);
+	  }
+	  break;
+	case lang_wild_statement_enum:
+	  lang_mark_used_section_1 (s->wild_statement.children.head,
+				    output_section_statement);
+
+	  break;
+
+	case lang_object_symbols_statement_enum:
+	case lang_output_statement_enum:
+	case lang_target_statement_enum:
+	  break;
+	case lang_data_statement_enum:
+	  exp_mark_used_section (s->data_statement.exp,
+				 abs_output_section);
+	  break;
+
+	case lang_reloc_statement_enum:
+	  break;
+
+	case lang_input_section_enum:
+	  break;
+
+	case lang_input_statement_enum:
+	  break;
+	case lang_fill_statement_enum:
+	  break;
+	case lang_assignment_statement_enum:
+	  exp_mark_used_section (s->assignment_statement.exp,
+				 output_section_statement);
+	  break;
+	case lang_padding_statement_enum:
+	  break;
+
+	case lang_group_statement_enum:
+	  lang_mark_used_section_1 (s->group_statement.children.head,
+				    output_section_statement);
+	  break;
+
+	default:
+	  FAIL ();
+	  break;
+	case lang_address_statement_enum:
+	  break;
+	}
+    }
+}
+
+static void
+lang_mark_used_section (void)
+{
+  unsigned int gc_sections = link_info.gc_sections;
+
+  /* Callers of exp_fold_tree need to increment this.  */
+  lang_statement_iteration++;
+  lang_mark_used_section_1 (statement_list.head, abs_output_section);
+
+  link_info.gc_sections = 0;
+  bfd_gc_sections (output_bfd, &link_info);
+  link_info.gc_sections = gc_sections;
+}
+
 /* An output section might have been removed after its statement was
    added.  For example, ldemul_before_allocation can remove dynamic
    sections if they turn out to be not needed.  Clean them up here.  */
@@ -3118,32 +3203,54 @@ strip_excluded_output_sections (void)
 {
   lang_output_section_statement_type *os;
 
+  lang_mark_used_section ();
+
   for (os = &lang_output_section_statement.head->output_section_statement;
        os != NULL;
        os = os->next)
     {
-      asection *s;
+      asection *output_section;
+      bfd_boolean exclude;
 
       if (os->constraint == -1)
 	continue;
 
-      if (os->bfd_section == NULL || os->bfd_section->map_head.s == NULL)
+      output_section = os->bfd_section;
+      if (output_section == NULL)
 	continue;
 
-      for (s = os->bfd_section->map_head.s; s != NULL; s = s->map_head.s)
-	if ((s->flags & SEC_EXCLUDE) == 0)
-	  break;
+      exclude = FALSE;
+      if (output_section->map_head.s != NULL)
+	{
+	  asection *s;
 
-      os->bfd_section->map_head.link_order = NULL;
-      os->bfd_section->map_tail.link_order = NULL;
+	  for (s = output_section->map_head.s; s != NULL;
+	       s = s->map_head.s)
+	    if ((s->flags & SEC_EXCLUDE) == 0)
+	      break;
+
+	  output_section->map_head.link_order = NULL;
+	  output_section->map_tail.link_order = NULL;
+
+	  if (s == NULL)
+	    exclude = TRUE;
+	}
 
-      if (s == NULL)
+      if (exclude
+	  || (output_section->linker_has_input == 0
+	      && ((output_section->flags
+		   & (SEC_KEEP | SEC_HAS_CONTENTS)) == 0)))
 	{
-	  s = os->bfd_section;
-	  os->bfd_section = NULL;
-	  if (!bfd_section_removed_from_list (output_bfd, s))
+	  if (exclude)
+	    os->bfd_section = NULL;
+	  else
+	    /* We don't set bfd_section to NULL since bfd_section of the
+	     * removed output section statement may still be used.  */
+	    os->ignored = TRUE;
+	  if (!bfd_section_removed_from_list (output_bfd,
+					      output_section))
 	    {
-	      bfd_section_list_remove (output_bfd, s);
+	      bfd_section_list_remove (output_bfd, output_section);
 	      output_bfd->section_count--;
 	    }
 	}
@@ -3925,8 +4032,8 @@ lang_size_sections_1
 	    lang_output_section_statement_type *os;
 
 	    os = &s->output_section_statement;
-	    if (os->bfd_section == NULL)
-	      /* This section was never actually created.  */
+	    if (os->bfd_section == NULL || os->ignored)
+	      /* This section was removed or never actually created.  */
 	      break;
 
 	    /* If this is a COFF shared library section, use the size and
@@ -4421,7 +4528,7 @@ lang_do_assignments_1
 	    lang_output_section_statement_type *os;
 
 	    os = &(s->output_section_statement);
-	    if (os->bfd_section != NULL)
+	    if (os->bfd_section != NULL && !os->ignored)
 	      {
 		dot = os->bfd_section->vma;
 		lang_do_assignments_1 (os->children.head, os, os->fill, dot);
@@ -4435,7 +4542,7 @@ lang_do_assignments_1
 	      {
 		/* If nothing has been placed into the output section then
 		   it won't have a bfd_section.  */
-		if (os->bfd_section)
+		if (os->bfd_section && !os->ignored)
 		  {
 		    os->bfd_section->lma
 		      = exp_get_abs_int (os->load_base, 0, "load base",
@@ -5240,16 +5347,6 @@ lang_gc_sections (void)
     bfd_gc_sections (output_bfd, &link_info);
 }
 
-static void
-lang_mark_used_section (void)
-{
-  unsigned int gc_sections = link_info.gc_sections;
-
-  link_info.gc_sections = 0;
-  bfd_gc_sections (output_bfd, &link_info);
-  link_info.gc_sections = gc_sections;
-}
-
 void
 lang_process (void)
 {
@@ -5408,7 +5505,6 @@ lang_process (void)
     lang_check_section_addresses ();
 
   /* Final stuffs.  */
-  lang_mark_used_section ();
   ldemul_finish ();
   lang_end ();
 }
--- binutils/ld/ldlang.h.empty	2005-05-07 06:58:49.000000000 -0700
+++ binutils/ld/ldlang.h	2005-05-07 08:59:05.000000000 -0700
@@ -147,7 +147,8 @@ typedef struct lang_output_section_state
   int subsection_alignment;	/* Alignment of components.  */
   int section_alignment;	/* Alignment of start of section.  */
   int constraint;
-  bfd_boolean all_input_readonly;
+  unsigned int all_input_readonly : 1;
+  unsigned int ignored : 1; 
 
   union etree_union *load_base;
 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR 797: Alignment in empty section changes the output layout
  2005-05-06  6:20             ` Alan Modra
@ 2005-05-07 19:16               ` H. J. Lu
  2005-05-07 20:08                 ` H. J. Lu
  0 siblings, 1 reply; 17+ messages in thread
From: H. J. Lu @ 2005-05-07 19:16 UTC (permalink / raw)
  To: binutils

On Fri, May 06, 2005 at 03:47:17PM +0930, Alan Modra wrote:
> On Thu, May 05, 2005 at 09:02:23AM -0700, H. J. Lu wrote:
> > With
> > 
> >   lang_size_sections (statement_list.head, abs_output_section,
> >                       &statement_list.head, 0, 0, NULL,
> >                       command_line.relax ? FALSE : TRUE);
> >   lang_do_assignments (statement_list.head, abs_output_section, NULL,
> > 0);
> >   lang_reset_memory_regions ();
> >   lang_mark_used_section ();
> >   strip_unused_output_sections ();
> > 
> > at the end of strip_excluded_output_sections, I got
> > failed: Bad value FAIL: PHDRS
> > FAIL: PHDRS2
> 
> You need this from ppc64elf.em.
> 
> 	  /* We must not cache anything from the preliminary sizing.  */
> 	  elf_tdata (output_bfd)->program_header_size = 0;
> 
> Perhaps a better approach would be to run a cut-down lang_do_assignments
> that just keeps track of output section and symbol assignments other
> than "." within output sections.  If it finds such an assignment, mark
> the section as needed.
> 

This patch implements it.


H.J.
-----
bfd/

2005-05-07  H.J. Lu  <hongjiu.lu@intel.com>

	PR 797
	* elf32-i386.c (elf_i386_size_dynamic_sections): Also remove
	empty sdynbss section.
	* elf64-x86-64.c (elf64_x86_64_size_dynamic_sections): Likewise.

ld/

2005-05-07  H.J. Lu  <hongjiu.lu@intel.com>

	PR 797
	* ldexp.c (exp_fold_tree_1): Renamed from exp_fold_tree and
	take take a bfd_boolean, mark_used. Skip etree_assert if
	mark_used is TRUE.
	(exp_fold_tree) Call exp_fold_tree_1 with mark_used == FALSE.
	(exp_fold_tree_no_dot): Updated to take a bfd_boolean,
	mark_used and pass down.
	(fold_unary): Likewise.
	(fold_binary): Likewise.
	(fold_trinary): Likewise.
	(exp_binop): Add FALSE to call to exp_fold_tree_no_dot.
	(exp_trinop): Likewise.
	(exp_unop): Likewise.
	(exp_nameop): Likewise.
	(exp_get_vma): Likewise.
	(exp_get_fill): Likewise.
	(exp_get_abs_int): Likewise.
	(fold_name): Likewise. Set SEC_KEEP in output section flags.
	(exp_mark_used_section): New.

	* ldexp.h (exp_mark_used_section): New.

	* ldlang.c (lang_output_section_statement_lookup_1): Set the
	ignored field to FALSE.
	(lang_mark_used_section_1): New.
	(lang_mark_used_section): Call lang_mark_used_section_1.
	(strip_excluded_output_sections): Call lang_mark_used_section
	and check for unused sections.
	(lang_size_sections_1): Skip an output section if it should
	be ignored.
	(lang_do_assignments_1): Likewise.
	(lang_process): Don't call lang_mark_used_section here.

	* ldlang.h (lang_output_section_statement_type): Change
	all_input_readonly to bitfield. Add ignored.

--- binutils/bfd/elf32-i386.c.empty	2005-05-05 07:44:37.000000000 -0700
+++ binutils/bfd/elf32-i386.c	2005-05-07 06:58:49.000000000 -0700
@@ -1914,7 +1914,8 @@ elf_i386_size_dynamic_sections (bfd *out
 
       if (s == htab->splt
 	  || s == htab->sgot
-	  || s == htab->sgotplt)
+	  || s == htab->sgotplt
+	  || s == htab->sdynbss)
 	{
 	  /* Strip this section if we don't need it; see the
 	     comment below.  */
--- binutils/bfd/elf64-x86-64.c.empty	2005-05-05 07:44:41.000000000 -0700
+++ binutils/bfd/elf64-x86-64.c	2005-05-07 06:58:49.000000000 -0700
@@ -1624,7 +1624,8 @@ elf64_x86_64_size_dynamic_sections (bfd 
 
       if (s == htab->splt
 	  || s == htab->sgot
-	  || s == htab->sgotplt)
+	  || s == htab->sgotplt
+	  || s == htab->sdynbss)
 	{
 	  /* Strip this section if we don't need it; see the
 	     comment below.  */
--- binutils/ld/ldexp.c.empty	2005-03-15 09:35:19.000000000 -0800
+++ binutils/ld/ldexp.c	2005-05-07 09:54:41.000000000 -0700
@@ -41,8 +41,12 @@
 #include "libiberty.h"
 #include "safe-ctype.h"
 
+static etree_value_type exp_fold_tree_1
+  (etree_type *, lang_output_section_statement_type *,
+   lang_phase_type, bfd_vma, bfd_vma *, bfd_boolean);
 static etree_value_type exp_fold_tree_no_dot
-  (etree_type *, lang_output_section_statement_type *, lang_phase_type);
+  (etree_type *, lang_output_section_statement_type *, lang_phase_type,
+   bfd_boolean);
 static bfd_vma align_n
   (bfd_vma, bfd_vma);
 
@@ -219,13 +223,14 @@ fold_unary (etree_type *tree,
 	    lang_output_section_statement_type *current_section,
 	    lang_phase_type allocation_done,
 	    bfd_vma dot,
-	    bfd_vma *dotp)
+	    bfd_vma *dotp,
+	    bfd_boolean mark_used)
 {
   etree_value_type result;
 
-  result = exp_fold_tree (tree->unary.child,
-			  current_section,
-			  allocation_done, dot, dotp);
+  result = exp_fold_tree_1 (tree->unary.child,
+			    current_section,
+			    allocation_done, dot, dotp, mark_used);
   if (result.valid_p)
     {
       switch (tree->type.node_code)
@@ -308,12 +313,13 @@ fold_binary (etree_type *tree,
 	     lang_output_section_statement_type *current_section,
 	     lang_phase_type allocation_done,
 	     bfd_vma dot,
-	     bfd_vma *dotp)
+	     bfd_vma *dotp,
+	     bfd_boolean mark_used)
 {
   etree_value_type result;
 
-  result = exp_fold_tree (tree->binary.lhs, current_section,
-			  allocation_done, dot, dotp);
+  result = exp_fold_tree_1 (tree->binary.lhs, current_section,
+			    allocation_done, dot, dotp, mark_used);
 
   /* The SEGMENT_START operator is special because its first
      operand is a string, not the name of a symbol.  */
@@ -338,9 +344,10 @@ fold_binary (etree_type *tree,
     {
       etree_value_type other;
 
-      other = exp_fold_tree (tree->binary.rhs,
-			     current_section,
-			     allocation_done, dot, dotp);
+      other = exp_fold_tree_1 (tree->binary.rhs,
+			       current_section,
+			       allocation_done,
+			       dot, dotp, mark_used);
       if (other.valid_p)
 	{
 	  /* If the values are from different sections, or this is an
@@ -498,18 +505,20 @@ fold_trinary (etree_type *tree,
 	      lang_output_section_statement_type *current_section,
 	      lang_phase_type allocation_done,
 	      bfd_vma dot,
-	      bfd_vma *dotp)
+	      bfd_vma *dotp,
+	      bfd_boolean mark_used)
 {
   etree_value_type result;
 
-  result = exp_fold_tree (tree->trinary.cond, current_section,
-			  allocation_done, dot, dotp);
+  result = exp_fold_tree_1 (tree->trinary.cond, current_section,
+			    allocation_done, dot, dotp, mark_used);
   if (result.valid_p)
-    result = exp_fold_tree ((result.value
-			     ? tree->trinary.lhs
-			     : tree->trinary.rhs),
-			    current_section,
-			    allocation_done, dot, dotp);
+    result = exp_fold_tree_1 ((result.value
+			       ? tree->trinary.lhs
+			       : tree->trinary.rhs),
+			      current_section,
+			      allocation_done,
+			      dot, dotp, mark_used);
 
   return result;
 }
@@ -518,7 +527,8 @@ static etree_value_type
 fold_name (etree_type *tree,
 	   lang_output_section_statement_type *current_section,
 	   lang_phase_type allocation_done,
-	   bfd_vma dot)
+	   bfd_vma dot,
+	   bfd_boolean mark_used)
 {
   etree_value_type result;
 
@@ -596,6 +606,7 @@ fold_name (etree_type *tree,
 					 + h->u.def.section->output_offset),
 					NULL,
 					os);
+		      os->bfd_section->flags |= SEC_KEEP;
 		    }
 		}
 	    }
@@ -619,8 +630,12 @@ fold_name (etree_type *tree,
 	  lang_output_section_statement_type *os;
 
 	  os = lang_output_section_find (tree->name.name);
-	  if (os && os->processed > 0)
-	    result = new_rel (0, NULL, os);
+	  if (os)
+	    {
+	      os->bfd_section->flags |= SEC_KEEP;
+	      if (os->processed > 0)
+		result = new_rel (0, NULL, os);
+	    }
 	}
       break;
 
@@ -630,14 +645,19 @@ fold_name (etree_type *tree,
 	  lang_output_section_statement_type *os;
 
 	  os = lang_output_section_find (tree->name.name);
-	  if (os && os->processed != 0)
+	  if (os)
 	    {
-	      if (os->load_base == NULL)
-		result = new_rel (0, NULL, os);
-	      else
-		result = exp_fold_tree_no_dot (os->load_base,
-					       abs_output_section,
-					       allocation_done);
+	      os->bfd_section->flags |= SEC_KEEP;
+	      if (os->processed != 0)
+		{
+		  if (os->load_base == NULL)
+		    result = new_rel (0, NULL, os);
+		  else
+		    result = exp_fold_tree_no_dot (os->load_base,
+						   abs_output_section,
+						   allocation_done,
+						   mark_used);
+		}
 	    }
 	}
       break;
@@ -649,8 +669,12 @@ fold_name (etree_type *tree,
 	  lang_output_section_statement_type *os;
 
 	  os = lang_output_section_find (tree->name.name);
-	  if (os && os->processed > 0)
-	    result = new_abs (os->bfd_section->size / opb);
+	  if (os)
+	    {
+	      os->bfd_section->flags |= SEC_KEEP;
+	      if (os->processed > 0)
+		result = new_abs (os->bfd_section->size / opb);
+	    }
 	}
       break;
 
@@ -688,12 +712,13 @@ fold_name (etree_type *tree,
   return result;
 }
 
-etree_value_type
-exp_fold_tree (etree_type *tree,
-	       lang_output_section_statement_type *current_section,
-	       lang_phase_type allocation_done,
-	       bfd_vma dot,
-	       bfd_vma *dotp)
+static etree_value_type
+exp_fold_tree_1 (etree_type *tree,
+		 lang_output_section_statement_type *current_section,
+		 lang_phase_type allocation_done,
+		 bfd_vma dot,
+		 bfd_vma *dotp,
+		 bfd_boolean mark_used)
 {
   etree_value_type result;
 
@@ -721,26 +746,32 @@ exp_fold_tree (etree_type *tree,
       break;
 
     case etree_assert:
-      result = exp_fold_tree (tree->assert_s.child,
-			      current_section,
-			      allocation_done, dot, dotp);
-      if (result.valid_p && !result.value)
-	einfo ("%X%P: %s\n", tree->assert_s.message);
+      if (!mark_used)
+	{
+	  result = exp_fold_tree_1 (tree->assert_s.child,
+				    current_section,
+				    allocation_done, dot, dotp,
+				    mark_used);
+	  if (result.valid_p && !result.value)
+	    einfo ("%X%P: %s\n", tree->assert_s.message);
+	}
+      else
+	memset (&result, 0, sizeof (result));
       break;
 
     case etree_unary:
       result = fold_unary (tree, current_section, allocation_done,
-			   dot, dotp);
+			   dot, dotp, mark_used);
       break;
 
     case etree_binary:
       result = fold_binary (tree, current_section, allocation_done,
-			    dot, dotp);
+			    dot, dotp, mark_used);
       break;
 
     case etree_trinary:
       result = fold_trinary (tree, current_section, allocation_done,
-			     dot, dotp);
+			     dot, dotp, mark_used);
       break;
 
     case etree_assign:
@@ -757,9 +788,10 @@ exp_fold_tree (etree_type *tree,
 	    {
 	      /* Notify the folder that this is an assignment to dot.  */
 	      assigning_to_dot = TRUE;
-	      result = exp_fold_tree (tree->assign.src,
-				      current_section,
-				      allocation_done, dot, dotp);
+	      result = exp_fold_tree_1 (tree->assign.src,
+					current_section,
+					allocation_done,
+					dot, dotp, mark_used);
 	      assigning_to_dot = FALSE;
 
 	      if (! result.valid_p)
@@ -788,9 +820,9 @@ exp_fold_tree (etree_type *tree,
 	}
       else
 	{
-	  result = exp_fold_tree (tree->assign.src,
-				  current_section, allocation_done,
-				  dot, dotp);
+	  result = exp_fold_tree_1 (tree->assign.src,
+				    current_section, allocation_done,
+				    dot, dotp, mark_used);
 	  if (result.valid_p)
 	    {
 	      bfd_boolean create;
@@ -832,7 +864,8 @@ exp_fold_tree (etree_type *tree,
       break;
 
     case etree_name:
-      result = fold_name (tree, current_section, allocation_done, dot);
+      result = fold_name (tree, current_section, allocation_done, dot,
+			  mark_used);
       break;
 
     default:
@@ -844,12 +877,25 @@ exp_fold_tree (etree_type *tree,
   return result;
 }
 
+etree_value_type
+exp_fold_tree (etree_type *tree,
+	       lang_output_section_statement_type *current_section,
+	       lang_phase_type allocation_done,
+	       bfd_vma dot,
+	       bfd_vma *dotp)
+{
+  return exp_fold_tree_1 (tree, current_section, allocation_done,
+			  dot, dotp, FALSE);
+}
+
 static etree_value_type
 exp_fold_tree_no_dot (etree_type *tree,
 		      lang_output_section_statement_type *current_section,
-		      lang_phase_type allocation_done)
+		      lang_phase_type allocation_done,
+		      bfd_boolean mark_used)
 {
-  return exp_fold_tree (tree, current_section, allocation_done, 0, NULL);
+  return exp_fold_tree_1 (tree, current_section, allocation_done, 0,
+			  NULL, mark_used);
 }
 
 etree_type *
@@ -864,7 +910,7 @@ exp_binop (int code, etree_type *lhs, et
   value.type.node_class = etree_binary;
   r = exp_fold_tree_no_dot (&value,
 			    abs_output_section,
-			    lang_first_phase_enum);
+			    lang_first_phase_enum, FALSE);
   if (r.valid_p)
     {
       return exp_intop (r.value);
@@ -884,7 +930,7 @@ exp_trinop (int code, etree_type *cond, 
   value.trinary.cond = cond;
   value.trinary.rhs = rhs;
   value.type.node_class = etree_trinary;
-  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum);
+  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum, FALSE);
   if (r.valid_p)
     return exp_intop (r.value);
 
@@ -903,7 +949,7 @@ exp_unop (int code, etree_type *child)
   value.unary.child = child;
   value.unary.type.node_class = etree_unary;
   r = exp_fold_tree_no_dot (&value, abs_output_section,
-			    lang_first_phase_enum);
+			    lang_first_phase_enum, FALSE);
   if (r.valid_p)
     return exp_intop (r.value);
 
@@ -921,7 +967,7 @@ exp_nameop (int code, const char *name)
   value.name.name = name;
   value.name.type.node_class = etree_name;
 
-  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum);
+  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum, FALSE);
   if (r.valid_p)
     return exp_intop (r.value);
 
@@ -1071,7 +1117,8 @@ exp_get_vma (etree_type *tree,
 
   if (tree != NULL)
     {
-      r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+      r = exp_fold_tree_no_dot (tree, abs_output_section,
+				allocation_done, FALSE);
       if (! r.valid_p && name != NULL)
 	einfo (_("%F%S nonconstant expression for %s\n"), name);
       return r.value;
@@ -1103,7 +1150,8 @@ exp_get_fill (etree_type *tree,
   if (tree == NULL)
     return def;
 
-  r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+  r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done,
+			    FALSE);
   if (! r.valid_p && name != NULL)
     einfo (_("%F%S nonconstant expression for %s\n"), name);
 
@@ -1154,7 +1202,8 @@ exp_get_abs_int (etree_type *tree,
 		 lang_phase_type allocation_done)
 {
   etree_value_type res;
-  res = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+  res = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done,
+			      FALSE);
 
   if (res.valid_p)
     res.value += res.section->bfd_section->vma;
@@ -1173,3 +1222,91 @@ align_n (bfd_vma value, bfd_vma align)
   value = (value + align - 1) / align;
   return value * align;
 }
+
+void
+exp_mark_used_section
+  (etree_type *tree,
+   lang_output_section_statement_type *current_section)
+{
+  switch (tree->type.node_class)
+    {
+    case etree_value:
+      break;
+
+    case etree_rel:
+      break;
+
+    case etree_assert:
+      break;
+
+    case etree_unary:
+      break;
+
+    case etree_binary:
+      break;
+
+    case etree_trinary:
+      break;
+
+    case etree_assign:
+    case etree_provide:
+    case etree_provided:
+      if (tree->assign.dst[0] != '.' || tree->assign.dst[1] != 0)
+	{
+	  etree_value_type result;
+	  bfd_vma dot = 0;
+
+	  result = exp_fold_tree_1 (tree->assign.src,
+				    current_section,
+				    lang_allocating_phase_enum,
+				    dot, &dot, TRUE);
+	  if (result.valid_p)
+	    {
+	      bfd_boolean create;
+	      struct bfd_link_hash_entry *h;
+
+	      if (tree->type.node_class == etree_assign)
+		create = TRUE;
+	      else
+		create = FALSE;
+	      h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
+					create, FALSE, TRUE);
+	      if (h == NULL)
+		{
+		  if (create)
+		    einfo (_("%P%F:%s: hash creation failed\n"),
+			   tree->assign.dst);
+		}
+	      else if (tree->type.node_class == etree_provide
+		       && h->type != bfd_link_hash_new
+		       && h->type != bfd_link_hash_undefined
+		       && h->type != bfd_link_hash_common)
+		{
+		  /* Do nothing.  The symbol was defined by some
+		     object.  */
+		}
+	      else
+		{
+		  /* FIXME: Should we worry if the symbol is already
+		     defined?  */
+		  lang_update_definedness (tree->assign.dst, h);
+		  h->type = bfd_link_hash_defined;
+		  h->u.def.value = result.value;
+		  h->u.def.section = result.section->bfd_section;
+		  if (tree->type.node_class == etree_provide)
+		    tree->type.node_class = etree_provided;
+		}
+	    }
+	}
+      break;
+
+    case etree_name:
+      fold_name (tree, current_section, lang_allocating_phase_enum, 0,
+		 TRUE);
+      break;
+
+    default:
+      abort ();
+      break;
+    }
+}
--- binutils/ld/ldexp.h.empty	2004-12-22 09:30:57.000000000 -0800
+++ binutils/ld/ldexp.h	2005-05-07 09:34:05.000000000 -0700
@@ -156,5 +156,7 @@ fill_type *exp_get_fill
   (etree_type *, fill_type *, char *, lang_phase_type);
 bfd_vma exp_get_abs_int
   (etree_type *, int, char *, lang_phase_type);
+void exp_mark_used_section
+  (etree_type *, struct lang_output_section_statement_struct *);
 
 #endif
--- binutils/ld/ldlang.c.empty	2005-05-07 06:58:49.000000000 -0700
+++ binutils/ld/ldlang.c	2005-05-07 10:13:04.000000000 -0700
@@ -1083,6 +1083,7 @@ lang_output_section_statement_lookup_1 (
       lookup->bfd_section = NULL;
       lookup->processed = 0;
       lookup->constraint = constraint;
+      lookup->ignored = FALSE;
       lookup->sectype = normal_section;
       lookup->addr_tree = NULL;
       lang_list_init (&lookup->children);
@@ -3109,6 +3110,90 @@ map_input_to_output_sections
     }
 }
 
+/* Worker function for lang_mark_used_section.  Recursiveness goes
+   here.  */
+
+static void
+lang_mark_used_section_1
+  (lang_statement_union_type *s,
+   lang_output_section_statement_type *output_section_statement)
+{
+  for (; s != NULL; s = s->header.next)
+    {
+      switch (s->header.type)
+	{
+	case lang_constructors_statement_enum:
+	  break;
+
+	case lang_output_section_statement_enum:
+	  {
+	    lang_output_section_statement_type *os;
+
+	    os = &(s->output_section_statement);
+	    if (os->bfd_section != NULL)
+	      lang_mark_used_section_1 (os->children.head, os);
+	  }
+	  break;
+	case lang_wild_statement_enum:
+	  lang_mark_used_section_1 (s->wild_statement.children.head,
+				    output_section_statement);
+
+	  break;
+
+	case lang_object_symbols_statement_enum:
+	case lang_output_statement_enum:
+	case lang_target_statement_enum:
+	  break;
+	case lang_data_statement_enum:
+	  exp_mark_used_section (s->data_statement.exp,
+				 abs_output_section);
+	  break;
+
+	case lang_reloc_statement_enum:
+	  break;
+
+	case lang_input_section_enum:
+	  break;
+
+	case lang_input_statement_enum:
+	  break;
+	case lang_fill_statement_enum:
+	  break;
+	case lang_assignment_statement_enum:
+	  exp_mark_used_section (s->assignment_statement.exp,
+				 output_section_statement);
+	  break;
+	case lang_padding_statement_enum:
+	  break;
+
+	case lang_group_statement_enum:
+	  lang_mark_used_section_1 (s->group_statement.children.head,
+				    output_section_statement);
+	  break;
+
+	default:
+	  FAIL ();
+	  break;
+	case lang_address_statement_enum:
+	  break;
+	}
+    }
+}
+
+static void
+lang_mark_used_section (void)
+{
+  unsigned int gc_sections = link_info.gc_sections;
+
+  /* Callers of exp_fold_tree need to increment this.  */
+  lang_statement_iteration++;
+  lang_mark_used_section_1 (statement_list.head, abs_output_section);
+
+  link_info.gc_sections = 0;
+  bfd_gc_sections (output_bfd, &link_info);
+  link_info.gc_sections = gc_sections;
+}
+
 /* An output section might have been removed after its statement was
    added.  For example, ldemul_before_allocation can remove dynamic
    sections if they turn out to be not needed.  Clean them up here.  */
@@ -3118,32 +3203,54 @@ strip_excluded_output_sections (void)
 {
   lang_output_section_statement_type *os;
 
+  lang_mark_used_section ();
+
   for (os = &lang_output_section_statement.head->output_section_statement;
        os != NULL;
        os = os->next)
     {
-      asection *s;
+      asection *output_section;
+      bfd_boolean exclude;
 
       if (os->constraint == -1)
 	continue;
 
-      if (os->bfd_section == NULL || os->bfd_section->map_head.s == NULL)
+      output_section = os->bfd_section;
+      if (output_section == NULL)
 	continue;
 
-      for (s = os->bfd_section->map_head.s; s != NULL; s = s->map_head.s)
-	if ((s->flags & SEC_EXCLUDE) == 0)
-	  break;
+      exclude = FALSE;
+      if (output_section->map_head.s != NULL)
+	{
+	  asection *s;
 
-      os->bfd_section->map_head.link_order = NULL;
-      os->bfd_section->map_tail.link_order = NULL;
+	  for (s = output_section->map_head.s; s != NULL;
+	       s = s->map_head.s)
+	    if ((s->flags & SEC_EXCLUDE) == 0)
+	      break;
+
+	  output_section->map_head.link_order = NULL;
+	  output_section->map_tail.link_order = NULL;
+
+	  if (s == NULL)
+	    exclude = TRUE;
+	}
 
-      if (s == NULL)
+      if (exclude
+	  || (output_section->linker_has_input == 0
+	      && ((output_section->flags
+		   & (SEC_KEEP | SEC_HAS_CONTENTS)) == 0)))
 	{
-	  s = os->bfd_section;
-	  os->bfd_section = NULL;
-	  if (!bfd_section_removed_from_list (output_bfd, s))
+	  if (exclude)
+	    os->bfd_section = NULL;
+	  else
+	    /* We don't set bfd_section to NULL since bfd_section of the
+	     * removed output section statement may still be used.  */
+	    os->ignored = TRUE;
+	  if (!bfd_section_removed_from_list (output_bfd,
+					      output_section))
 	    {
-	      bfd_section_list_remove (output_bfd, s);
+	      bfd_section_list_remove (output_bfd, output_section);
 	      output_bfd->section_count--;
 	    }
 	}
@@ -3925,8 +4032,8 @@ lang_size_sections_1
 	    lang_output_section_statement_type *os;
 
 	    os = &s->output_section_statement;
-	    if (os->bfd_section == NULL)
-	      /* This section was never actually created.  */
+	    if (os->bfd_section == NULL || os->ignored)
+	      /* This section was removed or never actually created.  */
 	      break;
 
 	    /* If this is a COFF shared library section, use the size and
@@ -4421,7 +4528,7 @@ lang_do_assignments_1
 	    lang_output_section_statement_type *os;
 
 	    os = &(s->output_section_statement);
-	    if (os->bfd_section != NULL)
+	    if (os->bfd_section != NULL && !os->ignored)
 	      {
 		dot = os->bfd_section->vma;
 		lang_do_assignments_1 (os->children.head, os, os->fill, dot);
@@ -4435,7 +4542,7 @@ lang_do_assignments_1
 	      {
 		/* If nothing has been placed into the output section then
 		   it won't have a bfd_section.  */
-		if (os->bfd_section)
+		if (os->bfd_section && !os->ignored)
 		  {
 		    os->bfd_section->lma
 		      = exp_get_abs_int (os->load_base, 0, "load base",
@@ -5240,16 +5347,6 @@ lang_gc_sections (void)
     bfd_gc_sections (output_bfd, &link_info);
 }
 
-static void
-lang_mark_used_section (void)
-{
-  unsigned int gc_sections = link_info.gc_sections;
-
-  link_info.gc_sections = 0;
-  bfd_gc_sections (output_bfd, &link_info);
-  link_info.gc_sections = gc_sections;
-}
-
 void
 lang_process (void)
 {
@@ -5408,7 +5505,6 @@ lang_process (void)
     lang_check_section_addresses ();
 
   /* Final stuffs.  */
-  lang_mark_used_section ();
   ldemul_finish ();
   lang_end ();
 }
--- binutils/ld/ldlang.h.empty	2005-05-07 06:58:49.000000000 -0700
+++ binutils/ld/ldlang.h	2005-05-07 08:59:05.000000000 -0700
@@ -147,7 +147,8 @@ typedef struct lang_output_section_state
   int subsection_alignment;	/* Alignment of components.  */
   int section_alignment;	/* Alignment of start of section.  */
   int constraint;
-  bfd_boolean all_input_readonly;
+  unsigned int all_input_readonly : 1;
+  unsigned int ignored : 1; 
 
   union etree_union *load_base;
 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR 797: Alignment in empty section changes the output layout
  2005-05-05 16:12           ` H. J. Lu
@ 2005-05-06  6:20             ` Alan Modra
  2005-05-07 19:16               ` H. J. Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Alan Modra @ 2005-05-06  6:20 UTC (permalink / raw)
  To: H. J. Lu; +Cc: binutils

On Thu, May 05, 2005 at 09:02:23AM -0700, H. J. Lu wrote:
> With
> 
>   lang_size_sections (statement_list.head, abs_output_section,
>                       &statement_list.head, 0, 0, NULL,
>                       command_line.relax ? FALSE : TRUE);
>   lang_do_assignments (statement_list.head, abs_output_section, NULL,
> 0);
>   lang_reset_memory_regions ();
>   lang_mark_used_section ();
>   strip_unused_output_sections ();
> 
> at the end of strip_excluded_output_sections, I got
> failed: Bad value FAIL: PHDRS
> FAIL: PHDRS2

You need this from ppc64elf.em.

	  /* We must not cache anything from the preliminary sizing.  */
	  elf_tdata (output_bfd)->program_header_size = 0;

Perhaps a better approach would be to run a cut-down lang_do_assignments
that just keeps track of output section and symbol assignments other
than "." within output sections.  If it finds such an assignment, mark
the section as needed.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR 797: Alignment in empty section changes the output layout
  2005-05-05  6:33         ` Alan Modra
@ 2005-05-05 16:12           ` H. J. Lu
  2005-05-06  6:20             ` Alan Modra
  0 siblings, 1 reply; 17+ messages in thread
From: H. J. Lu @ 2005-05-05 16:12 UTC (permalink / raw)
  To: binutils

On Thu, May 05, 2005 at 03:26:16PM +0930, Alan Modra wrote:
> On Wed, May 04, 2005 at 10:35:44PM -0700, H. J. Lu wrote:
> > On Thu, May 05, 2005 at 02:44:56PM +0930, Alan Modra wrote:
> > > On Wed, May 04, 2005 at 09:48:17PM -0700, H. J. Lu wrote:
> > > > On Thu, May 05, 2005 at 12:07:17PM +0930, Alan Modra wrote:
> > > > > Can you please look at merging lang_mark_used_section and
> > > > > strip_unused_output_sections into strip_excluded_output_sections?
> > > > > 
> > > > > I think it should be possible if you call lang_do_assignments before
> > > > > bfd_gc_sections to ensure that linker script symbols defined inside
> > > > > output sections are in the hash table.
> > > > 
> > > > I am not sure it will work since the order is quite important. I
> > > > got many
> > > > 
> > > > /export/build/gnu/binutils-debug/build-i686-linux/ld/ld-new:
> > > > tmpdir/ld1: Not enough room for program headers (allocated 2, need 4)
> > > > /export/build/gnu/binutils-debug/build-i686-linux/ld/ld-new: final link
> > > > failed: Bad value
> > > 
> > > Did you find that you needed to run lang_size_sections early as well?
> > > If so, see emultempl/ppc64elf.em:ppc_before_allocation for what needs to
> > > be undone.
> > 
> > Same problem. ldemul_before_allocation is called after
> > map_input_to_output_sections. I guess it is hard to call
> > lang_do_assignments before it. Besides, it makes lang_process even
> > more complicated.
> 
> I meant for you to call lang_do_assignments, bfd_gc_sections and
> strip_unused_output_sections from strip_excluded_output_sections.  Is
> that what you're doing?
> 

With

  lang_size_sections (statement_list.head, abs_output_section,
                      &statement_list.head, 0, 0, NULL,
                      command_line.relax ? FALSE : TRUE);
  lang_do_assignments (statement_list.head, abs_output_section, NULL,
0);
  lang_reset_memory_regions ();
  lang_mark_used_section ();
  strip_unused_output_sections ();

at the end of strip_excluded_output_sections, I got

Running
/export/gnu/src/binutils/binutils/ld/testsuite/ld-scripts/phdrs.exp ...
/export/build/gnu/binutils-debug/build-i686-linux/ld/../gas/as-new   -o
tmpdir/phdrs.o
/export/gnu/src/binutils/binutils/ld/testsuite/ld-scripts/phdrs.s
/export/build/gnu/binutils-debug/build-i686-linux/ld/ld-new  -o
tmpdir/phdrs -T
/export/gnu/src/binutils/binutils/ld/testsuite/ld-scripts/phdrs.t
tmpdir/phdrs.o/export/build/gnu/binutils-debug/build-i686-linux/ld/ld-new:
tmpdir/phdrs: Not enough room for program headers (allocated 2, need 3)
/export/build/gnu/binutils-debug/build-i686-linux/ld/ld-new: final link
failed: Bad value FAIL: PHDRS

and

Running
/export/gnu/src/binutils/binutils/ld/testsuite/ld-scripts/phdrs2.exp
.../export/build/gnu/binutils-debug/build-i686-linux/ld/../gas/as-new
-o tmpdir/phdrs2.o
/export/gnu/src/binutils/binutils/ld/testsuite/ld-scripts/phdrs2.s
/export/build/gnu/binutils-debug/build-i686-linux/ld/ld-new  -o
tmpdir/phdrs2 -T
/export/gnu/src/binutils/binutils/ld/testsuite/ld-scripts/phdrs2.t
tmpdir/phdrs2.o
/export/build/gnu/binutils-debug/build-i686-linux/ld/../binutils/objdump
--private tmpdir/phdrs2

tmpdir/phdrs2:     file format elf32-i386

Program Header:
    LOAD off    0x00001000 vaddr 0x00800000 paddr 0x00800000 align
2**12
         filesz 0x00000004 memsz 0x00000004 flags r-x
    LOAD off    0x00001000 vaddr 0x00000000 paddr 0x00000000 align
2**12
         filesz 0x0080000c memsz 0x0080000c flags rw-

FAIL: PHDRS2


H.J.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR 797: Alignment in empty section changes the output layout
  2005-05-05  5:56       ` H. J. Lu
@ 2005-05-05  6:33         ` Alan Modra
  2005-05-05 16:12           ` H. J. Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Alan Modra @ 2005-05-05  6:33 UTC (permalink / raw)
  To: H. J. Lu; +Cc: binutils

On Wed, May 04, 2005 at 10:35:44PM -0700, H. J. Lu wrote:
> On Thu, May 05, 2005 at 02:44:56PM +0930, Alan Modra wrote:
> > On Wed, May 04, 2005 at 09:48:17PM -0700, H. J. Lu wrote:
> > > On Thu, May 05, 2005 at 12:07:17PM +0930, Alan Modra wrote:
> > > > Can you please look at merging lang_mark_used_section and
> > > > strip_unused_output_sections into strip_excluded_output_sections?
> > > > 
> > > > I think it should be possible if you call lang_do_assignments before
> > > > bfd_gc_sections to ensure that linker script symbols defined inside
> > > > output sections are in the hash table.
> > > 
> > > I am not sure it will work since the order is quite important. I
> > > got many
> > > 
> > > /export/build/gnu/binutils-debug/build-i686-linux/ld/ld-new:
> > > tmpdir/ld1: Not enough room for program headers (allocated 2, need 4)
> > > /export/build/gnu/binutils-debug/build-i686-linux/ld/ld-new: final link
> > > failed: Bad value
> > 
> > Did you find that you needed to run lang_size_sections early as well?
> > If so, see emultempl/ppc64elf.em:ppc_before_allocation for what needs to
> > be undone.
> 
> Same problem. ldemul_before_allocation is called after
> map_input_to_output_sections. I guess it is hard to call
> lang_do_assignments before it. Besides, it makes lang_process even
> more complicated.

I meant for you to call lang_do_assignments, bfd_gc_sections and
strip_unused_output_sections from strip_excluded_output_sections.  Is
that what you're doing?

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR 797: Alignment in empty section changes the output layout
  2005-05-05  5:35     ` Alan Modra
@ 2005-05-05  5:56       ` H. J. Lu
  2005-05-05  6:33         ` Alan Modra
  0 siblings, 1 reply; 17+ messages in thread
From: H. J. Lu @ 2005-05-05  5:56 UTC (permalink / raw)
  To: binutils

On Thu, May 05, 2005 at 02:44:56PM +0930, Alan Modra wrote:
> On Wed, May 04, 2005 at 09:48:17PM -0700, H. J. Lu wrote:
> > On Thu, May 05, 2005 at 12:07:17PM +0930, Alan Modra wrote:
> > > Can you please look at merging lang_mark_used_section and
> > > strip_unused_output_sections into strip_excluded_output_sections?
> > > 
> > > I think it should be possible if you call lang_do_assignments before
> > > bfd_gc_sections to ensure that linker script symbols defined inside
> > > output sections are in the hash table.
> > 
> > I am not sure it will work since the order is quite important. I
> > got many
> > 
> > /export/build/gnu/binutils-debug/build-i686-linux/ld/ld-new:
> > tmpdir/ld1: Not enough room for program headers (allocated 2, need 4)
> > /export/build/gnu/binutils-debug/build-i686-linux/ld/ld-new: final link
> > failed: Bad value
> 
> Did you find that you needed to run lang_size_sections early as well?
> If so, see emultempl/ppc64elf.em:ppc_before_allocation for what needs to
> be undone.

Same problem. ldemul_before_allocation is called after
map_input_to_output_sections. I guess it is hard to call
lang_do_assignments before it. Besides, it makes lang_process even
more complicated.


H.J.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR 797: Alignment in empty section changes the output layout
  2005-05-05  4:52   ` H. J. Lu
@ 2005-05-05  5:35     ` Alan Modra
  2005-05-05  5:56       ` H. J. Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Alan Modra @ 2005-05-05  5:35 UTC (permalink / raw)
  To: H. J. Lu; +Cc: binutils

On Wed, May 04, 2005 at 09:48:17PM -0700, H. J. Lu wrote:
> On Thu, May 05, 2005 at 12:07:17PM +0930, Alan Modra wrote:
> > Can you please look at merging lang_mark_used_section and
> > strip_unused_output_sections into strip_excluded_output_sections?
> > 
> > I think it should be possible if you call lang_do_assignments before
> > bfd_gc_sections to ensure that linker script symbols defined inside
> > output sections are in the hash table.
> 
> I am not sure it will work since the order is quite important. I
> got many
> 
> /export/build/gnu/binutils-debug/build-i686-linux/ld/ld-new:
> tmpdir/ld1: Not enough room for program headers (allocated 2, need 4)
> /export/build/gnu/binutils-debug/build-i686-linux/ld/ld-new: final link
> failed: Bad value

Did you find that you needed to run lang_size_sections early as well?
If so, see emultempl/ppc64elf.em:ppc_before_allocation for what needs to
be undone.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR 797: Alignment in empty section changes the output layout
  2005-05-05  3:48 ` Alan Modra
@ 2005-05-05  4:52   ` H. J. Lu
  2005-05-05  5:35     ` Alan Modra
  0 siblings, 1 reply; 17+ messages in thread
From: H. J. Lu @ 2005-05-05  4:52 UTC (permalink / raw)
  To: binutils

On Thu, May 05, 2005 at 12:07:17PM +0930, Alan Modra wrote:
> On Wed, May 04, 2005 at 11:09:41AM -0700, H. J. Lu wrote:
> > +  if (command_line.relax || !link_info.relocatable)
> > +    {
> >        /* Final extra sizing to report errors.  */
> >        lang_do_assignments (statement_list.head, abs_output_section, NULL, 0);
> > +      if (!link_info.relocatable)
> > +	{
> > +	  lang_mark_used_section ();
> > +	  /* Do it here so that the unused output_sections won't affect
> > +	     memory layout.  */ 
> > +	  strip_unused_output_sections ();
> > +	}
> 
> Can you please look at merging lang_mark_used_section and
> strip_unused_output_sections into strip_excluded_output_sections?
> 
> I think it should be possible if you call lang_do_assignments before
> bfd_gc_sections to ensure that linker script symbols defined inside
> output sections are in the hash table.

I am not sure it will work since the order is quite important. I
got many

/export/build/gnu/binutils-debug/build-i686-linux/ld/ld-new:
tmpdir/ld1: Not enough room for program headers (allocated 2, need 4)
/export/build/gnu/binutils-debug/build-i686-linux/ld/ld-new: final link
failed: Bad value


H.J.
H.J.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR 797: Alignment in empty section changes the output layout
  2005-05-04 19:53 H. J. Lu
@ 2005-05-05  3:48 ` Alan Modra
  2005-05-05  4:52   ` H. J. Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Alan Modra @ 2005-05-05  3:48 UTC (permalink / raw)
  To: H. J. Lu; +Cc: binutils

On Wed, May 04, 2005 at 11:09:41AM -0700, H. J. Lu wrote:
> +  if (command_line.relax || !link_info.relocatable)
> +    {
>        /* Final extra sizing to report errors.  */
>        lang_do_assignments (statement_list.head, abs_output_section, NULL, 0);
> +      if (!link_info.relocatable)
> +	{
> +	  lang_mark_used_section ();
> +	  /* Do it here so that the unused output_sections won't affect
> +	     memory layout.  */ 
> +	  strip_unused_output_sections ();
> +	}

Can you please look at merging lang_mark_used_section and
strip_unused_output_sections into strip_excluded_output_sections?

I think it should be possible if you call lang_do_assignments before
bfd_gc_sections to ensure that linker script symbols defined inside
output sections are in the hash table.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 17+ messages in thread

* PATCH: PR 797: Alignment in empty section changes the output layout
@ 2005-05-04 19:53 H. J. Lu
  2005-05-05  3:48 ` Alan Modra
  0 siblings, 1 reply; 17+ messages in thread
From: H. J. Lu @ 2005-05-04 19:53 UTC (permalink / raw)
  To: binutils

The recent linker change makes this bug easier to fix. Here is an
updated patch.


H.J.
---
bfd/

2005-05-04  H.J. Lu  <hongjiu.lu@intel.com>

	PR 797
	* elf32-i386.c (elf_i386_size_dynamic_sections): Also remove
	empty sdynbss section.
	* elf64-x86-64.c (elf64_x86_64_size_dynamic_sections): Likewise.

ld/

2005-05-04  H.J. Lu  <hongjiu.lu@intel.com>

	PR 797
	* ldlang.c (lang_output_section_statement_lookup_1): Set the
	ignored field to FALSE.
	(strip_unused_output_sections): New.
	(strip_excluded_or_unused_output_sections): This. Accept an
	argument to check for unused sections.
	(lang_size_sections_1): Skip an output section if it should
	be ignored.
	(lang_do_assignments_1): Likewise.
	(lang_process): Call strip_unused_output_sections to remove
	unused output sections after lang_mark_used_section.

	* ldlang.h (lang_output_section_statement_type): Change
	all_input_readonly to bitfield. Add ignored.

--- binutils/bfd/elf32-i386.c.empty	2005-05-04 08:52:10.000000000 -0700
+++ binutils/bfd/elf32-i386.c	2005-05-04 10:08:02.000000000 -0700
@@ -1830,7 +1830,8 @@ elf_i386_size_dynamic_sections (bfd *out
 
       if (s == htab->splt
 	  || s == htab->sgot
-	  || s == htab->sgotplt)
+	  || s == htab->sgotplt
+	  || s == htab->sdynbss)
 	{
 	  /* Strip this section if we don't need it; see the
 	     comment below.  */
--- binutils/bfd/elf64-x86-64.c.empty	2005-05-04 08:52:16.000000000 -0700
+++ binutils/bfd/elf64-x86-64.c	2005-05-04 10:08:02.000000000 -0700
@@ -1622,7 +1622,8 @@ elf64_x86_64_size_dynamic_sections (bfd 
 
       if (s == htab->splt
 	  || s == htab->sgot
-	  || s == htab->sgotplt)
+	  || s == htab->sgotplt
+	  || s == htab->sdynbss)
 	{
 	  /* Strip this section if we don't need it; see the
 	     comment below.  */
--- binutils/ld/ldlang.c.empty	2005-05-04 08:52:34.000000000 -0700
+++ binutils/ld/ldlang.c	2005-05-04 11:03:09.000000000 -0700
@@ -1022,6 +1022,7 @@ lang_output_section_statement_lookup_1 (
       lookup->bfd_section = NULL;
       lookup->processed = 0;
       lookup->constraint = constraint;
+      lookup->ignored = FALSE;
       lookup->sectype = normal_section;
       lookup->addr_tree = NULL;
       lang_list_init (&lookup->children);
@@ -3084,6 +3085,41 @@ strip_excluded_output_sections (void)
   stripped_excluded_sections = TRUE;
 }
 
+/* An output section might have been removed after its statement was
+   added if it isn't used at all. Clean them up here.  */
+
+static void
+strip_unused_output_sections (void)
+{
+  lang_output_section_statement_type *os;
+
+  for (os = &lang_output_section_statement.head->output_section_statement;
+       os != NULL;
+       os = os->next)
+    {
+      asection *s;
+
+      if (os->constraint == -1)
+	continue;
+
+      s = os->bfd_section;
+
+      if (s != NULL
+	  && s->linker_has_input == 0
+	  && (s->flags & (SEC_KEEP | SEC_HAS_CONTENTS)) == 0)
+	{
+	  /* We don't set bfd_section to NULL since bfd_section of the
+	     removed output section statement may still be used.  */
+	  os->ignored = TRUE;
+	  if (!bfd_section_removed_from_list (output_bfd, s))
+	    {
+	      bfd_section_list_remove (output_bfd, s);
+	      output_bfd->section_count--;
+	    }
+	}
+    }
+}
+
 static void
 print_output_section_statement
   (lang_output_section_statement_type *output_section_statement)
@@ -3855,8 +3891,8 @@ lang_size_sections_1
 	    lang_output_section_statement_type *os;
 
 	    os = &s->output_section_statement;
-	    if (os->bfd_section == NULL)
-	      /* This section was never actually created.  */
+	    if (os->bfd_section == NULL || os->ignored)
+	      /* This section was removed or never actually created.  */
 	      break;
 
 	    /* If this is a COFF shared library section, use the size and
@@ -4351,7 +4387,7 @@ lang_do_assignments_1
 	    lang_output_section_statement_type *os;
 
 	    os = &(s->output_section_statement);
-	    if (os->bfd_section != NULL)
+	    if (os->bfd_section != NULL && !os->ignored)
 	      {
 		dot = os->bfd_section->vma;
 		lang_do_assignments_1 (os->children.head, os, os->fill, dot);
@@ -4365,7 +4401,7 @@ lang_do_assignments_1
 	      {
 		/* If nothing has been placed into the output section then
 		   it won't have a bfd_section.  */
-		if (os->bfd_section)
+		if (os->bfd_section && !os->ignored)
 		  {
 		    os->bfd_section->lma
 		      = exp_get_abs_int (os->load_base, 0, "load base",
@@ -5301,9 +5337,19 @@ lang_process (void)
 	    }
 	}
       while (relax_again);
+    }
 
+  if (command_line.relax || !link_info.relocatable)
+    {
       /* Final extra sizing to report errors.  */
       lang_do_assignments (statement_list.head, abs_output_section, NULL, 0);
+      if (!link_info.relocatable)
+	{
+	  lang_mark_used_section ();
+	  /* Do it here so that the unused output_sections won't affect
+	     memory layout.  */ 
+	  strip_unused_output_sections ();
+	}
       lang_reset_memory_regions ();
       lang_size_sections (statement_list.head, abs_output_section,
 			  &statement_list.head, 0, 0, NULL, TRUE);
@@ -5327,7 +5373,7 @@ lang_process (void)
     lang_check_section_addresses ();
 
   /* Final stuffs.  */
-  lang_mark_used_section ();
+
   ldemul_finish ();
   lang_finish ();
 }
--- binutils/ld/ldlang.h.empty	2005-05-04 08:52:34.000000000 -0700
+++ binutils/ld/ldlang.h	2005-05-04 10:36:53.000000000 -0700
@@ -147,7 +147,8 @@ typedef struct lang_output_section_state
   int subsection_alignment;	/* Alignment of components.  */
   int section_alignment;	/* Alignment of start of section.  */
   int constraint;
-  bfd_boolean all_input_readonly;
+  unsigned int all_input_readonly : 1;
+  unsigned int ignored : 1; 
 
   union etree_union *load_base;
 

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2005-05-17 15:10 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-03-24 11:45 PATCH: PR 797: Alignment in empty section changes the output layout H. J. Lu
2005-03-25  2:22 ` H. J. Lu
2005-03-29  4:21   ` Alan Modra
2005-03-29  7:13     ` H. J. Lu
2005-03-29  8:12       ` Alan Modra
2005-03-30 16:30         ` H. J. Lu
2005-05-04 19:53 H. J. Lu
2005-05-05  3:48 ` Alan Modra
2005-05-05  4:52   ` H. J. Lu
2005-05-05  5:35     ` Alan Modra
2005-05-05  5:56       ` H. J. Lu
2005-05-05  6:33         ` Alan Modra
2005-05-05 16:12           ` H. J. Lu
2005-05-06  6:20             ` Alan Modra
2005-05-07 19:16               ` H. J. Lu
2005-05-07 20:08                 ` H. J. Lu
2005-05-17 15:13                   ` Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).