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 70A243858D28 for ; Tue, 11 Apr 2023 10:54:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 70A243858D28 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=1681210450; 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=16VXh9JEmZQbqQLIYFCUADY0wa+ZQBU5bgFItz5gmjw=; b=U5b/gCOz5ezEw3FWuF3Rmeo2754eIyoT3OmuENk69hLM6hn9LJhMCpZcajC7nXnnIWwuVP 3YODkoUpe+Hce7MiTU4DuZvAEoHbRMenQAM22Qkxzv/vBX47xxsl3UoKUukT5deGLHeqJg XSvqB8lR5rRRZnYKHOFDFYxaF3Dg2xU= Received: from mail-ed1-f69.google.com (mail-ed1-f69.google.com [209.85.208.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-111-nq6Fxrh9PQC7zcAnuRnHnA-1; Tue, 11 Apr 2023 06:54:08 -0400 X-MC-Unique: nq6Fxrh9PQC7zcAnuRnHnA-1 Received: by mail-ed1-f69.google.com with SMTP id 21-20020a508755000000b005024a8cef5cso215488edv.22 for ; Tue, 11 Apr 2023 03:54:08 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681210447; h=content-transfer-encoding:mime-version:message-id:date:references :in-reply-to:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=4BEHLcAM6MggRwxH0uydmj5+64zE+Oczh7Lug7fKBsg=; b=In/cL//fSsNjzxCNcNjkDSTc7jRqxHDsu7rGKyh88n1qwjMZW0ER86wRU6m3ZqAFkc XVQYMlY2EoE6iXSmlaswtzNftuJgO5zR8QX6kmO/vB9VJJDxOT2NbQdWUycmQhkQslcu 4ZomJ3f0bfWvPqk9DtbWyZwQ7KHnJcMdAnoyzY2XR1JtzgIFvzw46UTcKctEvpH6xz5/ 0C/cJh6nXBHnMZ0OknsXJDoPNSR6tcd8fqlY6sUOH4cZyjLCXU3SZbYi4LFFq9UtuDE2 FGf7fn3NVCKEpwn7x5TlfouzYMcdypCqImfYKfstHxhPjP1hPmXgWXMO9LmjNCQR6hHm /BGQ== X-Gm-Message-State: AAQBX9cFvaum9b7Wq6qNS3Z5pM6zkWqZrLsWy17ceiGcsPkWznWl2aqV mW4sA8wZuwbqqIvoe1YdSi4U8WsYHiaMFHL+QbL60Wkd8hag78I5MSZmtmyP+aZ5pQzJT7UFDG/ PPKA2cOAnaZpnXBEWLd7BrH5/cZ+ILQ== X-Received: by 2002:a17:906:6981:b0:94b:5921:69f9 with SMTP id i1-20020a170906698100b0094b592169f9mr2143175ejr.64.1681210447450; Tue, 11 Apr 2023 03:54:07 -0700 (PDT) X-Google-Smtp-Source: AKy350YjieUDkZmwSM8rnKcS5vSn39Ewt1CCQXqQNkaJHuk3uybtS7sFu6TEUaWD6+InAf4zrFw+oA== X-Received: by 2002:a17:906:6981:b0:94b:5921:69f9 with SMTP id i1-20020a170906698100b0094b592169f9mr2143159ejr.64.1681210447023; Tue, 11 Apr 2023 03:54:07 -0700 (PDT) Received: from localhost (95.72.115.87.dyn.plus.net. [87.115.72.95]) by smtp.gmail.com with ESMTPSA id c14-20020a170906170e00b00947a939f6e0sm6098907eje.77.2023.04.11.03.54.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Apr 2023 03:54:06 -0700 (PDT) From: Andrew Burgess To: Lancelot SIX Cc: gdb-patches@sourceware.org Subject: Re: [PATCH] gdb: warn when converting h/w watchpoints to s/w In-Reply-To: <20230404123734.g2clksou23uit5ul@octopus> References: <20230330084850.i62rd5kbd7wfcqo6@octopus> <87355hdyg4.fsf@redhat.com> <20230404123734.g2clksou23uit5ul@octopus> Date: Tue, 11 Apr 2023 11:54:05 +0100 Message-ID: <87y1myadv6.fsf@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable 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: Lancelot SIX writes: > Hi, > > Thanks for the update. I went through the changes and tested them on > x86_64 GNU/Linux. FWIW, this looks good to me. > > The only remark I have, is that the test case tests that a watchpoint is > "downgraded" from hardware to software, while the warning message only > says "changed". In my mind this change is indeed a downgrade and I > think this is what we want to communicate. So I wouldn=E2=80=99t mind us= ing > this term in the warning message, but I am aware this is close to > bike-shedding. > > If you prefer the current message, I am also fine with it. > > Feel free to add: > Reviewed-By: Lancelot Six I switched to use 'downgraded' in the message and pushed this change. Thanks, Andrew > > Best, > Lancelot. > >>=20 >> Thanks for the feedback. I updated to resolve these issues. >>=20 >> Thanks, >> Andrew >>=20 >> --- >>=20 >> commit 237037fce9954d50a013548c9575ed5ba6674ba2 >> Author: Andrew Burgess >> Date: Tue Mar 28 11:24:58 2023 +0100 >>=20 >> gdb: warn when converting h/w watchpoints to s/w >> =20 >> On amd64 (at least) if a user sets a watchpoint before the inferior >> has started then GDB will assume that a hardware watchpoint can be >> created. >> =20 >> When the inferior starts there is a chance that the watchpoint can't >> actually be create as a hardware watchpoint, in which case (currentl= y) >> GDB will silently convert the watchpoint to a software watchpoint. >> Here's an example session: >> =20 >> (gdb) p sizeof var >> $1 =3D 4000 >> (gdb) watch var >> Hardware watchpoint 1: var >> (gdb) info watchpoints >> Num Type Disp Enb Address What >> 1 hw watchpoint keep y var >> (gdb) starti >> Starting program: /home/andrew/tmp/watch >> =20 >> Program stopped. >> 0x00007ffff7fd3110 in _start () from /lib64/ld-linux-x86-64.so.2 >> (gdb) info watchpoints >> Num Type Disp Enb Address What >> 1 watchpoint keep y var >> (gdb) >> =20 >> Notice that before the `starti` command the watchpoint is showing as= a >> hardware watchpoint, but afterwards it is showing as a software >> watchpoint. Additionally, note that we clearly told the user we >> created a hardware watchpoint: >> =20 >> (gdb) watch var >> Hardware watchpoint 1: var >> =20 >> I think this is bad. I used `starti`, but if the user did `start` o= r >> even `run` then the inferior is going to be _very_ slow, which will = be >> unexpected -- after all, we clearly told the user that we created a >> hardware watchpoint, and the manual clearly says that hardware >> watchpoints are fast (at least compared to s/w watchpoints). >> =20 >> In this patch I propose adding a new warning which will be emitted >> when GDB downgrades a h/w watchpoint to s/w. The session now looks >> like this: >> =20 >> (gdb) p sizeof var >> $1 =3D 4000 >> (gdb) watch var >> Hardware watchpoint 1: var >> (gdb) info watchpoints >> Num Type Disp Enb Address What >> 1 hw watchpoint keep y var >> (gdb) starti >> Starting program: /home/andrew/tmp/watch >> warning: watchpoint 1 changed to software watchpoint >> =20 >> Program stopped. >> 0x00007ffff7fd3110 in _start () from /lib64/ld-linux-x86-64.so.2 >> (gdb) info watchpoints >> Num Type Disp Enb Address What >> 1 watchpoint keep y var >> (gdb) >> =20 >> The important line is: >> =20 >> warning: watchpoint 1 changed to software watchpoint >> =20 >> It's not much, but hopefully it will be enough to indicate to the us= er >> that something unexpected has occurred, and hopefully, they will not >> be surprised when the inferior runs much slower than they expected. >> =20 >> I've added an amd64 only test in gdb.arch/, I didn't want to try >> adding this as a global test as other architectures might be able to >> support the watchpoint request in h/w. >> =20 >> Also the test is skipped for extended-remote boards as there's a >> different set of options for limiting hardware watchpoints on remote >> targets, and this test isn't about them. >>=20 >> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c >> index 7228acfd8fe..8b8c2937d8d 100644 >> --- a/gdb/breakpoint.c >> +++ b/gdb/breakpoint.c >> @@ -2143,6 +2143,21 @@ update_watchpoint (struct watchpoint *b, bool rep= arse) >> =09 } >> =09} >> =20 >> + /* Helper function to bundle possibly emitting a warning along wi= th >> +=09 changing the type of B to bp_watchpoint. */ >> + auto change_type_to_bp_watchpoint =3D [] (breakpoint *bp) >> + { >> +=09/* Only warn for breakpoints that have been assigned a +ve number, >> +=09 anything else is either an internal watchpoint (which we don't >> +=09 currently create) or has not yet been finalized, in which case >> +=09 this change of type will be occurring before the user is told >> +=09 the type of this watchpoint. */ >> +=09if (bp->type =3D=3D bp_hardware_watchpoint && bp->number > 0) >> +=09 warning (_("watchpoint %d changed to software watchpoint"), >> +=09=09 bp->number); >> +=09bp->type =3D bp_watchpoint; >> + }; >> + >> /* Change the type of breakpoint between hardware assisted or >> =09 an ordinary watchpoint depending on the hardware support and >> =09 free hardware slots. Recheck the number of free hardware slots >> @@ -2200,7 +2215,7 @@ update_watchpoint (struct watchpoint *b, bool repa= rse) >> =09=09=09 "resources for this watchpoint.")); >> =20 >> =09=09 /* Downgrade to software watchpoint. */ >> -=09=09 b->type =3D bp_watchpoint; >> +=09=09 change_type_to_bp_watchpoint (b); >> =09=09} >> =09 else >> =09=09{ >> @@ -2221,7 +2236,7 @@ update_watchpoint (struct watchpoint *b, bool repa= rse) >> =09=09=09 "read/access watchpoint.")); >> =09 } >> =09 else >> -=09 b->type =3D bp_watchpoint; >> +=09 change_type_to_bp_watchpoint (b); >> =20 >> =09 loc_type =3D (b->type =3D=3D bp_watchpoint? bp_loc_software_watchp= oint >> =09=09 : bp_loc_hardware_watchpoint); >> diff --git a/gdb/testsuite/gdb.arch/amd64-watchpoint-downgrade.c b/gdb/t= estsuite/gdb.arch/amd64-watchpoint-downgrade.c >> new file mode 100644 >> index 00000000000..c2f5f2cc78e >> --- /dev/null >> +++ b/gdb/testsuite/gdb.arch/amd64-watchpoint-downgrade.c >> @@ -0,0 +1,29 @@ >> +/* This testcase is part of GDB, the GNU debugger. >> + >> + Copyright 2023 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 = . */ >> + >> +struct struct_type >> +{ >> + unsigned long long array[100]; >> +}; >> + >> +struct struct_type global_var; >> + >> +int >> +main () >> +{ >> + return 0; >> +} >> diff --git a/gdb/testsuite/gdb.arch/amd64-watchpoint-downgrade.exp b/gdb= /testsuite/gdb.arch/amd64-watchpoint-downgrade.exp >> new file mode 100644 >> index 00000000000..a4814305c72 >> --- /dev/null >> +++ b/gdb/testsuite/gdb.arch/amd64-watchpoint-downgrade.exp >> @@ -0,0 +1,67 @@ >> +# Copyright 2023 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 . >> + >> +# Ask GDB to watch a large structure before the inferior has started, >> +# GDB will assume it can place a hardware watchpoint. >> +# >> +# Once the inferior starts GDB realises that it is not able to watch >> +# such a large structure and downgrades to a software watchpoint. >> +# >> +# This test checks that GDB emits a warnings about this downgrade, as >> +# a software watchpoint will be significantly slower than a hardware >> +# watchpoint, and the user probably wants to know about this. >> + >> +require target_can_use_run_cmd is_x86_64_m64_target >> + >> +# The remote/extended-remote target has its own set of flags to >> +# control the use of s/w vs h/w watchpoints, this test isn't about >> +# those, so skip the test in these cases. >> +if {[target_info gdb_protocol] =3D=3D "remote" >> + || [target_info gdb_protocol] =3D=3D "extended-remote"} { >> + unsupported "using [target_info gdb_protocol] protocol" >> + return -1 >> +} >> + >> +standard_testfile >> + >> +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \ >> +=09 { debug }] } { >> + return -1 >> +} >> + >> +# Insert the watchpoint, it should default to a h/w watchpoint. >> +gdb_test "watch global_var" \ >> + "Hardware watchpoint $decimal: global_var" >> +set num [get_integer_valueof "\$bpnum" "*UNKNOWN*" \ >> +=09 "get watchpoint number"] >> + >> +# Watchpoint should initially show as a h/w watchpoint. >> +gdb_test "info watchpoints" \ >> + "\r\n$num\\s+hw watchpoint\\s+keep\\s+y\\s+global_var" \ >> + "check info watchpoints before starting" >> + >> +# Start the inferior, GDB should emit a warning that the watchpoint >> +# type has changed. >> +gdb_test "starti" \ >> + [multi_line \ >> +=09 "warning: watchpoint $num changed to software watchpoint" \ >> +=09 "" \ >> +=09 "Program stopped\\." \ >> +=09 ".*"] >> + >> +# Watchpoint should now have downgraded to a s/w watchpoint. >> +gdb_test "info watchpoints" \ >> + "\r\n$num\\s+watchpoint\\s+keep\\s+y\\s+global_var" \ >> + "check info watchpoints after starting" >> diff --git a/gdb/testsuite/gdb.base/watchpoint.exp b/gdb/testsuite/gdb.b= ase/watchpoint.exp >> index 513964ebf86..28276681afc 100644 >> --- a/gdb/testsuite/gdb.base/watchpoint.exp >> +++ b/gdb/testsuite/gdb.base/watchpoint.exp >> @@ -273,7 +273,8 @@ proc test_stepping {} { >> global gdb_prompt >> =20 >> if {[runto marker1]} { >> -=09gdb_test "watch ival2" ".*\[Ww\]atchpoint \[0-9\]*: ival2" >> +=09gdb_test "watch ival2" \ >> +=09 "^watch ival2\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]*: ival2" >> =20 >> =09# Well, let's not be too mundane. It should be a *bit* of a challen= ge >> =09gdb_test "break func2 if 0" "Breakpoint.*at.*" >> @@ -432,7 +433,8 @@ proc test_complex_watchpoint {} { >> global gdb_prompt >> =20 >> if {[runto marker4]} { >> -=09gdb_test "watch ptr1->val" ".*\[Ww\]atchpoint \[0-9\]*: ptr1->val" >> +=09gdb_test "watch ptr1->val" \ >> +=09 "^watch ptr1->val\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]*: ptr1->v= al" >> =09gdb_test "break marker5" ".*Breakpoint.*" >> =20 >> =09gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ptr1->val.*Old value = =3D 1.*New value =3D 2.*" "test complex watchpoint" >> @@ -458,7 +460,9 @@ proc test_complex_watchpoint {} { >> # is the function we're now in. This should auto-delete when >> # execution exits the scope of the watchpoint. >> # >> - gdb_test "watch local_a" ".*\[Ww\]atchpoint \[0-9\]*: local_a" = "set local watch" >> +=09gdb_test "watch local_a" \ >> +=09 "^watch local_a\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]*: local_a" = \ >> +=09 "set local watch" >> gdb_test "cont" "\[Ww\]atchpoint.*local_a.*" "trigger local wat= ch" >> =20 >> =09set test "self-delete local watch" >> @@ -487,7 +491,8 @@ proc test_complex_watchpoint {} { >> # something whose scope is larger than this invocation >> # of "func2". This should also auto-delete. >> # >> - gdb_test "watch local_a + ival5" ".*\[Ww\]atchpoint \[0-9\]*: l= ocal_a . ival5" \ >> +=09gdb_test "watch local_a + ival5" \ >> +=09 "^watch local_a \\+ ival5\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]*:= local_a . ival5" \ >> "set partially local watch" >> gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: local_a . ival= 5.*" \ >> "trigger1 partially local watch" >> @@ -502,7 +507,8 @@ proc test_complex_watchpoint {} { >> # delete. >> # >> =09gdb_continue_to_breakpoint "func2 breakpoint here, third time" >> - gdb_test "watch static_b" ".*\[Ww\]atchpoint \[0-9\]*: static_b= " \ >> +=09gdb_test "watch static_b" \ >> +=09 "^watch static_b\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]*: static_b= " \ >> "set static local watch" >> gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: static_b.*" \ >> "trigger static local watch" >> @@ -521,7 +527,8 @@ proc test_complex_watchpoint {} { >> =09 gdb_test "tbreak recurser" ".*breakpoint.*" >> =09 gdb_test "cont" "Continuing.*recurser.*" >> =09 gdb_test "next" "if \\(x > 0.*" "next past local_x initializatio= n" >> -=09 gdb_test "watch local_x" ".*\[Ww\]atchpoint \[0-9\]*: local_x" \ >> +=09 gdb_test "watch local_x" \ >> +=09=09"^watch local_x\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]*: local_x" \ >> =09=09"set local watch in recursive call" >> =09 gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: local_x.*New va= lue =3D 2.*" \ >> =09=09"trigger local watch in recursive call" >> @@ -536,7 +543,8 @@ proc test_complex_watchpoint {} { >> =09 gdb_test "tbreak recurser" ".*breakpoint.*" >> =09 gdb_test "cont" "Continuing.*recurser.*" "continue to recurser" >> =09 gdb_test "next" "if \\(x > 0.*" "next past local_x initializatio= n" >> -=09 gdb_test "watch recurser::local_x" ".*\[Ww\]atchpoint \[0-9\]*: = recurser::local_x" \ >> +=09 gdb_test "watch recurser::local_x" \ >> +=09=09"^watch recurser::local_x\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]*: = recurser::local_x" \ >> =09=09"set local watch in recursive call with explicit scope" >> =09 gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: recurser::local= _x.*New value =3D 2.*" \ >> =09=09"trigger local watch with explicit scope in recursive call" >> @@ -562,7 +570,8 @@ proc test_watchpoint_and_breakpoint {} { >> if {[runto func3]} { >> =09gdb_breakpoint [gdb_get_line_number "second x assignment"] >> =09gdb_continue_to_breakpoint "second x assignment" >> -=09gdb_test "watch x" ".*atchpoint \[0-9\]+: x" >> +=09gdb_test "watch x" \ >> +=09 "^watch x\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]+: x" >> =09gdb_test "next" \ >> =09 ".*atchpoint \[0-9\]+: x\r\n\r\nOld value =3D 0\r\nNew value =3D= 1\r\n.*" \ >> =09 "next after watch x" >> @@ -579,7 +588,8 @@ proc test_constant_watchpoint {} { >> "marker1 is constant" >> gdb_test "watch count + 6" ".*atchpoint \[0-9\]+: count \\+ 6" >> gdb_test_no_output "delete \$bpnum" "delete watchpoint `count + 6'" >> - gdb_test "watch 7 + count" ".*atchpoint \[0-9\]+: 7 \\+ count" >> + gdb_test "watch 7 + count" \ >> +=09"^watch 7 \\+ count\r\n\[^\r\n\]*atchpoint \[0-9\]+: 7 \\+ count" >> gdb_test_no_output "delete \$bpnum" "delete watchpoint `7 + count'" >> } >> =20 >> @@ -588,7 +598,7 @@ proc test_disable_enable_software_watchpoint {} { >> # for software watchpoints. >> =20 >> # Watch something not memory to force a software watchpoint. >> - gdb_test {watch $pc} ".*atchpoint \[0-9\]+: .pc" >> + gdb_test {watch $pc} "^watch \\\$pc\r\n\[^\r\n\]*\[Ww\]atchpoint \[= 0-9\]+: .pc" >> =20 >> gdb_test_no_output "disable \$bpnum" "disable watchpoint `\$pc'" >> gdb_test_no_output "enable \$bpnum" "reenable watchpoint `\$pc'" >> @@ -822,7 +832,7 @@ proc test_no_hw_watchpoints {} { >> =09"show disable fast watches" >> =20 >> gdb_test "watch ival3 if count > 1" \ >> -=09"Watchpoint \[0-9\]*: ival3.*" \ >> +=09"^watch ival3 if count > 1\r\nWatchpoint \[0-9\]*: ival3.*" \ >> =09"set slow conditional watch" >> =20 >> gdb_test "continue" \ >> @@ -832,7 +842,7 @@ proc test_no_hw_watchpoints {} { >> gdb_test_no_output "delete \$bpnum" "delete watch ival3" >> =20 >> gdb_test "watch ival3 if count > 1 thread 1 " \ >> - "Watchpoint \[0-9\]*: ival3.*" \ >> +=09"watch ival3 if count > 1 thread 1 \r\nWatchpoint \[0-9\]*: ival3.= *" \ >> "set slow condition watch w/thread" >> =20 >> gdb_test_no_output "delete \$bpnum" "delete watch w/condition and t= hread" >>=20