diff options
Diffstat (limited to 'bfd/plugin.c')
-rw-r--r-- | bfd/plugin.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/bfd/plugin.c b/bfd/plugin.c index 16a706a..7c5bba2 100644 --- a/bfd/plugin.c +++ b/bfd/plugin.c @@ -166,14 +166,22 @@ bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file) bfd *iobfd; iobfd = ibfd; - if (ibfd->my_archive && !bfd_is_thin_archive (ibfd->my_archive)) - iobfd = ibfd->my_archive; + while (iobfd->my_archive + && !bfd_is_thin_archive (iobfd->my_archive)) + iobfd = iobfd->my_archive; file->name = iobfd->filename; if (!iobfd->iostream && !bfd_open_file (iobfd)) return 0; - file->fd = fileno ((FILE *) iobfd->iostream); + /* 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) + return 0; if (iobfd == ibfd) { @@ -197,12 +205,12 @@ try_claim (bfd *abfd) int claimed = 0; struct ld_plugin_input_file file; + file.handle = abfd; if (!bfd_plugin_open_input (abfd, &file)) return 0; - file.handle = abfd; - off_t cur_offset = lseek (file.fd, 0, SEEK_CUR); claim_file (&file, &claimed); - lseek (file.fd, cur_offset, SEEK_SET); + if (!claimed) + close (file.fd); return claimed; } |