X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=ld%2Fplugin.c;h=03e2e69a639151285e9a06c41a722cdf87a03ca9;hb=2571583aed598dd3f9651b53434e5f177a0e3cf7;hp=5f7bbd895031f736b2d3aeab71dafd1157b9f558;hpb=0e1862bb401f47716446aef143b2bf7a4563f541;p=external%2Fbinutils.git diff --git a/ld/plugin.c b/ld/plugin.c index 5f7bbd8..03e2e69 100644 --- a/ld/plugin.c +++ b/ld/plugin.c @@ -1,5 +1,5 @@ /* Plugin control for the GNU linker. - Copyright (C) 2010-2015 Free Software Foundation, Inc. + Copyright (C) 2010-2017 Free Software Foundation, Inc. This file is part of the GNU Binutils. @@ -21,7 +21,6 @@ #include "sysdep.h" #include "libiberty.h" #include "bfd.h" -#include "libbfd.h" #include "bfdlink.h" #include "bfdver.h" #include "ld.h" @@ -30,9 +29,9 @@ #include "ldexp.h" #include "ldlang.h" #include "ldfile.h" +#include "plugin-api.h" #include "../bfd/plugin.h" #include "plugin.h" -#include "plugin-api.h" #include "elf-bfd.h" #if HAVE_MMAP # include @@ -237,6 +236,7 @@ void plugin_opt_plugin (const char *plugin) { plugin_t *newplug; + plugin_t *curplug = plugins_list; newplug = xmalloc (sizeof *newplug); memset (newplug, 0, sizeof *newplug); @@ -245,6 +245,18 @@ plugin_opt_plugin (const char *plugin) if (!newplug->dlhandle) einfo (_("%P%F: %s: error loading plugin: %s\n"), plugin, dlerror ()); + /* Check if plugin has been loaded already. */ + while (curplug) + { + if (newplug->dlhandle == curplug->dlhandle) + { + einfo (_("%P: %s: duplicated plugin\n"), plugin); + free (newplug); + return; + } + curplug = curplug->next; + } + /* Chain on end, so when we run list it is in command-line order. */ *plugins_tail_chain_ptr = newplug; plugins_tail_chain_ptr = &newplug->next; @@ -295,16 +307,18 @@ static bfd * plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate) { bfd *abfd; + bfd_boolean bfd_plugin_target; bfd_use_reserved_id = 1; + bfd_plugin_target = bfd_plugin_target_p (srctemplate->xvec); abfd = bfd_create (concat (name, IRONLY_SUFFIX, (const char *) NULL), - link_info.output_bfd); + bfd_plugin_target ? link_info.output_bfd : srctemplate); if (abfd != NULL) { abfd->flags |= BFD_LINKER_CREATED | BFD_PLUGIN; if (!bfd_make_writable (abfd)) goto report_error; - if (! bfd_plugin_target_p (srctemplate->xvec)) + if (!bfd_plugin_target) { bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate)); bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate)); @@ -416,6 +430,8 @@ asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym, default: einfo (_("%P%F: unknown ELF symbol visibility: %d!\n"), ldsym->visibility); + return LDPS_ERR; + case LDPV_DEFAULT: visibility = STV_DEFAULT; break; @@ -672,7 +688,24 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms, syms[n].name, FALSE, FALSE, TRUE); if (!blhe) { - res = LDPR_UNKNOWN; + /* The plugin is called to claim symbols in an archive element + from plugin_object_p. But those symbols aren't needed to + create output. They are defined and referenced only within + IR. */ + switch (syms[n].def) + { + default: + abort (); + case LDPK_UNDEF: + case LDPK_WEAKUNDEF: + res = LDPR_UNDEF; + break; + case LDPK_DEF: + case LDPK_WEAKDEF: + case LDPK_COMMON: + res = LDPR_PREVAILING_DEF_IRONLY; + break; + } goto report_symbol; } @@ -823,21 +856,23 @@ message (int level, const char *format, ...) break; case LDPL_WARNING: { - char *newfmt = ACONCAT (("%P: warning: ", format, "\n", - (const char *) NULL)); + char *newfmt = concat ("%P: warning: ", format, "\n", + (const char *) NULL); vfinfo (stdout, newfmt, args, TRUE); + free (newfmt); } break; case LDPL_FATAL: case LDPL_ERROR: default: { - char *newfmt = ACONCAT ((level == LDPL_FATAL ? "%P%F" : "%P%X", - ": error: ", format, "\n", - (const char *) NULL)); + char *newfmt = concat (level == LDPL_FATAL ? "%P%F" : "%P%X", + ": error: ", format, "\n", + (const char *) NULL); fflush (stdout); vfinfo (stderr, newfmt, args, TRUE); fflush (stderr); + free (newfmt); } break; } @@ -872,11 +907,10 @@ set_tv_header (struct ld_plugin_tv *tv) TVU(val) = major * 100 + minor; break; case LDPT_LINKER_OUTPUT: - TVU(val) = (bfd_link_relocatable (&link_info) - ? LDPO_REL - : (bfd_link_executable (&link_info) - ? (bfd_link_pic (&link_info) ? LDPO_PIE : LDPO_EXEC) - : LDPO_DYN)); + TVU(val) = (bfd_link_relocatable (&link_info) ? LDPO_REL + : bfd_link_pde (&link_info) ? LDPO_EXEC + : bfd_link_pie (&link_info) ? LDPO_PIE + : LDPO_DYN); break; case LDPT_OUTPUT_NAME: TVU(string) = output_filename; @@ -1013,15 +1047,18 @@ plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed) { plugin_t *curplug = plugins_list; *claimed = FALSE; - if (no_more_claiming) - return 0; while (curplug && !*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); @@ -1052,18 +1089,14 @@ plugin_object_p (bfd *ibfd) { int claimed; plugin_input_file_t *input; - off_t offset, filesize; struct ld_plugin_input_file file; bfd *abfd; - bfd_boolean inarchive; - const char *name; - int fd; /* Don't try the dummy object file. */ if ((ibfd->flags & BFD_PLUGIN) != 0) return NULL; - if (ibfd->plugin_format != bfd_plugin_uknown) + if (ibfd->plugin_format != bfd_plugin_unknown) { if (ibfd->plugin_format == bfd_plugin_yes) return ibfd->plugin_dummy_bfd->xvec; @@ -1071,13 +1104,6 @@ plugin_object_p (bfd *ibfd) return NULL; } - inarchive = bfd_my_archive (ibfd) != NULL; - name = inarchive ? bfd_my_archive (ibfd)->filename : ibfd->filename; - fd = open (name, O_RDONLY | O_BINARY); - - if (fd < 0) - 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); @@ -1087,39 +1113,31 @@ plugin_object_p (bfd *ibfd) einfo (_("%P%F: plugin failed to allocate memory for input: %s\n"), bfd_get_error ()); - if (inarchive) - { - /* Offset and filesize must refer to the individual archive - member, not the whole file, and must exclude the header. - Fortunately for us, that is how the data is stored in the - origin field of the bfd and in the arelt_data. */ - offset = ibfd->origin; - filesize = arelt_size (ibfd); - } - else - { - offset = 0; - filesize = lseek (fd, 0, SEEK_END); + if (!bfd_plugin_open_input (ibfd, &file)) + return NULL; + if (file.name == ibfd->filename) + { /* We must copy filename attached to ibfd if it is not an archive member since it may be freed by bfd_close below. */ - name = plugin_strdup (abfd, name); + file.name = plugin_strdup (abfd, file.name); } - file.name = name; - file.offset = offset; - file.filesize = filesize; - file.fd = fd; 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; input->view_buffer.offset = 0; - input->fd = fd; + input->fd = file.fd; input->use_mmap = FALSE; - input->offset = offset; - input->filesize = filesize; + input->offset = file.offset; + input->filesize = file.filesize; input->name = plugin_strdup (abfd, ibfd->filename); claimed = 0; @@ -1128,7 +1146,7 @@ plugin_object_p (bfd *ibfd) einfo (_("%P%F: %s: plugin reported error claiming file\n"), plugin_error_plugin ()); - if (input->fd != -1 && ! bfd_plugin_target_p (ibfd->xvec)) + if (input->fd != -1 && !bfd_plugin_target_p (ibfd->xvec)) { /* FIXME: fd belongs to us, not the plugin. GCC plugin, which doesn't need fd after plugin_call_claim_file, doesn't use @@ -1138,7 +1156,7 @@ plugin_object_p (bfd *ibfd) release_input_file after it is done, uses BFD plugin target vector. This scheme doesn't work when a plugin needs fd and doesn't use BFD plugin target vector neither. */ - close (fd); + close (input->fd); input->fd = -1; } @@ -1177,14 +1195,17 @@ plugin_object_p (bfd *ibfd) void plugin_maybe_claim (lang_input_statement_type *entry) { + ASSERT (entry->header.type == lang_input_statement_enum); if (plugin_object_p (entry->the_bfd)) { bfd *abfd = entry->the_bfd->plugin_dummy_bfd; /* Discard the real file's BFD and substitute the dummy one. */ - /* BFD archive handling caches elements so we can't call - bfd_close for archives. */ + /* We can't call bfd_close on archives. BFD archive handling + caches elements, and add_archive_element keeps pointers to + the_bfd and the_bfd->filename in a lang_input_statement_type + linker script statement. */ if (entry->the_bfd->my_archive == NULL) bfd_close (entry->the_bfd); entry->the_bfd = abfd; @@ -1304,20 +1325,30 @@ plugin_notice (struct bfd_link_info *info, h->non_ir_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. */ - else 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))) + /* Otherwise, it must be a new def. */ + else { - h->type = bfd_link_hash_undefweak; - h->u.undef.abfd = sym_bfd; + /* 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)) + h->non_ir_ref = TRUE; + + /* 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))) + { + h->type = bfd_link_hash_undefweak; + h->u.undef.abfd = sym_bfd; + } } }