bfd/
authorRichard Sandiford <rdsandiford@googlemail.com>
Wed, 1 Apr 2009 19:53:53 +0000 (19:53 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Wed, 1 Apr 2009 19:53:53 +0000 (19:53 +0000)
* bfd-in.h (bfd_xcoff_split_import_path): Declare.
(bfd_xcoff_set_archive_import_path): Likewise.
* bfd-in2.h: Regenerate.
* xcofflink.c: Include libiberty.h.
(xcoff_archive_info): New structure.
(xcoff_archive_info_hash): New function.
(xcoff_archive_info_eq): Likewise.
(xcoff_get_archive_info): Likewise.
(_bfd_xcoff_bfd_link_hash_table_create): Initialize archive_info.
(bfd_xcoff_split_import_path): New function.
(bfd_xcoff_set_archive_import_path): Likewise.
(xcoff_set_import_path): Move earlier in file.
(xcoff_link_add_dynamic_symbols): Set the import path of a non-archive
object to the the directory part of the bfd's filename.  Get the
import path and filename of an archive object from the archive's
xcoff_tdata, initializing it if necessary.  Update use of
import_file_id.
(bfd_link_input_bfd): Update use of import_file_id.
(xcoff_write_global_symbol): Likewise.

ld/
* emultempl/aix.em (gld${EMULATION_NAME}_open_dynamic_archive): New
function.
(ld_${EMULATION_NAME}_emulation): Use it.

bfd/ChangeLog
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/xcofflink.c
ld/ChangeLog
ld/emultempl/aix.em

index 217730145ce2107efb42324d1513840524132c57..54f37ab2e7661cb55f980c84148fbfec9e662ccd 100644 (file)
@@ -1,3 +1,25 @@
+2009-04-01  Richard Sandiford  <r.sandiford@uk.ibm.com>
+
+       * bfd-in.h (bfd_xcoff_split_import_path): Declare.
+       (bfd_xcoff_set_archive_import_path): Likewise.
+       * bfd-in2.h: Regenerate.
+       * xcofflink.c: Include libiberty.h.
+       (xcoff_archive_info): New structure.
+       (xcoff_archive_info_hash): New function.
+       (xcoff_archive_info_eq): Likewise.
+       (xcoff_get_archive_info): Likewise.
+       (_bfd_xcoff_bfd_link_hash_table_create): Initialize archive_info.
+       (bfd_xcoff_split_import_path): New function.
+       (bfd_xcoff_set_archive_import_path): Likewise.
+       (xcoff_set_import_path): Move earlier in file.
+       (xcoff_link_add_dynamic_symbols): Set the import path of a non-archive
+       object to the the directory part of the bfd's filename.  Get the
+       import path and filename of an archive object from the archive's
+       xcoff_tdata, initializing it if necessary.  Update use of
+       import_file_id.
+       (bfd_link_input_bfd): Update use of import_file_id.
+       (xcoff_write_global_symbol): Likewise.
+
 2009-04-01  Richard Sandiford  <r.sandiford@uk.ibm.com>
 
        * xcofflink.c (xcoff_link_hash_table): Moved from include/coff/xcoff.h.
index 5a3e13f1bbb2f8a3a9b06ef537f2069c4ea8ccc5..9a303e0a80fb19495c0cac23bd9506174411cd93 100644 (file)
@@ -765,6 +765,10 @@ extern bfd_boolean bfd_get_file_window
 
 /* XCOFF support routines for the linker.  */
 
+extern bfd_boolean bfd_xcoff_split_import_path
+  (bfd *, const char *, const char **, const char **);
+extern bfd_boolean bfd_xcoff_set_archive_import_path
+  (struct bfd_link_info *, bfd *, const char *);
 extern bfd_boolean bfd_xcoff_link_record_set
   (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, bfd_size_type);
 extern bfd_boolean bfd_xcoff_import_symbol
index 78a5bd92d25b2c21f62d96fec00bec8a7eabbccb..646be2cae15df499a6f58c46649be78b708d4563 100644 (file)
@@ -772,6 +772,10 @@ extern bfd_boolean bfd_get_file_window
 
 /* XCOFF support routines for the linker.  */
 
+extern bfd_boolean bfd_xcoff_split_import_path
+  (bfd *, const char *, const char **, const char **);
+extern bfd_boolean bfd_xcoff_set_archive_import_path
+  (struct bfd_link_info *, bfd *, const char *);
 extern bfd_boolean bfd_xcoff_link_record_set
   (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, bfd_size_type);
 extern bfd_boolean bfd_xcoff_import_symbol
index 1c205f934b85b7c100478d36c6c6f2a941acd70c..97c051a2b9fe6f8bd6ec64a0dbaae1f32522fb61 100644 (file)
@@ -28,6 +28,7 @@
 #include "coff/xcoff.h"
 #include "libcoff.h"
 #include "libxcoff.h"
+#include "libiberty.h"
 
 /* This file holds the XCOFF linker code.  */
 
@@ -75,6 +76,18 @@ struct xcoff_link_section_info
   } *toc_rel_hashes;
 };
 
+/* Information that the XCOFF linker collects about an archive.  */
+struct xcoff_archive_info
+{
+  /* The archive described by this entry.  */
+  bfd *archive;
+
+  /* The import path and import filename to use when referring to
+     this archive in the .loader section.  */
+  const char *imppath;
+  const char *impfile;
+};
+
 struct xcoff_link_hash_table
 {
   struct bfd_link_hash_table root;
@@ -132,6 +145,9 @@ struct xcoff_link_hash_table
   } 
   *size_list;
 
+  /* Information about archives.  */
+  htab_t archive_info;
+
   /* Magic sections: _text, _etext, _data, _edata, _end, end. */
   asection *special_sections[XCOFF_NUMBER_OF_SPECIAL_SECTIONS];
 };
@@ -464,6 +480,56 @@ _bfd_xcoff_canonicalize_dynamic_reloc (bfd *abfd,
   return ldhdr.l_nreloc;
 }
 \f
+/* Hash functions for xcoff_link_hash_table's archive_info.  */
+
+static hashval_t
+xcoff_archive_info_hash (const void *data)
+{
+  const struct xcoff_archive_info *info;
+
+  info = (const struct xcoff_archive_info *) data;
+  return htab_hash_pointer (info->archive);
+}
+
+static int
+xcoff_archive_info_eq (const void *data1, const void *data2)
+{
+  const struct xcoff_archive_info *info1;
+  const struct xcoff_archive_info *info2;
+
+  info1 = (const struct xcoff_archive_info *) data1;
+  info2 = (const struct xcoff_archive_info *) data2;
+  return info1->archive == info2->archive;
+}
+
+/* Return information about archive ARCHIVE.  Return NULL on error.  */
+
+static struct xcoff_archive_info *
+xcoff_get_archive_info (struct bfd_link_info *info, bfd *archive)
+{
+  struct xcoff_link_hash_table *htab;
+  struct xcoff_archive_info *entryp, entry;
+  void **slot;
+
+  htab = xcoff_hash_table (info);
+  entry.archive = archive;
+  slot = htab_find_slot (htab->archive_info, &entry, INSERT);
+  if (!slot)
+    return NULL;
+
+  entryp = *slot;
+  if (!entryp)
+    {
+      entryp = bfd_zalloc (archive, sizeof (entry));
+      if (!entryp)
+       return NULL;
+
+      entryp->archive = archive;
+      *slot = entryp;
+    }
+  return entryp;
+}
+\f
 /* Routine to create an entry in an XCOFF link hash table.  */
 
 static struct bfd_hash_entry *
@@ -530,6 +596,8 @@ _bfd_xcoff_bfd_link_hash_table_create (bfd *abfd)
   ret->file_align = 0;
   ret->textro = FALSE;
   ret->gc = FALSE;
+  ret->archive_info = htab_create (37, xcoff_archive_info_hash,
+                                  xcoff_archive_info_eq, NULL);
   memset (ret->special_sections, 0, sizeof ret->special_sections);
 
   /* The linker will always generate a full a.out header.  We need to
@@ -606,6 +674,109 @@ xcoff_read_internal_relocs (bfd *abfd,
                                         require_internal, internal_relocs);
 }
 \f
+/* Split FILENAME into an import path and an import filename,
+   storing them in *IMPPATH and *IMPFILE respectively.  */
+
+bfd_boolean
+bfd_xcoff_split_import_path (bfd *abfd, const char *filename,
+                            const char **imppath, const char **impfile)
+{
+  const char *basename;
+  size_t length;
+  char *path;
+
+  basename = lbasename (filename);
+  length = basename - filename;
+  if (length == 0)
+    /* The filename has no directory component, so use an empty path.  */
+    *imppath = "";
+  else if (length == 1)
+    /* The filename is in the root directory.  */
+    *imppath = "/";
+  else
+    {
+      /* Extract the (non-empty) directory part.  Note that we don't
+        need to strip duplicate directory separators from any part
+        of the string; the native linker doesn't do that either.  */
+      path = bfd_alloc (abfd, length);
+      if (path == NULL)
+       return FALSE;
+      memcpy (path, filename, length - 1);
+      path[length - 1] = 0;
+      *imppath = path;
+    }
+  *impfile = basename;
+  return TRUE;
+}
+
+/* Set ARCHIVE's import path as though its filename had been given
+   as FILENAME.  */
+
+bfd_boolean
+bfd_xcoff_set_archive_import_path (struct bfd_link_info *info,
+                                  bfd *archive, const char *filename)
+{
+  struct xcoff_archive_info *archive_info;
+
+  archive_info = xcoff_get_archive_info (info, archive);
+  return (archive_info != NULL
+         && bfd_xcoff_split_import_path (archive, filename,
+                                         &archive_info->imppath,
+                                         &archive_info->impfile));
+}
+
+/* H is an imported symbol.  Set the import module's path, file and member
+   to IMPATH, IMPFILE and IMPMEMBER respectively.  All three are null if
+   no specific import module is specified.  */
+
+static bfd_boolean
+xcoff_set_import_path (struct bfd_link_info *info,
+                      struct xcoff_link_hash_entry *h,
+                      const char *imppath, const char *impfile,
+                      const char *impmember)
+{
+  unsigned int c;
+  struct xcoff_import_file **pp;
+
+  /* We overload the ldindx field to hold the l_ifile value for this
+     symbol.  */
+  BFD_ASSERT (h->ldsym == NULL);
+  BFD_ASSERT ((h->flags & XCOFF_BUILT_LDSYM) == 0);
+  if (imppath == NULL)
+    h->ldindx = -1;
+  else
+    {
+      /* We start c at 1 because the first entry in the import list is
+        reserved for the library search path.  */
+      for (pp = &xcoff_hash_table (info)->imports, c = 1;
+          *pp != NULL;
+          pp = &(*pp)->next, ++c)
+       {
+         if (strcmp ((*pp)->path, imppath) == 0
+             && strcmp ((*pp)->file, impfile) == 0
+             && strcmp ((*pp)->member, impmember) == 0)
+           break;
+       }
+
+      if (*pp == NULL)
+       {
+         struct xcoff_import_file *n;
+         bfd_size_type amt = sizeof (* n);
+
+         n = bfd_alloc (info->output_bfd, amt);
+         if (n == NULL)
+           return FALSE;
+         n->next = NULL;
+         n->path = imppath;
+         n->file = impfile;
+         n->member = impmember;
+         *pp = n;
+       }
+      h->ldindx = c;
+    }
+  return TRUE;
+}
+\f
 /* H is the bfd symbol associated with exported .loader symbol LDSYM.
    Return true if LDSYM defines H.  */
 
@@ -648,9 +819,6 @@ xcoff_link_add_dynamic_symbols (bfd *abfd, struct bfd_link_info *info)
   const char *strings;
   bfd_byte *elsym, *elsymend;
   struct xcoff_import_file *n;
-  const char *bname;
-  const char *mname;
-  const char *s;
   unsigned int c;
   struct xcoff_import_file **pp;
 
@@ -827,25 +995,30 @@ xcoff_link_add_dynamic_symbols (bfd *abfd, struct bfd_link_info *info)
     return FALSE;
   n->next = NULL;
 
-  /* For some reason, the path entry in the import file list for a
-     shared object appears to always be empty.  The file name is the
-     base name.  */
-  n->path = "";
   if (abfd->my_archive == NULL)
     {
-      bname = bfd_get_filename (abfd);
-      mname = "";
+      if (!bfd_xcoff_split_import_path (abfd, abfd->filename,
+                                       &n->path, &n->file))
+       return FALSE;
+      n->member = "";
     }
   else
     {
-      bname = bfd_get_filename (abfd->my_archive);
-      mname = bfd_get_filename (abfd);
+      struct xcoff_archive_info *archive_info;
+
+      archive_info = xcoff_get_archive_info (info, abfd->my_archive);
+      if (!archive_info->impfile)
+       {
+         if (!bfd_xcoff_split_import_path (archive_info->archive,
+                                           archive_info->archive->filename,
+                                           &archive_info->imppath,
+                                           &archive_info->impfile))
+           return FALSE;
+       }
+      n->path = archive_info->imppath;
+      n->file = archive_info->impfile;
+      n->member = bfd_get_filename (abfd);
     }
-  s = strrchr (bname, '/');
-  if (s != NULL)
-    bname = s + 1;
-  n->file = bname;
-  n->member = mname;
 
   /* We start c at 1 because the first import file number is reserved
      for LIBPATH.  */
@@ -2327,58 +2500,6 @@ xcoff_find_function (struct bfd_link_info *info,
     }
   return TRUE;
 }
-
-/* H is an imported symbol.  Set the import module's path, file and member
-   to IMPATH, IMPFILE and IMPMEMBER respectively.  All three are null if
-   no specific import module is specified.  */
-
-static bfd_boolean
-xcoff_set_import_path (struct bfd_link_info *info,
-                      struct xcoff_link_hash_entry *h,
-                      const char *imppath, const char *impfile,
-                      const char *impmember)
-{
-  unsigned int c;
-  struct xcoff_import_file **pp;
-
-  /* We overload the ldindx field to hold the l_ifile value for this
-     symbol.  */
-  BFD_ASSERT (h->ldsym == NULL);
-  BFD_ASSERT ((h->flags & XCOFF_BUILT_LDSYM) == 0);
-  if (imppath == NULL)
-    h->ldindx = -1;
-  else
-    {
-      /* We start c at 1 because the first entry in the import list is
-        reserved for the library search path.  */
-      for (pp = &xcoff_hash_table (info)->imports, c = 1;
-          *pp != NULL;
-          pp = &(*pp)->next, ++c)
-       {
-         if (strcmp ((*pp)->path, imppath) == 0
-             && strcmp ((*pp)->file, impfile) == 0
-             && strcmp ((*pp)->member, impmember) == 0)
-           break;
-       }
-
-      if (*pp == NULL)
-       {
-         struct xcoff_import_file *n;
-         bfd_size_type amt = sizeof (* n);
-
-         n = bfd_alloc (info->output_bfd, amt);
-         if (n == NULL)
-           return FALSE;
-         n->next = NULL;
-         n->path = imppath;
-         n->file = impfile;
-         n->member = impmember;
-         *pp = n;
-       }
-      h->ldindx = c;
-    }
-  return TRUE;
-}
 \f
 /* Return true if the given bfd contains at least one shared object.  */
 
index 2eefd162fb3d943301b38be071fa847508dab4fd..378e85557c7105ffaa98b6f1ad6d72b97757de67 100644 (file)
@@ -1,3 +1,9 @@
+2009-04-01  Richard Sandiford  <r.sandiford@uk.ibm.com>
+
+       * emultempl/aix.em (gld${EMULATION_NAME}_open_dynamic_archive): New
+       function.
+       (ld_${EMULATION_NAME}_emulation): Use it.
+
 2009-03-20  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/9970
index 85586607b5c800d85f6ca8923cb3d87024233b12..b43ffbb36ee810ae913f420ebb078fcbb8e1c2fb 100644 (file)
@@ -1096,32 +1096,18 @@ gld${EMULATION_NAME}_read_file (const char *filename, bfd_boolean import)
          else
            {
              char cs;
-             char *file;
+             char *start;
 
              (void) obstack_finish (o);
              keep = TRUE;
-             imppath = s;
-             file = NULL;
+             start = s;
              while (!ISSPACE (*s) && *s != '(' && *s != '\0')
-               {
-                 if (*s == '/')
-                   file = s + 1;
-                 ++s;
-               }
-             if (file != NULL)
-               {
-                 file[-1] = '\0';
-                 impfile = file;
-                 if (imppath == file - 1)
-                   imppath = "/";
-               }
-             else
-               {
-                 impfile = imppath;
-                 imppath = "";
-               }
+               ++s;
              cs = *s;
              *s = '\0';
+             if (!bfd_xcoff_split_import_path (link_info.output_bfd,
+                                               start, &imppath, &impfile))
+               einfo ("%F%P: Could not parse import path: %E\n");
              while (ISSPACE (cs))
                {
                  ++s;
@@ -1433,6 +1419,31 @@ gld${EMULATION_NAME}_set_output_arch (void)
   ldfile_output_machine_name = bfd_printable_name (link_info.output_bfd);
 }
 
+static bfd_boolean
+gld${EMULATION_NAME}_open_dynamic_archive (const char *arch,
+                                          search_dirs_type *search,
+                                          lang_input_statement_type *entry)
+{
+  const char *filename;
+  char *path;
+
+  if (!entry->is_archive)
+    return FALSE;
+
+  filename = entry->filename;
+  path = concat (search->name, "/lib", entry->filename, arch, ".a", NULL);
+  if (!ldfile_try_open_bfd (path, entry))
+    {
+      free (path);
+      return FALSE;
+    }
+  /* Don't include the searched directory in the import path.  */
+  bfd_xcoff_set_archive_import_path (&link_info, entry->the_bfd,
+                                    path + strlen (search->name) + 1);
+  entry->filename = path;
+  return TRUE;
+}
+
 struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = {
   gld${EMULATION_NAME}_before_parse,
   syslib_default,
@@ -1448,7 +1459,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = {
   "${OUTPUT_FORMAT}",
   finish_default,
   gld${EMULATION_NAME}_create_output_section_statements,
-  0,                           /* open_dynamic_archive */
+  gld${EMULATION_NAME}_open_dynamic_archive,
   0,                           /* place_orphan */
   0,                           /* set_symbols */
   gld${EMULATION_NAME}_parse_args,