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]

binutils-2.10 elf32.em place_orphan merge


I've applied this patch to the branch which merges most of the
place_orphan changes from the trunk.  Keeps orphan sections in order
rather than reversing them, and fixes a few corner cases where it was
possible to lose sections.

ld/ChangeLog
	Merge most place_orphan changes from mainline.
	2000-09-07  Alan Modra  <alan@linuxcare.com.au>
	* emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Fix
	broken list handling.  Create __start_SECNAME and __stop_SECNAME
	when no place-holder.  Add some comments.  Test both SEC_CODE and
	SEC_READONLY for hold_text to prevent .rodata orphan poisoning.
	Handle case where no output section statement created.

	2000-09-06  Alan Modra  <alan@linuxcare.com.au>
	* emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Don't
	try shuffling sections when the orphan happens to be the place
	holder.  Keep count of unique section names generated so we speed
	the search for a new name.

	2000-04-25  Alan Modra  <alan@linuxcare.com.au>
	* emultempl/elf32.em (gld${EMULATION_NAME}_place_section): Delete.
	(output_rel_find): New function.
	(hold_section, hold_use): Delete.
	(hold_text, hold_rodata, hold_data, hold_bss, hold_rel,
	hold_interp): Make local to place_orphan.
	(gld${EMULATION_NAME}_place_orphan): Use lang_output_section_find
	rather than place_section to find possible previous use of orphan.
	Similarly find the place-holder output sections.  Use returned
	value from lang_enter_output_section_statement rather than calling
	lang_output_section_statement_lookup.
	* ldlang.c (lang_enter_output_section_statement): Return output
	section statement.
	* ldlang.h (lang_enter_output_section_statement): Change
	declaration too.
	* ldlang.h (lang_output_section_statement): Export it.
	* ldlang.c (lang_output_section_statement): Ditto.

	2000-04-18  H.J. Lu  <hjl@gnu.org>
	* emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Call
	lang_leave_output_section_statement () after calling
	lang_enter_output_section_statement ().

	2000-04-18  Alan Modra  <alan@linuxcare.com.au>
	* emultempl/elf32.em (struct orphan_save): Add section field.
	(gld${EMULATION_NAME}_place_orphan): Use above to keep sections in
	better order, and place first orphan section as we did before the
	2000-04-12 patch.  Ignore ~SEC_ALLOC sections when choosing place.
	Don't call make_bfd_section here, let wild_doit do the job for us.
	Don't build a statement list when we'll only throw it away.

	2000-04-14  Alan Modra  <alan@linuxcare.com.au>
	* emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Process
	~SEC_ALLOC sections too.  Init start address of debug sections.

	2000-04-12  Alan Modra  <alan@linuxcare.com.au>
	* emultempl/elf32.em (struct orphan_save): New.
	(hold_text, hold_rodata, hold_data, hold_bss, hold_rel,
	hold_interp): Make them struct orphan_save.
	(gld${EMULATION_NAME}_place_section): Modify for new hold_*.
	(gld${EMULATION_NAME}_place_orphan): Add new orphan sections to
	the end of the relevant section list.  Also add associated section
	statements to the end of any previous orphan statements.

Alan Modra
-- 
Linuxcare.  Support for the Revolution.

Index: ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.24
diff -u -p -r1.24 ldlang.c
--- ldlang.c	2000/02/21 12:01:27	1.24
+++ ldlang.c	2000/11/06 09:11:41
@@ -58,7 +58,6 @@ static lang_output_section_statement_typ
 static boolean map_option_f;
 static bfd_vma print_dot;
 static lang_input_statement_type *first_file;
-static lang_statement_list_type lang_output_section_statement;
 static CONST char *current_target;
 static CONST char *output_target;
 static lang_statement_list_type statement_list;
@@ -166,6 +165,7 @@ static char * get_first_input_target PAR
 					
 /* EXPORTS */
 lang_output_section_statement_type *abs_output_section;
+lang_statement_list_type lang_output_section_statement;
 lang_statement_list_type *stat_ptr = &statement_list;
 lang_statement_list_type file_chain = { NULL, NULL };
 const char *entry_symbol = NULL;
@@ -3813,7 +3813,7 @@ topower (x)
   return 0;
 }
 
-void
+lang_output_section_statement_type *
 lang_enter_output_section_statement (output_section_statement_name,
 				     address_exp, sectype, block_value,
 				     align, subalign, ebase)
@@ -3861,6 +3861,7 @@ lang_enter_output_section_statement (out
 		     "section alignment", 0));
 
   os->load_base = ebase;
+  return os;
 }
 
 
Index: ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.4
diff -u -p -r1.4 ldlang.h
--- ldlang.h	2000/02/16 18:53:32	1.4
+++ ldlang.h	2000/11/06 09:11:43
@@ -371,6 +371,7 @@ struct lang_nocrossrefs
 extern struct lang_nocrossrefs *nocrossref_list;
 
 extern lang_output_section_statement_type *abs_output_section;
+extern lang_statement_list_type lang_output_section_statement;
 extern boolean lang_has_input_file;
 extern etree_type *base;
 extern lang_statement_list_type *stat_ptr;
@@ -388,7 +389,7 @@ extern void lang_map PARAMS ((void));
 extern void lang_set_flags PARAMS ((lang_memory_region_type *, const char *,
 				    int));
 extern void lang_add_output PARAMS ((const char *, int from_script));
-extern void lang_enter_output_section_statement
+extern lang_output_section_statement_type *lang_enter_output_section_statement
   PARAMS ((const char *output_section_statement_name,
 	   etree_type * address_exp,
 	   enum section_type sectype,
Index: emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.12.2.1
diff -u -p -r1.12.2.1 elf32.em
--- elf32.em	2000/10/12 13:56:39	1.12.2.1
+++ elf32.em	2000/11/06 09:11:48
@@ -7,7 +7,7 @@ cat >e${EMULATION_NAME}.c <<EOF
 /* This file is is generated by a shell script.  DO NOT EDIT! */
 
 /* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
-   Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 1999
+   Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 99, 2000
    Free Software Foundation, Inc.
    Written by Steve Chamberlain <sac@cygnus.com>
    ELF support by Ian Lance Taylor <ian@cygnus.com>
@@ -63,10 +63,9 @@ static void gld${EMULATION_NAME}_before_
 static void gld${EMULATION_NAME}_find_statement_assignment
   PARAMS ((lang_statement_union_type *));
 static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
+static lang_output_section_statement_type *output_rel_find PARAMS ((void));
 static boolean gld${EMULATION_NAME}_place_orphan
   PARAMS ((lang_input_statement_type *, asection *));
-static void gld${EMULATION_NAME}_place_section
-  PARAMS ((lang_statement_union_type *));
 static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
 
 static void
@@ -862,58 +861,83 @@ gld${EMULATION_NAME}_find_exp_assignment
     }
 }
 
+/* A variant of lang_output_section_find.  Used by place_orphan.  */
+
+static lang_output_section_statement_type *
+output_rel_find ()
+{
+  lang_statement_union_type *u;
+  lang_output_section_statement_type *lookup;
+
+  for (u = lang_output_section_statement.head;
+       u != (lang_statement_union_type *) NULL;
+       u = lookup->next)
+    {
+      lookup = &u->output_section_statement;
+      if (strncmp (".rel", lookup->name, 4) == 0
+	  && lookup->bfd_section != NULL
+	  && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
+	{
+	  return lookup;
+	}
+    }
+  return (lang_output_section_statement_type *) NULL;
+}
+
 /* Place an orphan section.  We use this to put random SHF_ALLOC
    sections in the right segment.  */
 
-static asection *hold_section;
-static lang_output_section_statement_type *hold_use;
-static lang_output_section_statement_type *hold_text;
-static lang_output_section_statement_type *hold_rodata;
-static lang_output_section_statement_type *hold_data;
-static lang_output_section_statement_type *hold_bss;
-static lang_output_section_statement_type *hold_rel;
-static lang_output_section_statement_type *hold_interp;
+struct orphan_save {
+  lang_output_section_statement_type *os;
+  asection **section;
+  lang_statement_union_type **stmt;
+};
 
-/*ARGSUSED*/
 static boolean
 gld${EMULATION_NAME}_place_orphan (file, s)
      lang_input_statement_type *file;
      asection *s;
 {
-  lang_output_section_statement_type *place;
-  asection *snew, **pps;
-  lang_statement_list_type *old = NULL;
+  static struct orphan_save hold_text;
+  static struct orphan_save hold_rodata;
+  static struct orphan_save hold_data;
+  static struct orphan_save hold_bss;
+  static struct orphan_save hold_rel;
+  static struct orphan_save hold_interp;
+  struct orphan_save *place;
+  lang_statement_list_type *old;
   lang_statement_list_type add;
   etree_type *address;
-  const char *secname, *ps = NULL;
+  const char *secname;
   const char *outsecname;
+  const char *ps = NULL;
   lang_output_section_statement_type *os;
 
-  if ((s->flags & SEC_ALLOC) == 0)
-    return false;
+  secname = bfd_get_section_name (s->owner, s);
 
-  /* Look through the script to see where to place this section.  */
-  hold_section = s;
-  hold_use = NULL;
-  lang_for_each_statement (gld${EMULATION_NAME}_place_section);
+  /* Look through the script to see where to place this section.  */ 
+  os = lang_output_section_find (secname);
 
-  if (hold_use != NULL)
+  if (os != NULL
+      && os->bfd_section != NULL
+      && ((s->flags ^ os->bfd_section->flags) & (SEC_LOAD | SEC_ALLOC)) == 0)
     {
       /* We have already placed a section with this name.  */
-      wild_doit (&hold_use->children, s, hold_use, file);
+      wild_doit (&os->children, s, os, file);
       return true;
     }
 
-  secname = bfd_get_section_name (s->owner, s);
+  if (hold_text.os == NULL)
+    hold_text.os = lang_output_section_find (".text");
 
   /* If this is a final link, then always put .gnu.warning.SYMBOL
      sections into the .text section to get them out of the way.  */
   if (! link_info.shared
       && ! link_info.relocateable
       && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
-      && hold_text != NULL)
+      && hold_text.os != NULL)
     {
-      wild_doit (&hold_text->children, s, hold_text, file);
+      wild_doit (&hold_text.os->children, s, hold_text.os, file);
       return true;
     }
 
@@ -922,31 +946,37 @@ gld${EMULATION_NAME}_place_orphan (file,
      right after the .interp section, so that the PT_NOTE segment is
      stored right after the program headers where the OS can read it
      in the first page.  */
-  place = NULL;
+#define HAVE_SECTION(hold, name) \
+(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
+
   if (s->flags & SEC_EXCLUDE)
     return false;
+
+  place = NULL;
+  if ((s->flags & SEC_ALLOC) == 0)
+    ;
   else if ((s->flags & SEC_LOAD) != 0
-      && strncmp (secname, ".note", 4) == 0
-      && hold_interp != NULL)
-    place = hold_interp;
+	   && strncmp (secname, ".note", 4) == 0
+	   && HAVE_SECTION (hold_interp, ".interp"))
+    place = &hold_interp;
   else if ((s->flags & SEC_HAS_CONTENTS) == 0
-	   && hold_bss != NULL)
-    place = hold_bss;
+	   && HAVE_SECTION (hold_bss, ".bss"))
+    place = &hold_bss;
   else if ((s->flags & SEC_READONLY) == 0
-	   && hold_data != NULL)
-    place = hold_data;
+	   && HAVE_SECTION (hold_data, ".data"))
+    place = &hold_data;
   else if (strncmp (secname, ".rel", 4) == 0
-	   && hold_rel != NULL)
-    place = hold_rel;
-  else if ((s->flags & SEC_CODE) == 0
-	   && (s->flags & SEC_READONLY) != 0
-	   && hold_rodata != NULL)
-    place = hold_rodata;
-  else if ((s->flags & SEC_READONLY) != 0
-	   && hold_text != NULL)
-    place = hold_text;
-  if (place == NULL)
-    return false;
+	   && (hold_rel.os != NULL
+	       || (hold_rel.os = output_rel_find ()) != NULL))
+    place = &hold_rel;
+  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;
+
+#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
@@ -971,114 +1001,143 @@ gld${EMULATION_NAME}_place_orphan (file,
 
       outsecname = newname;
     }
-
-  /* Create the section in the output file, and put it in the right
-     place.  This shuffling is to make the output file look neater.  */
-  snew = bfd_make_section (output_bfd, outsecname);
-  if (snew == NULL)
-      einfo ("%P%F: output format %s cannot represent section called %s\n",
-	     output_bfd->xvec->name, outsecname);
-  if (place->bfd_section != NULL)
-    {
-      for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
-	;
-      *pps = snew->next;
-      snew->next = place->bfd_section->next;
-      place->bfd_section->next = snew;
-    }
 
-  /* Start building a list of statements for this section.  */
+  /* Start building a list of statements for this section.
+     First save the current statement pointer.  */
   old = stat_ptr;
-  stat_ptr = &add;
-  lang_list_init (stat_ptr);
 
-  /* If the name of the section is representable in C, then create
-     symbols to mark the start and the end of the section.  */
-  for (ps = outsecname; *ps != '\0'; ps++)
-    if (! isalnum ((unsigned char) *ps) && *ps != '_')
-      break;
-  if (*ps == '\0' && config.build_constructors)
+  /* 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)
     {
-      char *symname;
+      stat_ptr = &add;
+      lang_list_init (stat_ptr);
+    }
 
-      symname = (char *) xmalloc (ps - outsecname + sizeof "__start_");
-      sprintf (symname, "__start_%s", outsecname);
-      lang_add_assignment (exp_assop ('=', symname,
-				      exp_unop (ALIGN_K,
-						exp_intop ((bfd_vma) 1
-							   << s->alignment_power))));
+  if (config.build_constructors)
+    {
+      /* If the name of the section is representable in C, then create
+	 symbols to mark the start and the end of the section.  */
+      for (ps = outsecname; *ps != '\0'; ps++)
+	if (! isalnum ((unsigned char) *ps) && *ps != '_')
+	  break;
+      if (*ps == '\0')
+	{
+	  char *symname;
+	  etree_type *e_align;
+
+	  symname = (char *) xmalloc (ps - outsecname + sizeof "__start_");
+	  sprintf (symname, "__start_%s", outsecname);
+	  e_align = exp_unop (ALIGN_K,
+			      exp_intop ((bfd_vma) 1 << s->alignment_power));
+	  lang_add_assignment (exp_assop ('=', symname, e_align));
+	}
     }
 
-  if (! link_info.relocateable)
-    address = NULL;
-  else
+  if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
     address = exp_intop ((bfd_vma) 0);
+  else
+    address = NULL;
 
-  lang_enter_output_section_statement (outsecname, address, 0,
-				       (bfd_vma) 0,
-				       (etree_type *) NULL,
-				       (etree_type *) NULL,
-				       (etree_type *) NULL);
+  os = lang_enter_output_section_statement (outsecname, address, 0,
+					    (bfd_vma) 0,
+					    (etree_type *) NULL,
+					    (etree_type *) NULL,
+					    (etree_type *) NULL);
 
-  os = lang_output_section_statement_lookup (outsecname);
   wild_doit (&os->children, s, os, file);
 
   lang_leave_output_section_statement
-    ((bfd_vma) 0, "*default*", (struct lang_output_section_phdr_list *) NULL,
-     "*default*");
-  stat_ptr = &add;
+    ((bfd_vma) 0, "*default*",
+     (struct lang_output_section_phdr_list *) NULL, "*default*");
 
-  if (*ps == '\0' && config.build_constructors)
+  if (config.build_constructors && *ps == '\0')
     {
       char *symname;
 
+      /* lang_leave_ouput_section_statement resets stat_ptr.  Put
+	 stat_ptr back where we want it.  */
+      if (place != NULL)
+	stat_ptr = &add;
+
       symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
       sprintf (symname, "__stop_%s", outsecname);
       lang_add_assignment (exp_assop ('=', symname,
 				      exp_nameop (NAME, ".")));
     }
 
-  /* Now stick the new statement list right after PLACE.  */
-  *add.tail = place->header.next;
-  place->header.next = add.head;
-
+  /* Restore the global list pointer.  */
   stat_ptr = old;
 
-  return true;
-}
+  if (place != NULL)
+    {
+      asection *snew, **pps;
 
-static void
-gld${EMULATION_NAME}_place_section (s)
-     lang_statement_union_type *s;
-{
-  lang_output_section_statement_type *os;
+      snew = os->bfd_section;
+      if (place->section != NULL
+	  || (place->os->bfd_section != NULL
+	      && place->os->bfd_section != snew))
+	{
+	  /* Shuffle the section to make the output file look neater.
+	     This is really only cosmetic.  */
+	  if (place->section == NULL)
+	    {
+#if 0
+	      /* Finding the end of the list is a little tricky.  We
+		 make a wild stab at it by comparing section flags.  */
+	      flagword first_flags = place->os->bfd_section->flags;
+	      for (pps = &place->os->bfd_section->next;
+		   *pps != NULL && (*pps)->flags == first_flags;
+		   pps = &(*pps)->next)
+		;
+	      place->section = pps;
+#else
+	      /* Put orphans after the first section on the list.  */
+	      place->section = &place->os->bfd_section->next;
+#endif
+	    }
 
-  if (s->header.type != lang_output_section_statement_enum)
-    return;
+	  /*  Unlink the section.  */
+	  for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
+	    ;
+	  *pps = snew->next;
+
+	  /* Now tack it on to the "place->os" section list.  */
+	  snew->next = *place->section;
+	  *place->section = snew;
+	}
+      place->section = &snew->next;	/* Save the end of this list.  */
+
+      if (add.head != NULL)
+	{
+	  /* We try to put the output statements in some sort of
+	     reasonable order here, because they determine the final
+	     load addresses of the orphan sections.  */
+	  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;
+	    }
+	  else
+	    {
+	      /* Put it after the last orphan statement we added.  */
+	      *add.tail = *place->stmt;
+	      *place->stmt = add.head;
+	    }
 
-  os = &s->output_section_statement;
+	  /* Fix the global list pointer if we happened to tack our
+	     new list at the tail.  */
+	  if (*old->tail == add.head)
+	    old->tail = add.tail;
 
-  if (strcmp (os->name, hold_section->name) == 0
-      && os->bfd_section != NULL
-      && ((hold_section->flags & (SEC_LOAD | SEC_ALLOC))
-	  == (os->bfd_section->flags & (SEC_LOAD | SEC_ALLOC))))
-    hold_use = os;
-
-  if (strcmp (os->name, ".text") == 0)
-    hold_text = os;
-  else if (strcmp (os->name, ".rodata") == 0)
-    hold_rodata = os;
-  else if (strcmp (os->name, ".data") == 0)
-    hold_data = os;
-  else if (strcmp (os->name, ".bss") == 0)
-    hold_bss = os;
-  else if (hold_rel == NULL
-	   && os->bfd_section != NULL
-	   && (os->bfd_section->flags & SEC_ALLOC) != 0
-	   && strncmp (os->name, ".rel", 4) == 0)
-    hold_rel = os;
-  else if (strcmp (os->name, ".interp") == 0)
-    hold_interp = os;
+	  /* Save the end of this list.  */
+	  place->stmt = add.tail;
+	}
+    }
+
+  return true;
 }
 
 static char *


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