From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 42954385840E for ; Fri, 20 Jan 2023 09:46:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 42954385840E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1674208003; 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=JQzdSJCbJWsLOw0OqVRSuqXAomBJM0byM0lNhL8pFbc=; b=Z6b9zdz4jngJ1GMnKaPOZcv/pN3IotDX9Kql9E80qDcf9P/tMwxcjIlEl+ncR8Krw7hTZr Zuz/fxdkpxWd07wRs75kP61fIOstqtHCVbuZHBRqHh6yt2FtDVdcSEWrzCNVrlR4SwXwRh cKHEupmbxcw4OFHGAfSuiI9Lr+uFwXk= Received: from mail-qk1-f200.google.com (mail-qk1-f200.google.com [209.85.222.200]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-185-GgYjR0zXPOGgqPkNAaz2Fg-1; Fri, 20 Jan 2023 04:46:42 -0500 X-MC-Unique: GgYjR0zXPOGgqPkNAaz2Fg-1 Received: by mail-qk1-f200.google.com with SMTP id bl13-20020a05620a1a8d00b00709117e3125so961714qkb.18 for ; Fri, 20 Jan 2023 01:46:42 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=JQzdSJCbJWsLOw0OqVRSuqXAomBJM0byM0lNhL8pFbc=; b=sRGf9NcISrSrRH3U2HgBvWRPOtq4PZmZEtUwMowGr597BBk/upIHF6b6jTjLaodVyN AYQYgQN59/8Jsm9JRP9dpNsjp94MP64EQJDC8A9sUHhahMfBsd/90OiCnLs3b2PMO363 dYTiLaTlMKuCWZy+oP7JHJ1F7Yjcc2r0bIGHzEllX7PEfw5Ywvln1A3Q5D/dFqWYHzAe 3wxoQVR6MwGN2Dm3dh3uSMNCLD66AALpa3cxX1GqlD/MeckslX/rZtm5nSB+5DfMLam4 8Z/Q/twqrEr7kLQ1/9F7QEGPiRv9q68WRWT545SpCVCDEv6u9Z49qUYQ4wnVlGQF1G76 vLdg== X-Gm-Message-State: AFqh2kpBnV2Hf9qo4R8E73/iS7Zajz2RbyqdKd8szfNVwGjbzb5Q6DIB WP5/6y5AUZUZClcePE1UUPAqKarRKzVs+YSmzWt+AUNIyTRqALeW8ao3xIcCr6AGZcDkGFJhYNo 67T8wiQTumrby16tZoxsWs8z6Msi0U0xPeePSBBbOfJNNVs6azC4RgsZhWx5LWM2BTXNpithu+A == X-Received: by 2002:a05:622a:4a83:b0:3a8:55c:a893 with SMTP id fw3-20020a05622a4a8300b003a8055ca893mr21951813qtb.0.1674208001464; Fri, 20 Jan 2023 01:46:41 -0800 (PST) X-Google-Smtp-Source: AMrXdXuqHQRp4GOpfQFMvcUoF8lEu5ss0LjpEjxP6ZojvmIzL3gBJ0Wb3itnLQOLLQij2Xk5o0A3Zw== X-Received: by 2002:a05:622a:4a83:b0:3a8:55c:a893 with SMTP id fw3-20020a05622a4a8300b003a8055ca893mr21951785qtb.0.1674208001012; Fri, 20 Jan 2023 01:46:41 -0800 (PST) Received: from localhost (95.72.115.87.dyn.plus.net. [87.115.72.95]) by smtp.gmail.com with ESMTPSA id l5-20020ac87245000000b003b62bc6cd1csm3104213qtp.82.2023.01.20.01.46.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Jan 2023 01:46:40 -0800 (PST) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCHv2 3/6] gdb: fix display of thread condition for multi-location breakpoints Date: Fri, 20 Jan 2023 09:46:26 +0000 Message-Id: <403eeb015d985423d995b34a345e4e7816b8c349.1674207665.git.aburgess@redhat.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,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_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 List-Id: If a breakpoint with multiple locations has a thread condition, then the 'info breakpoints' output is a little messed up, here's an example of the current output: (gdb) break foo thread 1 Breakpoint 2 at 0x401114: foo. (3 locations) (gdb) break bar thread 1 Breakpoint 3 at 0x40110a: file /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c, line 32. (gdb) info breakpoints Num Type Disp Enb Address What 2 breakpoint keep y thread 1 stop only in thread 1 2.1 y 0x0000000000401114 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 2.2 y 0x0000000000401146 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 2.3 y 0x0000000000401168 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 3 breakpoint keep y 0x000000000040110a in bar at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:32 thread 1 stop only in thread 1 Notice that, at the end of the location for breakpoint 3, the 'thread 1' condition is printed, but this is then repeated on the next line with 'stop only in thread 1'. In contrast, for breakpoint 2, the 'thread 1' appears randomly, in the "What" column, though slightly offset, non of the separate locations have the 'thread 1' information. Additionally for breakpoint 2 we also get a 'stop only in thread 1' line. There's two things going on here. First the randomly placed 'thread 1' for breakpoint 2 is due to a bug in print_one_breakpoint_location, where we check the variable part_of_multiple instead of header_of_multiple. If I fix this oversight, then the output is now: (gdb) break foo thread 1 Breakpoint 2 at 0x401114: foo. (3 locations) (gdb) break bar thread 1 Breakpoint 3 at 0x40110a: file /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c, line 32. (gdb) info breakpoints Num Type Disp Enb Address What 2 breakpoint keep y stop only in thread 1 2.1 y 0x0000000000401114 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 thread 1 2.2 y 0x0000000000401146 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 thread 1 2.3 y 0x0000000000401168 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 thread 1 3 breakpoint keep y 0x000000000040110a in bar at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:32 thread 1 stop only in thread 1 The 'thread 1' condition is now displayed at the end of each location, which makes the output the same for single location breakpoints and multi-location breakpoints. However, there's still some duplication here. Both breakpoints 2 and 3 include a 'stop only in thread 1' line, and it feels like the additional 'thread 1' is redundant. In fact, there's a comment to this very effect in the code: /* FIXME: This seems to be redundant and lost here; see the "stop only in" line a little further down. */ So, lets fix this FIXME. The new plan is to remove all the trailing 'thread 1' markers from the CLI output, we now get this: (gdb) break foo thread 1 Breakpoint 2 at 0x401114: foo. (3 locations) (gdb) break bar thread 1 Breakpoint 3 at 0x40110a: file /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c, line 32. (gdb) info breakpoints Num Type Disp Enb Address What 2 breakpoint keep y stop only in thread 1 2.1 y 0x0000000000401114 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 2.2 y 0x0000000000401146 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 2.3 y 0x0000000000401168 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 3 breakpoint keep y 0x000000000040110a in bar at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:32 stop only in thread 1 All of the above points are also true for the Ada 'task' breakpoint condition, and the changes I've made also update how the task information is printed, though in the case of the Ada task there was no 'stop only in task XXX' line printed, so I've added one of those. Obviously it can't be quite that easy. For MI backwards compatibility I've retained the existing code (but now only for MI like outputs), which ensures we should generate backwards compatible output. I've extended an Ada test to cover the new task related output, and updated all the tests I could find that checked for the old output. --- gdb/breakpoint.c | 30 ++++---- gdb/testsuite/gdb.ada/tasks.exp | 15 ++-- gdb/testsuite/gdb.base/save-bp.exp | 2 +- gdb/testsuite/gdb.base/thread-bp-multi-loc.c | 44 ++++++++++++ .../gdb.base/thread-bp-multi-loc.exp | 72 +++++++++++++++++++ 5 files changed, 141 insertions(+), 22 deletions(-) create mode 100644 gdb/testsuite/gdb.base/thread-bp-multi-loc.c create mode 100644 gdb/testsuite/gdb.base/thread-bp-multi-loc.exp diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 00cc2ab401c..b2cd89511fb 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -6468,20 +6468,19 @@ print_one_breakpoint_location (struct breakpoint *b, output_thread_groups (uiout, "thread-groups", inf_nums, mi_only); } - if (!part_of_multiple) + /* In the MI output, each location of a thread or task specific + breakpoint is with the relevant thread or task ID. This is done for + backwards compatibility reasons. + + For the CLI output, the thread/task information is printed on a + separate line, see the 'stop only in thread' and 'stop only in task' + output below. */ + if (!header_of_multiple && uiout->is_mi_like_p ()) { if (b->thread != -1) - { - /* FIXME: This seems to be redundant and lost here; see the - "stop only in" line a little further down. */ - uiout->text (" thread "); - uiout->field_signed ("thread", b->thread); - } + uiout->field_signed ("thread", b->thread); else if (b->task != 0) - { - uiout->text (" task "); - uiout->field_signed ("task", b->task); - } + uiout->field_signed ("task", b->task); } uiout->text ("\n"); @@ -6536,7 +6535,14 @@ print_one_breakpoint_location (struct breakpoint *b, } uiout->text ("\n"); } - + + if (!part_of_multiple && b->task != 0) + { + uiout->text ("\tstop only in task "); + uiout->field_signed ("task", b->task); + uiout->text ("\n"); + } + if (!part_of_multiple) { if (b->hit_count) diff --git a/gdb/testsuite/gdb.ada/tasks.exp b/gdb/testsuite/gdb.ada/tasks.exp index a9b58f20cf6..23bf3937a20 100644 --- a/gdb/testsuite/gdb.ada/tasks.exp +++ b/gdb/testsuite/gdb.ada/tasks.exp @@ -46,21 +46,18 @@ gdb_test "info tasks" \ # breakpoint in the list that matched the triggered-breakpoint's # address, no matter which task it was specific to. gdb_test "break break_me task 1" "Breakpoint .* at .*" +gdb_test "info breakpoints" "foo.adb:${decimal}\r\n\\s+stop only in task 1" \ + "check info breakpoints for task 1 breakpoint" # Now, insert a breakpoint that should stop only if task 3 stops, and # extract its number. -set bp_number -1 -set test "break break_me task 3" -gdb_test_multiple $test $test { - -re "Breakpoint (.*) at .*$gdb_prompt $" { - set bp_number $expect_out(1,string) - pass $test - } -} - +gdb_breakpoint "break_me task 3" +set bp_number [get_integer_valueof "\$bpnum" -1] if {$bp_number < 0} { return } +gdb_test "info breakpoints" "foo.adb:${decimal}\r\n\\s+stop only in task 3" \ + "check info breakpoints for task 3 breakpoint" # Continue to that breakpoint. Task 2 should hit it first, and GDB # is expected to ignore that hit and resume the execution. Only then diff --git a/gdb/testsuite/gdb.base/save-bp.exp b/gdb/testsuite/gdb.base/save-bp.exp index a39712c7f5c..41d71837fb6 100644 --- a/gdb/testsuite/gdb.base/save-bp.exp +++ b/gdb/testsuite/gdb.base/save-bp.exp @@ -79,7 +79,7 @@ gdb_test_sequence "info break" "info break" [list \ "\[\r\n\]+Num +Type +Disp +Enb +Address +What" \ "\[\r\n\]+$bp_row_start break_me at \[^\r\n\]*$srcfile:\[0-9\]+" \ "\[\r\n\]+$bp_row_start main at \[^\r\n\]*$srcfile:$loc_bp2" \ - "\[\r\n\]+$bp_row_start main at \[^\r\n\]*$srcfile:$loc_bp3 +thread 1" \ + "\[\r\n\]+$bp_row_start main at \[^\r\n\]*$srcfile:$loc_bp3" \ "\[\r\n\]+\[ \t]+stop only in thread 1" \ "\[\r\n\]+$bp_row_start main at \[^\r\n\]*$srcfile:$loc_bp4" \ "\[\r\n\]+\[ \t\]+stop only if i == 1( \\((host|target) evals\\))?" \ diff --git a/gdb/testsuite/gdb.base/thread-bp-multi-loc.c b/gdb/testsuite/gdb.base/thread-bp-multi-loc.c new file mode 100644 index 00000000000..cab009c39ec --- /dev/null +++ b/gdb/testsuite/gdb.base/thread-bp-multi-loc.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 . */ + +volatile int global_var = 0; + +__attribute__((__always_inline__)) static inline void +foo (void) +{ + int i; + + for (i = 0; i < 10; ++i) + global_var = i; +} + +static void +bar (void) +{ + global_var = 0; + foo (); +} + +int +main (void) +{ + global_var = 0; + foo (); + bar (); + foo (); + return 0; +} diff --git a/gdb/testsuite/gdb.base/thread-bp-multi-loc.exp b/gdb/testsuite/gdb.base/thread-bp-multi-loc.exp new file mode 100644 index 00000000000..9665fe9e21f --- /dev/null +++ b/gdb/testsuite/gdb.base/thread-bp-multi-loc.exp @@ -0,0 +1,72 @@ +# 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 . + +# Create a multi-location breakpoint with a thread condition, then check the +# output of 'info breakpoints' to ensure that the thread condition is +# displayed correctly. + +standard_testfile + +if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } { + return -1 +} + +if {![runto_main]} { + return -1 +} + +delete_breakpoints + +gdb_breakpoint "foo thread 1" +set bp_number [get_integer_valueof "\$bpnum" 0] +if { $bp_number == 0 } { + unresolved "breakpoint not placed correctly" + return -1 +} + +set saw_header false +set saw_cond false +set loc_count 0 +gdb_test_multiple "info breakpoints" "" { + -re "\r\nNum\\s+\[^\r\n\]+\r\n" { + exp_continue + } + + -re "^$bp_number\\s+breakpoint\\s+keep\\s+y\\s+\\s*\r\n" { + set saw_header true + exp_continue + } + + -re "^\\s+stop only in thread 1\r\n" { + set saw_cond true + exp_continue + } + + -re "^$bp_number\\.\[123\]\\s+\[^\r\n\]+:${decimal}\r\n" { + incr loc_count + exp_continue + } + + -re "^$gdb_prompt $" { + with_test_prefix $gdb_test_name { + gdb_assert { $saw_header } \ + "saw header line" + gdb_assert { $saw_cond } \ + "saw b/p condition line" + gdb_assert { $loc_count == 3 } \ + "saw all three locations" + } + } +} -- 2.25.4