diff options
-rw-r--r-- | bfd/archive.c | 4 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 6 | ||||
-rw-r--r-- | bfd/bfd.c | 6 | ||||
-rw-r--r-- | bfd/opncls.c | 2 | ||||
-rw-r--r-- | bfd/plugin.c | 105 | ||||
-rw-r--r-- | bfd/plugin.h | 1 | ||||
-rw-r--r-- | ld/plugin.c | 26 | ||||
-rw-r--r-- | ld/testsuite/config/default.exp | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/lto.exp | 7 |
9 files changed, 122 insertions, 39 deletions
diff --git a/bfd/archive.c b/bfd/archive.c index 2f3a1d4..5f350b8 100644 --- a/bfd/archive.c +++ b/bfd/archive.c @@ -2845,6 +2845,10 @@ _bfd_archive_close_and_cleanup (bfd *abfd) htab_delete (htab); bfd_ardata (abfd)->cache = NULL; } + + /* Close the archive plugin file descriptor if needed. */ + if (abfd->archive_plugin_fd > 0) + close (abfd->archive_plugin_fd); } _bfd_unlink_from_archive_parent (abfd); diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 57b3c45..9a69831 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -6707,6 +6707,12 @@ struct bfd /* The number of sections. */ unsigned int section_count; + /* The archive plugin file descriptor. */ + int archive_plugin_fd; + + /* The number of opens on the archive plugin file descriptor. */ + unsigned int archive_plugin_fd_open_count; + /* A field used by _bfd_generic_link_add_archive_symbols. This will be used only for archive elements. */ int archive_pass; @@ -276,6 +276,12 @@ CODE_FRAGMENT . {* The number of sections. *} . unsigned int section_count; . +. {* The archive plugin file descriptor. *} +. int archive_plugin_fd; +. +. {* The number of opens on the archive plugin file descriptor. *} +. unsigned int archive_plugin_fd_open_count; +. . {* A field used by _bfd_generic_link_add_archive_symbols. This will . be used only for archive elements. *} . int archive_pass; diff --git a/bfd/opncls.c b/bfd/opncls.c index 74df4c2..4fb7932 100644 --- a/bfd/opncls.c +++ b/bfd/opncls.c @@ -89,6 +89,8 @@ _bfd_new_bfd (void) return NULL; } + nbfd->archive_plugin_fd = -1; + return nbfd; } diff --git a/bfd/plugin.c b/bfd/plugin.c index 1fee4d0..b3d6739 100644 --- a/bfd/plugin.c +++ b/bfd/plugin.c @@ -192,6 +192,7 @@ int bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file) { bfd *iobfd; + int fd; iobfd = ibfd; while (iobfd->my_archive @@ -202,50 +203,60 @@ bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file) if (!iobfd->iostream && !bfd_open_file (iobfd)) return 0; - /* The plugin API expects that the file descriptor won't be closed - and reused as done by the bfd file cache. So open it again. - dup isn't good enough. plugin IO uses lseek/read while BFD uses - fseek/fread. It isn't wise to mix the unistd and stdio calls on - the same underlying file descriptor. */ - file->fd = open (file->name, O_RDONLY | O_BINARY); - if (file->fd < 0) + /* Reuse the archive plugin file descriptor. */ + if (iobfd != ibfd) + fd = iobfd->archive_plugin_fd; + else + fd = -1; + + if (fd < 0) { + /* The plugin API expects that the file descriptor won't be closed + and reused as done by the bfd file cache. So open it again. + dup isn't good enough. plugin IO uses lseek/read while BFD uses + fseek/fread. It isn't wise to mix the unistd and stdio calls on + the same underlying file descriptor. */ + fd = open (file->name, O_RDONLY | O_BINARY); + if (fd < 0) + { #ifndef EMFILE - return 0; + return 0; #else - if (errno != EMFILE) - return 0; + if (errno != EMFILE) + return 0; #ifdef HAVE_GETRLIMIT - struct rlimit lim; - - /* Complicated links involving lots of files and/or large archives - can exhaust the number of file descriptors available to us. - If possible, try to allocate more descriptors. */ - if (getrlimit (RLIMIT_NOFILE, & lim) == 0 - && lim.rlim_cur < lim.rlim_max) - { - lim.rlim_cur = lim.rlim_max; - if (setrlimit (RLIMIT_NOFILE, &lim) == 0) - file->fd = open (file->name, O_RDONLY | O_BINARY); - } + struct rlimit lim; + + /* Complicated links involving lots of files and/or large + archives can exhaust the number of file descriptors + available to us. If possible, try to allocate more + descriptors. */ + if (getrlimit (RLIMIT_NOFILE, & lim) == 0 + && lim.rlim_cur < lim.rlim_max) + { + lim.rlim_cur = lim.rlim_max; + if (setrlimit (RLIMIT_NOFILE, &lim) == 0) + fd = open (file->name, O_RDONLY | O_BINARY); + } - if (file->fd < 0) + if (fd < 0) #endif - { - _bfd_error_handler (_("plugin framework: out of file descriptors. Try using fewer objects/archives\n")); - return 0; - } + { + _bfd_error_handler (_("plugin framework: out of file descriptors. Try using fewer objects/archives\n")); + return 0; + } #endif - } + } + } if (iobfd == ibfd) { struct stat stat_buf; - if (fstat (file->fd, &stat_buf)) + if (fstat (fd, &stat_buf)) { - close(file->fd); + close (fd); return 0; } @@ -254,12 +265,44 @@ bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file) } else { + /* Cache the archive plugin file descriptor. */ + iobfd->archive_plugin_fd = fd; + iobfd->archive_plugin_fd_open_count++; + file->offset = ibfd->origin; file->filesize = arelt_size (ibfd); } + + file->fd = fd; return 1; } +/* Close the plugin file descriptor. */ + +void +bfd_plugin_close_file_descriptor (bfd *abfd, int fd) +{ + bfd *iobfd; + + iobfd = abfd; + while (iobfd->my_archive + && !bfd_is_thin_archive (iobfd->my_archive)) + iobfd = iobfd->my_archive; + if (iobfd == abfd) + close (fd); + else + { + iobfd->archive_plugin_fd_open_count--; + /* Dup the archive plugin file descriptor for later use, which + will be closed by _bfd_archive_close_and_cleanup. */ + if (iobfd->archive_plugin_fd_open_count == 0) + { + iobfd->archive_plugin_fd = dup (fd); + close (fd); + } + } +} + static int try_claim (bfd *abfd) { @@ -271,7 +314,7 @@ try_claim (bfd *abfd) && current_plugin->claim_file) { current_plugin->claim_file (&file, &claimed); - close (file.fd); + bfd_plugin_close_file_descriptor (abfd, file.fd); } return claimed; diff --git a/bfd/plugin.h b/bfd/plugin.h index ce3fe58..709478e 100644 --- a/bfd/plugin.h +++ b/bfd/plugin.h @@ -28,6 +28,7 @@ bool bfd_plugin_target_p (const bfd_target *); bool bfd_plugin_specified_p (void); bool bfd_link_plugin_object_p (bfd *); void register_ld_plugin_object_p (bfd_cleanup (*object_p) (bfd *)); +void bfd_plugin_close_file_descriptor (bfd *, int); typedef struct plugin_data_struct { diff --git a/ld/plugin.c b/ld/plugin.c index 98a83bc..bb369f4 100644 --- a/ld/plugin.c +++ b/ld/plugin.c @@ -103,6 +103,7 @@ typedef struct view_buffer typedef struct plugin_input_file { bfd *abfd; + bfd *ibfd; view_buffer_t view_buffer; char *name; int fd; @@ -605,17 +606,25 @@ get_view (const void *handle, const void **viewp) return LDPS_OK; } +/* Release plugin file descriptor. */ + +static void +release_plugin_file_descriptor (plugin_input_file_t *input) +{ + if (input->fd != -1) + { + bfd_plugin_close_file_descriptor (input->ibfd, input->fd); + input->fd = -1; + } +} + /* Release the input file. */ static enum ld_plugin_status release_input_file (const void *handle) { plugin_input_file_t *input = (plugin_input_file_t *) handle; ASSERT (called_plugin); - if (input->fd != -1) - { - close (input->fd); - input->fd = -1; - } + release_plugin_file_descriptor (input); return LDPS_OK; } @@ -1211,6 +1220,7 @@ plugin_object_p (bfd *ibfd) file.handle = input; input->abfd = abfd; + input->ibfd = ibfd; input->view_buffer.addr = NULL; input->view_buffer.filesize = 0; input->view_buffer.offset = 0; @@ -1226,7 +1236,8 @@ plugin_object_p (bfd *ibfd) einfo (_("%F%P: %s: plugin reported error claiming file\n"), plugin_error_plugin ()); - if (input->fd != -1 && !bfd_plugin_target_p (ibfd->xvec)) + if (input->fd != -1 + && (!claimed || !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 @@ -1236,8 +1247,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 (input->fd); - input->fd = -1; + release_plugin_file_descriptor (input); } if (claimed) diff --git a/ld/testsuite/config/default.exp b/ld/testsuite/config/default.exp index 4090f12..0795ea8 100644 --- a/ld/testsuite/config/default.exp +++ b/ld/testsuite/config/default.exp @@ -286,6 +286,10 @@ if ![info exists OBJCOPYFLAGS] then { set OBJCOPYFLAGS {} } +if ![info exists RANLIB] then { + set RANLIB [findfile $base_dir/../binutils/ranlib] +} + if ![info exists READELF] then { set READELF [findfile $base_dir/../binutils/readelf] } diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp index 2271211..def69e4 100644 --- a/ld/testsuite/ld-plugin/lto.exp +++ b/ld/testsuite/ld-plugin/lto.exp @@ -786,6 +786,13 @@ if { [at_least_gcc_version 4 7] } { } else { fail "PR binutils/23460" } + set exec_output [run_host_cmd "$RANLIB" "$plug_opt tmpdir/libpr23460.a"] + set exec_output [prune_warnings $exec_output] + if [string match "" $exec_output] then { + pass "PR binutils/23460" + } else { + fail "PR binutils/23460" + } } # Run "ld -r" to generate inputs for complex LTO tests. |