binutils: backport an upstream fix for a linker bug that triggers with LTO
authorFelix Fietkau <nbd@nbd.name>
Tue, 10 Jul 2018 12:19:36 +0000 (14:19 +0200)
committerFelix Fietkau <nbd@nbd.name>
Tue, 10 Jul 2018 12:26:35 +0000 (14:26 +0200)
Signed-off-by: Felix Fietkau <nbd@nbd.name>
toolchain/binutils/patches/2.30/100-PR23254-ld.bfd-mishandles-file-pointers-while-scanni.patch [new file with mode: 0644]

diff --git a/toolchain/binutils/patches/2.30/100-PR23254-ld.bfd-mishandles-file-pointers-while-scanni.patch b/toolchain/binutils/patches/2.30/100-PR23254-ld.bfd-mishandles-file-pointers-while-scanni.patch
new file mode 100644 (file)
index 0000000..8a0b675
--- /dev/null
@@ -0,0 +1,112 @@
+From: Alan Modra <amodra@gmail.com>
+Date: Tue, 5 Jun 2018 21:04:00 +0930
+Subject: [PATCH] PR23254, ld.bfd mishandles file pointers while scanning
+ archive
+
+Best practice is to not mix lseek/read with fseek/fread on the same
+underlying file descriptor, as not all stdio implementations will cope.
+Since the plugin uses lseek/read while bfd uses fseek/fread this patch
+reopens the file for exclusive use by the plugin rather than trying to
+restore the file descriptor.  That allows the plugin to read the file
+after plugin_call_claim_file too.
+
+bfd/
+       PR 23254
+       * plugin.c (bfd_plugin_open_input): Allow for possibility of
+       nested archives.  Open file again for plugin.
+       (try_claim): Don't save and restore file position.  Close file
+       if not claimed.
+       * sysdep.h (O_BINARY): Define.
+ld/
+       PR 23254
+       * plugin.c (plugin_call_claim_file): Revert 2016-07-19 patch.
+       (plugin_object_p): Don't dup file descriptor.
+---
+
+--- a/bfd/plugin.c
++++ b/bfd/plugin.c
+@@ -165,14 +165,22 @@ bfd_plugin_open_input (bfd *ibfd, struct
+   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)
+     {
+@@ -196,12 +204,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;
+ }
+--- a/bfd/sysdep.h
++++ b/bfd/sysdep.h
+@@ -108,6 +108,10 @@ extern char *strrchr ();
+ #ifndef O_ACCMODE
+ #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
+ #endif
++/* Systems that don't already define this, don't need it.  */
++#ifndef O_BINARY
++#define O_BINARY 0
++#endif
+ #ifndef SEEK_SET
+ #define SEEK_SET 0
+--- a/ld/plugin.c
++++ b/ld/plugin.c
+@@ -1053,14 +1053,10 @@ plugin_call_claim_file (const struct ld_
+     {
+       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);
+@@ -1126,12 +1122,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;