https://sourceware.org/bugzilla/show_bug.cgi?id=23254
--- Comment #3 from zenith432 at users dot sourceforge.net --- - Your attached patch fixes the problem. - For the record, I did a workaround with the patch ======== --- orig_plugin.c 2018-01-13 13:31:16.000000000 +0000 +++ plugin.c 2018-06-04 14:41:38.000000000 +0000 @@ -1059,7 +1059,9 @@ plugin_call_claim_file (const struct ld_ called_plugin = curplug; cur_offset = lseek (file->fd, 0, SEEK_CUR); rv = (*curplug->claim_file_handler) (file, claimed); +#if 0 if (!*claimed) +#endif lseek (file->fd, cur_offset, SEEK_SET); called_plugin = NULL; if (rv != LDPS_OK) ======== I do not believe this workaround is formally correct - because the plugin is allowed to continue moving the file pointer via the file descriptor it got. As a practical matter, I found by setting debug breakpoints that the current plugin only moves the file pointer in claim_file_handler, so protecting the pointer around that call resolved the issue. - I attached above a standalone example to reproduce the problem, however I can only get it to happen on macOS. On Fedora everything runs fine. gcc is 8.1, binutils built from 2.30 (same happens on git master) On macOS the output is /usr/local/bin/gcc -flto -c -o a.o a.c /usr/local/bin/gcc -flto -c -o b.o b.c /usr/local/bin/gcc -flto -c -o c.o c.c /usr/local/bin/gcc-ar cr libarch.a a.o b.o c.o /usr/local/bin/gcc -nostdlib -flto -o main main.c -L . -larch ./libarch.a: error adding symbols: Malformed archive collect2: error: ld returned 1 exit status make: *** [all] Error 1 I had to use -nostdib on macOS because it's a cross compiler and I don't have the runtime, but it doesn't matter because the "Malformed archive" error is encountered *before* other errors about unfound entry point or undefined printf. The size of stdio FILE buffer is 4096 (it's the same on Fedora) a.c is cooked up so inside libarch.a the ar_hdr for b.o is split across the 4096 position boundary. Here is what happens exactly: - First LD scans and processes a.o inside libarch.a using fseek/fread. To do this, stdio reads a 4096 buffer managed through FILE and caches 4096 as the file pointer. - Eventually a.o is passed down to claim_file_handler. The plugin re-processes a.o using lseek/read, with the file pointer ending up at the end of a.o inside libarch.a instead of at 4096. - Then it goes back to process b.o. At this point stdio FILE has a 4096 byte buffer and believes the file pointer is at 4096. - b.o ar_hdr starts a few bytes below 4096, which is in the cached buffer. fseek is called to move to b.o header - Since it's in the buffer, fseek does not lseek, but positions its internal pointer. - then fread is called to read the ar_hdr for b.o. The few bytes in the cached buffer are copied. Then fread, believing the file pointer to be at 4096, reads another 4096, but from the wrong location in the file. - Because the wrong location was read, the ar_hdr for b.o ends up being read corrupted which is why it breaks with "Malformed archive". So even if you can't reproduce it, this is what happens and you can follow it by adding printfs to ld code (or running in debugger). It doesn't break on Fedora and I'm not sure why. One possibility is that the pre-canned binaries are patched somehow. The other possibility is that Fedora fseek always calls lseek when moving to b.o ar_hdr which prevents the glitch. Regards. -- You are receiving this mail because: You are on the CC list for the bug. _______________________________________________ bug-binutils mailing list bug-binutils@gnu.org https://lists.gnu.org/mailman/listinfo/bug-binutils