From: Farid Khaidari <khaidari.fg@gmail.com>
To: gdb-patches@sourceware.org
Cc: Farid Khaidari <khaidari.fg@gmail.com>,
Andrew Burgess <aburgess@redhat.com>,
Palmer Dabbelt <palmer@dabbelt.com>,
Timur Golubovich <timurgol007@gmail.com>
Subject: [PATCH 1/4] gdb/riscv: recover FLEN from the NT_FPREGSET note size in core files
Date: Thu, 22 Oct 2026 18:44:14 +0300 [thread overview]
Message-ID: <20261022154417.235510-2-khaidari.fg@gmail.com> (raw)
In-Reply-To: <20261022154417.235510-1-khaidari.fg@gmail.com>
A Linux kernel core has no float ABI in e_flags and no RISC-V
attributes. Opened without the executable, it gets an integer-only
target description, and "p $fa0" fails with "Invalid register 'fa0'"
even though the core holds the FP state.
The kernel writes 32 FP registers of FLEN bytes plus fcsr into
NT_FPREGSET, so the note size gives FLEN. Use it when e_flags says
nothing.
The test core is a real kernel dump with a 264-byte NT_FPREGSET,
i.e. FLEN = 8.
Signed-off-by: Farid Khaidari <khaidari.fg@gmail.com>
---
gdb/riscv-tdep.c | 89 +++++++++++++++++-
.../gdb.arch/riscv-core-fpregset.core.bz2 | Bin 0 -> 15134 bytes
.../gdb.arch/riscv-core-fpregset.exp | 78 +++++++++++++++
3 files changed, 164 insertions(+), 3 deletions(-)
create mode 100644 gdb/testsuite/gdb.arch/riscv-core-fpregset.core.bz2
create mode 100644 gdb/testsuite/gdb.arch/riscv-core-fpregset.exp
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index 68c56fbafb3..1af4be77091 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -56,6 +56,7 @@
#include "arch/riscv.h"
#include "record-full.h"
#include "riscv-ravenscar-thread.h"
+#include "gdbsupport/selftest.h"
#include <vector>
@@ -3923,11 +3924,58 @@ static const struct frame_unwind_legacy riscv_frame_unwind (
/*.prev_arch =*/ NULL
);
+/* FP register width, in bytes, implied by the D and F extensions. */
+static constexpr int riscv_flen_d = 8;
+static constexpr int riscv_flen_f = 4;
+
+/* Return the FLEN implied by SIZE, the size of an NT_FPREGSET note, or 0
+ if SIZE matches no known layout. The note holds 32 FP registers of
+ FLEN bytes each, followed by fcsr, which the kernel pads to 8 bytes on
+ RV64 but leaves at its natural 4 bytes on RV32. */
+
+static int
+riscv_flen_from_fpregset_size (bfd_size_type size)
+{
+ constexpr bfd_size_type num_fpregs = 32;
+ constexpr bfd_size_type fcsr_slot_padded = 8;
+ constexpr bfd_size_type fcsr_slot = 4;
+
+ if (size == num_fpregs * riscv_flen_d + fcsr_slot_padded)
+ return riscv_flen_d;
+ if (size == num_fpregs * riscv_flen_f + fcsr_slot_padded
+ || size == num_fpregs * riscv_flen_f + fcsr_slot)
+ return riscv_flen_f;
+
+ return 0;
+}
+
+/* A kernel core file carries no float ABI in its e_flags, but the size
+ of its NT_FPREGSET note (the ".reg2" pseudo-section) reveals the FLEN.
+ Return the implied FLEN, or 0 if ABFD has no such note or its size
+ matches no known layout. */
+
+static int
+riscv_flen_from_core_fpregset (bfd *abfd)
+{
+ auto *fpregs = bfd_get_section_by_name (abfd, ".reg2");
+ if (fpregs == nullptr)
+ return 0;
+
+ auto size = bfd_section_size (fpregs);
+ int flen = riscv_flen_from_fpregset_size (size);
+ if (flen == 0)
+ warning (_ ("unrecognized .reg2 note size %s in core file; "
+ "FLEN left unknown"),
+ pulongest (size));
+
+ return flen;
+}
+
/* Extract a set of required target features out of ABFD. If ABFD is
nullptr then a RISCV_GDBARCH_FEATURES is returned in its default state. */
static struct riscv_gdbarch_features
-riscv_features_from_bfd (const bfd *abfd)
+riscv_features_from_bfd (bfd *abfd)
{
struct riscv_gdbarch_features features;
@@ -3950,9 +3998,14 @@ riscv_features_from_bfd (const bfd *abfd)
internal_error (_("unknown ELF header class %d"), eclass);
if (e_flags & EF_RISCV_FLOAT_ABI_DOUBLE)
- features.flen = 8;
+ features.flen = riscv_flen_d;
else if (e_flags & EF_RISCV_FLOAT_ABI_SINGLE)
- features.flen = 4;
+ features.flen = riscv_flen_f;
+
+ /* A core file carries no float ABI in its e_flags; recover the FLEN
+ from the size of its NT_FPREGSET note instead. */
+ if (features.flen == 0 && bfd_get_format (abfd) == bfd_core)
+ features.flen = riscv_flen_from_core_fpregset (abfd);
if (e_flags & EF_RISCV_RVE)
{
@@ -4784,12 +4837,42 @@ riscv_supply_regset (const struct regset *regset,
}
}
+#if GDB_SELF_TEST
+namespace selftests
+{
+
+/* Check that an NT_FPREGSET note size maps to the right FLEN. */
+
+static void
+riscv_flen_from_fpregset_size_test ()
+{
+ /* 32 doubles plus a padded fcsr. */
+ SELF_CHECK (riscv_flen_from_fpregset_size (32 * 8 + 8) == riscv_flen_d);
+
+ /* 32 floats plus fcsr, padded on RV64 and unpadded on RV32. */
+ SELF_CHECK (riscv_flen_from_fpregset_size (32 * 4 + 8) == riscv_flen_f);
+ SELF_CHECK (riscv_flen_from_fpregset_size (32 * 4 + 4) == riscv_flen_f);
+
+ /* Anything else leaves the FLEN unknown. */
+ SELF_CHECK (riscv_flen_from_fpregset_size (0) == 0);
+ SELF_CHECK (riscv_flen_from_fpregset_size (32 * 8) == 0);
+ SELF_CHECK (riscv_flen_from_fpregset_size (32 * 16 + 8) == 0);
+}
+
+} /* namespace selftests */
+#endif /* GDB_SELF_TEST */
+
INIT_GDB_FILE (riscv_tdep)
{
riscv_init_reggroups ();
gdbarch_register (bfd_arch_riscv, riscv_gdbarch_init, NULL);
+#if GDB_SELF_TEST
+ selftests::register_test ("riscv-flen-from-fpregset-size",
+ selftests::riscv_flen_from_fpregset_size_test);
+#endif
+
/* Add root prefix command for all "set debug riscv" and "show debug
riscv" commands. */
add_setshow_prefix_cmd ("riscv", no_class,
diff --git a/gdb/testsuite/gdb.arch/riscv-core-fpregset.core.bz2 b/gdb/testsuite/gdb.arch/riscv-core-fpregset.core.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..e82474d025edbb75e9d123af8cb2a3c45e4ee960
GIT binary patch
literal 15134
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
M$rRy2K^EDvxVsSu6#xJL
literal 0
HcmV?d00001
diff --git a/gdb/testsuite/gdb.arch/riscv-core-fpregset.exp b/gdb/testsuite/gdb.arch/riscv-core-fpregset.exp
new file mode 100644
index 00000000000..16363299a0a
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-core-fpregset.exp
@@ -0,0 +1,78 @@
+# 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/>.
+
+# Check that GDB recovers the FP registers from a kernel core file
+# opened without the executable. A kernel core has no NT_GDB_TDESC
+# note, no .riscv.attributes, and zero e_flags, so the size of the
+# NT_FPREGSET note is the only evidence of the FLEN. The kernel dumps
+# the FP state in the D layout: 32 doubles plus 8 bytes for fcsr,
+# 264 bytes in total.
+#
+# The bundled core (riscv-core-fpregset.core.bz2) is a real kernel core
+# whose PT_NOTE carries NT_FPREGSET (264 bytes) but neither NT_GDB_TDESC
+# nor any RISC-V attributes, and whose e_flags are zero. The dumped
+# program never touched the FP unit, so every FP register in the note
+# is zero.
+#
+# The test checks that, with no executable loaded:
+# 1. the FP registers exist in the target description at all, rather
+# than GDB reporting "Invalid register 'fa0'";
+# 2. their contents are supplied from the note rather than left
+# <unavailable> ("(raw 0x...)" in the output proves that);
+# 3. the FP registers are 8 bytes wide, i.e. the FLEN really came from
+# the 264-byte note size.
+#
+# Only the D layout is exercised here, since that is what the bundled
+# core carries. The size-to-FLEN mapping itself, including the F
+# layout, is covered by the "riscv-flen-from-fpregset-size" selftest.
+#
+# How to regenerate the fixture: run any RV64 program on a Linux system
+# under "ulimit -c unlimited" with kernel.core_pattern=core, make it
+# dump core, and bzip2 the result. Check with "readelf -n" that the
+# core carries a 264-byte NT_FPREGSET and neither an NT_GDB_TDESC note
+# nor RISC-V attributes.
+
+# The fixture is an ELF64 core and the FLEN assertions are
+# RV64-specific.
+require {istarget "riscv64-*-*"}
+
+if {![istarget *-*-linux*]} {
+ unsupported "linux only"
+ return -1
+}
+
+set core [decompress_bz2 $srcdir/$subdir/riscv-core-fpregset.core.bz2]
+if {$core == ""} {
+ untested "failed to decompress core file"
+ return -1
+}
+set core [gdb_remote_download host $core]
+
+clean_restart
+
+if {![gdb_core_cmd $core "load kernel core without executable"]} {
+ return -1
+}
+
+# The size of the NT_FPREGSET note implies FLEN, hence the FP registers.
+# The value must come from the note: a raw hex dump in the output means
+# the register bytes were supplied, not left <unavailable>.
+gdb_test "info registers \$fa0" \
+ "fa0\[ \t\]+\\{float = 0, double = 0\\}\[ \t\]+\\(raw 0x0+\\)" \
+ "fp register value supplied from fpregset note"
+
+# 264 bytes = 32 doubles + fcsr, so the FLEN must be 8.
+gdb_test "print sizeof (\$fa0)" "= 8" \
+ "flen recovered from fpregset note size"
--
2.43.0
next prev parent reply other threads:[~2026-10-22 15:45 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-22 15:44 [PATCH 0/4] gdb/riscv: analyse a core file without the executable Farid Khaidari
2026-10-22 15:44 ` Farid Khaidari [this message]
2026-10-25 20:07 ` [PATCH 1/4] gdb/riscv: recover FLEN from the NT_FPREGSET note size in core files Kevin Buettner
2026-10-26 10:01 ` Farid Khaidari
2026-10-22 15:44 ` [PATCH 2/4] gdb/riscv: recover core file ISA features from AT_HWCAP Farid Khaidari
2026-10-22 15:44 ` [PATCH 3/4] gdb/riscv: test the "arch=" disassembler option Farid Khaidari
2026-10-22 15:44 ` [PATCH 4/4] gdb/riscv: disassemble an attribute-less object by the description ISA Farid Khaidari
2026-10-25 20:50 ` Kevin Buettner
2026-10-26 10:01 ` Farid Khaidari
2026-10-25 20:17 ` [PATCH 0/4] gdb/riscv: analyse a core file without the executable Kevin Buettner
2026-10-26 9:56 ` [PATCH v2 " Farid Khaidari
2026-10-26 9:56 ` [PATCH v2 1/4] gdb/riscv: recover FLEN from the NT_FPREGSET note size in core files Farid Khaidari
2026-10-26 9:56 ` [PATCH v2 2/4] gdb/riscv: recover core file ISA features from AT_HWCAP Farid Khaidari
2026-10-26 9:56 ` [PATCH v2 3/4] gdb/riscv: test the "arch=" disassembler option Farid Khaidari
2026-10-26 9:56 ` [PATCH v2 4/4] gdb/riscv: disassemble an attribute-less object by the description ISA Farid Khaidari
2026-10-27 14:31 ` [PATCH v2 0/4] gdb/riscv: analyse a core file without the executable Farid Khaidari
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=20261022154417.235510-2-khaidari.fg@gmail.com \
--to=khaidari.fg@gmail.com \
--cc=aburgess@redhat.com \
--cc=gdb-patches@sourceware.org \
--cc=palmer@dabbelt.com \
--cc=timurgol007@gmail.com \
/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