From 7b15fa7ac802f430f7fb7c2b77f40ab78c2e4018 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Fri, 1 Apr 2016 17:08:45 +1030 Subject: [PATCH] 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. --- bfd/ChangeLog | 6 ++++++ bfd/elflink.c | 27 +++++++++++++++++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index b1b053b43a4..9b877804091 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2016-04-01 Alan Modra + + PR 19886 + * elflink.c (on_needed_list): Recursively check needed status. + (elf_link_add_object_symbols): Adjust. + 2016-03-30 Senthil Kumar Selvaraj * elf32-avr.c (avr_elf32_load_records_from_section): Free diff --git a/bfd/elflink.c b/bfd/elflink.c index c2ad11bfbb3..445fb013258 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); -- 2.30.2