summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog14
-rw-r--r--bfd/bfd-in.h2
-rw-r--r--bfd/bfd-in2.h2
-rw-r--r--bfd/elf-bfd.h3
-rw-r--r--bfd/elf.c14
-rw-r--r--bfd/elflink.h71
6 files changed, 106 insertions, 0 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4bbb6c0846e..1733311f90b 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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,
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index e0561f85f16..cfef8dbbb7b 100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -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
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index f9803c0aa7d..d755d754e01 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -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
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 0ef27ea9fc2..b84948f63a2 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -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. */
diff --git a/bfd/elf.c b/bfd/elf.c
index 7e30580d3a0..4377797d4aa 100644
--- 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. */
diff --git a/bfd/elflink.h b/bfd/elflink.h
index 1dadc49c4c6..cd55664836c 100644
--- a/bfd/elflink.h
+++ b/bfd/elflink.h
@@ -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);