]> Git Repo - binutils.git/blobdiff - ld/emultempl/elf32.em
* emultempl/elf32.em (output_rel_find): Prefer .rel script sections
[binutils.git] / ld / emultempl / elf32.em
index a85d97d76892de54fe8e95f6c190973b233240a5..62c39f442afb70b9396996b44ce75eaca927c42a 100644 (file)
@@ -75,7 +75,7 @@ static void gld${EMULATION_NAME}_before_allocation
 static boolean gld${EMULATION_NAME}_open_dynamic_archive
   PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *));
 static lang_output_section_statement_type *output_rel_find
-  PARAMS ((void));
+  PARAMS ((asection *));
 static asection *output_prev_sec_find
   PARAMS ((lang_output_section_statement_type *));
 static boolean gld${EMULATION_NAME}_place_orphan
@@ -281,6 +281,13 @@ gld${EMULATION_NAME}_try_needed (name, force)
       return false;
     }
 
+  /* For DT_NEEDED, they have to match.  */
+  if (abfd->xvec != output_bfd->xvec)
+    {
+      bfd_close (abfd);
+      return false;
+    }
+
   /* Check whether this object would include any conflicting library
      versions.  If FORCE is set, then we skip this check; we use this
      the second time around, if we couldn't find any compatible
@@ -989,24 +996,46 @@ cat >>e${EMULATION_NAME}.c <<EOF
 /* A variant of lang_output_section_find.  Used by place_orphan.  */
 
 static lang_output_section_statement_type *
-output_rel_find ()
+output_rel_find (sec)
+     asection *sec;
 {
   lang_statement_union_type *u;
   lang_output_section_statement_type *lookup;
+  lang_output_section_statement_type *last = NULL;
+  lang_output_section_statement_type *last_rel = NULL;
+  lang_output_section_statement_type *last_rel_alloc = NULL;
+  int rela = sec->name[4] == 'a';
 
-  for (u = lang_output_section_statement.head;
-       u != (lang_statement_union_type *) NULL;
-       u = lookup->next)
+  for (u = lang_output_section_statement.head; u; 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)
+      if (strncmp (".rel", lookup->name, 4) == 0)
        {
-         return lookup;
+         /* Don't place after .rel.plt as doing so results in wrong
+            dynamic tags.  Also, place allocated reloc sections before
+            non-allocated.  */
+         int lookrela = lookup->name[4] == 'a';
+
+         if (strcmp (".plt", lookup->name + 4 + lookrela) == 0
+             || (lookup->bfd_section != NULL
+                 && (lookup->bfd_section->flags & SEC_ALLOC) == 0))
+           break;
+         last = lookup;
+         if (rela == lookrela)
+           last_rel = lookup;
+         if (lookup->bfd_section != NULL
+             && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
+           last_rel_alloc = lookup;
        }
     }
-  return (lang_output_section_statement_type *) NULL;
+
+  if (last_rel_alloc)
+    return last_rel_alloc;
+
+  if (last_rel)
+    return last_rel;
+
+  return last;
 }
 
 /* Find the last output section before given output statement.
@@ -1062,13 +1091,23 @@ gld${EMULATION_NAME}_place_orphan (file, s)
   lang_statement_list_type add;
   etree_type *address;
   const char *secname;
-  const char *outsecname;
   const char *ps = NULL;
   lang_output_section_statement_type *os;
+  int isdyn = 0;
 
   secname = bfd_get_section_name (s->owner, s);
+  if (! link_info.relocateable
+      && link_info.combreloc
+      && strncmp (secname, ".rel", 4) == 0)
+    {
+      if (secname[4] == 'a')
+       secname = ".rela.dyn";
+      else
+       secname = ".rel.dyn";
+      isdyn = 1;
+    }
 
-  if (! config.unique_orphan_sections && ! unique_section_p (secname))
+  if (isdyn || (!config.unique_orphan_sections && !unique_section_p (secname)))
     {
       /* Look through the script to see where to place this section.  */
       os = lang_output_section_find (secname);
@@ -1107,7 +1146,7 @@ gld${EMULATION_NAME}_place_orphan (file, s)
 #define HAVE_SECTION(hold, name) \
 (hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
 
-  if (s->flags & SEC_EXCLUDE)
+  if ((s->flags & SEC_EXCLUDE) != 0 && !link_info.relocateable)
     {
       if (s->output_section == NULL)
        s->output_section = bfd_abs_section_ptr;
@@ -1131,27 +1170,10 @@ gld${EMULATION_NAME}_place_orphan (file, s)
           && HAVE_SECTION (hold_data, ".data"))
     place = &hold_data;
   else if (strncmp (secname, ".rel", 4) == 0
+          && (s->flags & SEC_LOAD) != 0
           && (hold_rel.os != NULL
-              || (hold_rel.os = output_rel_find ()) != NULL))
-    {
-      if (! link_info.relocateable && link_info.combreloc)
-       {
-         if (strncmp (secname, ".rela", 5) == 0)
-           os = lang_output_section_find (".rela.dyn");
-         else
-           os = lang_output_section_find (".rel.dyn");
-
-         if (os != NULL
-             && os->bfd_section != NULL
-             && ((s->flags ^ os->bfd_section->flags)
-                 & (SEC_LOAD | SEC_ALLOC)) == 0)
-           {
-             lang_add_section (&os->children, s, os, file);
-             return true;
-           }
-       }
-      place = &hold_rel;
-    }
+              || (hold_rel.os = output_rel_find (s)) != NULL))
+    place = &hold_rel;
   else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
           && HAVE_SECTION (hold_rodata, ".rodata"))
     place = &hold_rodata;
@@ -1164,13 +1186,10 @@ gld${EMULATION_NAME}_place_orphan (file, s)
   /* 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 = secname;
-  if (bfd_get_section_by_name (output_bfd, outsecname) != NULL)
+  if (bfd_get_section_by_name (output_bfd, secname) != NULL)
     {
-      outsecname = bfd_get_unique_section_name (output_bfd,
-                                               outsecname,
-                                               &count);
-      if (outsecname == NULL)
+      secname = bfd_get_unique_section_name (output_bfd, secname, &count);
+      if (secname == NULL)
        einfo ("%F%P: place_orphan failed: %E\n");
     }
 
@@ -1191,7 +1210,7 @@ gld${EMULATION_NAME}_place_orphan (file, s)
     {
       /* 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++)
+      for (ps = secname; *ps != '\0'; ps++)
        if (! ISALNUM (*ps) && *ps != '_')
          break;
       if (*ps == '\0')
@@ -1199,8 +1218,8 @@ gld${EMULATION_NAME}_place_orphan (file, s)
          char *symname;
          etree_type *e_align;
 
-         symname = (char *) xmalloc (ps - outsecname + sizeof "__start_");
-         sprintf (symname, "__start_%s", outsecname);
+         symname = (char *) xmalloc (ps - secname + sizeof "__start_");
+         sprintf (symname, "__start_%s", secname);
          e_align = exp_unop (ALIGN_K,
                              exp_intop ((bfd_vma) 1 << s->alignment_power));
          lang_add_assignment (exp_assop ('=', symname, e_align));
@@ -1212,7 +1231,7 @@ gld${EMULATION_NAME}_place_orphan (file, s)
   else
     address = NULL;
 
-  os = lang_enter_output_section_statement (outsecname, address, 0,
+  os = lang_enter_output_section_statement (secname, address, 0,
                                            (bfd_vma) 0,
                                            (etree_type *) NULL,
                                            (etree_type *) NULL,
@@ -1222,7 +1241,7 @@ gld${EMULATION_NAME}_place_orphan (file, s)
 
   lang_leave_output_section_statement
     ((bfd_vma) 0, "*default*",
-     (struct lang_output_section_phdr_list *) NULL, "*default*");
+     (struct lang_output_section_phdr_list *) NULL, NULL);
 
   if (config.build_constructors && *ps == '\0')
     {
@@ -1233,8 +1252,8 @@ gld${EMULATION_NAME}_place_orphan (file, s)
       if (place != NULL)
        stat_ptr = &add;
 
-      symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
-      sprintf (symname, "__stop_%s", outsecname);
+      symname = (char *) xmalloc (ps - secname + sizeof "__stop_");
+      sprintf (symname, "__stop_%s", secname);
       lang_add_assignment (exp_assop ('=', symname,
                                      exp_nameop (NAME, ".")));
     }
@@ -1242,7 +1261,7 @@ gld${EMULATION_NAME}_place_orphan (file, s)
   /* Restore the global list pointer.  */
   stat_ptr = old;
 
-  if (place != NULL)
+  if (place != NULL && os->bfd_section != NULL)
     {
       asection *snew, **pps;
 
@@ -1376,13 +1395,17 @@ echo '  ; else if (!config.magic_demand_paged) return'     >> e${EMULATION_NAME}
 sed $sc ldscripts/${EMULATION_NAME}.xn                     >> e${EMULATION_NAME}.c
 fi
 if test -n "$GENERATE_SHLIB_SCRIPT" ; then
+if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
 echo '  ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xsc                    >> e${EMULATION_NAME}.c
+fi
 echo '  ; else if (link_info.shared) return'              >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xs                     >> e${EMULATION_NAME}.c
 fi
+if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
 echo '  ; else if (link_info.combreloc) return'            >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xc                     >> e${EMULATION_NAME}.c
+fi
 echo '  ; else return'                                     >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.x                      >> e${EMULATION_NAME}.c
 echo '; }'                                                 >> e${EMULATION_NAME}.c
This page took 0.032827 seconds and 4 git commands to generate.