This is the mail archive of the
binutils-cvs@sourceware.org
mailing list for the binutils project.
[binutils-gdb] PR19886, --as-needed regression
- From: Alan Modra <amodra at sourceware dot org>
- To: bfd-cvs at sourceware dot org
- Date: 1 Apr 2016 12:50:47 -0000
- Subject: [binutils-gdb] PR19886, --as-needed regression
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7b15fa7ac802f430f7fb7c2b77f40ab78c2e4018
commit 7b15fa7ac802f430f7fb7c2b77f40ab78c2e4018
Author: Alan Modra <amodra@gmail.com>
Date: Fri Apr 1 17:08:45 2016 +1030
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.
Diff:
---
bfd/ChangeLog | 6 ++++++
bfd/elflink.c | 27 +++++++++++++++++++++------
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);