From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id kVYEH/FbYWnSizcAWB0awg (envelope-from ) for ; Fri, 09 Jan 2026 14:50:09 -0500 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=obSnlXFl; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 7B4731E0B6; Fri, 09 Jan 2026 14:50:09 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-2.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,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED 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 C7A2B1E08D for ; Fri, 09 Jan 2026 14:50:06 -0500 (EST) Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 6C5384BA2E28 for ; Fri, 9 Jan 2026 19:50:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6C5384BA2E28 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=obSnlXFl Received: from sonic309-25.consmr.mail.ir2.yahoo.com (sonic309-25.consmr.mail.ir2.yahoo.com [77.238.179.83]) by sourceware.org (Postfix) with ESMTPS id 0D8414BA2E23 for ; Fri, 9 Jan 2026 19:49:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0D8414BA2E23 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 0D8414BA2E23 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=77.238.179.83 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767988144; cv=none; b=IfD4O7cd8cm51vCDxKpWCUWNwb5LRkX6Pa0btOK3T+CaPnF0iBa5URfHAJ5k7jpmLpxPLk0I8cVA0S24GmVMq6X77JP6hCGMQMZiM8GZmB2WKF3YkNOJeCNTqk+2P4gFQQvV3u5L41uhDfDf0aEv/EgifFrAModcKi2pIm1DV60= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767988144; c=relaxed/simple; bh=qZxnBunOxEp/7IUOZjGHweJfKu+Cr0tatGH5GAtzFH8=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=HX4EP0SBFSq+cLgo3D8afX1SoQCLuIcNM3L5EyHoBwW0hF8xZfdE32q5pXo64tLrAU9tIevsn+0KMed7Y98662hqqoEuc8gxvXChEORXtHid1Du18gVc5So3Z+YgJQJyIzaz8TQcFPw82BoHDCyGjtzkL8PJON+nnsGtMejARZ8= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0D8414BA2E23 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.de; s=s2048; t=1767988142; bh=Z7LOYumaCW5xLSDYyqgHWJEmu5kplFoQ2OSh7uaG63g=; h=From:To:Subject:Date:References:From:Subject:Reply-To; b=obSnlXFlOR4w/k2w1iX/3l+VnL1cW8iezD8+XLaXQqJ3F8ZoLyzJvCG1x7hgvl+MRbl/slFCbsZIEdvV2FdkhCyhDruMP4UCPJCGHwCf6cAxYjqc2ThNk/rZQQqSYvN9DrXV8DKlXSE5hYrA2RrA6Rjd+yUOw3Fk8ry2w388U5OS40g3BH6xhNTSswKmH/WfA88/1WN1YTk+HOJmJcV1rSOW6DR9zcCyBGMm5yoHwH3DIdIwLnT2hFuxKIeePourOWmZQd4HXuVLy3oUEaQ7oP2jfEl/PwIleOZdOpZJdj9Zf4FnBJIJSD2dkJS52NzSz1SN27bc87Il0mjCLua7RQ== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1767988142; bh=AqY+EmSABJvHJyWW7kjDWWfJN9QnESJHa6qy7AobMQh=; h=X-Sonic-MF:From:To:Subject:Date:From:Subject; b=ncsqILd7LBiJz+ZY2N62yGt0fQV5yTG65YrmcAHL8fyyLfcP+xU/hq1ZnKN2R6BORCwEUALZJAZOxNZpiywO9/8YLQQ/7kqDMMvYnNwMyr6gMl1WbcQssR5LP4/Ay3PhZeTpICO2qYdg2iWM+QcwzVcue/pkuQNTJQ/nNf8XOW3CIUer5ebiVcPBjWI9ZYXRD06P0WOtD86M/2FkVKkt405pr4wJSrfblnzHYXStMpLUjTSkRatcdX5soQ3qk3OCcp4FjJoJC/DzB4sv8B4Hq2+ZWoo1m4wQ5ATyVf1+XYjQfU1bcyMH+txj9wgqk1ED/rK0+6f2+UE6Bz62D91xdg== X-YMail-OSG: ywZfjP4VM1k67LtlmLb47ODyvDWwZZsiXxqIX1rXvYXlDSI5qgm7qdvCQ7Am2UX 1MZbNDB9fjoMmWj142tknaRFQmZKXOV92laG2_BOrp5fmAngjX2kwVKVemjtOMae1WlxZoapbrci zmXOKrQ2piXvrR2p53l0fwt2.X3R38DQm1LYHBTuGW504Jbkjv4.4WbtBPEWJsIvznpeZzkGZhFo XwC9ur6oCPVkMy2uflWB4VXWRrp0fgP7l6T1hKPd0rOp6f6_FaiIxfi_z3gI63MoqxCSwr8ErQt0 IzLhM7sh006zboYU01eZT8EyxQdmECP8X2Ars24j8s9wrVk971MQg6Fa4_S03QihYNK02u5mIcl6 Gy3fss_dTlg97DQPiMX_3n3tq37n317qTxD7_QsrGYzZsAObYAl4jSJRQkSo8YCSpCWg1FSu5.hK UGpcEAzeaGcygDRKljk1V9YGvxk02i2iEl3mrasz2CEaCqYH.dqrftqy6lFgZ5Xq9URSVnn4gBb7 YJPpaNPh3bZ_we7.mXUNdQio6bQ.o0p81_mlAZSU.roYciqrTtYHwPNwMHACiWQSHka5GDZB9g6S VCtiRmO.vS2s5YP36vTXdjzasOEL8U9_nODhIWvfCcqFYceZvJdmeWSH4mUVBYvKTmcP6kO5NYSL VbNVaFRJNsLn8yUZlPVzdwRgRcPRsZgylW45OpzgZKoIY1h5Duv4i0dD63M8gE4HX1o_Dae1.tZS vpIkjqwHCpN0g1QZdhkQmVqivIAVLu0_RplZVFypXaOSr896wAzSdh_WNPhLOfYjfGSvo9EsXMRN 4LNBESNqRq8DU9V_WXPXzi74oklijmT.KmrM_6HeqBmW07_HibGCf0jVQesY3iy77EosGZ6XziGB j5ms0avQmxvXCcpxObDB1vEyKFlFVFQHjqfXKpBvzSvCVO_OVUCyP9sRp5atM7GV0X.qha8apeWV TFXi8atd9xUOdlVWzsjnhneNCRoQR8HD2K2fHSPy.F6SJAvcBtpikF5lYv7DuOpU8I4BJ6ntcbWU jo4dM6PgxuMuXzKkQE_TewxAnB3f8bYf_8x98aFHIEkJO0GFpEujKU.WmVa6iQWSby1nId0LPn4Z Tfk_SPl0wl6R7sZGoE7b_WaJYGX.BxznzfukjC17azCwBSimk.j2XhMc3DJPDBJZFsgK7vGvkW04 6_2.zcJ0gCWO9TAxpYMmLSa3Hkau6CzyW7kbVxw_OT35X2FJybmKUmlgNmb6El.uzgTzG9NO4Ng9 JtTg6.xrSR6cjITY4F6KZJtLwdn_YJyDXqfF195f1dEZPdtf1T1OQfyRoUez22_GrVQ4pRBVoR_E 0zCPDZ.4DY35kH1i7jIvljgYlDVib1kdJndenzwn20J8XuQhWEzLhLmV_XNM_ZE7mkNnVnYQKll0 KtnICiSGyI7AOk6Z_kIXAPMfyuGRxd3xIXS9_u5KOSgRE82Tx9yoAfdlJ0tkHZdIIEjPeryhNe7w jqJch0EmbRra7cDqhvT4g27uP7vk61Ea7EFHh_X_NbBXYZwEM5tOrl3.w6jlOw3l9EYe1Eu_QNRV JUfrnKORGpkdTn2jPiKXa20BicPostcotkpGC.TXlqLilZu5bkpZNohiHzhQpiUu0sQW27Lr_Od_ dqvr00x2ITHUFii1Get5Nj73LnI.FcxpeuOFvjDX5nW1C_hWaelHfE8fo9PwGrRy2ab7qFJGJfR0 PuUKdW.ilazlLFks2tLRVcIDM9hXoECOEhbgv2SpMeNSvh7vQo4zl2Ai0HonZqWm0V7Aq4pI5Apv xVKw6RGWsoAIjyar9melKn0i07ZNUplowybI6bqd7b2Nm9Cksdt3pvXnWywyAR4.AUeV0m5Uw8Nx dg5sU_djIgHWrBThFslyJSuEqM_OVQZAjqbm3Frozs5lge36If9v4kHlRa5xt7k35Z8d_eKU2vmS 4aVlkh8_wtw74xmVrE2KpznL2ky9irWPL5KYWrngjTBGoCWlHiPLpxE.GCY68k0x..Kl.rPREu.e vvD2han7W4j9l9M_pYx3LX59noZMQOeShfY2Wg6A.IAoZOUvKif7T4D_NKhiHbR_l.3nHhXkvG7g TNGLwGnt1ebGF5oWiyeXDnjbdicd6EB9kzVTtAKR4r7X68EWUSnjVTueTdXApX.39040aLXiySFl 5rz5cdR17UOQlckecL_Qv9.i4SOg2kJPSBtvxIhpiGdOoYkhN1W8Ai.FXgCo.9L90QGmhVOUhgli XciUvMYZivfrtLV3dWIWnXInBOHoPQKMykw-- X-Sonic-MF: X-Sonic-ID: c5071041-3bb8-45f2-a90c-1505b9ef9ab9 Received: from sonic.gate.mail.ne1.yahoo.com by sonic309.consmr.mail.ir2.yahoo.com with HTTP; Fri, 9 Jan 2026 19:49:02 +0000 Received: by hermes--production-ir2-6fcf857f6f-52lzv (Yahoo Inc. Hermes SMTP Server) with ESMTPA ID 2dd03f86413d9bb2b734f69bf63a5a47; Fri, 09 Jan 2026 19:48:56 +0000 (UTC) From: Hannes Domani To: gdb-patches@sourceware.org Subject: [PATCH] Prevent downgrading of hardware watchpoints if possible Date: Fri, 9 Jan 2026 20:48:39 +0100 Message-ID: <20260109194839.1598134-1-ssbssa@yahoo.de> X-Mailer: git-send-email 2.52.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit References: <20260109194839.1598134-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 --- 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 af4de248ab6..13d95325604 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -2293,11 +2293,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 ()); @@ -10716,12 +10715,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..94ef335c77f --- /dev/null +++ b/gdb/testsuite/gdb.base/watchpoint-hw-no-degradation.exp @@ -0,0 +1,38 @@ +# Copyright 2009-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 -1 +} + +if {![runto_main]} { + return -1 +} + +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 a52d4a6742c..c076617d102 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -1546,6 +1546,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; @@ -4122,6 +4123,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 8dc3192f637..77919082fe3 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 @@ -681,6 +688,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 sucessfully. */ + bool m_fetch_lazy_failed : 1; + /* Location of value (if lval). */ union { -- 2.52.0