From patchwork Sun May 12 13:38:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Damianov X-Patchwork-Id: 1934276 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=disroot.org header.i=@disroot.org header.a=rsa-sha256 header.s=mail header.b=cCH+I8h3; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4VckJJ2d3Gz20KK for ; Sun, 12 May 2024 23:40:00 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 1A00C3860766 for ; Sun, 12 May 2024 13:39:57 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from layka.disroot.org (layka.disroot.org [178.21.23.139]) by sourceware.org (Postfix) with ESMTPS id CE3A03858C31 for ; Sun, 12 May 2024 13:39:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CE3A03858C31 Authentication-Results: sourceware.org; dmarc=pass (p=reject dis=none) header.from=disroot.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=disroot.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org CE3A03858C31 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=178.21.23.139 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1715521176; cv=none; b=jld1LqDQKGQiOS9yDS6jn8iQGejHRqvk63Zi1KGZz4BB38f5tXlc8hXDsPZ5ryAsoO3BrB+x7ttW7+SZHVVTnljSD/3y/edlXh+9q1xiqThW0x9MMpQRVGzA9PDXUly0E1YU1GIy/HfVAym+EKinaaCkwhFdObjVI/7NZKVuh/Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1715521176; c=relaxed/simple; bh=zBq4tH/x/ihPQKNTpL/XZ2mu3PaMxfiJKV9Xz3F67AA=; h=From:DKIM-Signature:To:Subject:Date:Message-Id:MIME-Version; b=akXNIlb7QZOjQ8la+OthTvUt7fkt5cTNaTZxNRgwnGJgfpHpXGnoklHYfitDEcZOHPeMCWVRcmB+GZ0he0k4UPrUYsS+UpJSqZp7cuQVt8So87KqWA7uNhPdfITki/7B3EY7EHdJwFHgwag8dLJz5W6i5HpWHHXOfn5a2y6udsg= ARC-Authentication-Results: i=1; server2.sourceware.org X-Virus-Scanned: SPAM Filter at disroot.org From: Peter Damianov DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1715521172; bh=zBq4tH/x/ihPQKNTpL/XZ2mu3PaMxfiJKV9Xz3F67AA=; h=From:To:Cc:Subject:Date; b=cCH+I8h30GQE6y5OPT/GB0Z4bEtpFT2vb3m9hFdEwfoZoWrrsB/FgvHV6k18axceJ E7osENQxRG6wCd5uRuDGBH1icEQEquE/S+TMtIB7T9rPkqaxv4yfQHqgKdzIPZ10qr aVd5QQeUO8dzIF9zRoPKhSiZh2I+SXcEhE3yIPUYkcVkdo1R610yeTXrRJ877sxGnz q/gjW61SXIgowqdZBQc7Z9Y3waRGKcz3R4RHkzLihiLMYmyqTAfCGic9VPmOkl9C02 0wApzehWEatES1YMao8QvgptXOHBZcYvS2bPNHykh2jB4v9QtvQDyp97Gp3GunqYxs XYB5lrdvZ9Oxw== To: gcc-patches@gcc.gnu.org Cc: Peter Damianov Subject: [PATCH v3] driver: Output to a temp file; rename upon success [PR80182] Date: Sun, 12 May 2024 06:38:58 -0700 Message-Id: <20240512133857.1634-1-peter0x44@disroot.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Currently, commands like: gcc -o file.c -lm will delete the user's code. This patch makes the linker write executables to a temp file, and then renames the temp file if successful. This fixes the case above, but has limitations. The source file will still get overwritten if the link "succeeds", such as the case of: gcc -o file.c -lm -r It's not perfect, but it should hopefully stop some people from ruining their day. gcc/ChangeLog: PR driver/80182 * gcc.cc (output_file_temp): New global variable (driver_handle_option): Create temp file for executable output (driver::maybe_run_linker): Rename output_file_temp to output_file if the linker ran successfully Signed-off-by: Peter Damianov --- v3: don't attempt to create temp files -> rename for -o /dev/null gcc/gcc.cc | 53 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/gcc/gcc.cc b/gcc/gcc.cc index 830a4700a87..5e38c6e578a 100644 --- a/gcc/gcc.cc +++ b/gcc/gcc.cc @@ -2138,6 +2138,11 @@ static int have_E = 0; /* Pointer to output file name passed in with -o. */ static const char *output_file = 0; +/* We write the output file to a temp file, and rename it if linking + is successful. This is to prevent mistakes like: gcc -o file.c -lm from + deleting the user's code. */ +static const char *output_file_temp = 0; + /* Pointer to input file name passed in with -truncate. This file should be truncated after linking. */ static const char *totruncate_file = 0; @@ -4610,10 +4615,18 @@ driver_handle_option (struct gcc_options *opts, #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX) arg = convert_filename (arg, ! have_c, 0); #endif - output_file = arg; + output_file_temp = output_file = arg; + /* If creating an executable, create a temp file for the output, unless + -o /dev/null was requested. This will later get renamed, if the linker + succeeds. */ + if (!have_c && strcmp (output_file, HOST_BIT_BUCKET) != 0) + { + output_file_temp = make_temp_file (""); + record_temp_file (output_file_temp, false, true); + } /* On some systems, ld cannot handle "-o" without a space. So split the option from its argument. */ - save_switch ("-o", 1, &arg, validated, true); + save_switch ("-o", 1, &output_file_temp, validated, true); return true; case OPT_pie: @@ -9266,22 +9279,30 @@ driver::maybe_run_linker (const char *argv0) const linker_was_run = (tmp != execution_count); } - /* If options said don't run linker, - complain about input files to be given to the linker. */ - - if (! linker_was_run && !seen_error ()) - for (i = 0; (int) i < n_infiles; i++) - if (explicit_link_files[i] - && !(infiles[i].language && infiles[i].language[0] == '*')) + if (!seen_error ()) + { + if (linker_was_run) + /* If the linker finished without errors, rename the output from the + temporary file to the real output name. */ + rename (output_file_temp, output_file); + else { - warning (0, "%s: linker input file unused because linking not done", - outfiles[i]); - if (access (outfiles[i], F_OK) < 0) - /* This is can be an indication the user specifed an errorneous - separated option value, (or used the wrong prefix for an - option). */ - error ("%s: linker input file not found: %m", outfiles[i]); + /* If options said don't run linker, + complain about input files to be given to the linker. */ + for (i = 0; (int) i < n_infiles; i++) + if (explicit_link_files[i] + && !(infiles[i].language && infiles[i].language[0] == '*')) + { + warning (0, "%s: linker input file unused because linking not done", + outfiles[i]); + if (access (outfiles[i], F_OK) < 0) + /* This is can be an indication the user specifed an errorneous + separated option value, (or used the wrong prefix for an + option). */ + error ("%s: linker input file not found: %m", outfiles[i]); + } } + } } /* The end of "main". */