From patchwork Sat May 11 22:52:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter0x44 X-Patchwork-Id: 1934181 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=hhCNUmzW; 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 4VcLhD4VN6z1yfq for ; Sun, 12 May 2024 08:55:54 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C896F3858D33 for ; Sat, 11 May 2024 22:55:49 +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 1222D3858D33 for ; Sat, 11 May 2024 22:55:31 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1222D3858D33 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 1222D3858D33 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=1715468133; cv=none; b=raw81fKiEwH2BeUB6gPawS9xK9ukofKb4uF+J2WGfAmcaySMnKJHFlVpYmS6ippjG0Ywnn0VYJtvJkx526z3TypnTBd4AZ1xfkTjBYWFhyeoZAsURtyYJIQXPUo0Zy0lzFsTDeYpmFI8S7q3FPTBiy07CwdKbfz7kjxLQPhzmUA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1715468133; c=relaxed/simple; bh=yNrPgMMLPw1PXmLitWjb7xwKgcVHE90XL6g3t3NW8YY=; h=From:DKIM-Signature:To:Subject:Date:Message-Id:MIME-Version; b=FOUFnz/thzeA48EszydkMe9PFzWupRaP/9PVo+TeaVKBaXV6H9pc2rxhzcz7WkW5F+u5FPR97xqM8tCzKmjXWb8fNCifouB1AzkcQ+itlh6EYOD3EFEsY3KMJLwtG/fJekALry8/7IKMFXsnBRDUcIWcsrXYGCpcjj3bpqXXNNY= 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=1715468128; bh=yNrPgMMLPw1PXmLitWjb7xwKgcVHE90XL6g3t3NW8YY=; h=From:To:Cc:Subject:Date; b=hhCNUmzWhTidVUeGmDVs9zSGk8JlyCIJNduokfnOG5pVZS/6J3t9eE2DOxOL2wr/W spHgN+zxLdKh3YbTT5wI7jcpf8wSdgYuuSuFYAs8QOYEyMgkGtTnncBdIIV5w446jk Wwx51AKFqQ8kyH/IM61AnRVuZ+MNejgmoQLWmxUnzMwNS1YKBWW3Vl3Q631hXWEf7H TA6mtIaErL7EOpZSfXSCcXtTfBy9aPG5AHMTrT3IFCgWpGhaIAhQQyCiGR5zGtQP63 1xKb/WSdcQ5nyL9jnNlShluZIYZEt+rE27R1xPtAOAlVeFcmqzlkVXBZLGkiYjnR59 kKbid/s2IUjaw== To: gcc-patches@gcc.gnu.org Cc: Peter Damianov Subject: [PATCH v2] driver: Output to a temp file; rename upon success [PR80182] Date: Sat, 11 May 2024 15:52:57 -0700 Message-Id: <20240511225256.63-1-peter0x44@disroot.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.5 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 --- v2: Make sure temp file is removed in the case of a compiler error gcc/gcc.cc | 51 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/gcc/gcc.cc b/gcc/gcc.cc index 830a4700a87..fabb83c43ee 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,16 @@ 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, output to a temp file. */ + if (!have_c) + { + 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 +9277,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". */