Problem with referenceable sections ("link sets")

Jason R Thorpe thorpej@wasabisystems.com
Tue Nov 19 09:44:00 GMT 2002


On Mon, Nov 18, 2002 at 09:44:28PM -0800, Ian Lance Taylor wrote:

 > This could probably be done.  In gld${EMULATION_NAME}_place_orphan()
 > in ld/emultempl/elf32.em copy any AT statement into the call to
 > lang_leave_output_section_statement().  You will need to properly
 > adjust it for the size of the section which you are following.  This
 > will be ld expression hackery--shouldn't be too tough.

Well, this patch (against 2.11.2) almost does it ... if there is one
orphan section, the right thing happens.  But if there are two, the
two orphans get overlapped.

Am I on the right track, here?

-- 
        -- Jason R. Thorpe <thorpej@wasabisystems.com>
-------------- next part --------------
Index: ldexp.c
===================================================================
RCS file: /cvsroot/gnusrc/gnu/dist/toolchain/ld/ldexp.c,v
retrieving revision 1.1.1.3
diff -c -r1.1.1.3 ldexp.c
*** ldexp.c	2001/08/14 02:59:08	1.1.1.3
--- ldexp.c	2002/11/19 17:30:37
***************
*** 460,465 ****
--- 460,471 ----
  	  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: /cvsroot/gnusrc/gnu/dist/toolchain/ld/ldlang.c,v
retrieving revision 1.1.1.4
diff -c -r1.1.1.4 ldlang.c
*** ldlang.c	2001/08/14 02:59:13	1.1.1.4
--- ldlang.c	2002/11/19 17:30:44
***************
*** 718,723 ****
--- 718,724 ----
        lookup->subsection_alignment = -1;
        lookup->section_alignment = -1;
        lookup->load_base = (union etree_union *) NULL;
+       lookup->size_adj = (union etree_union *) NULL;
        lookup->phdrs = NULL;
  
        lang_statement_append (&lang_output_section_statement,
Index: ldlang.h
===================================================================
RCS file: /cvsroot/gnusrc/gnu/dist/toolchain/ld/ldlang.h,v
retrieving revision 1.1.1.4
diff -c -r1.1.1.4 ldlang.h
*** ldlang.h	2001/08/14 02:59:14	1.1.1.4
--- ldlang.h	2002/11/19 17:30:45
***************
*** 131,136 ****
--- 131,137 ----
    int section_alignment;	/* alignment of start of section */
  
    union etree_union *load_base;
+   union etree_union *size_adj;
  
    struct lang_output_section_phdr_list *phdrs;
  } lang_output_section_statement_type;
Index: emultempl/elf32.em
===================================================================
RCS file: /cvsroot/gnusrc/gnu/dist/toolchain/ld/emultempl/elf32.em,v
retrieving revision 1.3
diff -c -r1.3 elf32.em
*** emultempl/elf32.em	2002/11/01 16:07:37	1.3
--- emultempl/elf32.em	2002/11/19 17:30:48
***************
*** 1005,1010 ****
--- 1005,1011 ----
    lang_statement_list_type *old;
    lang_statement_list_type add;
    etree_type *address;
+   etree_type *load_base;
    const char *secname;
    const char *outsecname;
    const char *ps = NULL;
***************
*** 1133,1143 ****
    else
      address = NULL;
  
    os = lang_enter_output_section_statement (outsecname, address, 0,
  					    (bfd_vma) 0,
  					    (etree_type *) NULL,
  					    (etree_type *) NULL,
! 					    (etree_type *) NULL);
  
    wild_doit (&os->children, s, os, file);
  
--- 1134,1153 ----
    else
      address = NULL;
  
+   /* If the output section we're sorting with has an AT expression,
+      then we need to copy that AT expression, adjusting it for the
+      size of the previous section.  */
+   if (place != NULL && place->os->load_base != NULL)
+     load_base = exp_binop ('+', place->os->load_base,
+ 			   exp_nameop (SIZEOF, place->os->name));
+   else
+     load_base = NULL;
+ 
    os = lang_enter_output_section_statement (outsecname, address, 0,
  					    (bfd_vma) 0,
  					    (etree_type *) NULL,
  					    (etree_type *) NULL,
! 					    load_base);
  
    wild_doit (&os->children, s, os, file);
  
***************
*** 1158,1163 ****
--- 1168,1185 ----
        sprintf (symname, "__stop_%s", outsecname);
        lang_add_assignment (exp_assop ('=', symname,
  				      exp_nameop (NAME, ".")));
+     }
+ 
+   if (load_base != 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.  */


More information about the Binutils mailing list