This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] avoid premature errors when linking with relaxation


This patch fixes a problem that we have encountered with the linker.  The 
problem occurs when the original sections from the input files are too big to 
fit in the space available in the output section, but when linker relaxation 
is enabled, the sections shrink enough so that they fit.  This should be OK 
but the linker reports it as an error.  Even if the final result of the 
relaxation is still too big, the linker ends up reporting the error multiple 
times, once for each iteration of relaxation.

The root cause is that lang_size_sections() always calls os_region_check().  
It seems that os_region_check() should be called only for the last invocation 
of lang_size_sections().  The patch adds another argument to 
lang_size_sections to indicate whether os_region_check() should be called.

This patch has been tested extensively with the Xtensa port of binutils 2.11 
and a fair amount with 2.12.  After porting the patch to binutils mainline, I 
built it for x86-linux and ran the ld testsuite without any regressions.


2003-02-18  Bob Wilson  <bob.wilson@acm.org>

	* ldlang.c (lang_size_sections_1): Add CHECK_REGIONS argument and only
	call os_region_check when it is set.
	(lang_size_sections): Add CHECK_REGIONS argument and pass it through to
	lang_size_sections_1.
	(lang_process): Change lang_size_sections calls to set CHECK_REGIONS
	only for the last call, not on every relaxation iteration.
	* ldlang.h (lang_size_sections): Update prototype.
	* pe-dll.c (pe_dll_fill_sections): Set CHECK_REGIONS argument in calls
	to lang_size_sections.
	(pe_exe_fill_sections): Likewise.
	* emultempl/elf32.em (gld${EMULATION_NAME}_finish): Likewise.
	* emultempl/hppaelf.em (hppaelf_layout_sections_again): Likewise.
	* emultempl/ppc64elf.em (ppc_before_allocation): Likewise.
	(ppc_layout_sections_again): Likewise.

Index: ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.108
diff -c -3 -r1.108 ldlang.c
*** ldlang.c	2 Jan 2003 03:53:53 -0000	1.108
--- ldlang.c	15 Feb 2003 01:04:15 -0000
***************
*** 201,207 ****
  	   struct memory_region_struct *, etree_type *, bfd_vma));
  static bfd_vma lang_size_sections_1
    PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *,
! 	   lang_statement_union_type **, fill_type *, bfd_vma, bfd_boolean *));
  typedef void (*callback_t)
    PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
  	   lang_input_statement_type *, PTR));
--- 201,208 ----
  	   struct memory_region_struct *, etree_type *, bfd_vma));
  static bfd_vma lang_size_sections_1
    PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *,
! 	   lang_statement_union_type **, fill_type *, bfd_vma, bfd_boolean *,
! 	   bfd_boolean));
  typedef void (*callback_t)
    PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
  	   lang_input_statement_type *, PTR));
***************
*** 2971,2983 ****
  /* Set the sizes for all the output sections.  */
  
  static bfd_vma
! lang_size_sections_1 (s, output_section_statement, prev, fill, dot, relax)
       lang_statement_union_type *s;
       lang_output_section_statement_type *output_section_statement;
       lang_statement_union_type **prev;
       fill_type *fill;
       bfd_vma dot;
       bfd_boolean *relax;
  {
    unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
  						ldfile_output_machine);
--- 2972,2986 ----
  /* Set the sizes for all the output sections.  */
  
  static bfd_vma
! lang_size_sections_1 (s, output_section_statement, prev, fill, dot, relax,
! 		      check_regions)
       lang_statement_union_type *s;
       lang_output_section_statement_type *output_section_statement;
       lang_statement_union_type **prev;
       fill_type *fill;
       bfd_vma dot;
       bfd_boolean *relax;
+      bfd_boolean check_regions;
  {
    unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
  						ldfile_output_machine);
***************
*** 3046,3051 ****
--- 3049,3055 ----
  			 & (SEC_ALLOC | SEC_LOAD)) != 0
  			&& (bfd_get_section_flags (output_bfd, os->bfd_section)
  			    & SEC_NEVER_LOAD) == 0
+ 			&& check_regions
  			&& ! link_info.relocateable
  			&& strcmp (os->region->name, "*default*") == 0
  			&& lang_memory_region_list != NULL
***************
*** 3098,3104 ****
  	      }
  
  	    lang_size_sections_1 (os->children.head, os, &os->children.head,
! 				  os->fill, dot, relax);
  
  	    /* Put the section within the requested block size, or
  	       align at the block boundary.  */
--- 3102,3108 ----
  	      }
  
  	    lang_size_sections_1 (os->children.head, os, &os->children.head,
! 				  os->fill, dot, relax, check_regions);
  
  	    /* Put the section within the requested block size, or
  	       align at the block boundary.  */
***************
*** 3140,3147 ****
  		os->region->current = dot;
  
  		/* Make sure the new address is within the region.  */
! 		os_region_check (os, os->region, os->addr_tree,
! 				 os->bfd_section->vma);
  
  		/* If there's no load address specified, use the run
  		   region as the load region.  */
--- 3144,3152 ----
  		os->region->current = dot;
  
  		/* Make sure the new address is within the region.  */
! 		if (check_regions)
! 		  os_region_check (os, os->region, os->addr_tree,
! 				   os->bfd_section->vma);
  
  		/* If there's no load address specified, use the run
  		   region as the load region.  */
***************
*** 3154,3161 ****
  		    os->load_base = exp_intop (os->lma_region->current);
  		    os->lma_region->current +=
  		      os->bfd_section->_raw_size / opb;
! 		    os_region_check (os, os->lma_region, NULL,
! 				     os->bfd_section->lma);
  		  }
  	      }
  	  }
--- 3159,3167 ----
  		    os->load_base = exp_intop (os->lma_region->current);
  		    os->lma_region->current +=
  		      os->bfd_section->_raw_size / opb;
! 		    if (check_regions)
! 		      os_region_check (os, os->lma_region, NULL,
! 				       os->bfd_section->lma);
  		  }
  	      }
  	  }
***************
*** 3165,3171 ****
  	  dot = lang_size_sections_1 (constructor_list.head,
  				      output_section_statement,
  				      &s->wild_statement.children.head,
! 				      fill, dot, relax);
  	  break;
  
  	case lang_data_statement_enum:
--- 3171,3177 ----
  	  dot = lang_size_sections_1 (constructor_list.head,
  				      output_section_statement,
  				      &s->wild_statement.children.head,
! 				      fill, dot, relax, check_regions);
  	  break;
  
  	case lang_data_statement_enum:
***************
*** 3229,3235 ****
  	  dot = lang_size_sections_1 (s->wild_statement.children.head,
  				      output_section_statement,
  				      &s->wild_statement.children.head,
! 				      fill, dot, relax);
  
  	  break;
  
--- 3235,3241 ----
  	  dot = lang_size_sections_1 (s->wild_statement.children.head,
  				      output_section_statement,
  				      &s->wild_statement.children.head,
! 				      fill, dot, relax, check_regions);
  
  	  break;
  
***************
*** 3327,3333 ****
  	  dot = lang_size_sections_1 (s->group_statement.children.head,
  				      output_section_statement,
  				      &s->group_statement.children.head,
! 				      fill, dot, relax);
  	  break;
  
  	default:
--- 3333,3339 ----
  	  dot = lang_size_sections_1 (s->group_statement.children.head,
  				      output_section_statement,
  				      &s->group_statement.children.head,
! 				      fill, dot, relax, check_regions);
  	  break;
  
  	default:
***************
*** 3344,3362 ****
  }
  
  bfd_vma
! lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
       lang_statement_union_type *s;
       lang_output_section_statement_type *output_section_statement;
       lang_statement_union_type **prev;
       fill_type *fill;
       bfd_vma dot;
       bfd_boolean *relax;
  {
    bfd_vma result;
  
    exp_data_seg.phase = exp_dataseg_none;
    result = lang_size_sections_1 (s, output_section_statement, prev, fill,
! 				 dot, relax);
    if (exp_data_seg.phase == exp_dataseg_end_seen)
      {
        /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_END pair was seen, check whether
--- 3350,3370 ----
  }
  
  bfd_vma
! lang_size_sections (s, output_section_statement, prev, fill, dot, relax,
! 		    check_regions)
       lang_statement_union_type *s;
       lang_output_section_statement_type *output_section_statement;
       lang_statement_union_type **prev;
       fill_type *fill;
       bfd_vma dot;
       bfd_boolean *relax;
+      bfd_boolean check_regions;
  {
    bfd_vma result;
  
    exp_data_seg.phase = exp_dataseg_none;
    result = lang_size_sections_1 (s, output_section_statement, prev, fill,
! 				 dot, relax, check_regions);
    if (exp_data_seg.phase == exp_dataseg_end_seen)
      {
        /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_END pair was seen, check whether
***************
*** 3372,3378 ****
  	{
  	  exp_data_seg.phase = exp_dataseg_adjust;
  	  result = lang_size_sections_1 (s, output_section_statement, prev,
! 					 fill, dot, relax);
  	}
      }
  
--- 3380,3386 ----
  	{
  	  exp_data_seg.phase = exp_dataseg_adjust;
  	  result = lang_size_sections_1 (s, output_section_statement, prev,
! 					 fill, dot, relax, check_regions);
  	}
      }
  
***************
*** 4348,4354 ****
    /* Size up the sections.  */
    lang_size_sections (statement_list.head,
  		      abs_output_section,
! 		      &statement_list.head, 0, (bfd_vma) 0, NULL);
  
    /* Now run around and relax if we can.  */
    if (command_line.relax)
--- 4356,4363 ----
    /* Size up the sections.  */
    lang_size_sections (statement_list.head,
  		      abs_output_section,
! 		      &statement_list.head, 0, (bfd_vma) 0, NULL,
! 		      command_line.relax ? FALSE : TRUE);
  
    /* Now run around and relax if we can.  */
    if (command_line.relax)
***************
*** 4377,4385 ****
  	  lang_size_sections (statement_list.head,
  			      abs_output_section,
  			      &statement_list.head, 0, (bfd_vma) 0,
! 			      &relax_again);
  	}
        while (relax_again);
      }
  
    /* See if anything special should be done now we know how big
--- 4386,4404 ----
  	  lang_size_sections (statement_list.head,
  			      abs_output_section,
  			      &statement_list.head, 0, (bfd_vma) 0,
! 			      &relax_again, FALSE);
  	}
        while (relax_again);
+ 
+       /* Final extra sizing to report errors.  */
+       lang_reset_memory_regions ();
+       lang_do_assignments (statement_list.head,
+ 			   abs_output_section,
+ 			   (fill_type *) 0, (bfd_vma) 0);
+       lang_size_sections (statement_list.head,
+ 			  abs_output_section,
+ 			  &statement_list.head, 0, (bfd_vma) 0, 
+ 			  NULL, TRUE);
      }
  
    /* See if anything special should be done now we know how big
Index: ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.25
diff -c -3 -r1.25 ldlang.h
*** ldlang.h	8 Dec 2002 03:56:04 -0000	1.25
--- ldlang.h	15 Feb 2003 01:04:15 -0000
***************
*** 476,482 ****
    PARAMS ((lang_statement_union_type *s,
  	   lang_output_section_statement_type *output_section_statement,
  	   lang_statement_union_type **prev, fill_type *fill,
! 	   bfd_vma dot, bfd_boolean *relax));
  extern void lang_enter_group
    PARAMS ((void));
  extern void lang_leave_group
--- 476,482 ----
    PARAMS ((lang_statement_union_type *s,
  	   lang_output_section_statement_type *output_section_statement,
  	   lang_statement_union_type **prev, fill_type *fill,
! 	   bfd_vma dot, bfd_boolean *relax, bfd_boolean check_regions));
  extern void lang_enter_group
    PARAMS ((void));
  extern void lang_leave_group
Index: pe-dll.c
===================================================================
RCS file: /cvs/src/src/ld/pe-dll.c,v
retrieving revision 1.54
diff -c -3 -r1.54 pe-dll.c
*** pe-dll.c	28 Jan 2003 11:39:43 -0000	1.54
--- pe-dll.c	15 Feb 2003 01:04:15 -0000
***************
*** 2694,2700 ****
  
        /* Resize the sections.  */
        lang_size_sections (stat_ptr->head, abs_output_section,
! 			  &stat_ptr->head, 0, (bfd_vma) 0, NULL);
  
        /* Redo special stuff.  */
        ldemul_after_allocation ();
--- 2694,2700 ----
  
        /* 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 ();
***************
*** 2728,2734 ****
  
        /* Resize the sections.  */
        lang_size_sections (stat_ptr->head, abs_output_section,
! 			  &stat_ptr->head, 0, (bfd_vma) 0, NULL);
  
        /* Redo special stuff.  */
        ldemul_after_allocation ();
--- 2728,2734 ----
  
        /* 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 ();
Index: emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.90
diff -c -3 -r1.90 elf32.em
*** emultempl/elf32.em	3 Feb 2003 17:47:23 -0000	1.90
--- emultempl/elf32.em	15 Feb 2003 01:04:15 -0000
***************
*** 1427,1433 ****
  
        /* Resize the sections.  */
        lang_size_sections (stat_ptr->head, abs_output_section,
! 			  &stat_ptr->head, 0, (bfd_vma) 0, NULL);
  
        /* Redo special stuff.  */
        ldemul_after_allocation ();
--- 1427,1433 ----
  
        /* 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 ();
Index: emultempl/hppaelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/hppaelf.em,v
retrieving revision 1.26
diff -c -3 -r1.26 hppaelf.em
*** emultempl/hppaelf.em	11 Feb 2003 02:20:30 -0000	1.26
--- emultempl/hppaelf.em	15 Feb 2003 01:04:15 -0000
***************
*** 231,237 ****
  
    /* Resize the sections.  */
    lang_size_sections (stat_ptr->head, abs_output_section,
! 		      &stat_ptr->head, 0, (bfd_vma) 0, NULL);
  
    /* Redo special stuff.  */
    ldemul_after_allocation ();
--- 231,237 ----
  
    /* 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 ();
Index: emultempl/ppc64elf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/ppc64elf.em,v
retrieving revision 1.14
diff -c -3 -r1.14 ppc64elf.em
*** emultempl/ppc64elf.em	17 Feb 2003 22:49:24 -0000	1.14
--- emultempl/ppc64elf.em	18 Feb 2003 17:28:01 -0000
***************
*** 118,124 ****
  	  /* Size the sections.  This is premature, but we want to know the
  	     TLS segment layout so that certain optimizations can be done.  */
  	  lang_size_sections (stat_ptr->head, abs_output_section,
! 			      &stat_ptr->head, 0, (bfd_vma) 0, NULL);
  
  	  if (!ppc64_elf_tls_optimize (output_bfd, &link_info))
  	    {
--- 118,124 ----
  	  /* Size the sections.  This is premature, but we want to know the
  	     TLS segment layout so that certain optimizations can be done.  */
  	  lang_size_sections (stat_ptr->head, abs_output_section,
! 			      &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
  
  	  if (!ppc64_elf_tls_optimize (output_bfd, &link_info))
  	    {
***************
*** 273,279 ****
  
    /* Resize the sections.  */
    lang_size_sections (stat_ptr->head, abs_output_section,
! 		      &stat_ptr->head, 0, (bfd_vma) 0, NULL);
  
    /* Recalculate TOC base.  */
    ldemul_after_allocation ();
--- 273,279 ----
  
    /* Resize the sections.  */
    lang_size_sections (stat_ptr->head, abs_output_section,
! 		      &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
  
    /* Recalculate TOC base.  */
    ldemul_after_allocation ();

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]