2000-08-22 H.J. Lu <hjl@gnu.org>
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 22 Aug 2000 19:33:16 +0000 (19:33 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 22 Aug 2000 19:33:16 +0000 (19:33 +0000)
* elf-bfd.h (elf_link_hash_table): Add runpath.

* bfd-in.h (bfd_elf_get_runpath_list): New prototype.
* bfd-in2.h: Rebuilt.

* elf.c (_bfd_elf_link_hash_table_init): Initialize the
"runpath" field to NULL.
(bfd_elf_get_runpath_list): New function.

* elflink.h (elf_link_add_object_symbols): Record DT_RPATH and
DT_RUNPATH entries.

bfd/ChangeLog
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/elf-bfd.h
bfd/elf.c
bfd/elflink.h

index 4bbb6c0..1733311 100644 (file)
@@ -1,3 +1,17 @@
+2000-08-22  H.J. Lu  <hjl@gnu.org>
+
+       * elf-bfd.h (elf_link_hash_table): Add runpath.
+
+       * bfd-in.h (bfd_elf_get_runpath_list): New prototype.
+       * bfd-in2.h: Rebuilt.
+
+       * elf.c (_bfd_elf_link_hash_table_init): Initialize the
+       "runpath" field to NULL.
+       (bfd_elf_get_runpath_list): New function.
+
+       * elflink.h (elf_link_add_object_symbols): Record DT_RPATH and
+       DT_RUNPATH entries.
+
 2000-08-22  Alexandre Oliva  <aoliva@redhat.com>
 
        * elf32-sh.c (sh_elf_relocate_section) [R_SH_IND12W,
index e0561f8..cfef8db 100644 (file)
@@ -629,6 +629,8 @@ extern boolean bfd_elf64_size_dynamic_sections
 extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
 extern void bfd_elf_set_dt_needed_soname PARAMS ((bfd *, const char *));
 extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
+extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
+  PARAMS ((bfd *, struct bfd_link_info *));
 
 /* Return an upper bound on the number of bytes required to store a
    copy of ABFD's program header table entries.  Return -1 if an error
index f9803c0..d755d75 100644 (file)
@@ -629,6 +629,8 @@ extern boolean bfd_elf64_size_dynamic_sections
 extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
 extern void bfd_elf_set_dt_needed_soname PARAMS ((bfd *, const char *));
 extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
+extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
+  PARAMS ((bfd *, struct bfd_link_info *));
 
 /* Return an upper bound on the number of bytes required to store a
    copy of ABFD's program header table entries.  Return -1 if an error
index 0ef27ea..b84948f 100644 (file)
@@ -243,6 +243,9 @@ struct elf_link_hash_table
   PTR stab_info;
   /* A linked list of local symbols to be added to .dynsym.  */
   struct elf_link_local_dynamic_entry *dynlocal;
+  /* A linked list of DT_RPATH/DT_RUNPATH names found in dynamic
+     objects included in the link.  */
+  struct bfd_link_needed_list *runpath;
 };
 
 /* Look up an entry in an ELF linker hash table.  */
index 7e30580..4377797 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1007,6 +1007,7 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc)
   table->dynstr = NULL;
   table->bucketcount = 0;
   table->needed = NULL;
+  table->runpath = NULL;
   table->hgot = NULL;
   table->stab_info = NULL;
   table->dynlocal = NULL;
@@ -1073,6 +1074,19 @@ bfd_elf_get_needed_list (abfd, info)
   return elf_hash_table (info)->needed;
 }
 
+/* Get the list of DT_RPATH/DT_RUNPATH entries for a link.  This is a
+   hook for the linker ELF emulation code.  */
+
+struct bfd_link_needed_list *
+bfd_elf_get_runpath_list (abfd, info)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     struct bfd_link_info *info;
+{
+  if (info->hash->creator->flavour != bfd_target_elf_flavour)
+    return NULL;
+  return elf_hash_table (info)->runpath;
+}
+
 /* Get the name actually used for a dynamic object for a link.  This
    is the SONAME entry if there is one.  Otherwise, it is the string
    passed to bfd_elf_set_dt_needed_name, or it is the filename.  */
index 1dadc49..cd55664 100644 (file)
@@ -1112,6 +1112,8 @@ elf_link_add_object_symbols (abfd, info)
          Elf_External_Dyn *extdynend;
          int elfsec;
          unsigned long link;
+         int rpath;
+         int runpath;
 
          dynbuf = (Elf_External_Dyn *) bfd_malloc ((size_t) s->_raw_size);
          if (dynbuf == NULL)
@@ -1145,6 +1147,8 @@ elf_link_add_object_symbols (abfd, info)
 
          extdyn = dynbuf;
          extdynend = extdyn + s->_raw_size / sizeof (Elf_External_Dyn);
+         rpath = 0;
+         runpath = 0;
          for (; extdyn < extdynend; extdyn++)
            {
              Elf_Internal_Dyn dyn;
@@ -1181,6 +1185,73 @@ elf_link_add_object_symbols (abfd, info)
                    ;
                  *pn = n;
                }
+             if (dyn.d_tag == DT_RUNPATH)
+               {
+                 struct bfd_link_needed_list *n, **pn;
+                 char *fnm, *anm;
+
+                 /* When we see DT_RPATH before DT_RUNPATH, we have
+                    to free runpath. */
+                 if (rpath && elf_hash_table (info)->runpath)
+                   {
+                     struct bfd_link_needed_list *nn;
+                     for (n = elf_hash_table (info)->runpath;
+                          n != NULL; n = nn)
+                       {
+                         nn = n->next;
+                         bfd_release (abfd, n);
+                       }
+                     bfd_release (abfd, elf_hash_table (info)->runpath);
+                     elf_hash_table (info)->runpath = NULL;
+                   }
+
+                 n = ((struct bfd_link_needed_list *)
+                      bfd_alloc (abfd, sizeof (struct bfd_link_needed_list)));
+                 fnm = bfd_elf_string_from_elf_section (abfd, link,
+                                                        dyn.d_un.d_val);
+                 if (n == NULL || fnm == NULL)
+                   goto error_return;
+                 anm = bfd_alloc (abfd, strlen (fnm) + 1);
+                 if (anm == NULL)
+                   goto error_return;
+                 strcpy (anm, fnm);
+                 n->name = anm;
+                 n->by = abfd;
+                 n->next = NULL;
+                 for (pn = &elf_hash_table (info)->runpath;
+                      *pn != NULL;
+                      pn = &(*pn)->next)
+                   ;
+                 *pn = n;
+                 runpath = 1;
+                 rpath = 0;
+               }
+             /* Ignore DT_RPATH if we have seen DT_RUNPATH. */
+             if (!runpath && dyn.d_tag == DT_RPATH)
+               {
+                 struct bfd_link_needed_list *n, **pn;
+                 char *fnm, *anm;
+
+                 n = ((struct bfd_link_needed_list *)
+                      bfd_alloc (abfd, sizeof (struct bfd_link_needed_list)));
+                 fnm = bfd_elf_string_from_elf_section (abfd, link,
+                                                        dyn.d_un.d_val);
+                 if (n == NULL || fnm == NULL)
+                   goto error_return;
+                 anm = bfd_alloc (abfd, strlen (fnm) + 1);
+                 if (anm == NULL)
+                   goto error_return;
+                 strcpy (anm, fnm);
+                 n->name = anm;
+                 n->by = abfd;
+                 n->next = NULL;
+                 for (pn = &elf_hash_table (info)->runpath;
+                      *pn != NULL;
+                      pn = &(*pn)->next)
+                   ;
+                 *pn = n;
+                 rpath = 1;
+               }
            }
 
          free (dynbuf);