+2020-02-26 Alan Modra <amodra@gmail.com>
+
+ PR 25593
+ * elf-bfd.h (struct elf_link_hash_table): Rename "loaded" to
+ "dyn_loaded".
+ (bfd_elf_add_dt_needed_tag): Declare.
+ * elf-strtab.c (_bfd_elf_strtab_restore): Handle NULL buf.
+ * elflink.c (bfd_elf_add_dt_needed_tag): Make global and rename
+ from elf_add_dt_needed_tag. Remove soname and doit param.
+ (elf_link_add_object_symbols): Don't use elf_add_dt_needed_tag
+ to see whether as-needed lib is already loaded, use dyn_loaded
+ list instead. When saving and restoring around as-needed lib
+ handle possibility that dynstr has not been initialised. Don't
+ add DT_NEEDED tags here. Limit dyn_loaded list to dynamic libs.
+ Mark libs loaded via DT_NEEDED entries of other libs with
+ DYN_NO_NEEDED if they should not be mentioned in DT_NEEDED of
+ the output.
+ (elf_link_check_versioned_symbol): Remove now unneccesary
+ DYNAMIC check when traversing dyn_loaded list.
+
2020-02-26 Alan Modra <amodra@gmail.com>
* bfdio.c (bfd_get_file_size): Ignore bogus archive element sizes.
return TRUE;
}
-/* Add a DT_NEEDED entry for this dynamic object if DO_IT is true,
- otherwise just check whether one already exists. Returns -1 on error,
+/* Add a DT_NEEDED entry for this dynamic object. Returns -1 on error,
1 if a DT_NEEDED tag already exists, and 0 on success. */
-static int
-elf_add_dt_needed_tag (bfd *abfd,
- struct bfd_link_info *info,
- const char *soname,
- bfd_boolean do_it)
+int
+bfd_elf_add_dt_needed_tag (bfd *abfd, struct bfd_link_info *info)
{
struct elf_link_hash_table *hash_table;
size_t strindex;
+ const char *soname;
if (!_bfd_elf_link_create_dynstrtab (abfd, info))
return -1;
hash_table = elf_hash_table (info);
+ soname = elf_dt_name (abfd);
strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE);
if (strindex == (size_t) -1)
return -1;
}
}
- if (do_it)
- {
- if (!_bfd_elf_link_create_dynamic_sections (hash_table->dynobj, info))
- return -1;
+ if (!_bfd_elf_link_create_dynamic_sections (hash_table->dynobj, info))
+ return -1;
- if (!_bfd_elf_add_dynamic_entry (info, DT_NEEDED, strindex))
- return -1;
- }
- else
- /* We were just checking for existence of the tag. */
- _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
+ if (!_bfd_elf_add_dynamic_entry (info, DT_NEEDED, strindex))
+ return -1;
return 0;
}
char *audit = NULL;
struct bfd_link_needed_list *rpath = NULL, *runpath = NULL;
const Elf_Internal_Phdr *phdr;
- int ret;
+ struct elf_link_loaded_list *loaded_lib;
/* ld --just-symbols and dynamic objects don't mix very well.
ld shouldn't allow it. */
will need to know it. */
elf_dt_name (abfd) = soname;
- ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed);
- if (ret < 0)
- goto error_return;
-
/* If we have already included this dynamic object in the
link, just ignore it. There is no reason to include a
particular dynamic object more than once. */
- if (ret > 0)
- return TRUE;
+ for (loaded_lib = htab->dyn_loaded;
+ loaded_lib != NULL;
+ loaded_lib = loaded_lib->next)
+ {
+ if (strcmp (elf_dt_name (loaded_lib->abfd), soname) == 0)
+ return TRUE;
+ }
+
+ /* Create dynamic sections for backends that require that be done
+ before setup_gnu_properties. */
+ if (add_needed
+ && !_bfd_elf_link_create_dynamic_sections (abfd, info))
+ return FALSE;
/* Save the DT_AUDIT entry for the linker emulation code. */
elf_dt_audit (abfd) = audit;
old_table = htab->root.table.table;
old_size = htab->root.table.size;
old_count = htab->root.table.count;
- old_strtab = _bfd_elf_strtab_save (htab->dynstr);
- if (old_strtab == NULL)
- goto error_free_vers;
+ old_strtab = NULL;
+ if (htab->dynstr != NULL)
+ {
+ old_strtab = _bfd_elf_strtab_save (htab->dynstr);
+ if (old_strtab == NULL)
+ goto error_free_vers;
+ }
for (i = 0; i < htab->root.table.size; i++)
{
&& !on_needed_list (elf_dt_name (abfd),
htab->needed, NULL))))
{
- int ret;
const char *soname = elf_dt_name (abfd);
info->callbacks->minfo ("%!", soname, old_bfd,
elf_dyn_lib_class (abfd) = (enum dynamic_lib_link_class)
(elf_dyn_lib_class (abfd) & ~DYN_AS_NEEDED);
+ /* Create dynamic sections for backends that require
+ that be done before setup_gnu_properties. */
+ if (!_bfd_elf_link_create_dynamic_sections (abfd, info))
+ return FALSE;
add_needed = TRUE;
- ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed);
- if (ret < 0)
- goto error_free_vers;
-
- BFD_ASSERT (ret == 0);
}
}
}
memcpy (htab->root.table.table, old_tab, tabsize);
htab->root.undefs = old_undefs;
htab->root.undefs_tail = old_undefs_tail;
- _bfd_elf_strtab_restore (htab->dynstr, old_strtab);
+ if (htab->dynstr != NULL)
+ _bfd_elf_strtab_restore (htab->dynstr, old_strtab);
free (old_strtab);
old_strtab = NULL;
for (i = 0; i < htab->root.table.size; i++)
}
}
- if (is_elf_hash_table (htab) && add_needed)
+ if (dynamic && add_needed)
{
/* Add this bfd to the loaded list. */
struct elf_link_loaded_list *n;
if (n == NULL)
goto error_return;
n->abfd = abfd;
- n->next = htab->loaded;
- htab->loaded = n;
+ n->next = htab->dyn_loaded;
+ htab->dyn_loaded = n;
}
+ if (dynamic && !add_needed
+ && (elf_dyn_lib_class (abfd) & DYN_DT_NEEDED) != 0)
+ elf_dyn_lib_class (abfd) |= DYN_NO_NEEDED;
return TRUE;
}
BFD_ASSERT (abfd != NULL);
- for (loaded = elf_hash_table (info)->loaded;
+ for (loaded = elf_hash_table (info)->dyn_loaded;
loaded != NULL;
loaded = loaded->next)
{
/* We check each DSO for a possible hidden versioned definition. */
if (input == abfd
- || (input->flags & DYNAMIC) == 0
|| elf_dynversym (input) == 0)
continue;
bfd_elf_set_dyn_lib_class (abfd, (enum dynamic_lib_link_class) link_class);
+ *link_info.input_bfds_tail = abfd;
+ link_info.input_bfds_tail = &abfd->link.next;
+
/* Add this file into the symbol table. */
if (! bfd_link_add_symbols (abfd, &link_info))
einfo (_("%F%P: %pB: error adding symbols: %E\n"), abfd);
struct elf_link_hash_table *htab;
asection *s;
bfd *abfd;
+ bfd **save_input_bfd_tail;
after_open_default ();
special action by the person doing the link. Note that the
needed list can actually grow while we are stepping through this
loop. */
+ save_input_bfd_tail = link_info.input_bfds_tail;
needed = bfd_elf_get_needed_list (link_info.output_bfd, &link_info);
for (l = needed; l != NULL; l = l->next)
{
l->name, l->by);
}
+ for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
+ if (bfd_get_format (abfd) == bfd_object
+ && ((abfd->flags) & DYNAMIC) != 0
+ && bfd_get_flavour (abfd) == bfd_target_elf_flavour
+ && (elf_dyn_lib_class (abfd) & (DYN_AS_NEEDED | DYN_NO_NEEDED)) == 0
+ && elf_dt_name (abfd) != NULL)
+ {
+ if (bfd_elf_add_dt_needed_tag (abfd, &link_info) < 0)
+ einfo (_("%F%P: failed to add DT_NEEDED dynamic tag\n"));
+ }
+
+ link_info.input_bfds_tail = save_input_bfd_tail;
+ *save_input_bfd_tail = NULL;
+
if (link_info.eh_frame_hdr_type == COMPACT_EH_HDR)
if (!bfd_elf_parse_eh_frame_entries (NULL, &link_info))
einfo (_("%F%P: failed to parse EH frame entries\n"));