From patchwork Mon Oct 17 13:43:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lancelot SIX X-Patchwork-Id: 58945 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6A77D3858D28 for ; Mon, 17 Oct 2022 13:45:26 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6A77D3858D28 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1666014326; bh=mz/AFLzB0Ld+fyzDTUTrrqq13BqZHFvPbJ8yI5jXHR0=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=Ibglu10wkc/2KDxqh0hHsmwq83i7zxuUxAgiPHV1Hm1cMbz29atBm9ufljJIkr2rg 19QQRztcS3KyhGyI/deWeRxY9xA53+9ZKPfY5Ls/mtCGAp71byEHOSWbT6PjhtET49 eHkV2zclLYRj/C8oF0yu+Q7XWHKdU+6wHM0dC42U= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from NAM12-BN8-obe.outbound.protection.outlook.com (mail-bn8nam12on2075.outbound.protection.outlook.com [40.107.237.75]) by sourceware.org (Postfix) with ESMTPS id C2D413858403 for ; Mon, 17 Oct 2022 13:43:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org C2D413858403 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=mR2betUhek6gCFKqUdKhiedJkQNX9eagLFIFx/7hRGeunZGa4LhdJtQtiStPARI8GcMUlgxTNeRgCwG6XBdPdq5iefM4yO82hwbHB4Q3uYk125SIraPXt6N8zgzV/ibYKsdIKbr9MJYjGBINH3lXqWK0gJxyojMx8T7NqqFmD4AN2CjPpDHCKAdw1BKKnn02fv1qLj//LEmLd1G/cHK8h53C+NGVV1YzmZaMxbR2h6nwqp5AlvJYs9e8c1DeAZK9phvmGTw2tNQ6tq71ddNiJ/VV15L+X0QJ1pSFjZ6ZFMhut5T+pTGwaNVpSRskwzXvumJyhkSzd6ZTv74h1C13qA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=mz/AFLzB0Ld+fyzDTUTrrqq13BqZHFvPbJ8yI5jXHR0=; b=dWo1qib7Typq2TMFgUwCtV5X7l5LrQW5/LDGENwaw8adUc7VURR+uGUWu9uooX7w3BcHFCjhqopxZ9LeiubliaoCK4EFDg4FQQO1mBcQiFY0mPgGDwxPUksMRHRHKe5wEApGxItNMfpTk2RFkzovLyFrRQZreqcSHusFrTLr0VvGim7l12p7AXrwUXXklv8XNUJlE0eUsEyauvPpchMStr3EWbKLbchldvykGtShfDQo/7lVd/XYWnXJdzRdcqVFgYUcFdxz7ZFd0huy/bdRW08GhdIaI2JUeQ9z50RH/GSpGeHwYOhlocRSARg/L1YnAzwAcnzCyQR3kTb4N+Ot9Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=sourceware.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none Received: from DS7PR05CA0084.namprd05.prod.outlook.com (2603:10b6:8:57::25) by MW4PR12MB5667.namprd12.prod.outlook.com (2603:10b6:303:18a::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5723.29; Mon, 17 Oct 2022 13:43:52 +0000 Received: from DM6NAM11FT021.eop-nam11.prod.protection.outlook.com (2603:10b6:8:57:cafe::85) by DS7PR05CA0084.outlook.office365.com (2603:10b6:8:57::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5746.6 via Frontend Transport; Mon, 17 Oct 2022 13:43:52 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by DM6NAM11FT021.mail.protection.outlook.com (10.13.173.76) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.5723.20 via Frontend Transport; Mon, 17 Oct 2022 13:43:52 +0000 Received: from khazad-dum.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.31; Mon, 17 Oct 2022 08:43:50 -0500 To: Subject: [PATCH v2] gdb/gcore: interrupt all threads before generating the corefile Date: Mon, 17 Oct 2022 14:43:35 +0100 Message-ID: <20221017134335.385594-1-lancelot.six@amd.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB03.amd.com (10.181.40.144) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DM6NAM11FT021:EE_|MW4PR12MB5667:EE_ X-MS-Office365-Filtering-Correlation-Id: f8b58ea4-b61a-4a29-b12f-08dab045a0e3 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: QBZyQNZPT01pd4skcwb3uBBxsmSmbUcv8YCSBz9Yy9cnOrT4ei0hNgrv74nHfAvhN/Yt4O1izkZsddOMuWL8ZErVv5B+QQgMqMqpO9eeqEST9M+5GyVqx1wBTuW8fPrTlFDvk8z04kIl9ZSPWnObVA44+WRVQQGnDKZGziVqiB6yYGgEykf8pNJ6AMioRMrIMff2VamjCePFlMKlzIlRYrXjezbilSrrlffww1DF1d+KdRttTIrNcgkxowE1WZbnRML3bSCzTiNnMMp4rjlFw7mISeHyt4fGf/K8lthQxF9I4yp3LFh9S3tqta7UT5TDNWr52YMadyx73PzpqXxJ/Rs+P+TWhXgHuzAkJE7xmVErDpiehr9UweLZOpm6O4iATtGGnZEoWr8ho+gGv5Xpto9nTrlnn9Gx8QkBt1LN1sHpu40nrUi7DBT5XYvkc02jpNSmcID6GdIFX8ljSs1GTohXOICBUr2zKpwhNN7FkBqDjaTJGkr7tO3BA38vjIV1RiYWOzouBESn61v3d1V5/xmkJcO/RTzz2cbGYJZVkMFI41gx5jbWktltL0IJOcqxOQwvvhkbXSZX0oab0e/bM02IImqT2gzUOC/sRh+IEq4P1vzGQyQ2JG1fvqxFDIZ+uleMnP1mDAd+9w+60zYaNSb/16AGc8MZ8/GffEREuZ/4riKCqjTljXAbF5mDib6Iqz6EwBjkKXnvYOKiVexnavlvvSgJW/CIfs/JoxrVMSF1wuDOR1jQfhrMym1Vj9kVJMGdoqnN4a3z77QE7H2warAwu9JmWilf34fde98TBhzS0eyS6cMzMQtRqdqbAllXb5QKjaIVy0MqqwMdhTJN8Q== X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230022)(4636009)(346002)(376002)(396003)(136003)(39860400002)(451199015)(40470700004)(46966006)(36840700001)(426003)(47076005)(16526019)(336012)(2906002)(1076003)(186003)(83380400001)(82310400005)(82740400003)(81166007)(40480700001)(40460700003)(36756003)(36860700001)(86362001)(356005)(478600001)(966005)(6916009)(54906003)(41300700001)(316002)(7696005)(8936002)(5660300002)(26005)(2616005)(30864003)(70206006)(8676002)(70586007)(4326008)(6666004)(2004002)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 Oct 2022 13:43:52.4073 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: f8b58ea4-b61a-4a29-b12f-08dab045a0e3 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: DM6NAM11FT021.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW4PR12MB5667 X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, 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: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Lancelot SIX via Gdb-patches From: Lancelot SIX Reply-To: Lancelot SIX Cc: lsix@lancelotsix.com, Lancelot SIX Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Hi, Here is a V2 for https://sourceware.org/pipermail/gdb-patches/2022-October/192420.html Changes since V1: - Fixed typos reported by Pedro. - Used scoped_finish_thread_state in gcore_command to avoid leaving threads in an inconsistent user-visible state in case of error. - Added a NEWS entry and updated the documentation to reflect the new behaviour. - Improved the testcase to check that the thread which was stopped before calling `gcore` remains stopped at the same spot after the gcore command is finished. Best, Lancelot. In non-stop mode, if the user tries to generate a core dump (using the gcore command) while some threads are running, a non-helpful error message is shown. Lets consider the following session as an example (debugging the test program included in this patch): (gdb) set non-stop on (gdb) b 37 (gdb) r Thread 1 "gcore-nonstop" hit Breakpoint 1, main () at gcore-nonstop.c:39 (gdb) info thread Id Target Id Frame * 1 Thread 0x7ffff7d7a740 (LWP 431838) "gcore-nonstop" main () at gcore-nonstop.c:39 2 Thread 0x7ffff7d79640 (LWP 431841) "gcore-nonstop" (running) (gdb) gcore Couldn't get registers: No such process. The reported error ("No such process") does not help the user understand what happens. This is due to the fact that we cannot access the registers of a running thread. Even if we ignore this error, generating a core dump while any thread might update memory would most likely result in a core file with an inconsistent view of the process' memory. To solve this, this patch proposes to change the gcore command so it first stops all running threads (from the current inferior) before generating the corefile, and then resumes them in their previous state. To achieve this, this patch exposes the restart_threads function in infrun.h (used to be local to infrun.c). We also allow the first parameter (event_thread) to be nullptr as it is possible that the gcore command is called while all threads are running, in which case we want all threads to be restarted at the end of the procedure. Tested on x86_64. --- gdb/NEWS | 5 ++ gdb/doc/gdb.texinfo | 5 ++ gdb/gcore.c | 11 ++++ gdb/infrun.c | 16 ++---- gdb/infrun.h | 9 +++ gdb/testsuite/gdb.base/gcore-nonstop.c | 44 ++++++++++++++ gdb/testsuite/gdb.base/gcore-nonstop.exp | 73 ++++++++++++++++++++++++ 7 files changed, 152 insertions(+), 11 deletions(-) create mode 100644 gdb/testsuite/gdb.base/gcore-nonstop.c create mode 100644 gdb/testsuite/gdb.base/gcore-nonstop.exp base-commit: e57f7fa070e16683c0e1ddd0d1307d243fad990d diff --git a/gdb/NEWS b/gdb/NEWS index 8b519a648f7..b448d0401a6 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -117,6 +117,11 @@ show debug infcall * Changed commands +gcore + GDB now ensures that all threads of the current inferior are stopped + before generating a core dump. At the end of the command, threads are + restored to their previous state. + document user-defined It is now possible to document user-defined aliases. When a user-defined alias is documented, the help and apropos commands diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 3de511a4844..c95d5c9bcf1 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -13570,6 +13570,11 @@ Produce a core dump of the inferior process. The optional argument specified, the file name defaults to @file{core.@var{pid}}, where @var{pid} is the inferior process ID. +@value{GDBN} ensures that all threads of the current inferior are stopped +while generating the core dump. If any of the inferior's thread is found +running when executing this command, @value{GDBN} stops it and resumes it +when the command is done. + Note that this command is implemented only for some systems (as of this writing, @sc{gnu}/Linux, FreeBSD, Solaris, and S390). diff --git a/gdb/gcore.c b/gdb/gcore.c index ede78534bd8..d64918fe983 100644 --- a/gdb/gcore.c +++ b/gdb/gcore.c @@ -34,6 +34,7 @@ #include "regset.h" #include "gdb_bfd.h" #include "readline/tilde.h" +#include "infrun.h" #include #include "gdbsupport/gdb_unlinker.h" #include "gdbsupport/byte-vector.h" @@ -131,6 +132,13 @@ gcore_command (const char *args, int from_tty) if (!target_has_execution ()) noprocess (); + scoped_restore_current_thread restore_current_thread; + scoped_disable_commit_resumed disable_commit_resume ("generating coredump"); + struct inferior *inf = current_inferior (); + scoped_finish_thread_state finish_state (inf->process_target (), + ptid_t (inferior_ptid.pid ())); + stop_all_threads ("generating coredump", inf); + if (args && *args) corefilename.reset (tilde_expand (args)); else @@ -161,6 +169,9 @@ gcore_command (const char *args, int from_tty) } gdb_printf ("Saved corefile %s\n", corefilename.get ()); + + restart_threads (nullptr, inf); + disable_commit_resume.reset_and_commit (); } static enum bfd_architecture diff --git a/gdb/infrun.c b/gdb/infrun.c index cdfe02393f5..b5bd6cb1902 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -96,9 +96,6 @@ static void resume (gdb_signal sig); static void wait_for_inferior (inferior *inf); -static void restart_threads (struct thread_info *event_thread, - inferior *inf = nullptr); - static bool start_step_over (void); static bool step_over_info_valid_p (void); @@ -5889,18 +5886,15 @@ handle_inferior_event (struct execution_control_state *ecs) } } -/* Restart threads back to what they were trying to do back when we - paused them (because of an in-line step-over or vfork, for example). - The EVENT_THREAD thread is ignored (not restarted). - - If INF is non-nullptr, only resume threads from INF. */ +/* See infrun.h. */ -static void +void restart_threads (struct thread_info *event_thread, inferior *inf) { INFRUN_SCOPED_DEBUG_START_END ("event_thread=%s, inf=%d", - event_thread->ptid.to_string ().c_str (), - inf != nullptr ? inf->num : -1); + (event_thread != nullptr + ? event_thread->ptid.to_string ().c_str () + : "None"), inf != nullptr ? inf->num : -1); gdb_assert (!step_over_info_valid_p ()); diff --git a/gdb/infrun.h b/gdb/infrun.h index c711b9b21cc..4cd98ec06c5 100644 --- a/gdb/infrun.h +++ b/gdb/infrun.h @@ -175,6 +175,15 @@ extern void nullify_last_target_wait_ptid (); all threads of all inferiors. */ extern void stop_all_threads (const char *reason, inferior *inf = nullptr); +/* Restart threads back to what they were trying to do back when we + paused them (because of an in-line step-over or vfork, for example). + The EVENT_THREAD thread, if non-nullptr, is ignored (not restarted). + + If INF is non-nullptr, only resume threads from INF. */ + +extern void restart_threads (struct thread_info *event_thread, + inferior *inf = nullptr); + extern void prepare_for_detach (void); extern void fetch_inferior_event (); diff --git a/gdb/testsuite/gdb.base/gcore-nonstop.c b/gdb/testsuite/gdb.base/gcore-nonstop.c new file mode 100644 index 00000000000..191a1a26849 --- /dev/null +++ b/gdb/testsuite/gdb.base/gcore-nonstop.c @@ -0,0 +1,44 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2022 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +static pthread_barrier_t barrier; + +static void * +worker_func (void *) +{ + pthread_barrier_wait (&barrier); + return NULL; +} + +int +main (void) +{ + pthread_t worker_thread; + pthread_barrier_init (&barrier, NULL, 2); + + pthread_create (&worker_thread, NULL, worker_func, NULL); + + /* Break here. */ + + pthread_barrier_wait (&barrier); + pthread_join (worker_thread, NULL); + pthread_barrier_destroy (&barrier); + + return 0; +} diff --git a/gdb/testsuite/gdb.base/gcore-nonstop.exp b/gdb/testsuite/gdb.base/gcore-nonstop.exp new file mode 100644 index 00000000000..d4cbf6cf3c4 --- /dev/null +++ b/gdb/testsuite/gdb.base/gcore-nonstop.exp @@ -0,0 +1,73 @@ +# Copyright 2022 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This testcase checks that when in non-stop mode with some threads running +# the gcore command can interrupt all threads, generate a core dump and +# restart threads as required. + +standard_testfile + +if { [prepare_for_testing "failed to prepare" \ + ${testfile} ${srcfile} {threads debug}] } { + return +} + +gdb_test_no_output "set non-stop on" +set lineno [gdb_get_line_number "Break here"] +if { ![runto $lineno] } { + return +} + +# We should be stopped in thread 1 while thread 2 is running. +gdb_test_sequence "info threads" "info threads" { + {Id\s+Target Id\s+Frame} + {\*\s+1[^\n]*\n} + {\s+2\s+[^\n]*\(running\)[^\n]*\n} +} + +set th1_pc "" +gdb_test_multiple "p/x \$pc" "fetch thread 1 PC" { + -wrap -re "$::decimal = ($::hex)" { + set th1_pc $expect_out(1,string) + pass $gdb_test_name + } +} + +set corefile [standard_output_file "corefile"] +if {![gdb_gcore_cmd $corefile "generate corefile"]} { + # gdb_gcore_cmd issues a "UNSUPPORTED". + return +} + +# After the core file is generated, thread 2 should be back running +# and thread 1 should still be selected. +gdb_test_sequence "info threads" "correct thread selection after gcore" { + {Id\s+Target Id\s+Frame} + {\*\s+1[^\n]*\n} + {\s+2\s+[^\n]*\(running\)[^\n]*\n} +} + +# Thread 1 is at the same stop it was before calling the gcore command. +gdb_test "p/x \$pc" "\\\$$::decimal = $th1_pc" "thread 1 unchanged" + +clean_restart $binfile +gdb_test "core-file $corefile" "Core was generated by.*" "load corefile" + +# The core file has the 2 threads. +gdb_test_sequence "info threads" "threads in corefile" { + {Id\s+Target Id\s+Frame} + {\s+1\s+Thread[^\n]*\n} + {\s+2\s+Thread[^\n]*\n} +}