+void
+pe_find_data_imports (const char *symhead,
+ void (*cb) (arelent *, asection *, char *, const char *))
+{
+ struct bfd_link_hash_entry *undef;
+ const size_t headlen = strlen (symhead);
+ size_t namelen = 0;
+ char *buf, *name;
+ struct bfd_hash_table *import_hash;
+
+ for (undef = link_info.hash->undefs; undef; undef = undef->u.undef.next)
+ if (undef->type == bfd_link_hash_undefined)
+ {
+ size_t len = strlen (undef->root.string);
+ if (namelen < len)
+ namelen = len;
+ }
+ if (namelen == 0)
+ return;
+
+ /* For the pseudo-relocation support version 2, we can collect the symbols
+ that are subject to auto-import and adjust the relocations en masse. */
+ if (link_info.pei386_runtime_pseudo_reloc == 2)
+ {
+ import_hash
+ = (struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table));
+ if (!bfd_hash_table_init (import_hash,
+ bfd_hash_newfunc,
+ sizeof (struct bfd_hash_entry)))
+ einfo (_("%F%P: bfd_hash_table_init failed: %E\n"));
+ }
+ else
+ import_hash = NULL;
+
+ /* We are being a bit cunning here. The buffer will have space for
+ prefixes at the beginning. The prefix is modified here and in a
+ number of functions called from this function. */
+#define PREFIX_LEN 32
+ buf = xmalloc (PREFIX_LEN + namelen + 1);
+ name = buf + PREFIX_LEN;
+
+ for (undef = link_info.hash->undefs; undef; undef = undef->u.undef.next)
+ if (undef->type == bfd_link_hash_undefined)
+ {
+ struct bfd_link_hash_entry *sym;
+ char *impname;
+
+ if (pe_dll_extra_pe_debug)
+ printf ("%s:%s\n", __FUNCTION__, undef->root.string);
+
+ strcpy (name, undef->root.string);
+ impname = name - (sizeof "__imp_" - 1);
+ memcpy (impname, "__imp_", sizeof "__imp_" - 1);
+
+ sym = bfd_link_hash_lookup (link_info.hash, impname, 0, 0, 1);
+
+ if (sym && sym->type == bfd_link_hash_defined)
+ {
+ if (import_hash)
+ bfd_hash_lookup (import_hash, undef->root.string, TRUE, FALSE);
+ else
+ {
+ bfd *b = sym->u.def.section->owner;
+ const char *symname = NULL;
+ asymbol **symbols;
+ int nsyms, i;
+
+ if (!bfd_generic_link_read_symbols (b))
+ {
+ einfo (_("%F%P: %pB: could not read symbols: %E\n"), b);
+ return;
+ }
+
+ symbols = bfd_get_outsymbols (b);
+ nsyms = bfd_get_symcount (b);
+
+ for (i = 0; i < nsyms; i++)
+ if (strncmp (symbols[i]->name, symhead, headlen) == 0)
+ {
+ if (pe_dll_extra_pe_debug)
+ printf ("->%s\n", symbols[i]->name);
+
+ symname = symbols[i]->name + headlen;
+ break;
+ }
+
+ /* If the symobl isn't part of an import table, there is no
+ point in building a fixup, this would give rise to link
+ errors for mangled symbols instead of the original one. */
+ if (symname)
+ pe_walk_relocs (&link_info, name, symname, NULL, cb);
+ else
+ continue;
+ }
+
+ /* Let's differentiate it somehow from defined. */
+ undef->type = bfd_link_hash_defweak;
+ undef->u.def.value = sym->u.def.value;
+ undef->u.def.section = sym->u.def.section;
+
+ /* We replace the original name with the __imp_ prefixed one, this
+ 1) may trash memory 2) leads to duplicate symbols. But this is
+ better than having a misleading name that can confuse GDB. */
+ undef->root.string = sym->root.string;
+
+ if (link_info.pei386_auto_import == -1)
+ {
+ static bfd_boolean warned = FALSE;
+
+ info_msg (_("Info: resolving %s by linking to %s "
+ "(auto-import)\n"), name, impname);
+
+ /* PR linker/4844. */
+ if (!warned)
+ {
+ einfo (_("%P: warning: auto-importing has been activated "
+ "without --enable-auto-import specified on the "
+ "command line; this should work unless it "
+ "involves constant data structures referencing "
+ "symbols from auto-imported DLLs\n"));
+ warned = TRUE;
+ }
+ }
+ }
+ }
+
+ /* If we have the import hash table, walk the relocations only once. */
+ if (import_hash)
+ {
+ pe_walk_relocs (&link_info, name, NULL, import_hash, cb);
+ bfd_hash_table_free (import_hash);
+ free (import_hash);
+ }
+
+ free (buf);
+}
+