From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id 0bURImO00WpERBcAWB0awg (envelope-from ) for ; Fri, 16 Oct 2026 01:21:39 -0400 Received: by simark.ca (Postfix, from userid 112) id 61F701E04F; Fri, 16 Oct 2026 01:21:39 -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.3 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,WEIRD_PORT autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [IPv6:2620:52:6:3111::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 E1CF91E050 for ; Fri, 16 Oct 2026 01:21:32 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A5B244BA798D for ; Fri, 16 Oct 2026 05:21:31 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A5B244BA798D Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 77CC94BA2E15 for ; Fri, 16 Oct 2026 05:21:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 77CC94BA2E15 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 77CC94BA2E15 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1792128064; cv=none; b=vwmLUHWffLjFdOV4govGWWfFoCaLYYgsf1lN+J2mP+8q3ZTTmvNyLnJrqkX5SGP0x/Auh7wBlZ4jdT3pRBydU5qEAFT3Tbf0G5UARcsUvYAlrFymInq/oM02mWwv/NbkPtcOLdy1xB4xChakgwtD1TkVi7ql3Msh0hZdSgkkgl0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1792128064; c=relaxed/simple; bh=1nr7d11/0IJnXDcqgit4Uhz9OTKmZGq8/dI+OQ9TvJI=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=oYdhUoDn5CSZBk3E29b3YGIX2qEqZLdj3NmLF1Vu7xMY9Re/Isxc9Kgd4dtyi/1YSEk0I4TT3Rkfrci6n/iLi79Fd7wTZZ1trEdAjNCFGoCiYKOhyQCKN4P2vRyY0E+f2WUHxCf7x1V0Iw8CW7YpgIxl5JSa5i5HSeuANcBOwvk= ARC-Authentication-Results: i=1; sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 77CC94BA2E15 Received: by simark.ca (Postfix) id E8CA91E06B; Fri, 16 Oct 2026 01:21:03 -0400 (EDT) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Simon Marchi 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 Message-ID: <20261016052100.1386999-4-simon.marchi@efficios.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261016052100.1386999-1-simon.marchi@efficios.com> References: <20261016052100.1386999-1-simon.marchi@efficios.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 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 , 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 = {...}, 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