[PATCH/RFA] Fix C-referenceable sections with explicit LMAs

Jason R Thorpe thorpej@wasabisystems.com
Fri Dec 6 17:18:00 GMT 2002


On Fri, Dec 06, 2002 at 03:44:20PM -0800, Jason R Thorpe wrote:

 > On Sat, Dec 07, 2002 at 09:02:03AM +1030, Alan Modra wrote:
 > 
 >  > No way.  You can't change SIZEOF to mean "size of the output section
 >  > specified + random other following output sections"
 > 
 > Except that they're not "random other following output sections".  They're
 > sections that are effectively added to the named section by another feature
 > of the linker, and you can't name those orphans, because it breaks actually
 > using that other feature.
 > 
 > I realized while having lunch that my test case actually masks a potential
 > failure mode.  I will adjust it so that it shows the bogus behavior of not
 > adjusting SIZEOF.

Ok, the following fixes the test case so that it actually demonstrates
why not adjusting SIZEOF doesn't work properly.  Without my change to
SIZEOF to account for orphans that are added to the section, the linker
will produce the following error:

arm-unknown-netbsdelf1.7-ld: section .data [10800008 -> 1080000b] overlaps section link_set_1 [10800008 -> 1080000b]

...and with my change, the test case passes.

Here's the updated patch, including test case.

	* ldexp.c (fold_name): When handling SIZEOF, apply any size
	adjustment that has been recorded for the section.
	* ldlang.c (lang_output_section_statement_lookup): Initialize
	size_adj member.
	* ldlang.h (lang_output_section_statement_type): Add size_adj
	members.
	* emultempl/elf32.em (place_orphan): If no .rodata output section
	is present, allow read-only data to be placed with .text.  Record
	a size adjustment of the output section for each orphan placed with
	it.

	* ld-scripts/refsec-lma.exp: New test.
	* ld-scripts/refsec-lma.s: New test.
	* ld-scripts/refsec-lma.t: New test.

	* lib/ld-lib.exp (is_elf_format): Match NetBSD ELF targets.

-- 
        -- Jason R. Thorpe <thorpej@wasabisystems.com>
-------------- next part --------------
Index: ldexp.c
===================================================================
RCS file: /cvs/src/src/ld/ldexp.c,v
retrieving revision 1.22
diff -c -r1.22 ldexp.c
*** ldexp.c	30 Nov 2002 08:39:45 -0000	1.22
--- ldexp.c	7 Dec 2002 01:01:23 -0000
***************
*** 647,652 ****
--- 647,658 ----
  	  os = lang_output_section_find (tree->name.name);
  	  check (os, tree->name.name, "SIZEOF");
  	  result = new_abs (os->bfd_section->_raw_size / opb);
+ 
+ 	  /* If the output section has a size adjustment, apply it.  */
+ 	  if (os->size_adj)
+ 	    result = exp_fold_tree_no_dot
+ 	      (exp_binop ('+', exp_intop (result.value), os->size_adj),
+ 	       abs_output_section, allocation_done);
  	}
        else
  	result = invalid ();
Index: ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.106
diff -c -r1.106 ldlang.c
*** ldlang.c	6 Dec 2002 22:33:18 -0000	1.106
--- ldlang.c	7 Dec 2002 01:01:27 -0000
***************
*** 794,799 ****
--- 794,800 ----
        lookup->load_base = (union etree_union *) NULL;
        lookup->update_dot_tree = NULL;
        lookup->phdrs = NULL;
+       lookup->size_adj = (union etree_union *) NULL;
  
        lang_statement_append (&lang_output_section_statement,
  			     (lang_statement_union_type *) lookup,
Index: ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.24
diff -c -r1.24 ldlang.h
*** ldlang.h	30 Nov 2002 08:39:45 -0000	1.24
--- ldlang.h	7 Dec 2002 01:01:28 -0000
***************
*** 135,140 ****
--- 135,145 ----
  
    union etree_union *load_base;
  
+   /* This  member is used when sorting orphans after this section.
+      size_adj contains an expression tree representing the change
+      in effective size of this section caused by adding the orphans.  */
+   union etree_union *size_adj;
+ 
    /* If non-null, an expression to evaluate after setting the section's
       size.  The expression is evaluated inside REGION (above) with '.'
       set to the end of the section.  Used in the last overlay section
Index: emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.86
diff -c -r1.86 elf32.em
*** emultempl/elf32.em	4 Dec 2002 23:56:14 -0000	1.86
--- emultempl/elf32.em	7 Dec 2002 01:01:29 -0000
***************
*** 1179,1185 ****
    else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
  	   && HAVE_SECTION (hold_rodata, ".rodata"))
      place = &hold_rodata;
!   else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY)
  	   && hold_text.os != NULL)
      place = &hold_text;
  
--- 1179,1185 ----
    else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
  	   && HAVE_SECTION (hold_rodata, ".rodata"))
      place = &hold_rodata;
!   else if ((s->flags & SEC_READONLY) != 0
  	   && hold_text.os != NULL)
      place = &hold_text;
  
***************
*** 1267,1272 ****
--- 1267,1284 ----
        sprintf (symname, "__stop_%s", secname);
        lang_add_assignment (exp_assop ('=', symname,
  				      exp_nameop (NAME, ".")));
+     }
+ 
+   if (place != NULL)
+     {
+       /* By sorting the orphan after place->os, we effectively changed
+ 	 the size of that section.  Adjust the size of the section to
+ 	 reflect the additional output.  */
+       if (place->os->size_adj == NULL)
+ 	place->os->size_adj = exp_nameop (SIZEOF, os->name);
+       else
+ 	place->os->size_adj = exp_binop ('+', place->os->size_adj,
+ 					 exp_nameop (SIZEOF, os->name));
      }
  
    /* Restore the global list pointer.  */
Index: testsuite/ld-scripts/refsec-lma.exp
===================================================================
RCS file: testsuite/ld-scripts/refsec-lma.exp
diff -N testsuite/ld-scripts/refsec-lma.exp
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/ld-scripts/refsec-lma.exp	7 Dec 2002 01:01:30 -0000
***************
*** 0 ****
--- 1,59 ----
+ # Test C-referenceable sections when explicit LMAs are used
+ # in the linker script.
+ #
+ # Written by: Jason Thorpe <thorpej@wasabisystems.com>
+ # Based on phdrs.exp by Ian Taylor.
+ #
+ #   Copyright 2002
+ #   Free Software Foundation, Inc.
+ #
+ # This file is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or
+ # (at your option) any later version.
+ #
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ # GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License
+ # along with this program; if not, write to the Free Software
+ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ 
+ # This tests a feature found in the ELF back-end.
+ if ![is_elf_format] {
+     return
+ }
+ 
+ set testname "C-referenceable sections with explicit LMA"
+ 
+ if ![ld_assemble $as $srcdir/$subdir/refsec-lma.s tmpdir/refsec-lma.o] {
+     unresolved $testname
+     return
+ }
+ 
+ # We don't particularly care about the Program headers.  The information we
+ # want is easily found in the Section headers.
+ set refsec_regexp \
+ ".*Sections:.*\.text.*00000008.*00800000.*10800000.*link_set_1.*00000004.*00800008.*10800008.*link_set_2.*00000004.*0080000c.*1080000c.*\.data.*00000004.*00800010.*10800010.*\.bss.*00000004.*00800014.*00800014.*SYMBOL TABLE:.*0080000c.*g.*__stop_link_set_1.*00800010.*g.*__stop_link_set_2.*00800008.*g.*__start_link_set_1.*0080000c.*g.*__start_link_set_2"
+ 
+ if ![ld_simple_link $ld tmpdir/refsec-lma "-T $srcdir/$subdir/refsec-lma.t tmpdir/refsec-lma.o"] {
+     fail $testname
+ } else {
+     if {[which $objdump] == 0} {
+ 	unresolved $testname
+ 	return
+     }
+ 
+     verbose -log "$objdump --all-headers tmpdir/refsec-lma"
+     catch "exec $objdump --all-headers tmpdir/refsec-lma" exec_output
+     set exec_output [prune_warnings $exec_output]
+     verbose -log $exec_output
+ 
+     if [regexp $refsec_regexp $exec_output] {
+ 	pass $testname
+     } else {
+ 	fail $testname
+     }
+ }
Index: testsuite/ld-scripts/refsec-lma.s
===================================================================
RCS file: testsuite/ld-scripts/refsec-lma.s
diff -N testsuite/ld-scripts/refsec-lma.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/ld-scripts/refsec-lma.s	7 Dec 2002 01:01:30 -0000
***************
*** 0 ****
--- 1,17 ----
+ 	.text
+ 	.long	1
+ 
+ 	.section .rodata
+ 	.long	2
+ 
+ 	.data
+ 	.long	3
+ 
+ 	.section .bss
+ 	.long	0
+ 
+ 	.section link_set_1,"a"
+ 	.long	4
+ 
+ 	.section link_set_2,"a"
+ 	.long	5
Index: testsuite/ld-scripts/refsec-lma.t
===================================================================
RCS file: testsuite/ld-scripts/refsec-lma.t
diff -N testsuite/ld-scripts/refsec-lma.t
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/ld-scripts/refsec-lma.t	7 Dec 2002 01:01:30 -0000
***************
*** 0 ****
--- 1,11 ----
+ SECTIONS
+ {
+   .text (0x00800000) :
+   AT (0x10800000)
+   { *(.text) *(.rodata) }
+   .data :
+   AT (LOADADDR(.text) + SIZEOF(.text))
+   { *(.data) }
+   .bss : { *(.bss) *(COMMON) }
+   /DISCARD/ : { *(.*) }
+ }
Index: testsuite/lib/ld-lib.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/lib/ld-lib.exp,v
retrieving revision 1.17
diff -c -r1.17 ld-lib.exp
*** testsuite/lib/ld-lib.exp	11 Nov 2002 10:16:57 -0000	1.17
--- testsuite/lib/ld-lib.exp	7 Dec 2002 01:01:31 -0000
***************
*** 344,349 ****
--- 344,350 ----
  	 && ![istarget *-*-linux*] \
  	 && ![istarget *-*-irix5*] \
  	 && ![istarget *-*-irix6*] \
+ 	 && ![istarget *-*-netbsd*] \
  	 && ![istarget *-*-solaris2*] } {
  	return 0
      }
***************
*** 351,356 ****
--- 352,369 ----
      if { [istarget *-*-linux*aout*] \
  	 || [istarget *-*-linux*oldld*] } {
  	return 0
+     }
+ 
+     if { ![istarget *-*-netbsdelf*] \
+ 	 && ([istarget *-*-netbsd*aout*] \
+ 	     || [istarget *-*-netbsdpe*] \
+ 	     || [istarget arm*-*-netbsd*] \
+ 	     || [istarget sparc-*-netbsd*] \
+ 	     || [istarget i*86-*-netbsd*] \
+ 	     || [istarget m68*-*-netbsd*] \
+ 	     || [istarget vax-*-netbsd*] \
+ 	     || [istarget ns32k-*-netbsd*]) } {
+     	return 0
      }
      return 1
  }


More information about the Binutils mailing list