X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Fplugin.c;h=81bf14348c3de139602063fe8baa36b85751053e;hb=7e0a81123db953de03f6482f7c10f306407d348e;hp=5b8a7cfa1173fe554d78f44f5853f3158477bf6d;hpb=e13419c472637ebc6ad1554bdc6d50f2bd793574;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/plugin.c b/ld/plugin.c index 5b8a7cfa11..81bf14348c 100644 --- a/ld/plugin.c +++ b/ld/plugin.c @@ -30,6 +30,7 @@ #include "ldexp.h" #include "ldlang.h" #include "ldfile.h" +#include "../bfd/plugin.h" #include "plugin.h" #include "plugin-api.h" #include "elf-bfd.h" @@ -104,6 +105,7 @@ typedef struct plugin_input_file view_buffer_t view_buffer; char *name; int fd; + bfd_boolean use_mmap; off_t offset; off_t filesize; } plugin_input_file_t; @@ -137,6 +139,11 @@ static struct bfd_link_callbacks plugin_callbacks; its own newly-added input files and libs to claim. */ bfd_boolean no_more_claiming = FALSE; +#if HAVE_MMAP && HAVE_GETPAGESIZE +/* Page size used by mmap. */ +static off_t plugin_pagesize; +#endif + /* List of tags to set in the constant leading part of the tv array. */ static const enum ld_plugin_tag tv_header_tags[] = { @@ -168,6 +175,8 @@ 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 *); + #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) #define RTLD_NOW 0 /* Dummy value. */ @@ -289,14 +298,19 @@ plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate) bfd_use_reserved_id = 1; abfd = bfd_create (concat (name, IRONLY_SUFFIX, (const char *) NULL), - srctemplate); + link_info.output_bfd); if (abfd != NULL) { abfd->flags |= BFD_LINKER_CREATED | BFD_PLUGIN; - bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate)); - bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate)); - if (bfd_make_writable (abfd) - && bfd_copy_private_bfd_data (srctemplate, abfd)) + if (!bfd_make_writable (abfd)) + goto report_error; + if (! bfd_plugin_target_p (srctemplate->xvec)) + { + bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate)); + bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate)); + if (!bfd_copy_private_bfd_data (srctemplate, abfd)) + goto report_error; + } { flagword flags; @@ -307,6 +321,7 @@ plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate) return abfd; } } +report_error: einfo (_("could not create dummy IR bfd: %F%E\n")); return NULL; } @@ -499,6 +514,10 @@ get_view (const void *handle, const void **viewp) plugin_input_file_t *input = (plugin_input_file_t *) handle; char *buffer; size_t size = input->filesize; + off_t offset = input->offset; +#if HAVE_MMAP && HAVE_GETPAGESIZE + off_t bias; +#endif ASSERT (called_plugin); @@ -510,24 +529,37 @@ get_view (const void *handle, const void **viewp) /* Check the cached view buffer. */ if (input->view_buffer.addr != NULL && input->view_buffer.filesize == size - && input->view_buffer.offset == input->offset) + && input->view_buffer.offset == offset) { *viewp = input->view_buffer.addr; return LDPS_OK; } input->view_buffer.filesize = size; - input->view_buffer.offset = input->offset; + input->view_buffer.offset = offset; #if HAVE_MMAP - buffer = mmap (NULL, size, PROT_READ, MAP_PRIVATE, input->fd, - input->offset); - if (buffer == MAP_FAILED) +# if HAVE_GETPAGESIZE + bias = offset % plugin_pagesize; + offset -= bias; + size += bias; +# endif + buffer = mmap (NULL, size, PROT_READ, MAP_PRIVATE, input->fd, offset); + if (buffer != MAP_FAILED) + { + input->use_mmap = TRUE; +# if HAVE_GETPAGESIZE + buffer += bias; +# endif + } + else #endif { char *p; - if (lseek (input->fd, input->offset, SEEK_SET) < 0) + input->use_mmap = FALSE; + + if (lseek (input->fd, offset, SEEK_SET) < 0) return LDPS_ERR; buffer = bfd_alloc (input->abfd, size); @@ -740,10 +772,14 @@ get_symbols_v2 (const void *handle, int nsyms, struct ld_plugin_symbol *syms) static enum ld_plugin_status add_input_file (const char *pathname) { + lang_input_statement_type *is; + ASSERT (called_plugin); - if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum, - NULL)) + is = lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum, + NULL); + if (!is) return LDPS_ERR; + is->flags.lto_output = 1; return LDPS_OK; } @@ -751,10 +787,14 @@ add_input_file (const char *pathname) static enum ld_plugin_status add_input_library (const char *pathname) { + lang_input_statement_type *is; + ASSERT (called_plugin); - if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum, - NULL)) + is = lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum, + NULL); + if (!is) return LDPS_ERR; + is->flags.lto_output = 1; return LDPS_OK; } @@ -782,15 +822,19 @@ message (int level, const char *format, ...) putchar ('\n'); break; case LDPL_WARNING: - vfinfo (stdout, format, args, TRUE); - putchar ('\n'); + { + char *newfmt = ACONCAT (("%P: warning: ", format, "\n", + (const char *) NULL)); + vfinfo (stdout, newfmt, args, TRUE); + } break; case LDPL_FATAL: case LDPL_ERROR: default: { - char *newfmt = ACONCAT ((level == LDPL_FATAL ? "%P%F: " : "%P%X: ", - format, "\n", (const char *) NULL)); + char *newfmt = ACONCAT ((level == LDPL_FATAL ? "%P%F" : "%P%X", + ": error: ", format, "\n", + (const char *) NULL)); fflush (stdout); vfinfo (stderr, newfmt, args, TRUE); fflush (stderr); @@ -955,6 +999,12 @@ plugin_load_plugins (void) link_info.notice_all = TRUE; link_info.lto_plugin_active = TRUE; link_info.callbacks = &plugin_callbacks; + + register_ld_plugin_object_p (plugin_object_p); + +#if HAVE_MMAP && HAVE_GETPAGESIZE + plugin_pagesize = getpagesize (); +#endif } /* Call 'claim file' hook for all plugins. */ @@ -997,22 +1047,36 @@ plugin_strdup (bfd *abfd, const char *str) return copy; } -void -plugin_maybe_claim (lang_input_statement_type *entry) +static const bfd_target * +plugin_object_p (bfd *ibfd) { - int claimed = 0; + int claimed; plugin_input_file_t *input; off_t offset, filesize; struct ld_plugin_input_file file; bfd *abfd; - bfd *ibfd = entry->the_bfd; - bfd_boolean inarchive = bfd_my_archive (ibfd) != NULL; - const char *name - = inarchive ? bfd_my_archive (ibfd)->filename : ibfd->filename; - int fd = open (name, O_RDONLY | O_BINARY); + 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_yes) + return ibfd->plugin_dummy_bfd->xvec; + else + 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; + return NULL; /* We create a dummy BFD, initially empty, to house whatever symbols the plugin may want to add. */ @@ -1053,46 +1117,78 @@ plugin_maybe_claim (lang_input_statement_type *entry) input->view_buffer.filesize = 0; input->view_buffer.offset = 0; input->fd = fd; + input->use_mmap = FALSE; input->offset = offset; input->filesize = filesize; input->name = plugin_strdup (abfd, ibfd->filename); + claimed = 0; + if (plugin_call_claim_file (&file, &claimed)) einfo (_("%P%F: %s: plugin reported error claiming file\n"), plugin_error_plugin ()); - if (input->fd != -1 && ibfd->format == bfd_object) + if (input->fd != -1 && ! bfd_plugin_target_p (ibfd->xvec)) { - /* FIXME: fd belongs to us, not the plugin. IR for GCC plugin, - which doesn't need fd after plugin_call_claim_file, is - stored in bfd_object file. Since GCC plugin before GCC 5 - doesn't call release_input_file, we close it here. IR for - LLVM plugin, which needs fd after plugin_call_claim_file and - calls release_input_file after it is done, is stored in - non-bfd_object file. This scheme doesn't work when a plugin - needs fd and its IR is stored in bfd_object file. */ + /* FIXME: fd belongs to us, not the plugin. GCC plugin, which + doesn't need fd after plugin_call_claim_file, doesn't use + BFD plugin target vector. Since GCC plugin doesn't call + release_input_file, we close it here. LLVM plugin, which + needs fd after plugin_call_claim_file and calls + 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); input->fd = -1; } if (claimed) { - /* 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. */ - if (!inarchive) - bfd_close (ibfd); + ibfd->plugin_format = bfd_plugin_yes; + ibfd->plugin_dummy_bfd = abfd; bfd_make_readable (abfd); - entry->the_bfd = abfd; - entry->flags.claimed = TRUE; + return abfd->xvec; } else { +#if HAVE_MMAP + if (input->use_mmap) + { + /* If plugin didn't claim the file, unmap the buffer. */ + char *addr = input->view_buffer.addr; + off_t size = input->view_buffer.filesize; +# if HAVE_GETPAGESIZE + off_t bias = input->view_buffer.offset % plugin_pagesize; + size += bias; + addr -= bias; +# endif + munmap (addr, size); + } +#endif + /* If plugin didn't claim the file, we don't need the dummy bfd. Can't avoid speculatively creating it, alas. */ + ibfd->plugin_format = bfd_plugin_no; bfd_close_all_done (abfd); - entry->flags.claimed = FALSE; + return NULL; + } +} + +void +plugin_maybe_claim (lang_input_statement_type *entry) +{ + 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. */ + if (entry->the_bfd->my_archive == NULL) + bfd_close (entry->the_bfd); + entry->the_bfd = abfd; + entry->flags.claimed = 1; } }