Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Lancelot SIX <lancelot.six@amd.com>
To: Simon Marchi <simon.marchi@polymtl.ca>
Cc: <gdb-patches@sourceware.org>
Subject: Re: [PATCH 2/2] gdb/amd-dbgapi: add basic watchpoint support
Date: Wed, 4 Feb 2026 20:33:32 +0000	[thread overview]
Message-ID: <gvvkzaxpswsa2cwoz753jqrupgczs5td3kpqz6tgja6pkmb34m@kmxxxhzq6ym5> (raw)
In-Reply-To: <20260124051512.731-2-simon.marchi@polymtl.ca>

Hi Simon,

On Sat, Jan 24, 2026 at 12:15:00AM -0500, Simon Marchi wrote:
> Add basic watchpoint support for the amd-dbgapi target.  This means
> placing write watchpoints on globally addressable memory.  More
> complexity will come eventually to allow placing watchpoints on the
> various other address spaces, but that will require adding proper
> support for non-default address spaces first.
> 
> Implementation
> --------------
> 
> I think the implementation is not too surprising, just adding the
> required target methods.  But there are some things worthy of mention:
> 
>  - amd-dbgapi does not support read watchpoints.  If the core attempts
>    to insert a read (or access, which means read/write) watchpoint,
>    amd_dbgapi_target::insert_watchpoint returns an error.
> 
>    If we silently let the beneath target (linux-nat) install the read
>    watchpoint, it would be potentially confusing.  Everything would look
>    fine to the user, but a read from the GPU would not be caught, so it
>    would look like the watchpoint doesn't work.
> 
>    There is a loophole though: read watchpoints created before the
>    runtime is loaded (and therefore the amd-dbgapi target is pushed)
>    will still be inserted.  Only when execution stops, and the user
>    tries to resume again, will the check in
>    amd_dbgapi_target::insert_watchpoint be hit.
> 
>    Another option would be to allow the host read watchpoint to go
>    through, but warn that the reads from the AMD GPU device will not be
>    watched.  We would need to be smart to avoid flooding the user with
>    warnings.  But I decided to upstream the current ROCgdb behavior
>    first, we can always change it later.
> 
>  - When the amd-dbgapi target gets pushed, we create amd-dbgapi
>    watchpoints for any existing hardware write watchpoint location.
> 
>  - When the core asks the target to insert a watchpoint, we ask the
>    target beneath to insert it first.  If the beneath target fails, we
>    return immediately with an error.
> 
>  - When the core asks to remove a watchpoint, we ask the target beneath
>    to to remove it first.  Even if it fails, we still try to remove the
>    amd-dbgapi watchpoint.
> 
>  - When stopping after a watchpoint hit while the "precise-memory"
>    setting is not enabled, it is possible for the wave to stop a few
>    instructions later than the instruction that made the write that
>    triggered the watchpoint.  We print a warning in that case, similar
>    to what we do when a memory violation happens while "precis-memory"
>    is disabled.
> 
> Testing
> -------
> 
>  - Tests precise-memory-warning-watchpoint.exp and
>    watchpoint-at-end-of-shader.exp are more or less brought as-is from
>    downstream ROCgdb.  I modified precise-memory-warning-watchpoint.exp
>    to watch a hipMalloc'ed region instead of a `__device__` global
>    variable.  The latter doesn't work upstream, because we don't yet
>    support the DWARF constructs that describe the variable location.
> 
>  - I added test watchpoint-basic.exp with various simple cases to
>    exercises different code paths added by this patch.
> 
> Differences from downstream ROCgdb
> ----------------------------------
> 
> While extracting this code from ROCgdb, I made a few minor but possibly
> significant (read: erroneous) changes.  Those should be reviewed
> carefully.  I think that some code in ROCgdb was written at a time where
> the amd-dbgapi target was always pushed at the very start of the
> inferior execution, so assumptions were different.
> 
>  - The value type for the `amd_dbgapi_inferior_info::watchpoint_map` map
>    is now a structure, instead of an std::pair, just because it makes
>    the code more readable.
> 
>  - The insert_watchpoint and remove_watchpoint methods (and perhaps
>    others) now assume that if they are called, the runtime is in the
>    "enabled" state.
> 
>  - insert_initial_watchpoints has one more check (loc->owner->type !=
>    bp_hardware_watchpoint), to filter out non-write watchpoints.
>    Otherwise, I think that we could mistakenly insert some write
>    watchpoints for some pre-existing read watchpoints.
> 
>  - Because it is possible for read watchpoints to be created before the
>    target is pushed, remove_watchpoint returns early if it sees that the
>    code asks for the removal of a read watchpoint, instead of asserting
>    "type == hw_write" (this was caught by the new test).
> 
>  - In ROCgdb, remove_watchpoint does:
> 
>      if (addr < it->first || (addr + len) > it->second.first)
>        return 1;
> 
>    I replaced it with some assertions.
> 
>    The first half of this condition should always be true, due to how
>    std::upper_bound works.
> 
>    For the second part: if the watchpoint was created successfully, it
>    is because it did fully cover the requested region (see
>    insert_one_watchpoint).  I don't see why the core would ask us to
>    remove a watchpoint that wasn't successfully inserted.  I am not 100%
>    sure about that one, there might be some edge cases where this is not
>    true.
> 

I can't really see how this would be an issue, and your changes seem a
reasonable assumption to me.  I am happy going with this.

>  - I changed a manual free in stopped_by_watchpoint to a
>    gdb::unique_xmalloc_ptr, even though it changes nothing functionally.
> 
>  - I merged some conditions in amd_dbgapi_target_normal_stop.
> 

Might be worth adding Laurent as co-auther, he did the initial
implementation of this patch.

With that, this looks good to me.  I have tested it against the
downstream testsuite as well, no issue reported there.

Best,
Lancelot.

Approved-by: Lancelot Six <lancelot.six@amd.com>

> Change-Id: Ia15fb7434dc0c142a5a32997ada2e3a163c89f98
> ---
>  gdb/amd-dbgapi-target.c                       | 272 +++++++++++++++-
>  gdb/breakpoint.c                              |   4 +-
>  gdb/breakpoint.h                              |   4 +
>  .../precise-memory-warning-watchpoint.cpp     |  43 +++
>  .../precise-memory-warning-watchpoint.exp     |  52 +++
>  gdb/testsuite/gdb.rocm/rocm-test-utils.h      |  12 +
>  .../gdb.rocm/watchpoint-at-end-of-shader.cpp  |  44 +++
>  .../gdb.rocm/watchpoint-at-end-of-shader.exp  | 114 +++++++
>  gdb/testsuite/gdb.rocm/watchpoint-basic.cpp   |  69 ++++
>  gdb/testsuite/gdb.rocm/watchpoint-basic.exp   | 307 ++++++++++++++++++
>  10 files changed, 918 insertions(+), 3 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.rocm/precise-memory-warning-watchpoint.cpp
>  create mode 100644 gdb/testsuite/gdb.rocm/precise-memory-warning-watchpoint.exp
>  create mode 100644 gdb/testsuite/gdb.rocm/watchpoint-at-end-of-shader.cpp
>  create mode 100644 gdb/testsuite/gdb.rocm/watchpoint-at-end-of-shader.exp
>  create mode 100644 gdb/testsuite/gdb.rocm/watchpoint-basic.cpp
>  create mode 100644 gdb/testsuite/gdb.rocm/watchpoint-basic.exp
> 
> diff --git a/gdb/amd-dbgapi-target.c b/gdb/amd-dbgapi-target.c
> index 471b7a7725ed..4e52683dc55a 100644
> --- a/gdb/amd-dbgapi-target.c
> +++ b/gdb/amd-dbgapi-target.c
> @@ -21,6 +21,7 @@
>  #include "amd-dbgapi-target.h"
>  #include "amdgpu-tdep.h"
>  #include "async-event.h"
> +#include "breakpoint.h"
>  #include "cli/cli-cmds.h"
>  #include "cli/cli-decode.h"
>  #include "cli/cli-style.h"
> @@ -34,6 +35,8 @@
>  #include "solib.h"
>  #include "target.h"
>  
> +#include <map>
> +
>  /* When true, print debug messages relating to the amd-dbgapi target.  */
>  
>  static bool debug_amd_dbgapi = false;
> @@ -227,6 +230,19 @@ struct amd_dbgapi_inferior_info
>  		     struct breakpoint *>
>      breakpoint_map;
>  
> +  /* Data associated to an inserted watchpoint.  */
> +  struct watchpoint_info
> +  {
> +    /* End address of the watched region.  */
> +    CORE_ADDR end_addr;
> +
> +    /* ID returned by amd-dbgapi.  */
> +    amd_dbgapi_watchpoint_id_t id;
> +  };
> +
> +  /* Ordered map of inserted watchpoints.  The key is the start address.  */
> +  std::map<CORE_ADDR, watchpoint_info> watchpoint_map;
> +
>    /* List of pending events the amd-dbgapi target retrieved from the dbgapi.  */
>    std::list<std::pair<ptid_t, target_waitstatus>> wave_events;
>  
> @@ -307,7 +323,12 @@ struct amd_dbgapi_target final : public target_ops
>  					ULONGEST offset, ULONGEST len,
>  					ULONGEST *xfered_len) override;
>  
> +  int insert_watchpoint (CORE_ADDR addr, int len, target_hw_bp_type type,
> +			 expression *cond) override;
> +  int remove_watchpoint (CORE_ADDR addr, int len, target_hw_bp_type type,
> +			 expression *cond) override;
>    bool stopped_by_watchpoint () override;
> +  std::vector<CORE_ADDR> stopped_data_addresses () override;
>  
>    bool stopped_by_sw_breakpoint () override;
>    bool stopped_by_hw_breakpoint () override;
> @@ -711,13 +732,222 @@ amd_dbgapi_target::xfer_partial (enum target_object object, const char *annex,
>    return TARGET_XFER_OK;
>  }
>  
> +/* Ask amd-dbgapi to insert a watchpoint in [ADDR, ADDR + len).
> +
> +   Return 0 on success, 1 on failure.  */
> +
> +static int
> +insert_one_watchpoint (amd_dbgapi_inferior_info *info, CORE_ADDR addr, int len)
> +{
> +  amd_dbgapi_watchpoint_id_t watch_id;
> +
> +  if (amd_dbgapi_set_watchpoint (info->process_id, addr, len,
> +				 AMD_DBGAPI_WATCHPOINT_KIND_STORE_AND_RMW,
> +				 &watch_id)
> +      != AMD_DBGAPI_STATUS_SUCCESS)
> +    return 1;
> +
> +  auto cleanup = make_scope_exit ([&] ()
> +    { amd_dbgapi_remove_watchpoint (watch_id); });
> +
> +  /* A reduced range watchpoint may have been inserted, which would require
> +     additional watchpoints to be inserted to cover the requested range.
> +
> +     For now, verify that the inserted watchpoint covers the requested range
> +     and error out if not.  */
> +  amd_dbgapi_global_address_t adjusted_address;
> +
> +  if (amd_dbgapi_watchpoint_get_info (watch_id,
> +				      AMD_DBGAPI_WATCHPOINT_INFO_ADDRESS,
> +				      sizeof (adjusted_address),
> +				      &adjusted_address)
> +	!= AMD_DBGAPI_STATUS_SUCCESS
> +      || adjusted_address > addr)
> +    return 1;
> +
> +  amd_dbgapi_size_t adjusted_size;
> +
> +  if (amd_dbgapi_watchpoint_get_info (watch_id,
> +				      AMD_DBGAPI_WATCHPOINT_INFO_SIZE,
> +				      sizeof (adjusted_size), &adjusted_size)
> +	!= AMD_DBGAPI_STATUS_SUCCESS
> +      || (adjusted_address + adjusted_size) < (addr + len))
> +    return 1;
> +
> +  using wp_info_t = amd_dbgapi_inferior_info::watchpoint_info;
> +
> +  if (!(info->watchpoint_map.emplace (addr, wp_info_t {addr + len, watch_id})
> +	.second))
> +    return 1;
> +
> +  cleanup.release ();
> +  return 0;
> +}
> +
> +/* Insert watchpoints for all existing watchpoint locations associated to
> +   the program space of INFO.  */
> +
> +static void
> +insert_initial_watchpoints (amd_dbgapi_inferior_info *info)
> +{
> +  gdb_assert (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS);
> +
> +  for (bp_location *loc : all_bp_locations ())
> +    {
> +      /* Filter out other program spaces.  */
> +      if (loc->pspace != info->inf->pspace)
> +	continue;
> +
> +      /* Filter out non-hardware watchpoints.  */
> +      if (loc->loc_type != bp_loc_hardware_watchpoint)
> +	continue;
> +
> +      /* Filter out non-write watchpoints (access/read watchpoints might have
> +	 been created before the runtime got loaded).  */
> +      if (loc->owner->type != bp_hardware_watchpoint)
> +	continue;
> +
> +      if (insert_one_watchpoint (info, loc->address, loc->length) != 0)
> +	warning (_("Failed to insert existing watchpoint after loading "
> +		   "runtime."));
> +    }
> +}
> +
> +int
> +amd_dbgapi_target::insert_watchpoint (CORE_ADDR addr, int len,
> +				      target_hw_bp_type type, expression *cond)
> +{
> +  amd_dbgapi_inferior_info &info
> +    = get_amd_dbgapi_inferior_info (current_inferior ());
> +
> +  /* The amd-dbgapi target is not pushed when the runtime is not active.  */
> +  gdb_assert (info.runtime_state == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS);
> +
> +  if (type != hw_write)
> +    {
> +      /* We only allow write watchpoints when GPU debugging is active.  */
> +      return 1;
> +    }
> +
> +  if (int ret = beneath ()->insert_watchpoint (addr, len, type, cond);
> +      ret != 0)
> +    return ret;
> +
> +  if (int ret = insert_one_watchpoint (&info, addr, len);
> +      ret != 0)
> +    {
> +      /* We failed to insert the GPU watchpoint, so remove the CPU watchpoint
> +	 before returning an error.  */
> +      beneath ()->remove_watchpoint (addr, len, type, cond);
> +      return ret;
> +    }
> +
> +  return 0;
> +}
> +
> +int
> +amd_dbgapi_target::remove_watchpoint (CORE_ADDR addr, int len,
> +				      target_hw_bp_type type,
> +				      expression *cond)
> +{
> +  amd_dbgapi_inferior_info &info
> +    = get_amd_dbgapi_inferior_info (current_inferior ());
> +
> +  /* The amd-dbgapi target is not pushed when the runtime is not active.  */
> +  gdb_assert (info.runtime_state == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS);
> +
> +  /* Try to remove the amd-dbgapi watchpoint even if the removal fails for the
> +     target beneath.  */
> +  int ret = beneath ()->remove_watchpoint (addr, len, type, cond);
> +
> +  /* We don't allow non-write watchpoints (see the insert_watchpoints method)
> +     when the runtime is enabled (i.e. when the amd-dbgapi target is pushed).
> +     But there is a loophole: non-write watchpoints can still be created by the
> +     user before the runtime is enabled and the amd-dbgapi target is pushed.
> +     In that case, there won't be an amd-dbgapi watchpoint to remove, so just
> +     return.  */
> +  if (type != hw_write)
> +    return ret;
> +
> +  /* Find the watchpoint id for the [addr, addr + len) range.  */
> +  auto it = info.watchpoint_map.upper_bound (addr);
> +  if (it == info.watchpoint_map.begin ())
> +    return 1;
> +
> +  std::advance (it, -1);
> +
> +  /* Not a reference, so that we can reference wp_info after erasing *it.  */
> +  const auto [start_addr, wp_info] = *it;
> +
> +  /* Since upper_bound finds the first element greater than ADDR, the previous
> +     element has to be less than or equal to ADDR.  */
> +  gdb_assert (start_addr <= addr);
> +
> +  /* In insert_one_watchpoint, we ensured that the inserted watchpoint fully
> +     covered the requested range.  It should be the same here.  */
> +  gdb_assert (addr + len <= wp_info.end_addr);
> +
> +  info.watchpoint_map.erase (it);
> +  if (amd_dbgapi_remove_watchpoint (wp_info.id) != AMD_DBGAPI_STATUS_SUCCESS)
> +    return 1;
> +
> +  return ret;
> +}
> +
>  bool
>  amd_dbgapi_target::stopped_by_watchpoint ()
>  {
>    if (!ptid_is_gpu (inferior_ptid))
>      return beneath ()->stopped_by_watchpoint ();
>  
> -  return false;
> +  amd_dbgapi_watchpoint_list_t watchpoints;
> +  if (amd_dbgapi_wave_get_info (get_amd_dbgapi_wave_id (inferior_ptid),
> +				AMD_DBGAPI_WAVE_INFO_WATCHPOINTS,
> +				sizeof (watchpoints), &watchpoints)
> +      != AMD_DBGAPI_STATUS_SUCCESS)
> +    return false;
> +
> +  /* Ensure watchpoints.watchpoint_ids is freed on exit.  */
> +  gdb::unique_xmalloc_ptr<amd_dbgapi_watchpoint_id_t>
> +    watchpoint_ids_holder (watchpoints.watchpoint_ids);
> +
> +  return watchpoints.count != 0;
> +}
> +
> +std::vector<CORE_ADDR>
> +amd_dbgapi_target::stopped_data_addresses ()
> +{
> +  amd_dbgapi_inferior_info &info
> +    = get_amd_dbgapi_inferior_info (current_inferior ());
> +
> +  if (!ptid_is_gpu (inferior_ptid))
> +    return beneath ()->stopped_data_addresses ();
> +
> +  amd_dbgapi_watchpoint_list_t watchpoints = {};
> +  if (amd_dbgapi_wave_get_info (get_amd_dbgapi_wave_id (inferior_ptid),
> +				AMD_DBGAPI_WAVE_INFO_WATCHPOINTS,
> +				sizeof (watchpoints), &watchpoints)
> +      != AMD_DBGAPI_STATUS_SUCCESS)
> +    return {};
> +
> +  /* Ensure watchpoints.watchpoint_ids is freed on exit.  */
> +  gdb::unique_xmalloc_ptr<amd_dbgapi_watchpoint_id_t>
> +    watchpoint_ids_holder (watchpoints.watchpoint_ids);
> +
> +  std::vector<CORE_ADDR> watch_addr_hit;
> +  for (amd_dbgapi_watchpoint_id_t watch_id
> +       : gdb::make_array_view (watchpoints.watchpoint_ids, watchpoints.count))
> +    {
> +      auto it = std::find_if (info.watchpoint_map.begin (),
> +			      info.watchpoint_map.end (),
> +			      [watch_id] (auto &wp)
> +				{ return wp.second.id == watch_id; });
> +
> +      if (it != info.watchpoint_map.end ())
> +	watch_addr_hit.push_back (it->first);
> +    }
> +
> +  return watch_addr_hit;
>  }
>  
>  void
> @@ -1031,9 +1261,12 @@ dbgapi_notifier_handler (int err, gdb_client_data client_data)
>  	case AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS:
>  	  gdb_assert (info.runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
>  	  info.runtime_state = runtime_state;
> +
>  	  amd_dbgapi_debug_printf ("pushing amd-dbgapi target");
>  	  info.inf->push_target (&the_amd_dbgapi_target);
>  
> +	  insert_initial_watchpoints (&info);
> +
>  	  /* The underlying target will already be async if we are running, but not if
>  	     we are attaching.  */
>  	  if (info.inf->process_target ()->is_async_p ())
> @@ -2297,6 +2530,42 @@ Warning: precise memory violation signal reporting is not enabled, reported\n\
>  location may not be accurate.  See \"show amdgpu precise-memory\".\n"));
>  }
>  
> +/* Observer callback for normal_stop.  Warn the user if a hardware watchpoint
> +   was hit but precise memory is not enabled.  */
> +
> +static void
> +amd_dbgapi_target_normal_stop (bpstat *bs_list, int print_frame)
> +{
> +  if (bs_list == nullptr
> +      || !print_frame
> +      || !ptid_is_gpu (inferior_thread ()->ptid))
> +    return;
> +
> +  amd_dbgapi_inferior_info &info
> +    = get_amd_dbgapi_inferior_info (current_inferior ());
> +
> +  if (info.process_id == AMD_DBGAPI_PROCESS_NONE
> +      || info.precise_memory.enabled)
> +    return;
> +
> +  bool found_hardware_watchpoint = false;
> +
> +  for (bpstat *bs = bs_list; bs != nullptr; bs = bs->next)
> +    if (bs->breakpoint_at != nullptr
> +	&& is_hardware_watchpoint (bs->breakpoint_at))
> +      {
> +	found_hardware_watchpoint = true;
> +	break;
> +      }
> +
> +  if (!found_hardware_watchpoint)
> +    return;
> +
> +  gdb_printf (_("\
> +Warning: precise memory signal reporting is not enabled, watchpoint stop\n\
> +location may not be accurate.  See \"show amdgpu precise-memory\".\n"));
> +}
> +
>  /* Style for some kinds of messages.  */
>  
>  static cli_style_option fatal_error_style
> @@ -2529,6 +2798,7 @@ INIT_GDB_FILE (amd_dbgapi_target)
>    gdb::observers::inferior_exit.attach (amd_dbgapi_inferior_exited, "amd-dbgapi");
>    gdb::observers::inferior_pre_detach.attach (amd_dbgapi_inferior_pre_detach, "amd-dbgapi");
>    gdb::observers::thread_deleted.attach (amd_dbgapi_thread_deleted, "amd-dbgapi");
> +  gdb::observers::normal_stop.attach (amd_dbgapi_target_normal_stop, "amd-dbgapi");
>  
>    add_basic_prefix_cmd ("amdgpu", no_class,
>  			_("Generic command for setting amdgpu flags."),
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index a4ccad32a8b9..da99ec27e19f 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -2016,9 +2016,9 @@ is_breakpoint (const struct breakpoint *bpt)
>  	  || bpt->type == bp_dprintf);
>  }
>  
> -/* Return true if BPT is of any hardware watchpoint kind.  */
> +/* See breakpoint.h.  */
>  
> -static bool
> +bool
>  is_hardware_watchpoint (const struct breakpoint *bpt)
>  {
>    return (bpt->type == bp_hardware_watchpoint
> diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
> index 0d9111ba92e9..6b5dbcfe8a3c 100644
> --- a/gdb/breakpoint.h
> +++ b/gdb/breakpoint.h
> @@ -1085,6 +1085,10 @@ struct watchpoint : public breakpoint
>  
>  extern bool is_breakpoint (const struct breakpoint *bpt);
>  
> +/* Return true if BPT is of any hardware watchpoint kind.  */
> +
> +extern bool is_hardware_watchpoint (const struct breakpoint *bpt);
> +
>  /* Return true if BPT is of any watchpoint kind, hardware or
>     software.  */
>  
> diff --git a/gdb/testsuite/gdb.rocm/precise-memory-warning-watchpoint.cpp b/gdb/testsuite/gdb.rocm/precise-memory-warning-watchpoint.cpp
> new file mode 100644
> index 000000000000..dfa50be4b0da
> --- /dev/null
> +++ b/gdb/testsuite/gdb.rocm/precise-memory-warning-watchpoint.cpp
> @@ -0,0 +1,43 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2021-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 <http://www.gnu.org/licenses/>.  */
> +
> +#include <hip/hip_runtime.h>
> +
> +#include "rocm-test-utils.h"
> +
> +__global__ void
> +kernel (int *ptr)
> +{
> +  for (int i = 0; i < 1000; ++i)
> +    (*ptr)++;
> +}
> +
> +int *global_ptr;
> +
> +int
> +main (int argc, char* argv[])
> +{
> +  CHECK (hipMalloc (&global_ptr, sizeof (int)));
> +  CHECK (hipMemset (global_ptr, 0, sizeof (int)));
> +
> +  /* Break here.  */
> +  hipLaunchKernelGGL (kernel, dim3 (1), dim3 (1), 0, 0, global_ptr);
> +  CHECK (hipDeviceSynchronize ());
> +
> +  CHECK (hipFree (global_ptr));
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.rocm/precise-memory-warning-watchpoint.exp b/gdb/testsuite/gdb.rocm/precise-memory-warning-watchpoint.exp
> new file mode 100644
> index 000000000000..9f8dac68047b
> --- /dev/null
> +++ b/gdb/testsuite/gdb.rocm/precise-memory-warning-watchpoint.exp
> @@ -0,0 +1,52 @@
> +# Copyright 2021-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 <http://www.gnu.org/licenses/>.
> +
> +# Test that when "amdgpu precise-memory" is off, hitting a watchpoint shows a
> +# warning about the stop location maybe being inaccurate.
> +
> +load_lib rocm.exp
> +
> +require allow_hipcc_tests
> +
> +if { ![istarget "*-linux*"] } then {
> +    continue
> +}
> +
> +standard_testfile .cpp
> +
> +if {[build_executable "failed to prepare" $testfile $srcfile {debug hip}]} {
> +    return
> +}
> +
> +proc do_test { } {
> +    clean_restart
> +    gdb_load $::binfile
> +
> +    with_rocm_gpu_lock {
> +	if {![runto kernel allow-pending qualified]} {
> +	    fail "can't run to main"
> +	    return
> +	}
> +	gdb_test "watch *((int *) global_ptr)" \
> +	    "Hardware watchpoint $::decimal: .*" \
> +	    "insert watchpoint"
> +
> +	gdb_test "continue" \
> +	    "hit Hardware watchpoint $::decimal.*Warning: precise memory signal reporting is not enabled.*" \
> +	    "continue to watchpoint"
> +    }
> +}
> +
> +do_test
> diff --git a/gdb/testsuite/gdb.rocm/rocm-test-utils.h b/gdb/testsuite/gdb.rocm/rocm-test-utils.h
> index 70d232b873b8..cbb1f6544617 100644
> --- a/gdb/testsuite/gdb.rocm/rocm-test-utils.h
> +++ b/gdb/testsuite/gdb.rocm/rocm-test-utils.h
> @@ -37,4 +37,16 @@
>      }									\
>    while (0)
>  
> +/* Ensure that all memory operations are completed before continuing,
> +   even when "precise-memory" is off.  */
> +
> +#define WAIT_MEM							\
> +  asm volatile (".if .amdgcn.gfx_generation_number < 10\n"		\
> +		"  s_waitcnt 0\n"					\
> +		".elseif .amdgcn.gfx_generation_number < 11\n"		\
> +		"  s_waitcnt_vscnt null, 0\n"				\
> +		".else\n"						\
> +		"  s_wait_idle\n"					\
> +		".endif")
> +
>  #endif /* ROCM_TEST_UTILS_H */
> diff --git a/gdb/testsuite/gdb.rocm/watchpoint-at-end-of-shader.cpp b/gdb/testsuite/gdb.rocm/watchpoint-at-end-of-shader.cpp
> new file mode 100644
> index 000000000000..e25c93e78489
> --- /dev/null
> +++ b/gdb/testsuite/gdb.rocm/watchpoint-at-end-of-shader.cpp
> @@ -0,0 +1,44 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2024-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 <http://www.gnu.org/licenses/>.  */
> +
> +#include <hip/hip_runtime.h>
> +
> +#include "rocm-test-utils.h"
> +
> +__global__ void
> +set_val (int *p, int v)
> +{
> +  *p = v;
> +}
> +
> +int
> +main ()
> +{
> +  int *v;
> +  CHECK (hipMalloc (&v, sizeof (*v)));
> +
> +  /* First dispatch to initialize the memory.  */
> +  set_val<<<1, 1>>> (v, 64);
> +  CHECK (hipDeviceSynchronize ());
> +
> +  /* Break here.  */
> +  set_val<<<1, 1>>> (v, 8);
> +
> +  CHECK (hipDeviceSynchronize ());
> +
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.rocm/watchpoint-at-end-of-shader.exp b/gdb/testsuite/gdb.rocm/watchpoint-at-end-of-shader.exp
> new file mode 100644
> index 000000000000..ff233c8b26a6
> --- /dev/null
> +++ b/gdb/testsuite/gdb.rocm/watchpoint-at-end-of-shader.exp
> @@ -0,0 +1,114 @@
> +# Copyright 2024-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 <http://www.gnu.org/licenses/>.
> +
> +# This test checks that a write watchpoint is reported to the debugger
> +# when the memory is modified by the last statement of a shader.
> +
> +load_lib rocm.exp
> +
> +require allow_hipcc_tests
> +
> +standard_testfile .cpp
> +
> +if {[build_executable "failed to prepare" $testfile $srcfile {debug hip}]} {
> +    return
> +}
> +
> +# This test is known to fail for some architectures when precise memory is
> +# not enabled.  This proc finds out if the current target is expected to have
> +# a fail or not.
> +proc target_has_xfail {} {
> +    # Check for targets where this test will fail without precise memory.
> +    set targets [find_amdgpu_devices]
> +    if { [llength $targets] == 0} {
> +	# Can't determine GPU type, don't set up xfail.  The test will probably
> +	# not run correctly anyway.
> +	return 0
> +    }
> +
> +    # The test will run on GPU-0, so it should be the first of the list.
> +    set target [lindex $targets 0]
> +
> +    # Extract the target family by removing the last 2 chars from the target
> +    # gfx number.
> +    set target_family [string range $target 0 end-2]
> +    verbose -log "Target family: $target_family"
> +    return [expr {[lsearch -exact {gfx10 gfx11 gfx12} $target_family] != -1}]
> +}
> +
> +proc do_test {precise_memory has_xfail} {
> +    clean_restart
> +    gdb_load $::binfile
> +
> +    with_rocm_gpu_lock {
> +	if {![runto [gdb_get_line_number "Break here."] allow-pending]} {
> +	    return
> +	}
> +
> +	gdb_test "p *v" "= 64"
> +	gdb_test "watch -l *v" "Hardware watchpoint $::decimal: -location \\*v"
> +
> +	if {$precise_memory} {
> +	    # For architectures that does not support precise memory, a warning
> +	    # will be displayed.
> +	    gdb_test "set amdgpu precise-memory $precise_memory" \
> +		"(warning: AMDGPU precise memory access reporting could not be enabled\\.)?"
> +	}
> +
> +	if { !$precise_memory && $has_xfail } {
> +	    setup_xfail "*-*-*"
> +	}
> +	gdb_test "continue" \
> +	    [multi_line "Switching to thread $::decimal, lane 0.*" \
> +		"" \
> +		"Thread $::decimal \".*\" hit Hardware watchpoint $::decimal: -location \\*v" \
> +		"" \
> +		"Old value = 64" \
> +		"New value = 8" \
> +		".*"]
> +    }
> +}
> +
> +set has_xfail [target_has_xfail]
> +
> +# First check if we support precise-memory.
> +set supports_precise_memory 0
> +clean_restart
> +gdb_load $::binfile
> +with_rocm_gpu_lock {
> +    if {![runto_main]} {
> +	return
> +    }
> +
> +    gdb_test_multiple "set amdgpu precise-memory on" "" {
> +	-re -wrap "warning: AMDGPU precise memory access reporting could not be enabled\\." {
> +	    set supports_precise_memory 0
> +	    pass $gdb_test_name
> +	}
> +	-re -wrap "^" {
> +	    set supports_precise_memory 1
> +	    pass $gdb_test_name
> +	}
> +    }
> +}
> +
> +foreach_with_prefix precise_memory {on off} {
> +    if { $precise_memory && !$supports_precise_memory } {
> +	unsupported "target does not support precise memory"
> +	continue
> +    }
> +
> +    do_test $precise_memory $has_xfail
> +}
> diff --git a/gdb/testsuite/gdb.rocm/watchpoint-basic.cpp b/gdb/testsuite/gdb.rocm/watchpoint-basic.cpp
> new file mode 100644
> index 000000000000..a89f33678f4b
> --- /dev/null
> +++ b/gdb/testsuite/gdb.rocm/watchpoint-basic.cpp
> @@ -0,0 +1,69 @@
> +/* 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 <http://www.gnu.org/licenses/>.  */
> +
> +#include <hip/hip_runtime.h>
> +
> +#include "rocm-test-utils.h"
> +
> +__global__ void
> +kernel (int *val1, int *val2)
> +{
> +  *val1 += 10;
> +  WAIT_MEM;
> +  *val2 += 100;
> +  WAIT_MEM;
> +  *val1 += 20;
> +  WAIT_MEM;
> +  *val2 += 200;
> +  WAIT_MEM;
> +
> +  /* Some devices that don't support "precise memory" miss watchpoints when
> +     they would trigger near the end of the kernel.  Execute a bunch of sleeps
> +     to make sure this doesn't happen.  Just a handful of instructions should
> +     be enough, but this executes quickly anyway.  */
> +  for (int i = 0; i < 100000; ++i)
> +    __builtin_amdgcn_s_sleep (8);
> +}
> +
> +/* Global pointers for the test to watch.  */
> +int *global_ptr1;
> +int *global_ptr2;
> +int host_global = 5;
> +
> +int
> +main ()
> +{
> +  /* Break before runtime load.  */
> +  CHECK (hipMalloc (&global_ptr1, sizeof (int)));
> +  CHECK (hipMalloc (&global_ptr2, sizeof (int)));
> +  CHECK (hipMemset (global_ptr1, 0, sizeof (int)));
> +  CHECK (hipMemset (global_ptr2, 0, sizeof (int)));
> +
> +  /* Break after malloc.  */
> +  kernel<<<1, 1>>> (global_ptr1, global_ptr2);
> +  CHECK (hipDeviceSynchronize ());
> +
> +  host_global += 12;
> +
> +  /* Break before second launch.  */
> +  kernel<<<1, 1>>> (global_ptr1, global_ptr2);
> +  CHECK (hipDeviceSynchronize ());
> +
> +  CHECK (hipFree (global_ptr1));
> +  CHECK (hipFree (global_ptr2));
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.rocm/watchpoint-basic.exp b/gdb/testsuite/gdb.rocm/watchpoint-basic.exp
> new file mode 100644
> index 000000000000..cd4b9c68f58a
> --- /dev/null
> +++ b/gdb/testsuite/gdb.rocm/watchpoint-basic.exp
> @@ -0,0 +1,307 @@
> +# 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 <http://www.gnu.org/licenses/>.
> +
> +# Basic watchpoint tests for AMD GPU targets.
> +
> +load_lib rocm.exp
> +
> +require allow_hipcc_tests
> +
> +standard_testfile .cpp
> +
> +if {[build_executable "failed to prepare" $testfile $srcfile {debug hip}]} {
> +    return
> +}
> +
> +proc continue_to_watchpoint_hit { old_value new_value test } {
> +    gdb_test "continue" \
> +	[multi_line \
> +	    "hit Hardware watchpoint $::decimal:.*" \
> +	    "" \
> +	    "Old value = $old_value" \
> +	    "New value = $new_value" \
> +	    ".*"] \
> +	$test
> +}
> +
> +# Test inserting a watchpoint on a host variable before the runtime loads, and
> +# hitting hit after the runtime loads.
> +
> +proc_with_prefix test_host_watchpoint_before_runtime_load {} {
> +    clean_restart $::testfile
> +
> +    with_rocm_gpu_lock {
> +	if {![runto [gdb_get_line_number "Break before runtime load"]]} {
> +	    return
> +	}
> +
> +	gdb_test "watch host_global" \
> +	    "Hardware watchpoint $::decimal: .*" \
> +	    "set watchpoint on host_global"
> +
> +	continue_to_watchpoint_hit 5 17 "continue to watchpoint hit"
> +
> +	gdb_test "continue" \
> +	    "Inferior 1 .* exited normally.*" \
> +	    "continue to end"
> +    }
> +}
> +
> +# Test inserting a watchpoint on a host variable after the runtime loads and
> +# hitting hit.
> +
> +proc_with_prefix test_host_watchpoint_after_runtime_load {} {
> +    clean_restart $::testfile
> +
> +    with_rocm_gpu_lock {
> +	if {![runto [gdb_get_line_number "Break after malloc"]]} {
> +	    return
> +	}
> +
> +	gdb_test "watch host_global" \
> +	    "Hardware watchpoint $::decimal: .*" \
> +	    "set watchpoint on host_global"
> +
> +	continue_to_watchpoint_hit 5 17 "continue to watchpoint hit"
> +
> +	gdb_test "continue" \
> +	    "Inferior 1 .* exited normally.*" \
> +	    "continue to end"
> +    }
> +}
> +
> +# Test inserting a watchpoint before the kernel is launched, then hitting
> +# it when the kernel runs.
> +
> +proc_with_prefix test_watchpoint_before_kernel {} {
> +    clean_restart $::testfile
> +
> +    with_rocm_gpu_lock {
> +	if {![runto [gdb_get_line_number "Break after malloc"]]} {
> +	    return
> +	}
> +
> +	gdb_test "watch *((int *) global_ptr1)" \
> +	    "Hardware watchpoint $::decimal: .*" \
> +	    "set watchpoint on *ptr1"
> +
> +	continue_to_watchpoint_hit 0 10 "continue to watchpoint hit 1"
> +	continue_to_watchpoint_hit 10 30 "continue to watchpoint hit 2"
> +	continue_to_watchpoint_hit 30 40 "continue to watchpoint hit 3"
> +	continue_to_watchpoint_hit 40 60 "continue to watchpoint hit 4"
> +
> +	gdb_test "continue" \
> +	    "Inferior 1 .* exited normally.*" \
> +	    "continue to end"
> +    }
> +}
> +
> +# Test inserting a watchpoint while stopped inside the kernel.
> +
> +proc_with_prefix test_watchpoint_inside_kernel {} {
> +    clean_restart $::testfile
> +
> +    with_rocm_gpu_lock {
> +	if {![runto_main]} {
> +	    return
> +	}
> +
> +	gdb_breakpoint "kernel" allow-pending temporary
> +	gdb_test "continue" \
> +	    "hit Temporary breakpoint.*, kernel .*" \
> +	    "continue to kernel"
> +
> +	gdb_test "watch *((int *) global_ptr2)" \
> +	    "Hardware watchpoint $::decimal: .*" \
> +	    "set watchpoint on *ptr2 from inside kernel"
> +
> +	continue_to_watchpoint_hit 0 100 "continue to watchpoint hit 1"
> +	continue_to_watchpoint_hit 100 300 "continue to watchpoint hit 2"
> +	continue_to_watchpoint_hit 300 400 "continue to watchpoint hit 3"
> +	continue_to_watchpoint_hit 400 600 "continue to watchpoint hit 4"
> +
> +	gdb_test "continue" \
> +	    "Inferior 1 .* exited normally.*" \
> +	    "continue to end"
> +    }
> +}
> +
> +# Test removing a watchpoint while stopped inside the kernel, then
> +# continuing to the end.
> +
> +proc_with_prefix test_remove_watchpoint_inside_kernel {} {
> +    clean_restart $::testfile
> +
> +    with_rocm_gpu_lock {
> +	if {![runto [gdb_get_line_number "Break after malloc"]]} {
> +	    return
> +	}
> +
> +	gdb_test "watch *((int *) global_ptr1)" \
> +	    "Hardware watchpoint $::decimal: .*" \
> +	    "set watchpoint"
> +
> +	continue_to_watchpoint_hit 0 10 "continue to watchpoint hit"
> +	gdb_test "with confirm off -- delete" "" "delete all breakpoints"
> +
> +	gdb_test "continue" \
> +	    "Inferior 1 .* exited normally.*" \
> +	    "continue to end"
> +    }
> +}
> +
> +# Test watchpoints on different memory locations.
> +
> +proc_with_prefix test_multiple_watchpoints {} {
> +    clean_restart $::testfile
> +
> +    with_rocm_gpu_lock {
> +	if {![runto [gdb_get_line_number "Break after malloc"]]} {
> +	    return
> +	}
> +
> +	gdb_test "watch *((int *) global_ptr1)" \
> +	    "Hardware watchpoint $::decimal: .*" \
> +	    "set watchpoint on *ptr1"
> +
> +	gdb_test "watch *((int *) global_ptr2)" \
> +	    "Hardware watchpoint $::decimal: .*" \
> +	    "set watchpoint on *ptr2"
> +
> +	continue_to_watchpoint_hit 0 10 "continue to watchpoint hit 1"
> +	continue_to_watchpoint_hit 0 100 "continue to watchpoint hit 2"
> +	continue_to_watchpoint_hit 10 30 "continue to watchpoint hit 3"
> +	continue_to_watchpoint_hit 100 300 "continue to watchpoint hit 4"
> +	continue_to_watchpoint_hit 30 40 "continue to watchpoint hit 5"
> +	continue_to_watchpoint_hit 300 400 "continue to watchpoint hit 6"
> +	continue_to_watchpoint_hit 40 60 "continue to watchpoint hit 7"
> +	continue_to_watchpoint_hit 400 600 "continue to watchpoint hit 8"
> +
> +	gdb_test "continue" \
> +	    "Inferior 1 .* exited normally.*" \
> +	    "continue to end"
> +    }
> +}
> +
> +# Test disabling and enabling watchpoints.
> +
> +proc_with_prefix test_disable_enable_watchpoint {} {
> +    clean_restart $::testfile
> +
> +    with_rocm_gpu_lock {
> +	if {![runto [gdb_get_line_number "Break after malloc"]]} {
> +	    return
> +	}
> +
> +	set wp1_num -1
> +	set wp2_num -2
> +
> +	gdb_test_multiple "watch *((int *) global_ptr1)" "set watchpoint on *ptr1" {
> +	    -re -wrap "Hardware watchpoint ($::decimal): .*" {
> +		set wp1_num $expect_out(1,string)
> +		pass $gdb_test_name
> +	    }
> +	}
> +
> +	gdb_test_multiple "watch *((int *) global_ptr2)" "set watchpoint on *ptr2" {
> +	    -re -wrap "Hardware watchpoint ($::decimal): .*" {
> +		set wp2_num $expect_out(1,string)
> +		pass $gdb_test_name
> +	    }
> +	}
> +
> +	continue_to_watchpoint_hit 0 10 "continue to watchpoint hit 1"
> +
> +	gdb_test_no_output "disable $wp1_num" "disable watchpoint"
> +
> +	continue_to_watchpoint_hit 0 100 "continue to watchpoint hit 2"
> +	continue_to_watchpoint_hit 100 300 "continue to watchpoint hit 3"
> +
> +	gdb_test_no_output "enable $wp1_num" "enable wp1"
> +	gdb_test_no_output "disable $wp2_num" "disable wp2"
> +
> +	continue_to_watchpoint_hit 30 40 "continue to watchpoint hit 4"
> +	continue_to_watchpoint_hit 40 60 "continue to watchpoint hit 5"
> +
> +	gdb_test_no_output "enable $wp2_num" "enable wp2"
> +
> +	continue_to_watchpoint_hit 400 600 "continue to watchpoint hit 6"
> +
> +	gdb_test "continue" \
> +	    "Inferior 1 .* exited normally.*" \
> +	    "continue to end"
> +    }
> +}
> +
> +# Test that read and access watchpoints are rejected when GPU debugging is
> +# active.  The amd-dbgapi target only supports write watchpoints.  WP_CMD
> +# must either be "rwatch" or "awatch".
> +
> +proc_with_prefix test_non_write_watchpoint_rejected { wp_cmd } {
> +    clean_restart $::testfile
> +
> +    with_rocm_gpu_lock {
> +	if {![runto [gdb_get_line_number "Break after malloc"]]} {
> +	    return
> +	}
> +
> +	gdb_test "$wp_cmd host_global" \
> +	    "Hardware .*watchpoint $::decimal: .*" \
> +	    "set watchpoint"
> +
> +	gdb_test "continue" \
> +	    "Could not insert hardware watchpoint $::decimal.*Command aborted\\." \
> +	    "watchpoint rejected on resume"
> +    }
> +}
> +
> +# Test setting a read/access watchpoint before the GPU runtime loads.  The
> +# watchpoint is set successfully on the CPU, but when the runtime loads,
> +# we expect some behavior (error or warning) since the GPU only supports
> +# write watchpoints.  WP_CMD must either be "rwatch" or "awatch".
> +
> +proc_with_prefix test_non_write_watchpoint_before_runtime_load { wp_cmd } {
> +    clean_restart $::testfile
> +
> +    with_rocm_gpu_lock {
> +	if {![runto [gdb_get_line_number "Break before runtime load"]]} {
> +	    return
> +	}
> +
> +	gdb_test "$wp_cmd host_global" \
> +	    "Hardware .*watchpoint $::decimal: .*" \
> +	    "set watchpoint"
> +
> +	gdb_test "continue" "hit Hardware (read|access \\(read/write\\)) watchpoint.*Value = 5\r\n.*" \
> +	    "continue after setting watchpoint"
> +
> +	gdb_test "continue" \
> +	    "Could not insert hardware watchpoint $::decimal.*Command aborted\\." \
> +	    "watchpoint rejected on resume"
> +    }
> +}
> +
> +test_host_watchpoint_before_runtime_load
> +test_host_watchpoint_after_runtime_load
> +test_watchpoint_before_kernel
> +test_watchpoint_inside_kernel
> +test_remove_watchpoint_inside_kernel
> +test_multiple_watchpoints
> +test_disable_enable_watchpoint
> +
> +foreach_with_prefix wp_cmd { "rwatch" "awatch" } {
> +    test_non_write_watchpoint_rejected $wp_cmd
> +    test_non_write_watchpoint_before_runtime_load $wp_cmd
> +}
> -- 
> 2.52.0

  reply	other threads:[~2026-02-04 20:34 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-24  5:14 [PATCH 1/2] gdb/testsuite: add rocm-test-utils.h simon.marchi
2026-01-24  5:15 ` [PATCH 2/2] gdb/amd-dbgapi: add basic watchpoint support simon.marchi
2026-02-04 20:33   ` Lancelot SIX [this message]
2026-02-05 18:54     ` Simon Marchi
2026-02-04 18:39 ` [PATCH 1/2] gdb/testsuite: add rocm-test-utils.h Lancelot SIX

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=gvvkzaxpswsa2cwoz753jqrupgczs5td3kpqz6tgja6pkmb34m@kmxxxhzq6ym5 \
    --to=lancelot.six@amd.com \
    --cc=gdb-patches@sourceware.org \
    --cc=simon.marchi@polymtl.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox