diff options
author | Alan Modra <amodra@gmail.com> | 2016-04-01 17:08:45 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2016-04-01 23:20:12 +1030 |
commit | 7b15fa7ac802f430f7fb7c2b77f40ab78c2e4018 (patch) | |
tree | ba488940ff109deeaed2af061bb413123c9ab25d /bfd | |
parent | 6d4af3c269e64b0093b23bd63d302bd9f90de6a9 (diff) | |
download | gdb-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/ChangeLog | 6 | ||||
-rw-r--r-- | 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); |