aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2016-04-01 17:08:45 +1030
committerAlan Modra <amodra@gmail.com>2016-04-01 23:20:12 +1030
commit7b15fa7ac802f430f7fb7c2b77f40ab78c2e4018 (patch)
treeba488940ff109deeaed2af061bb413123c9ab25d /bfd
parent6d4af3c269e64b0093b23bd63d302bd9f90de6a9 (diff)
downloadgdb-7b15fa7ac802f430f7fb7c2b77f40ab78c2e4018.zip
gdb-7b15fa7ac802f430f7fb7c2b77f40ab78c2e4018.tar.gz
gdb-7b15fa7ac802f430f7fb7c2b77f40ab78c2e4018.tar.bz2
PR19886, --as-needed regression
This isn't perfect in checking whether libraries will be loaded since elf_link_add_object_symbols doesn't recurse down DT_NEEDED links. (That happens later in ld/emultempl/elf32.em after_open.) So in effect this recursive check really only looks one level down the DT_NEEDED tree. Which is enough for the most common case, and libc.so/ld.so in particular. PR 19886 * elflink.c (on_needed_list): Recursively check needed status. (elf_link_add_object_symbols): Adjust.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog6
-rw-r--r--bfd/elflink.c27
2 files changed, 27 insertions, 6 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index b1b053b..9b87780 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,9 @@
+2016-04-01 Alan Modra <amodra@gmail.com>
+
+ PR 19886
+ * elflink.c (on_needed_list): Recursively check needed status.
+ (elf_link_add_object_symbols): Adjust.
+
2016-03-30 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
* elf32-avr.c (avr_elf32_load_records_from_section): Free
diff --git a/bfd/elflink.c b/bfd/elflink.c
index c2ad11b..445fb01 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -3245,12 +3245,26 @@ elf_add_dt_needed_tag (bfd *abfd,
return 0;
}
+/* Return true if SONAME is on the needed list between NEEDED and STOP
+ (or the end of list if STOP is NULL), and needed by a library that
+ will be loaded. */
+
static bfd_boolean
-on_needed_list (const char *soname, struct bfd_link_needed_list *needed)
-{
- for (; needed != NULL; needed = needed->next)
- if ((elf_dyn_lib_class (needed->by) & DYN_AS_NEEDED) == 0
- && strcmp (soname, needed->name) == 0)
+on_needed_list (const char *soname,
+ struct bfd_link_needed_list *needed,
+ struct bfd_link_needed_list *stop)
+{
+ struct bfd_link_needed_list *look;
+ for (look = needed; look != stop; look = look->next)
+ if (strcmp (soname, look->name) == 0
+ && ((elf_dyn_lib_class (look->by) & DYN_AS_NEEDED) == 0
+ /* If needed by a library that itself is not directly
+ needed, recursively check whether that library is
+ indirectly needed. Since we add DT_NEEDED entries to
+ the end of the list, library dependencies appear after
+ the library. Therefore search prior to the current
+ LOOK, preventing possible infinite recursion. */
+ || on_needed_list (elf_dt_name (look->by), needed, look)))
return TRUE;
return FALSE;
@@ -4593,7 +4607,8 @@ error_free_dyn:
|| (old_bfd->flags & BFD_PLUGIN) == 0))
|| (h->ref_dynamic_nonweak
&& (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0
- && !on_needed_list (elf_dt_name (abfd), htab->needed))))
+ && !on_needed_list (elf_dt_name (abfd),
+ htab->needed, NULL))))
{
int ret;
const char *soname = elf_dt_name (abfd);