From: Simon Marchi <simon.marchi@efficios.com>
To: gdb-patches@sourceware.org
Cc: Simon Marchi <simon.marchi@efficios.com>
Subject: [PATCH 3/6] gdb/amd-dbgapi: handle regno == -1 in fetch_registers and store_registers
Date: Fri, 16 Oct 2026 01:20:08 -0400 [thread overview]
Message-ID: <20261016052100.1386999-4-simon.marchi@efficios.com> (raw)
In-Reply-To: <20261016052100.1386999-1-simon.marchi@efficios.com>
Running "gcore" while a GPU wave is stopped at a breakpoint makes GDB
crash:
$ gdb -q -nx testsuite/outputs/gdb.rocm/simple/simple \
-ex "with breakpoint pending on -- break do_an_addition" \
-ex r -ex gcore -batch
...
regcache.c:162: internal-error: register_type: Assertion `regnum >= 0 && regnum < descr->nr_cooked_registers' failed.
The backtrace is:
#0 internal_error_loc (file=0x55556355d500 "/home/smarchi/src/binutils-gdb/gdb/regcache.c", line=162, fmt=0x55556355cf60 "%s: Assertion `%s' failed.") at /home/smarchi/src/binutils-gdb/gdbsupport/errors.cc:53
#1 register_type (gdbarch=0x51c000073880, regnum=-1) at /home/smarchi/src/binutils-gdb/gdb/regcache.c:162
#2 amd_dbgapi_target::fetch_registers (this=0x555568df2760 <the_amd_dbgapi_target>, regcache=0x5070000c9420, regno=-1) at /home/smarchi/src/binutils-gdb/gdb/amd-dbgapi-target.c:2039
#3 target_fetch_registers (regcache=0x5070000c9420, regno=-1) at /home/smarchi/src/binutils-gdb/gdb/target.c:3925
#4 gcore_elf_build_thread_register_notes (gdbarch=0x51c000073880, info=0x51800008b480, stop_signal=GDB_SIGNAL_TRAP, obfd=0x5120001c0b40, note_data=0x7fffe698d420, note_size=0x7fffe68c0e30) at /home/smarchi/src/binutils-gdb/gdb/gcore-elf.c:132
#5 linux_corefile_thread (info=0x51800008b480, gdbarch=0x51c000073880, obfd=0x5120001c0b40, note_data=std::unique_ptr<char> = {...}, note_size=0x7fffe68c0e30, stop_signal=GDB_SIGNAL_TRAP) at /home/smarchi/src/binutils-gdb/gdb/linux-tdep.c:1957
#6 linux_make_corefile_notes (gdbarch=0x51c00002d080, obfd=0x5120001c0b40, note_size=0x7fffe68c0e30) at /home/smarchi/src/binutils-gdb/gdb/linux-tdep.c:2543
#7 gdbarch_make_corefile_notes (gdbarch=0x51c00002d080, obfd=0x5120001c0b40, note_size=0x7fffe68c0e30) at /home/smarchi/src/binutils-gdb/gdb/gdbarch-gen.c:3664
#8 write_gcore_file_1 (obfd=0x5120001c0b40) at /home/smarchi/src/binutils-gdb/gdb/gcore.c:95
#9 write_gcore_file (obfd=0x5120001c0b40) at /home/smarchi/src/binutils-gdb/gdb/gcore.c:137
#10 gcore_command (args=0x0, from_tty=0) at /home/smarchi/src/binutils-gdb/gdb/gcore.c:175
gcore_elf_build_thread_register_notes calls target_fetch_registers with
regno == -1, meaning "fetch all registers". The amd-dbgapi target
assumes regno is always a valid register number, and passes -1 directly
to register_type. store_registers has the same problem.
Make both functions handle regno == -1 by iterating over all raw
registers. This code is mostly taken from ROCgdb, except that it also
emits the warning when some registers fail to read or write in the
"regno == -1" cases. ROCgdb only warns in the single register case.
Like ROCgdb, invalidate volatile registers once, after all registers are
written, so that writing a register with the "invalidate volatile"
property (e.g. VCC) does not invalidate a volatile register (e.g.
STATUS) that has yet to be written.
With this fix, the gcore command above gets a bit further, but now hits:
gdbarch-gen.c:3637: internal-error: gdbarch_iterate_over_regset_sections: Assertion `gdbarch->iterate_over_regset_sections != nullptr' failed.
This is because linux_make_corefile_notes tries to dump GPU waves as if
they were host threads, using the amdgpu gdbarch, which does not
implement iterate_over_regset_sections. This is addressed by a
following patch.
Change-Id: Ie669eb8a538ddfd3f35745e3af53eaf5541aa01b
---
gdb/amd-dbgapi-target.c | 100 +++++++++++++++++++++++++---------------
1 file changed, 64 insertions(+), 36 deletions(-)
diff --git a/gdb/amd-dbgapi-target.c b/gdb/amd-dbgapi-target.c
index 2fd175de6f7d..099deceaabad 100644
--- a/gdb/amd-dbgapi-target.c
+++ b/gdb/amd-dbgapi-target.c
@@ -2035,20 +2035,32 @@ amd_dbgapi_target::fetch_registers (struct regcache *regcache, int regno)
amdgpu_gdbarch_tdep *tdep = get_amdgpu_gdbarch_tdep (gdbarch);
amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (regcache->ptid ());
- gdb_byte raw[AMDGPU_MAX_REGISTER_SIZE];
- ULONGEST reg_size = register_type (gdbarch, regno)->length ();
- gdb_assert (reg_size <= AMDGPU_MAX_REGISTER_SIZE);
- amd_dbgapi_status_t status
- = amd_dbgapi_read_register (wave_id, tdep->register_ids[regno], 0,
- reg_size, raw);
+ auto fetch_one_register = [&] (int r)
+ {
+ gdb_byte raw[AMDGPU_MAX_REGISTER_SIZE];
+ ULONGEST reg_size = register_type (gdbarch, r)->length ();
+ gdb_assert (reg_size <= AMDGPU_MAX_REGISTER_SIZE);
- if (status == AMD_DBGAPI_STATUS_SUCCESS)
- regcache->raw_supply (regno, raw);
- else if (status != AMD_DBGAPI_STATUS_ERROR_REGISTER_NOT_AVAILABLE)
- warning (_("Couldn't read register %s (#%d) (%s)."),
- gdbarch_register_name (gdbarch, regno), regno,
- get_status_string (status));
+ amd_dbgapi_status_t status
+ = amd_dbgapi_read_register (wave_id, tdep->register_ids[r], 0,
+ reg_size, raw);
+
+ if (status == AMD_DBGAPI_STATUS_SUCCESS)
+ regcache->raw_supply (r, raw);
+ else if (status != AMD_DBGAPI_STATUS_ERROR_REGISTER_NOT_AVAILABLE)
+ warning (_("Couldn't read register %s (#%d) (%s)."),
+ gdbarch_register_name (gdbarch, r), r,
+ get_status_string (status));
+ };
+
+ if (regno == -1)
+ {
+ for (int r = 0; r < gdbarch_num_regs (gdbarch); ++r)
+ fetch_one_register (r);
+ }
+ else
+ fetch_one_register (regno);
}
void
@@ -2063,38 +2075,54 @@ amd_dbgapi_target::store_registers (struct regcache *regcache, int regno)
struct gdbarch *gdbarch = regcache->arch ();
gdb_assert (is_amdgpu_arch (gdbarch));
- gdb_byte raw[AMDGPU_MAX_REGISTER_SIZE];
- ULONGEST reg_size = register_type (gdbarch, regno)->length ();
- gdb_assert (reg_size <= AMDGPU_MAX_REGISTER_SIZE);
- regcache->raw_collect (regno, &raw);
-
amdgpu_gdbarch_tdep *tdep = get_amdgpu_gdbarch_tdep (gdbarch);
+ amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (regcache->ptid ());
+ bool invalidate_volatile = false;
- /* If the register has read-only bits, invalidate the value in the regcache
- as the value actually written may differ. */
- if (tdep->register_properties[regno]
- & AMD_DBGAPI_REGISTER_PROPERTY_READONLY_BITS)
- regcache->invalidate (regno);
+ auto store_one_register = [&] (int r)
+ {
+ gdb_byte raw[AMDGPU_MAX_REGISTER_SIZE];
+ ULONGEST reg_size = register_type (gdbarch, r)->length ();
+ gdb_assert (reg_size <= AMDGPU_MAX_REGISTER_SIZE);
+ regcache->raw_collect (r, &raw);
- /* Invalidate all volatile registers if this register has the invalidate
- volatile property. For example, writing to VCC may change the content
- of STATUS.VCCZ. */
- if (tdep->register_properties[regno]
- & AMD_DBGAPI_REGISTER_PROPERTY_INVALIDATE_VOLATILE)
+ /* If the register has read-only bits, invalidate the value in the
+ regcache as the value actually written may differ. */
+ if (tdep->register_properties[r]
+ & AMD_DBGAPI_REGISTER_PROPERTY_READONLY_BITS)
+ regcache->invalidate (r);
+
+ /* Writing this register may change the value of volatile registers.
+ For example, writing to VCC may change the content of STATUS.VCCZ.
+ Invalidate them once all registers are written, so that we don't
+ invalidate a register we have yet to write. */
+ if (tdep->register_properties[r]
+ & AMD_DBGAPI_REGISTER_PROPERTY_INVALIDATE_VOLATILE)
+ invalidate_volatile = true;
+
+ amd_dbgapi_status_t status
+ = amd_dbgapi_write_register (wave_id, tdep->register_ids[r], 0,
+ reg_size, raw);
+
+ if (status != AMD_DBGAPI_STATUS_SUCCESS)
+ warning (_("Couldn't write register %s (#%d)."),
+ gdbarch_register_name (gdbarch, r), r);
+ };
+
+ if (regno == -1)
+ {
+ for (int r = 0; r < gdbarch_num_regs (gdbarch); ++r)
+ store_one_register (r);
+ }
+ else
+ store_one_register (regno);
+
+ if (invalidate_volatile)
{
for (size_t r = 0; r < tdep->register_properties.size (); ++r)
if (tdep->register_properties[r] & AMD_DBGAPI_REGISTER_PROPERTY_VOLATILE)
regcache->invalidate (r);
}
-
- amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (regcache->ptid ());
- amd_dbgapi_status_t status
- = amd_dbgapi_write_register (wave_id, tdep->register_ids[regno], 0,
- reg_size, raw);
-
- if (status != AMD_DBGAPI_STATUS_SUCCESS)
- warning (_("Couldn't write register %s (#%d)."),
- gdbarch_register_name (gdbarch, regno), regno);
}
struct gdbarch *
--
2.56.0
next prev parent reply other threads:[~2026-10-16 5:21 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-16 5:20 [PATCH 0/6] Fix generating core files when GPU waves are present Simon Marchi
2026-10-16 5:20 ` [PATCH 1/6] gdb/testsuite: make with_rocm_gpu_lock transparent to return Simon Marchi
2026-10-16 5:20 ` [PATCH 2/6] gdb/corefile: handle no signalled thread when writing NT_GDB_TDESC Simon Marchi
2026-10-16 5:20 ` Simon Marchi [this message]
2026-10-16 5:20 ` [PATCH 4/6] gdb/linux-tdep: don't write core file notes for non-Linux threads Simon Marchi
2026-10-16 5:20 ` [PATCH 5/6] gdb/amd-dbgapi: defer TARGET_OBJECT_AUXV xfers to the beneath target Simon Marchi
2026-10-16 5:20 ` [PATCH 6/6] gdb/linux-tdep: ignore non-Linux threads in get_ptid_for_slash_proc Simon Marchi
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=20261016052100.1386999-4-simon.marchi@efficios.com \
--to=simon.marchi@efficios.com \
--cc=gdb-patches@sourceware.org \
/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