PATCH: IA64 linker relaxation bug

H. J. Lu hjl@lucon.org
Wed Nov 5 00:10:00 GMT 2003


On Sat, Nov 01, 2003 at 02:37:29AM +0100, Andreas Schwab wrote:
> The testcase at <ftp://ftp.suse.com/pub/people/schwab/ia64-relax.tar.bz2>
> demonstrates a bug in the linker relaxation on ia64:
> 
> $ make
> ld -o temacs temacs.o libncurses.so libm.so libc.so elf-init.oS crtn.o
> elf-init.oS(.text+0x101): In function `__libc_csu_init':
> : relocation truncated to fit: GPREL22 __init_array_start
> make: *** [temacs] Error 1
> 
> The problem is that __init_array_start is changing its value multiple
> times during linking, always alternating between 0x6000000000000430 and
> 0x6000000000004fa0.  There is an LTOFF22X relocation against this symbol,
> and by the time the relaxing pass looks at this relocation the value of
> __init_array_start is 0x6000000000004fa0 which is close enough to the gp
> value.  But the final value happens to be 0x6000000000000430, outside of
> the range of a GPREL22 relocation.
> 

The problem is lang_do_assignments assigns 0x6000000000004fa0 and
lang_size_sections assigns 0x6000000000000430. The final one is
0x6000000000000430.

> This bug is reproducable both with mainline and 2.14 branch.  I think it
> is a side effect of
> <http://sources.redhat.com/ml/binutils/2001-02/msg00304.html>.
> 

I am testing this patch. Does this make any senses?


H.J.
-------------- next part --------------
2003-11-04  H.J. Lu  <hongjiu.lu@intel.com>

	* ldlang.c (lang_process): Move the relax finalize pass after
	all sizes are finalized.

--- ld/ldlang.c.relax	2003-11-04 14:25:03.000000000 -0800
+++ ld/ldlang.c	2003-11-04 15:48:24.000000000 -0800
@@ -4257,14 +4257,6 @@ lang_process (void)
 	     globals are, so can make a better guess.  */
 	  lang_size_sections (statement_list.head, abs_output_section,
 			      &statement_list.head, 0, 0, &relax_again, FALSE);
-
-	  /* If the normal relax is done and the relax finalize pass
-	     is not performed yet, we perform another relax pass.  */
-	  if (!relax_again && !link_info.relax_finalizing)
-	    {
-	      link_info.relax_finalizing = TRUE;
-	      relax_again = TRUE;
-	    }
 	}
       while (relax_again);
 
@@ -4273,6 +4265,15 @@ lang_process (void)
       lang_do_assignments (statement_list.head, abs_output_section, NULL, 0);
       lang_size_sections (statement_list.head, abs_output_section,
 			  &statement_list.head, 0, 0, NULL, TRUE);
+
+      /* The relax finalize pass should be done after all sizes are
+	 finalized and cause no size change. */
+      link_info.relax_finalizing = TRUE;
+      relax_again = TRUE;
+      lang_reset_memory_regions ();
+      lang_size_sections (statement_list.head, abs_output_section,
+			  &statement_list.head, 0, 0, &relax_again,
+			  FALSE);
     }
 
   /* See if anything special should be done now we know how big


More information about the Binutils mailing list