X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Fplugin.c;h=173aa1d07180636e8578f5c61555cebcb5d0e18e;hb=203a206d14e4892bc4ab9448e08617506b5d613d;hp=9abeaf029dda3809096096c84b8c8cd020a40c92;hpb=bc4e12ded1d4c8d589d82b2a10ade6b47f219db3;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/plugin.c b/ld/plugin.c index 9abeaf029d..173aa1d071 100644 --- a/ld/plugin.c +++ b/ld/plugin.c @@ -1,5 +1,5 @@ /* Plugin control for the GNU linker. - Copyright (C) 2010-2017 Free Software Foundation, Inc. + Copyright (C) 2010-2021 Free Software Foundation, Inc. This file is part of the GNU Binutils. @@ -21,8 +21,10 @@ #include "sysdep.h" #include "libiberty.h" #include "bfd.h" +#if BFD_SUPPORTS_PLUGINS #include "bfdlink.h" #include "bfdver.h" +#include "ctf-api.h" #include "ld.h" #include "ldmain.h" #include "ldmisc.h" @@ -174,7 +176,7 @@ static bfd_boolean plugin_notice (struct bfd_link_info *, struct bfd_link_hash_entry *, bfd *, asection *, bfd_vma, flagword); -static const bfd_target * plugin_object_p (bfd *); +static bfd_cleanup plugin_object_p (bfd *); #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) @@ -243,7 +245,7 @@ plugin_opt_plugin (const char *plugin) newplug->name = plugin; newplug->dlhandle = dlopen (plugin, RTLD_NOW); if (!newplug->dlhandle) - einfo (_("%P%F: %s: error loading plugin: %s\n"), plugin, dlerror ()); + einfo (_("%F%P: %s: error loading plugin: %s\n"), plugin, dlerror ()); /* Check if plugin has been loaded already. */ while (curplug) @@ -335,8 +337,8 @@ plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate) return abfd; } } -report_error: - einfo (_("could not create dummy IR bfd: %F%E\n")); + report_error: + einfo (_("%F%P: could not create dummy IR bfd: %E\n")); return NULL; } @@ -403,12 +405,6 @@ asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym, flags = BSF_GLOBAL; section = bfd_com_section_ptr; asym->value = ldsym->size; - /* For ELF targets, set alignment of common symbol to 1. */ - if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) - { - ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON; - ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1; - } break; default: @@ -417,18 +413,24 @@ asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym, asym->flags = flags; asym->section = section; - /* Visibility only applies on ELF targets. */ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) { - elf_symbol_type *elfsym = elf_symbol_from (abfd, asym); + elf_symbol_type *elfsym = elf_symbol_from (asym); unsigned char visibility; if (!elfsym) - einfo (_("%P%F: %s: non-ELF symbol in ELF BFD!\n"), asym->name); + einfo (_("%F%P: %s: non-ELF symbol in ELF BFD!\n"), asym->name); + + if (ldsym->def == LDPK_COMMON) + { + elfsym->internal_elf_sym.st_shndx = SHN_COMMON; + elfsym->internal_elf_sym.st_value = 1; + } + switch (ldsym->visibility) { default: - einfo (_("%P%F: unknown ELF symbol visibility: %d!\n"), + einfo (_("%F%P: unknown ELF symbol visibility: %d!\n"), ldsym->visibility); return LDPS_ERR; @@ -445,9 +447,7 @@ asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym, visibility = STV_HIDDEN; break; } - elfsym->internal_elf_sym.st_other - = (visibility | (elfsym->internal_elf_sym.st_other - & ~ELF_ST_VISIBILITY (-1))); + elfsym->internal_elf_sym.st_other |= visibility; } return LDPS_OK; @@ -539,7 +539,7 @@ get_view (const void *handle, const void **viewp) /* FIXME: einfo should support %lld. */ if ((off_t) size != input->filesize) - einfo (_("%P%F: unsupported input file size: %s (%ld bytes)\n"), + einfo (_("%F%P: unsupported input file size: %s (%ld bytes)\n"), input->name, (long) input->filesize); /* Check the cached view buffer. */ @@ -625,8 +625,6 @@ static inline bfd_boolean is_visible_from_outside (struct ld_plugin_symbol *lsym, struct bfd_link_hash_entry *blhe) { - struct bfd_sym_chain *sym; - if (bfd_link_relocatable (&link_info)) return TRUE; if (blhe->non_ir_ref_dynamic @@ -658,14 +656,76 @@ is_visible_from_outside (struct ld_plugin_symbol *lsym, || lsym->visibility == LDPV_PROTECTED); } - for (sym = &entry_symbol; sym != NULL; sym = sym->next) - if (sym->name - && strcmp (sym->name, blhe->root.string) == 0) - return TRUE; - return FALSE; } +/* Return LTO kind string name that corresponds to IDX enum value. */ +static const char * +get_lto_kind (unsigned int idx) +{ + static char buffer[64]; + const char *lto_kind_str[5] = + { + "DEF", + "WEAKDEF", + "UNDEF", + "WEAKUNDEF", + "COMMON" + }; + + if (idx < ARRAY_SIZE (lto_kind_str)) + return lto_kind_str [idx]; + + sprintf (buffer, _("unknown LTO kind value %x"), idx); + return buffer; +} + +/* Return LTO resolution string name that corresponds to IDX enum value. */ +static const char * +get_lto_resolution (unsigned int idx) +{ + static char buffer[64]; + static const char *lto_resolution_str[10] = + { + "UNKNOWN", + "UNDEF", + "PREVAILING_DEF", + "PREVAILING_DEF_IRONLY", + "PREEMPTED_REG", + "PREEMPTED_IR", + "RESOLVED_IR", + "RESOLVED_EXEC", + "RESOLVED_DYN", + "PREVAILING_DEF_IRONLY_EXP", + }; + + if (idx < ARRAY_SIZE (lto_resolution_str)) + return lto_resolution_str [idx]; + + sprintf (buffer, _("unknown LTO resolution value %x"), idx); + return buffer; +} + +/* Return LTO visibility string name that corresponds to IDX enum value. */ +static const char * +get_lto_visibility (unsigned int idx) +{ + static char buffer[64]; + const char *lto_visibility_str[4] = + { + "DEFAULT", + "PROTECTED", + "INTERNAL", + "HIDDEN" + }; + + if (idx < ARRAY_SIZE (lto_visibility_str)) + return lto_visibility_str [idx]; + + sprintf (buffer, _("unknown LTO visibility value %x"), idx); + return buffer; +} + /* Get the symbol resolution info for a plugin-claimed input file. */ static enum ld_plugin_status get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms, @@ -681,13 +741,32 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms, struct bfd_link_hash_entry *blhe; asection *owner_sec; int res; + struct bfd_link_hash_entry *h + = bfd_link_hash_lookup (link_info.hash, syms[n].name, + FALSE, FALSE, TRUE); + enum { wrap_none, wrapper, wrapped } wrap_status = wrap_none; - if (syms[n].def != LDPK_UNDEF) - blhe = bfd_link_hash_lookup (link_info.hash, syms[n].name, - FALSE, FALSE, TRUE); + if (syms[n].def != LDPK_UNDEF && syms[n].def != LDPK_WEAKUNDEF) + { + blhe = h; + if (blhe && link_info.wrap_hash != NULL) + { + /* Check if a symbol is a wrapper symbol. */ + struct bfd_link_hash_entry *unwrap + = unwrap_hash_lookup (&link_info, (bfd *) abfd, blhe); + if (unwrap && unwrap != h) + wrap_status = wrapper; + } + } else - blhe = bfd_wrapped_link_hash_lookup (link_info.output_bfd, &link_info, - syms[n].name, FALSE, FALSE, TRUE); + { + blhe = bfd_wrapped_link_hash_lookup (link_info.output_bfd, + &link_info, syms[n].name, + FALSE, FALSE, TRUE); + /* Check if a symbol is a wrapped symbol. */ + if (blhe && blhe != h) + wrap_status = wrapped; + } if (!blhe) { /* The plugin is called to claim symbols in an archive element @@ -723,7 +802,7 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms, && blhe->type != bfd_link_hash_common) { /* We should not have a new, indirect or warning symbol here. */ - einfo ("%P%F: %s: plugin symbol table corrupt (sym type %d)\n", + einfo (_("%F%P: %s: plugin symbol table corrupt (sym type %d)\n"), called_plugin->name, blhe->type); } @@ -773,9 +852,11 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms, /* We need to know if the sym is referenced from non-IR files. Or even potentially-referenced, perhaps in a future final link if this is a partial one, perhaps dynamically at load-time if the - symbol is externally visible. */ - if (blhe->non_ir_ref_regular) + symbol is externally visible. Also check for wrapper symbol. */ + if (blhe->non_ir_ref_regular || wrap_status == wrapper) res = LDPR_PREVAILING_DEF; + else if (wrap_status == wrapped) + res = LDPR_RESOLVED_IR; else if (is_visible_from_outside (&syms[n], blhe)) res = def_ironly_exp; } @@ -783,10 +864,12 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms, report_symbol: syms[n].resolution = res; if (report_plugin_symbols) - einfo (_("%P: %B: symbol `%s' " - "definition: %d, visibility: %d, resolution: %d\n"), + einfo (_("%P: %pB: symbol `%s' " + "definition: %s, visibility: %s, resolution: %s\n"), abfd, syms[n].name, - syms[n].def, syms[n].visibility, res); + get_lto_kind (syms[n].def), + get_lto_visibility (syms[n].visibility), + get_lto_resolution (res)); } return LDPS_OK; } @@ -858,7 +941,7 @@ message (int level, const char *format, ...) break; case LDPL_WARNING: { - char *newfmt = concat ("%P: warning: ", format, "\n", + char *newfmt = concat (_("%P: warning: "), format, "\n", (const char *) NULL); vfinfo (stdout, newfmt, args, TRUE); free (newfmt); @@ -868,8 +951,8 @@ message (int level, const char *format, ...) case LDPL_ERROR: default: { - char *newfmt = concat (level == LDPL_FATAL ? "%P%F" : "%P%X", - ": error: ", format, "\n", + char *newfmt = concat (level == LDPL_FATAL ? "%F" : "%X", + _("%P: error: "), format, "\n", (const char *) NULL); fflush (stdout); vfinfo (stderr, newfmt, args, TRUE); @@ -1014,14 +1097,14 @@ plugin_load_plugins (void) if (!onloadfn) onloadfn = (ld_plugin_onload) dlsym (curplug->dlhandle, "_onload"); if (!onloadfn) - einfo (_("%P%F: %s: error loading plugin: %s\n"), + einfo (_("%F%P: %s: error loading plugin: %s\n"), curplug->name, dlerror ()); set_tv_plugin_args (curplug, &my_tv[tv_header_size]); called_plugin = curplug; rv = (*onloadfn) (my_tv); called_plugin = NULL; if (rv != LDPS_OK) - einfo (_("%P%F: %s: plugin error: %d\n"), curplug->name, rv); + einfo (_("%F%P: %s: plugin error: %d\n"), curplug->name, rv); curplug = curplug->next; } @@ -1053,14 +1136,10 @@ plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed) { if (curplug->claim_file_handler) { - off_t cur_offset; enum ld_plugin_status rv; called_plugin = curplug; - cur_offset = lseek (file->fd, 0, SEEK_CUR); rv = (*curplug->claim_file_handler) (file, claimed); - if (!*claimed) - lseek (file->fd, cur_offset, SEEK_SET); called_plugin = NULL; if (rv != LDPS_OK) set_plugin_error (curplug->name); @@ -1080,13 +1159,18 @@ plugin_strdup (bfd *abfd, const char *str) strlength = strlen (str) + 1; copy = bfd_alloc (abfd, strlength); if (copy == NULL) - einfo (_("%P%F: plugin_strdup failed to allocate memory: %s\n"), + einfo (_("%F%P: plugin_strdup failed to allocate memory: %s\n"), bfd_get_error ()); memcpy (copy, str, strlength); return copy; } -static const bfd_target * +static void +plugin_cleanup (bfd *abfd ATTRIBUTE_UNUSED) +{ +} + +static bfd_cleanup plugin_object_p (bfd *ibfd) { int claimed; @@ -1101,24 +1185,24 @@ plugin_object_p (bfd *ibfd) if (ibfd->plugin_format != bfd_plugin_unknown) { if (ibfd->plugin_format == bfd_plugin_yes) - return ibfd->plugin_dummy_bfd->xvec; + return plugin_cleanup; else return NULL; } /* We create a dummy BFD, initially empty, to house whatever symbols the plugin may want to add. */ - abfd = plugin_get_ir_dummy_bfd (ibfd->filename, ibfd); + abfd = plugin_get_ir_dummy_bfd (bfd_get_filename (ibfd), ibfd); input = bfd_alloc (abfd, sizeof (*input)); if (input == NULL) - einfo (_("%P%F: plugin failed to allocate memory for input: %s\n"), + einfo (_("%F%P: plugin failed to allocate memory for input: %s\n"), bfd_get_error ()); if (!bfd_plugin_open_input (ibfd, &file)) return NULL; - if (file.name == ibfd->filename) + if (file.name == bfd_get_filename (ibfd)) { /* We must copy filename attached to ibfd if it is not an archive member since it may be freed by bfd_close below. */ @@ -1126,12 +1210,6 @@ plugin_object_p (bfd *ibfd) } file.handle = input; - /* The plugin API expects that the file descriptor won't be closed - and reused as done by the bfd file cache. So dup one. */ - file.fd = dup (file.fd); - if (file.fd < 0) - return NULL; - input->abfd = abfd; input->view_buffer.addr = NULL; input->view_buffer.filesize = 0; @@ -1140,12 +1218,12 @@ plugin_object_p (bfd *ibfd) input->use_mmap = FALSE; input->offset = file.offset; input->filesize = file.filesize; - input->name = plugin_strdup (abfd, ibfd->filename); + input->name = plugin_strdup (abfd, bfd_get_filename (ibfd)); claimed = 0; if (plugin_call_claim_file (&file, &claimed)) - einfo (_("%P%F: %s: plugin reported error claiming file\n"), + einfo (_("%F%P: %s: plugin reported error claiming file\n"), plugin_error_plugin ()); if (input->fd != -1 && !bfd_plugin_target_p (ibfd->xvec)) @@ -1167,7 +1245,8 @@ plugin_object_p (bfd *ibfd) ibfd->plugin_format = bfd_plugin_yes; ibfd->plugin_dummy_bfd = abfd; bfd_make_readable (abfd); - return abfd->xvec; + abfd->no_export = ibfd->no_export; + return plugin_cleanup; } else { @@ -1333,30 +1412,42 @@ plugin_notice (struct bfd_link_info *info, ref = TRUE; } - /* Otherwise, it must be a new def. */ - else + + /* A common symbol should be merged with other commons or + defs with the same name. In particular, a common ought + to be overridden by a def in a -flto object. In that + sense a common is also a ref. */ + else if (bfd_is_com_section (section)) { - /* Ensure any symbol defined in an IR dummy BFD takes on a - new value from a real BFD. Weak symbols are not normally - overridden by a new weak definition, and strong symbols - will normally cause multiple definition errors. Avoid - this by making the symbol appear to be undefined. */ - if (((h->type == bfd_link_hash_defweak - || h->type == bfd_link_hash_defined) - && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner)) - || (h->type == bfd_link_hash_common - && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner))) + if (h->type == bfd_link_hash_common + && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner)) { h->type = bfd_link_hash_undefweak; h->u.undef.abfd = sym_bfd; } + ref = TRUE; + } - /* A common symbol should be merged with other commons or - defs with the same name. In particular, a common ought - to be overridden by a def in a -flto object. In that - sense a common is also a ref. */ - if (bfd_is_com_section (section)) - ref = TRUE; + /* Otherwise, it must be a new def. + Ensure any symbol defined in an IR dummy BFD takes on a + new value from a real BFD. Weak symbols are not normally + overridden by a new weak definition, and strong symbols + will normally cause multiple definition errors. Avoid + this by making the symbol appear to be undefined. + + NB: We change the previous definition in the IR object to + undefweak only after all LTO symbols have been read or for + non-ELF targets. */ + else if ((info->lto_all_symbols_read + || bfd_get_flavour (abfd) != bfd_target_elf_flavour) + && (((h->type == bfd_link_hash_defweak + || h->type == bfd_link_hash_defined) + && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner)) + || (h->type == bfd_link_hash_common + && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner)))) + { + h->type = bfd_link_hash_undefweak; + h->u.undef.abfd = sym_bfd; } if (ref) @@ -1378,3 +1469,4 @@ plugin_notice (struct bfd_link_info *info, abfd, section, value, flags); return TRUE; } +#endif /* BFD_SUPPORTS_PLUGINS */