]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
ld: Rename a file on Windows fails if target already exists
authorTorbjörn SVENSSON <torbjorn.svensson@foss.st.com>
Fri, 18 Jul 2025 15:04:09 +0000 (17:04 +0200)
committerTorbjörn SVENSSON <torbjorn.svensson@foss.st.com>
Tue, 22 Jul 2025 14:39:50 +0000 (16:39 +0200)
To rename a file on Windows, the target name cannot exist. Removing file
prior to renaming ensures this is handled.
To remove a file on Windows, the file cannot be open. Closing the bfd
handle ensures this is handled.
Moved call to free on isympp / osympp to after bfd is closed to align
with comment earlier in the cmdline_add_object_only_section function.

Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
ld/ldlang.c

index d4b4ef2f29b1a724ae80e42239522ce6a5c592a9..6e31c359c9d82570614609f63210e96e4175ea38 100644 (file)
@@ -43,6 +43,7 @@
 #include "hashtab.h"
 #include "elf-bfd.h"
 #include "bfdver.h"
+#include <errno.h>
 
 #if BFD_SUPPORTS_PLUGINS
 #include "plugin.h"
@@ -10840,10 +10841,19 @@ cmdline_add_object_only_section (bfd_byte *contents, size_t size)
       fatal (_("%P: failed to finish output with object-only section\n"));
     }
 
+  /* ibfd needs to be closed *after* obfd, otherwise ld may crash with a
+     segmentation fault.  */
+  if (!bfd_close (ibfd))
+    einfo (_("%P%F: failed to close input\n"));
+
   /* Must be freed after bfd_close ().  */
   free (isympp);
   free (osympp);
 
+  /* Must unlink to ensure rename works on Windows.  */
+  if (unlink (output_filename) && errno != ENOENT)
+    einfo (_("%P%F: failed to unlink %s\n"), output_filename);
+
   if (rename (ofilename, output_filename))
     {
       unlink (ofilename);
@@ -10854,10 +10864,14 @@ cmdline_add_object_only_section (bfd_byte *contents, size_t size)
   return;
 
 loser:
-  free (isympp);
-  free (osympp);
   if (obfd)
     bfd_close (obfd);
+  /* ibfd needs to be closed *after* obfd, otherwise ld may crash with a
+     segmentation fault.  */
+  if (ibfd)
+    bfd_close (ibfd);
+  free (isympp);
+  free (osympp);
   if (ofilename)
     {
       unlink (ofilename);