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]

fix pr44


This is a partial fix for the PE "NOCROSSREFS 2" failure.  The PE
place_orphan code was missing a number of fixes added to the ELF
version, resulting in the linker losing output_section_statements for
.stab and .stabstr.  Backporting the ELF changes cures this problem.

The test

	int i = 4;

	int
	foo ()
	{
	  return i;
	}

still fails for me though.  A little debugging shows that the
reloc in .text for i has been reduced to one against .data, but
.data is just a local symbol rather than being the section symbol.

Inside check_reloc_refs:
(gdb) p symname
$6 = 0x0
(gdb) p **q->sym_ptr_ptr
$7 = {the_bfd = 0x80eb928, name = 0x80f49f0 ".data", value = 0, flags = 1, 
  section = 0x80f5004, udata = {p = 0x0, i = 0}}
(gdb) p *info->defsec->symbol
$8 = {the_bfd = 0x80eb928, name = 0x80f3f38 ".data", value = 0, flags = 256, 
  section = 0x80f5004, udata = {p = 0x0, i = 0}}

I haven't yet looked into why the reloc symbol is like this.

	* emultempl/pe.em (struct orphan_save): Add os_tail.
	(place_orphan): Backport assorted fixes from elf32.em.

Index: ld/emultempl/pe.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/pe.em,v
retrieving revision 1.96
diff -u -p -r1.96 pe.em
--- ld/emultempl/pe.em	30 Sep 2004 17:19:19 -0000	1.96
+++ ld/emultempl/pe.em	12 Oct 2004 23:33:13 -0000
@@ -1530,6 +1530,7 @@ struct orphan_save
   lang_output_section_statement_type *os;
   asection **section;
   lang_statement_union_type **stmt;
+  lang_statement_union_type **os_tail;
 };
 
 static bfd_boolean
@@ -1573,10 +1574,14 @@ gld_${EMULATION_NAME}_place_orphan (lang
       static struct orphan_save hold_rdata;
       static struct orphan_save hold_data;
       static struct orphan_save hold_bss;
+      static int count = 1;
       char *outsecname;
       lang_statement_list_type *old;
       lang_statement_list_type add;
+      lang_statement_union_type **os_tail;
       etree_type *address;
+      etree_type *load_base;
+      asection *sec;
 
       /* Try to put the new output section in a reasonable place based
 	 on the section name and section flags.  */
@@ -1596,41 +1601,42 @@ gld_${EMULATION_NAME}_place_orphan (lang
 	       && (s->flags & SEC_READONLY) != 0
 	       && HAVE_SECTION (hold_rdata, ".rdata"))
 	place = &hold_rdata;
-      else if ((s->flags & SEC_READONLY) != 0
+      else if ((s->flags & SEC_CODE) != 0
+	       && (s->flags & SEC_READONLY) != 0
 	       && HAVE_SECTION (hold_text, ".text"))
 	place = &hold_text;
 
 #undef HAVE_SECTION
 
-      /* Choose a unique name for the section.  This will be needed if
-	 the same section name appears in the input file with
-	 different loadable or allocatable characteristics.  */
-      outsecname = xstrdup (hold_section_name);
-      if (bfd_get_section_by_name (output_bfd, outsecname) != NULL)
+      /* Choose a unique name for the section.  This will be needed if the
+	 same section name appears in the input file with different
+	 loadable or allocatable characteristics.  But if the section
+	 already exists but does not have any flags set, then it has been
+	 created by the linker, probably as a result of a --section-start
+	 command line switch.  */
+      sec = bfd_get_section_by_name (output_bfd, hold_section_name);
+      if (sec != NULL
+	  && bfd_get_section_flags (output_bfd, sec) != 0)
 	{
-	  unsigned int len;
-	  char *newname;
-	  unsigned int i;
-
-	  len = strlen (outsecname);
-	  newname = xmalloc (len + 5);
-	  strcpy (newname, outsecname);
-	  i = 0;
-	  do
-	    {
-	      sprintf (newname + len, "%d", i);
-	      ++i;
-	    }
-	  while (bfd_get_section_by_name (output_bfd, newname) != NULL);
-
-	  free (outsecname);
-	  outsecname = newname;
+	  outsecname = bfd_get_unique_section_name (output_bfd,
+						    hold_section_name, &count);
+	  if (outsecname == NULL)
+	    einfo ("%F%P: place_orphan failed: %E\n");
 	}
+      else
+	outsecname = xstrdup (hold_section_name);
 
       /* Start building a list of statements for this section.  */
       old = stat_ptr;
-      stat_ptr = &add;
-      lang_list_init (stat_ptr);
+
+      /* If we have found an appropriate place for the output section
+	 statements for this orphan, add them to our own private list,
+	 inserting them later into the global statement list.  */
+      if (place != NULL)
+	{
+	  stat_ptr = &add;
+	  lang_list_init (stat_ptr);
+	}
 
       if (config.build_constructors)
 	{
@@ -1662,10 +1668,21 @@ gld_${EMULATION_NAME}_place_orphan (lang
 			      exp_nameop (NAME, "__section_alignment__"));
 	}
 
+      load_base = NULL;
+      if (place != NULL && place->os->load_base != NULL)
+	{
+	  etree_type *lma_from_vma;
+	  lma_from_vma = exp_binop ('-', place->os->load_base,
+				    exp_nameop (ADDR, place->os->name));
+	  load_base = exp_binop ('+', lma_from_vma,
+				 exp_nameop (ADDR, secname));
+	}
+
+      os_tail = lang_output_section_statement.tail;
       os = lang_enter_output_section_statement (outsecname, address, 0,
 						(etree_type *) NULL,
 						(etree_type *) NULL,
-						(etree_type *) NULL, 0);
+						load_base, 0);
 
       lang_add_section (&add_child, s, os, file);
 
@@ -1741,11 +1758,15 @@ gld_${EMULATION_NAME}_place_orphan (lang
 	     read/write section before or amongst the read-only ones.  */
 	  if (add.head != NULL)
 	    {
+	      lang_statement_union_type *newly_added_os;
+
 	      if (place->stmt == NULL)
 		{
 		  /* Put the new statement list right at the head.  */
 		  *add.tail = place->os->header.next;
 		  place->os->header.next = add.head;
+
+		  place->os_tail = &place->os->next;
 		}
 	      else
 		{
@@ -1761,6 +1782,21 @@ gld_${EMULATION_NAME}_place_orphan (lang
 
 	      /* Save the end of this list.  */
 	      place->stmt = add.tail;
+
+	      /* Do the same for the list of output section statements.  */
+	      newly_added_os = *os_tail;
+	      *os_tail = NULL;
+	      newly_added_os->output_section_statement.next = *place->os_tail;
+	      *place->os_tail = newly_added_os;
+	      place->os_tail = &newly_added_os->output_section_statement.next;
+
+	      /* Fixing the global list pointer here is a little different.
+		 We added to the list in lang_enter_output_section_statement,
+		 trimmed off the new output_section_statment above when
+		 assigning *os_tail = NULL, but possibly added it back in
+		 the same place when assigning *place->os_tail.  */
+	      if (*os_tail == NULL)
+		lang_output_section_statement.tail = os_tail;
 	    }
 	}
     }

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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