place_orphan optimisations
[deliverable/binutils-gdb.git] / ld / emultempl / elf32.em
index e33e0ca5fc7e3e7d45174e56b6a1b45a2df1cbd6..961528500273ef7125774054a20fd6e277506233 100644 (file)
@@ -65,8 +65,7 @@ static void gld${EMULATION_NAME}_find_statement_assignment
 static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
 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 lang_output_section_statement_type *output_rel_find PARAMS ((void));
 static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
 
 static void
@@ -95,24 +94,31 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
 
   filename = entry->filename;
 
+  /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION
+     is defined, but it does not seem worth the headache to optimize
+     away those two bytes of space.  */
   string = (char *) xmalloc (strlen (search->name)
                             + strlen (filename)
                             + strlen (arch)
+#ifdef EXTRA_SHLIB_EXTENSION
+                            + strlen (EXTRA_SHLIB_EXTENSION)
+#endif
                             + sizeof "/lib.so");
 
   sprintf (string, "%s/lib%s%s.so", search->name, filename, arch);
 
+#ifdef EXTRA_SHLIB_EXTENSION
+  /* Try the .so extension first.  If that fails build a new filename
+     using EXTRA_SHLIB_EXTENSION.  */
   if (! ldfile_try_open_bfd (string, entry))
-    {
-      /* It failed using .so, try again with .sl for oddball systems
-        that use a different naming scheme (ie hpux).  */
-      sprintf (string, "%s/lib%s%s.sl", search->name, filename, arch);
+    sprintf (string, "%s/lib%s%s%s", search->name,
+            filename, arch, EXTRA_SHLIB_EXTENSION);
+#endif
 
-      if (! ldfile_try_open_bfd (string, entry))
-       {
-         free (string);
-         return false;
-       }
+  if (! ldfile_try_open_bfd (string, entry))
+    {
+      free (string);
+      return false;
     }
 
   entry->filename = string;
@@ -133,12 +139,12 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry)
   if (bfd_check_format (entry->the_bfd, bfd_object)
       && (entry->the_bfd->flags & DYNAMIC) != 0)
     {
-      char *filname, *needed_name;
+      char *needed_name;
 
       ASSERT (entry->is_archive && entry->search_dirs_flag);
 
       /* Rather than duplicating the logic above.  Just use the
-        filename we recorded earlier.o
+        filename we recorded earlier.
 
         First strip off everything before the last '/'.  */
       filename = strrchr (entry->filename, '/');
@@ -858,14 +864,12 @@ gld${EMULATION_NAME}_find_exp_assignment (exp)
 /* 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
@@ -873,8 +877,13 @@ gld${EMULATION_NAME}_place_orphan (file, s)
      lang_input_statement_type *file;
      asection *s;
 {
-  lang_output_section_statement_type *place;
-  asection *snew, **pps;
+  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;
@@ -882,31 +891,31 @@ gld${EMULATION_NAME}_place_orphan (file, s)
   const char *outsecname;
   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);
+  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;
     }
 
@@ -915,31 +924,38 @@ gld${EMULATION_NAME}_place_orphan (file, s)
      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;
+  else if ((s->flags & SEC_ALLOC) == 0)
+    place = NULL;
   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;
+          && (hold_rel.os != NULL
+              || (hold_rel.os = output_rel_find ()) != NULL))
+    place = &hold_rel;
   else if ((s->flags & SEC_CODE) == 0
           && (s->flags & SEC_READONLY) != 0
-          && hold_rodata != NULL)
-    place = hold_rodata;
+          && HAVE_SECTION (hold_rodata, ".rodata"))
+    place = &hold_rodata;
   else if ((s->flags & SEC_READONLY) != 0
-          && hold_text != NULL)
-    place = hold_text;
-  if (place == NULL)
-    return false;
+          && hold_text.os != NULL)
+    place = &hold_text;
+  else
+    place = NULL;
+
+#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
@@ -965,112 +981,135 @@ gld${EMULATION_NAME}_place_orphan (file, s)
       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.  */
-  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 (place != NULL)
     {
-      char *symname;
-
-      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))));
+      /* Start building a list of statements for this section.  */
+      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)
+       {
+         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);
-  stat_ptr = &add;
+    ((bfd_vma) 0, "*default*",
+     (struct lang_output_section_phdr_list *) NULL, "*default*");
 
-  if (*ps == '\0' && config.build_constructors)
+  if (place != NULL)
     {
-      char *symname;
+      asection *snew, **pps;
 
-      symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
-      sprintf (symname, "__stop_%s", outsecname);
-      lang_add_assignment (exp_assop ('=', symname,
-                                     exp_nameop (NAME, ".")));
-    }
+      stat_ptr = &add;
+
+      if (*ps == '\0' && config.build_constructors)
+       {
+         char *symname;
 
-  /* Now stick the new statement list right after PLACE.  */
-  *add.tail = place->header.next;
-  place->header.next = add.head;
+         symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
+         sprintf (symname, "__stop_%s", outsecname);
+         lang_add_assignment (exp_assop ('=', symname,
+                                         exp_nameop (NAME, ".")));
+       }
+      stat_ptr = old;
 
-  stat_ptr = old;
+      snew = os->bfd_section;
+      if (place->os->bfd_section != NULL || place->section != NULL)
+       {
+         /* Shuffle the section to make the output file look neater.  */
+         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
+           }
+
+         /*  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 (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;
+       }
+      place->stmt = add.tail;          /* Save the end of this list.  */
+    }
 
   return true;
 }
 
-static void
-gld${EMULATION_NAME}_place_section (s)
-     lang_statement_union_type *s;
+/* A variant of lang_output_section_find.  */
+static lang_output_section_statement_type *
+output_rel_find ()
 {
-  lang_output_section_statement_type *os;
-
-  if (s->header.type != lang_output_section_statement_enum)
-    return;
-
-  os = &s->output_section_statement;
+  lang_statement_union_type *u;
+  lang_output_section_statement_type *lookup;
 
-  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;
+  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;
 }
 
 static char *
@@ -1173,6 +1212,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   gld_${EMULATION_NAME}_parse_args,
   NULL,                /* unrecognized_file */
   gld_${EMULATION_NAME}_list_options,
-  NULL         /* recognized_file */
+  NULL,                /* recognized_file */
+  NULL         /* find_potential_libraries */
 };
 EOF
This page took 0.035393 seconds and 4 git commands to generate.