diff options
-rw-r--r-- | bfd/ChangeLog | 14 | ||||
-rw-r--r-- | bfd/bfd-in.h | 2 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 2 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 3 | ||||
-rw-r--r-- | bfd/elf.c | 14 | ||||
-rw-r--r-- | bfd/elflink.h | 71 |
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); |