From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id I/aYDRhzZ2p9RzAAWB0awg (envelope-from ) for ; Mon, 27 Jul 2026 11:02:48 -0400 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=yahoo.de header.i=@yahoo.de header.a=rsa-sha256 header.s=s2048 header.b=cN9zBR07; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 230E71E09E; Mon, 27 Jul 2026 11:02:48 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-5.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 855AF1E099 for ; Mon, 27 Jul 2026 11:02:45 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 11FCF4BB1C11 for ; Mon, 27 Jul 2026 15:02:45 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 11FCF4BB1C11 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=yahoo.de header.i=@yahoo.de header.a=rsa-sha256 header.s=s2048 header.b=cN9zBR07 Received: from sonic308-18.consmr.mail.ir2.yahoo.com (sonic308-18.consmr.mail.ir2.yahoo.com [77.238.178.146]) by sourceware.org (Postfix) with ESMTPS id 49E194BA9004 for ; Mon, 27 Jul 2026 15:02:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 49E194BA9004 Authentication-Results: sourceware.org; dmarc=pass (p=reject dis=none) header.from=yahoo.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=yahoo.de ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 49E194BA9004 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=77.238.178.146 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1785164537; cv=none; b=hyRVvpqb5RVhgcB+8gN00l2cXGJ0Zwt+BhPdgr1aOer/gHkfWiBbCsISxKjhS3ibu9/zj+S5P6JQP9dhrf/yCa1/BKxWGsP6lnsT+eapRZ0kWos52sZ3FpV10Dze4+fu5Z+x8HkCGNnY8mHIruLW+a4JSSgF9zsDHr2PrvKfaw0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1785164537; c=relaxed/simple; bh=/TLYS3BKI7cusFrvBO+SsgvdLWiqJatbaLo+4PckRok=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=qTSs2H/AHExhvxikL9+h5fzAvA86PV8XHMEWk4fubmRInoLL/MiAm0spAI0k+uIksL85W3hrFEJ5g5CzRV2hhKvQAG1SsuRnzkSbGLn6Z+qQ8kTJOSLa3nX/DIO7Kti7F0QJ1NJKOFYSXZGLuKV34rzO06eLti4Av8vhNbNGHBo= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=yahoo.de header.i=@yahoo.de header.a=rsa-sha256 header.s=s2048 header.b=cN9zBR07 DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 49E194BA9004 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.de; s=s2048; t=1785164535; bh=UlS0LCzU27+hD4is8C1Oqsn6J2G7HI3wECSkz7Aeu4o=; h=From:To:Cc:Subject:Date:References:From:Subject:Reply-To; b=cN9zBR07j0g7Eavq3WZsWPX3/CFrc4eBwI4HzTYq5uGoUT3w91S8NF5RNLbzvm7PVEqD/eSFvyok+eEU9/OHUR6c+w8ZQdCOx9cf2/35sBdem4H91TdlewPfyaN1LwHg2z0PLCBCVvf4hYdTh26QZMJEouPC2cGnq26zqYHWvyC8Yze5pe5bCL0dQaOs0YKUqvLmi5RQWWNbolObxF740FQsZNsrEH5MGp0go4ljsj/Fdjge7mucyV9IfC/NeoM9Bb2ATIYSWJdqSea/D45HOgoUxGXLU8KrTR3vP7P8f1q9BnrbX461//GFE6stqLWwVzAlcNDiZVC+V567FaQoxg== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1785164535; bh=xONU41uX3OzMxqY005hrDB0kPw+EklXeOA0l4f7QjcS=; h=X-Sonic-MF:From:To:Subject:Date:From:Subject; b=pqSbPkSpaK1LiQDaOvHBOI7t6VBljTLwz7u6bAfxqmyH4VhdxWwyMm0ZZJu4wjsFzlm1GaNdvfw/bejnGj2g+gtQGmXDZqkZAdDgT5nbic1laul8KEaT1PRxus+W5tfKM2PCrtTusdoN1w2HP6vSV04JIKhDsYWy5Wf4Ovph5joAd0FClGI6ZIqqzfmNlWSH59HuYmcOf6Yzec93DL3TY323O4bppGv+9IZ1lluzYKCi20GANV1KfT3FN5czkkCSpADufXN2+OjvFudY+1vPCxhMHgZ6S//BWcWSADvdrGOG2pjZvdCH8nzq0whCCWCFtN+WwGo3gRuYiomrxt7nsg== X-YMail-OSG: Bz3YyAoVM1kpdtFaQ67fzUu3a74DWJ11anbs.Hm6F0EFnY9Y5wi8p_M2w66UCAq E9bhe_vagWQdwzgMYa1A3x8atM164VwfMz8q1we9IyvfplJ_7CoTi4021uhKlGczMGqk6xtew.CL 6MK3HtogFhFWBI4SrsbmClxxbYrnKQWq4sElRMP6Qq5gaWdIgTqXMq1HaZXYoU5O4jlqmJxOlIkE AXF3hKwop9U3s9FZHJVAM6Wd_uMCDniNYVX50B_4GCoMzDFP18ep5VW5ihlZcXN3YAqsk2zFHI5n OsmDxqoiZd5_dgHQ8x5wxl0uw_KvqHo5HFvgcQPd0gBi3n1X79kinHILp2nv1d_zLABVCUR_jUsY Y3QgkoBdhga8b4zKQv_VxUQpXoI14EuZ_l3a7QbBqrZapQgBjUbwSdk_iyIpEnFVmixubv9QFihm w2MBsYP_FaDnJ1SnbKP9yJa9jdHsbmZC6rzA.cYhGGd81jWErP3_my96JQxK3v7uCrEp2UVQ5iHE 1tEiErfFURLBgDbTlsgR7F8Hb2lkdzQdmweuz2R9CkoJlorX22jo4yZXOVnbmlC_TVzgJPZrGPB7 TDazUV_UKOB8RDhGBQEiapIeZFfA6chfnIOOD7alWtt3eukcVDaTOwmQM7rwmRh70ESN8gOnJUnX SvHx8rzR_Yn6aLhHsvKvFFdkWs_51vOOOE_VHoG90cL8tgrAajwbcMwDiO3ZPIOyRapxhYBScOe7 so2GFQ2rxv6ZTiCYwYIy9PBQiW8IN6WGSGwcgsHPI7z894S_2wXl_wI1YFPdUuCrmL.VSz5lK3hE sTLbvTQLB5cN8bax_3ujqLEaVg1YGnYVlT4zDEV_kw_xB.5yqf5vehBttK4M4pdoDfbFtGufEB3f BOkqA6HnuDGgLCrjmkzI8XMsvYhs88cqWxw5nN.3ONzAODxWdgnL54ZPG3X40C8XmRsIXbvV_RkQ VfImMB8L5PBqYBJf7ijH.tctj1Caucr6q7_.7QiaLFCBpsZEbq3bkwm4osMEIhFF2zZDJCuaimVJ xlvLKHw1HHtX_2YrcUGKOvBtsYayPkwVTHL6V1Rz923Ej_9BNSLM3.8V4Xi10WKffUXluA9Gx6E. pCNEK26qEAMWjFPUtFRRWsKMFDpf1X31nGppxkOqG4BaH1TlCrD4TsCYaKG6oPqPRA8CZ2iMS2zZ Nugfi.1hg5uXnj5C1Q_NPdPhJYM0rX3KmGG2N.YfoALuJNNgN97E94yCaJqoLJjWlMM2TIbr5QYl I1MWEcjw0ZQqov9oErj1AmwPMsDzz3bjOF0kRvdjY2zQB6DMW5buUjxzdh_V87l8ZJXZGQ8U6S00 OzGioGp0YiQMHYgNVtGULSClYbZxXXng9HopbztNqR883IL2DDigMfOgM_Pxf_d_IW3ZuUIbI1N6 TEN6IIoLc9E3SKRCL4BkNh1JJEHanCbOGFTVWtVBnjIiVQZVwVDHz5TAm05oaEC69fDe9LkAe.jq psPNsdO2hsiFe9v5YcJblOUf3Y2n47pywXXZaXzr1NDg8YV82843EjfwOVPp_CawM7kw0jjApBc8 UaszZNhaRa21TF2BJSvyWUze8QwamI81SuO7OoXBvJ5udJbc0uf5xy5d5KZ89mG33hIAGlCtJcXF IcwqSprJ6GJpycMlgZESrTUh.QfJZr60YLLxSCOkZHCqqnBQtFaj9tWee7LN3iUMGvqK03asiZop 5Ex9HtbPMakM7upBgHMKbxUrJCgLWEowphSlHD4FTcJMsrV_U4W8KsD0MDbyFqYezyL6tU5m2FtW _G94unCE5B6mFqbGHdJz42WnIy59IxKlV5YostW6tW126CMGL6R5CwjH1a3m2JRqHyWroii4n5NP n5RqIKLVrOBsB.yP2nT0taB7TARkJtBvB_WlNCVvEKGT_fl5j7C_F1fDl2Sea5UhcFU0ifqmyjZr M6T455TNpadWT9fXYXyDpZVVaNGAPPNoh2qZ0bBP6kASHyeC3jItgoKQp5T0X5.1KYskXjZf5gC2 OhDzGc90NIn48VhyQDejSR7hETEWzWBX3BDfk3UNbaxnfeZO6l6ERQqbP3_ZY5Ej2GzGgutknTo6 mAqLByE0t6Goa.wofIBUPiTaM_jquNLc932KGRTyQUdBFeQJlmF0Y.2.Z_TodmJQKrASDOfs18fM FW0ZvqH.uBrGl8R.KYOgnBvI6j7Q62gPBk8XtZkM3QxyfKD5wTno6AsYXTC5.GVqttrkf871gUs8 iN4A97z7DJ3bm4M_PPAOnZ9JdalSx07Q- X-Sonic-MF: X-Sonic-ID: de79443a-7691-4f63-8506-453a6408072f Received: from sonic.gate.mail.ne1.yahoo.com by sonic308.consmr.mail.ir2.yahoo.com with HTTP; Mon, 27 Jul 2026 15:02:15 +0000 Received: by hermes--production-ir2-676cb4d88b-pxjwb (Yahoo Inc. Hermes SMTP Server) with ESMTPA ID 8bee21d5372c231541f9fe34a4d7bd8d; Mon, 27 Jul 2026 15:02:14 +0000 (UTC) From: Hannes Domani To: gdb-patches@sourceware.org Cc: Guinevere Larsen , Thiago Jung Bauermann Subject: [PATCH v2] Prevent downgrading of hardware watchpoints if possible Date: Mon, 27 Jul 2026 16:57:01 +0200 Message-ID: <20260727150150.1014621-1-ssbssa@yahoo.de> X-Mailer: git-send-email 2.54.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit References: <20260727150150.1014621-1-ssbssa.ref@yahoo.de> 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~public-inbox=simark.ca@sourceware.org The lazy flag of a value can tell us if the value contents are available. But this could be either because it was simply never actually accessed, or it tried to be accessed, and failed. The latter are interesting for watchpoints, the former are not. Currently it only uses lazy values if they are at the head of the value chain, but this is fragile logic, and degrades some watchpoints to software watchpoints where it's actually not necessary. So this adds a new value flag 'm_fetch_lazy_failed' which tells if the watchpoint expression actually tried to access the value and failed. And this is used instead of the value chain location to tell if a lazy value should be used as a watchpoint location. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=27423 Tested-By: Guinevere Larsen Reviewed-by: Thiago Jung Bauermann --- v2: - value.h: fixed typo in comment - watchpoint-hw-no-degradation.exp: fixed copyright year and removed values from top-level returns --- gdb/breakpoint.c | 11 ++-- .../gdb.base/watchpoint-hw-no-degradation.c | 51 +++++++++++++++++++ .../gdb.base/watchpoint-hw-no-degradation.exp | 38 ++++++++++++++ gdb/value.c | 3 ++ gdb/value.h | 12 ++++- 5 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 gdb/testsuite/gdb.base/watchpoint-hw-no-degradation.c create mode 100644 gdb/testsuite/gdb.base/watchpoint-hw-no-degradation.exp diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index e4df4df04a7..462c16df7c5 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -2305,11 +2305,10 @@ update_watchpoint (struct watchpoint *b, bool reparse) /* If it's a memory location, and GDB actually needed its contents to evaluate the expression, then we - must watch it. If the first value returned is - still lazy, that means an error occurred reading it; + must watch it. If an error occurred reading it, watch it anyway in case it becomes readable. */ if (v->lval () == lval_memory - && (v == val_chain[0] || ! v->lazy ())) + && (! v->lazy () || v->fetch_lazy_failed ())) { struct type *vtype = check_typedef (v->type ()); @@ -10708,12 +10707,12 @@ can_use_hardware_watchpoint (const std::vector &vals) if (v->lval () == lval_memory) { - if (v != head && v->lazy ()) + if (v->lazy () && ! v->fetch_lazy_failed ()) /* A lazy memory lvalue in the chain is one that GDB never needed to fetch; we either just used its address (e.g., `a' in `a.b') or we never needed it at all (e.g., `a' - in `a,b'). This doesn't apply to HEAD; if that is - lazy then it was not readable, but watch it anyway. */ + in `a,b'). If it failed to fetch a lazy value, then it + was not readable, so watch it in this case as well. */ ; else { diff --git a/gdb/testsuite/gdb.base/watchpoint-hw-no-degradation.c b/gdb/testsuite/gdb.base/watchpoint-hw-no-degradation.c new file mode 100644 index 00000000000..cfff2a44f90 --- /dev/null +++ b/gdb/testsuite/gdb.base/watchpoint-hw-no-degradation.c @@ -0,0 +1,51 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2026 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 +#include +#include + +int +main (void) +{ + size_t len = sysconf(_SC_PAGESIZE); + + /* Map and unmap memory block to get address. */ + void *p = mmap (0, len, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); + if (p == MAP_FAILED) + { + perror ("mmap"); + return 1; + } + munmap (p, len); + + /* Now memory block at address P is inaccessible. + Remap block at same address, so it becomes accessible again. */ + p = mmap (p, len, PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0); + if (p == MAP_FAILED) + { + perror ("mmap"); + return 1; + } + + *(int *) p = 1; + + return 0; +} diff --git a/gdb/testsuite/gdb.base/watchpoint-hw-no-degradation.exp b/gdb/testsuite/gdb.base/watchpoint-hw-no-degradation.exp new file mode 100644 index 00000000000..9c545e22e2d --- /dev/null +++ b/gdb/testsuite/gdb.base/watchpoint-hw-no-degradation.exp @@ -0,0 +1,38 @@ +# Copyright 2026 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 . + +# Test if watchpoint doesn't degrade to a software watchpoint if part of +# expression isn't accessible at time of watchpoint creation. + +require allow_hw_watchpoint_access_tests + +standard_testfile + +if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} { + return +} + +if {![runto_main]} { + return +} + +gdb_breakpoint [gdb_get_line_number "mmap (p, len"] +gdb_continue_to_breakpoint "mmap" + +gdb_test "eval \"watch *(int *)%p == 0\",p" \ + "Hardware watchpoint $decimal: .*" + +gdb_test "continue" \ + "Old value = .*New value = 0.*" diff --git a/gdb/value.c b/gdb/value.c index 1f6d7949d4d..e4e3e407ddc 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -1552,6 +1552,7 @@ value::copy () const val->m_bitpos = m_bitpos; val->m_bitsize = m_bitsize; val->m_lazy = m_lazy; + val->m_fetch_lazy_failed = m_fetch_lazy_failed; val->m_embedded_offset = embedded_offset (); val->m_pointed_to_offset = m_pointed_to_offset; val->m_modifiable = m_modifiable; @@ -4119,6 +4120,8 @@ value::fetch_lazy () value. */ gdb_assert (m_optimized_out.empty ()); gdb_assert (m_unavailable.empty ()); + /* Will be reset with set_lazy () at the end if successful. */ + m_fetch_lazy_failed = true; if (m_is_zero) { /* Nothing. */ diff --git a/gdb/value.h b/gdb/value.h index 4cc0d7d0902..01a4c00d722 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -138,6 +138,7 @@ struct value m_stack (false), m_is_zero (false), m_in_history (false), + m_fetch_lazy_failed (false), m_type (type_), m_enclosing_type (type_) { @@ -279,7 +280,13 @@ struct value { return m_lazy; } void set_lazy (bool val) - { m_lazy = val; } + { + m_lazy = val; + m_fetch_lazy_failed = false; + } + + bool fetch_lazy_failed () const + { return m_fetch_lazy_failed; } /* If a value represents a C++ object, then the `type' field gives the object's compile-time type. If the object actually belongs to some @@ -689,6 +696,9 @@ struct value /* True if this a value recorded in value history; false otherwise. */ bool m_in_history : 1; + /* True if fetch_lazy () did not finish successfully. */ + bool m_fetch_lazy_failed : 1; + /* Location of value (if lval). */ union { -- 2.54.0