From patchwork Mon Dec 9 11:18:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 102663 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 9858A3858420 for ; Mon, 9 Dec 2024 11:22:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9858A3858420 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=gWvAwBkL X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 8D458385841D for ; Mon, 9 Dec 2024 11:18:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8D458385841D Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 8D458385841D Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1733743102; cv=none; b=HAKKqXRArToXP8FuZSaP5N3T9Yd4nSvbP0rE/9Ak+M4g6vZh9zOFw8T86rst6rFOsSOhKTr4xXq4D3lyg29tqlpxvlwumWjT74jLVrRSvZzm8H5a3Zr6ww2HP2JyGPrcTDXjAawazmLBY+r1gRrwDIpov0jIPRkhLj59rH/Z1MM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1733743102; c=relaxed/simple; bh=3C6gglOBgT5nvLLjY7fUkztodxITKlrV2yodhmX4lLQ=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=wtE8kreB9M9ohyNZK2PHs9JEV2yCg8oYU3ulqQwEk0ye3O2f5urCpkzPjioAIBmCFrKlhnA714AVq/8MEW2/zejdp5sGNiwnp2L3unk6qPa9Rdf8jSx8tfII44D+cppwnHstOSH1ZAyic6RRbBTL9zX24QqZ1pL3KCvixUsa5X8= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8D458385841D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1733743101; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jw1LLWXDpiVIKE0dwf04o0PvXtBtquOEdBBt6uxU/zM=; b=gWvAwBkLlGcuskd8SInlClzt8Oo3YwlIZ8qM4RHlxe7Jj/L75ujOGIKAYdHNdpwYtQm/D9 VCL1wCtYsTys0KXwnDxJZkFwrS0SjzhxAvz6Q+xuYknN4smOzNqtvKtDIQ8nTorkyDlVu1 O8wZbKPPXLpAjM33Vmg4QG3HcJI/srk= Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-584-vE_uVTLsOwWjYklivP5Qfw-1; Mon, 09 Dec 2024 06:18:20 -0500 X-MC-Unique: vE_uVTLsOwWjYklivP5Qfw-1 X-Mimecast-MFC-AGG-ID: vE_uVTLsOwWjYklivP5Qfw Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-3862a49fbdaso1361584f8f.1 for ; Mon, 09 Dec 2024 03:18:19 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733743098; x=1734347898; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jw1LLWXDpiVIKE0dwf04o0PvXtBtquOEdBBt6uxU/zM=; b=cNm1JAalfvOD8taCnExvLu0H+3XDBZcZ82niEDSilRNT+gFlETuSFiCk4Ikl4jmADV ucICHXQH6UqyGzim1SDssg7vwrq1VKWCXiYbgnWeAWXUHwNHr2GGs/0pZd2XkP6pTAhW GPzwIYoTvf7Gb8Dexi/jZgz9jQSu3mWVReMrpi8SYqJnNH+p8OwdU//PH7s25xlT06vL wUk3owRKAv9YuuRBJsx9sFAcz9yhNgJeDhuenpreMWUUHC4i6iv38F6RsXQRJzMMMoxy INJ1ejrFJ1MRnfuvUEs9HFCdJCglXPG9+pi0aRjjqB5MqzU3GG+8FNiTFnFD4bItXLHY JpLw== X-Gm-Message-State: AOJu0YyjMVFZ163F6W70CLwaByPT9fL7CHkA3vH3mA/FdNd44WvihuUR HuhDvPXpEIcExrtrF6aoFsggs1V6N+ujo06BhG6UWHBlAteyNry+X5SRnUoiMf06IDY3rd+LK5e Fnrwv6qrDFD9QjUKRgc+9Gdiz2dHdNX9WjDV3A1HJxB75elXGLXfR8QqI0vnKhHKMVCDS2gGYaA c2mgClZEyXOyQTDwDRTMHjNr65MRbxAkWnVxnJ4g+RgTE= X-Gm-Gg: ASbGncslqOtk6Fi0TP9LP6E7bETHL032RgODW/BVZB7fvMoNrNSO+iFOfx5SuJUvsMO 0JqAtyoSVsQnwJULyGDlIpCpiZDRKiWykkYOT7BYz4oVDAPLM+1DysY2tFJj8n0PC0THXOXZTtj 0c9sSlJmUaZ7aeuoUGWvurDrYgwwSPFhPmmY84wmUD/e9HPD3IBzEmT7AJ7AzMfNpzJD4BOFniC emAecC66FK2WJShGeBspUOh7iHsvoz7iAxgqrZe30D3efNfw9WkILArG4g9F2H0mXs4gzCHm4jS lw== X-Received: by 2002:a05:6000:1566:b0:386:39fd:5ec with SMTP id ffacd0b85a97d-38639fd07edmr3739027f8f.57.1733743098037; Mon, 09 Dec 2024 03:18:18 -0800 (PST) X-Google-Smtp-Source: AGHT+IEAdsrbB56MVnWdzH1h3H/20ra/udQUWwkoQMtuUtuQWwgcsCfnBXTJjgBoiPMzhmuDB0wkEA== X-Received: by 2002:a05:6000:1566:b0:386:39fd:5ec with SMTP id ffacd0b85a97d-38639fd07edmr3738995f8f.57.1733743097577; Mon, 09 Dec 2024 03:18:17 -0800 (PST) Received: from localhost (197.209.200.146.dyn.plus.net. [146.200.209.197]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3861ecf4087sm13127164f8f.5.2024.12.09.03.18.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Dec 2024 03:18:17 -0800 (PST) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCHv5 7/7] gdb: handle empty locspec when printing breakpoints Date: Mon, 9 Dec 2024 11:18:04 +0000 Message-Id: X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: ddZvHyW8_6KiBqKmbFbPrDVmdRa4iod9hyjzFqVshDY_1733743099 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, 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.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~patchwork=sourceware.org@sourceware.org For background reading, please see the previous patch, and the patch before that! After the last two patches, internal breakpoints can now be marked as shlib_disabled if the library in which they are placed is unloaded. The patch before last discusses a situation related to the gdb.base/nostdlib.exp test, when run on a GNU/Linux glibc based system where executables are compiled as PIE by default. In this case it is observed that the dynamic linker will actually report itself as unloaded (i.e. remove itself from the list of currently loaded shared libraries). This behaviour is likely a bug in the dynamic linker, but this behaviour exists in released versions of the dynamic linker, so GDB should (if the cost is not too great) be changed to handle this situation. This commit handles a problem with the 'maint info breakpoints' command. When the dynamic linker is unloaded the 'shlib event' breakpoint is marked as shlib_disabled (i.e. placed into the pending state). When displaying the breakpoint in the 'maint info breakpoints' output, GDB will try to print the locspec (location_spec *) as a string Unfortunately, the locspec will be nullptr as the internal breakpoints are not created via a location_spec, this means that GDB ends up trying to call location_sepc::to_string() on a nullptr, resulting in undefined behaviour (and a crash). For most internal breakpoint types this is not a problem. If we consider bp_longjmp_master for example, if the shared library containing a breakpoint of this type is unloaded then first GDB marks the breakpoint as shlib_disabled, then after unloading the shared library breakpoint_re_set is called, which will delete the internal breakpoint, and then try to re-create it (if needed). As a result, the user never gets a change to run 'maint info breakpoints' on a bp_longjmp_master breakpoint in the shlib_disabled state. But bp_shlib_event and bp_thread_event breakpoints are not deleted and recreated like this (see internal_breakpoint::re_set), so it is possible, in rare cases, that we could end up trying to view one of these breakpoint in a shlib_disabled state, and it would be nice if GDB didn't crash as a result. I've updated the printing code to check for and handle this case, and I've updated the docs to mention this (rare) case. For testing, I've extended gdb.base/nostdlib.exp to compile as pie and nopie, and then run 'maint info breakpoints'. If we're running on a buggy glibc then this will trigger the crash. I don't know how I can trigger this problem without a buggy glibc as this would require forcing the dynamic linker to be unloaded. --- gdb/breakpoint.c | 23 +++++++++- gdb/doc/gdb.texinfo | 5 +++ gdb/testsuite/gdb.base/nostdlib.exp | 69 +++++++++++++++++++---------- 3 files changed, 72 insertions(+), 25 deletions(-) diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index c6bd6f68363..5fdfdea3f05 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -6406,7 +6406,28 @@ print_breakpoint_location (const breakpoint *b, const bp_location *loc) uiout->field_stream ("at", stb); } else - uiout->field_string ("pending", b->locspec->to_string ()); + { + /* Internal breakpoints don't have a locspec string, but can become + pending if the shared library the breakpoint is in is unloaded. + For most internal breakpoint types though, after unloading the + shared library, the breakpoint will be deleted and never recreated + (see internal_breakpoint::re_set). But for two internal + breakpoint types bp_shlib_event and bp_thread_event this is not + true. Usually we don't expect the libraries that contain these + breakpoints to ever be unloaded, but a buggy inferior might do + such a thing, in which case GDB should be prepared to handle this + case. + + If these two breakpoint types become pending then there will be no + locspec string. */ + gdb_assert (b->locspec != nullptr + || (!user_breakpoint_p (b) + && (b->type == bp_shlib_event + || b->type == bp_thread_event))); + const char *locspec_str + = (b->locspec != nullptr ? b->locspec->to_string () : ""); + uiout->field_string ("pending", locspec_str); + } if (loc && is_breakpoint (b) && breakpoint_condition_evaluation_mode () == condition_evaluation_target diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 85ac3d9aab6..ea8d6421fd6 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -32290,6 +32290,11 @@ If this breakpoint is pending, this field is present and holds the text used to set the breakpoint, as entered by the user. +@value{GDBN}'s internal breakpoints (@pxref{maint info breakpoints}) +can sometime become pending too, for these breakpoints the +@var{pending} field will be empty as @value{GDBN} automatically +creates these breakpoints as shared libraries are loaded. + @item evaluated-by Where this breakpoint's condition is evaluated, either @samp{host} or @samp{target}. diff --git a/gdb/testsuite/gdb.base/nostdlib.exp b/gdb/testsuite/gdb.base/nostdlib.exp index 906e627a068..7c32e87ebdb 100644 --- a/gdb/testsuite/gdb.base/nostdlib.exp +++ b/gdb/testsuite/gdb.base/nostdlib.exp @@ -24,33 +24,54 @@ require !use_gdb_stub # dependent on whether the system libraries are already prelinked. # prelink: Could not set /lib64/libm-2.11.1.so owner or mode: Operation not permitted set compile { - gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-nostdlib} -} -set board [target_info name] -if [board_info $board exists mathlib] { - set mathlib [board_info $dest mathlib] - set_board_info mathlib "" - set err [eval $compile] - set_board_info mathlib $mathlib -} else { - set_board_info mathlib "" - set err [eval $compile] - unset_board_info mathlib -} -if {$err != ""} { - untested "failed to compile" - return -1 + gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable $opts } -clean_restart $binfile +foreach_with_prefix pie { "nopie" "pie" } { + # OPTS and BINFILE are used by the COMPILE string (defined above) + # when it is evaluated below. + set opts [list debug additional_flags=-nostdlib $pie] + set binfile [standard_output_file $testfile-$pie] + + set board [target_info name] + if [board_info $board exists mathlib] { + set mathlib [board_info $dest mathlib] + set_board_info mathlib "" + set err [eval $compile] + set_board_info mathlib $mathlib + } else { + set_board_info mathlib "" + set err [eval $compile] + unset_board_info mathlib + } + if {$err != ""} { + untested "failed to compile" + return -1 + } -gdb_breakpoint "*marker" -gdb_breakpoint "*_start" + clean_restart $binfile -gdb_run_cmd + gdb_breakpoint "*marker" + gdb_breakpoint "*_start" -# Breakpoint 2, Stopped due to shared library event -# _start () at ./gdb.base/nostdlib.c:20 -gdb_test "" {Breakpoint [0-9]+, .*_start .*} "stop at run" + gdb_run_cmd -gdb_test "continue" {Breakpoint [0-9]+, marker .*} "continue to marker" + # Breakpoint 2, Stopped due to shared library event + # _start () at ./gdb.base/nostdlib.c:20 + gdb_test "" {Breakpoint [0-9]+, .*_start .*} "stop at run" + + gdb_test "continue" {Breakpoint [0-9]+, marker .*} "continue to marker" + + # When compiling as PIE the executable will be a dynamic + # executable, the dynamic linker performs the PIE relocation. + # Some versions of glibc would (possibly due to a bug) report the + # dynamic linker as unmapped during startup, which places the + # 'shlib event' breakpoint(s) into the PENDING state. + # + # At one point trying to print these internal breakpoints in a + # PENDING state would crash GDB, so lets make sure that doesn't + # happen now. We don't really care about the exact output, + # gdb_test will spot if running this command crashes GDB, which is + # all we're really checking for. + gdb_test "maint info breakpoints" ".*" +}