Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
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 2/4] gdb/riscv: recover core file ISA features from AT_HWCAP
Date: Thu, 22 Oct 2026 18:44:15 +0300	[thread overview]
Message-ID: <20261022154417.235510-3-khaidari.fg@gmail.com> (raw)
In-Reply-To: <20261022154417.235510-1-khaidari.fg@gmail.com>

Add a core_read_description hook for RISC-V Linux.  It reads AT_HWCAP
from the core's auxv and takes FLEN from the F and D bits, on top of
what riscv_features_from_bfd finds (the function is now exported).  A
core with an NT_GDB_TDESC note still uses that note.

The V bit is ignored.  AT_HWCAP gives no vector length, and a guessed
vlenb would give the vector registers the wrong size.

The test core is a real kernel dump with NT_FPREGSET removed, so
AT_HWCAP (0x20112d, rv64imafdcv) is the only source of FP information.
Its V bit also lets the test check that GDB adds no vector registers.

Signed-off-by: Farid Khaidari <khaidari.fg@gmail.com>
---
 gdb/riscv-linux-tdep.c                        | 120 ++++++++++++++++++
 gdb/riscv-tdep.c                              |   8 +-
 gdb/riscv-tdep.h                              |   9 ++
 .../gdb.arch/riscv-core-hwcap.core.bz2        | Bin 0 -> 15122 bytes
 gdb/testsuite/gdb.arch/riscv-core-hwcap.exp   |  72 +++++++++++
 5 files changed, 203 insertions(+), 6 deletions(-)
 create mode 100644 gdb/testsuite/gdb.arch/riscv-core-hwcap.core.bz2
 create mode 100644 gdb/testsuite/gdb.arch/riscv-core-hwcap.exp

diff --git a/gdb/riscv-linux-tdep.c b/gdb/riscv-linux-tdep.c
index fcfa5f98ea4..d7cf6fcfd53 100644
--- a/gdb/riscv-linux-tdep.c
+++ b/gdb/riscv-linux-tdep.c
@@ -31,6 +31,8 @@
 #include "linux-record.h"
 #include "riscv-linux-tdep.h"
 #include "inferior.h"
+#include "auxv.h"
+#include "gdbsupport/selftest.h"
 
 extern unsigned int record_debug;
 
@@ -523,6 +525,57 @@ riscv_linux_get_syscall_number (struct gdbarch *gdbarch, thread_info *thread)
   return ret;
 }
 
+/* The AT_HWCAP bit for a single-letter ISA extension (COMPAT_HWCAP_ISA_*
+   in arch/riscv/include/asm/hwcap.h).  */
+
+static constexpr ULONGEST
+riscv_hwcap_isa (char ext)
+{
+  gdb_assert (ext >= 'a' && ext <= 'z');
+  return ULONGEST{ 1 } << (ext - 'a');
+}
+
+/* Refine FEATURES with the F and D bits of the AT_HWCAP mask HWCAP,
+   which imply the FLEN.  Only fields still at their unknown value (0)
+   are filled in, so a width already recovered from the core wins.
+
+   The V bit is deliberately ignored: AT_HWCAP carries no vector
+   length, and a target description with a guessed vlen would
+   misrepresent the vector registers.  The vector state is recovered
+   from the NT_RISCV_VECTOR note instead.  */
+
+static void
+riscv_apply_hwcap (struct riscv_gdbarch_features &features, ULONGEST hwcap)
+{
+  if (features.flen == 0)
+    {
+      if ((hwcap & riscv_hwcap_isa ('d')) != 0)
+	features.flen = riscv_flen_d;
+      else if ((hwcap & riscv_hwcap_isa ('f')) != 0)
+	features.flen = riscv_flen_f;
+    }
+}
+
+/* Implement the "core_read_description" gdbarch method.
+
+   Sources in decreasing order of precedence: an NT_GDB_TDESC note is
+   used by the core target directly and this hook is never consulted;
+   then the ELF header and the notes via riscv_features_from_bfd;
+   finally AT_HWCAP, which only fills in what is still unknown.  */
+
+static const struct target_desc *
+riscv_linux_core_read_description (struct gdbarch *gdbarch,
+				   struct target_ops *target, bfd *abfd)
+{
+  auto features = riscv_features_from_bfd (abfd);
+
+  auto auxv = target_read_auxv_raw (target);
+  auto hwcap = linux_get_hwcap (auxv, target, gdbarch);
+  riscv_apply_hwcap (features, hwcap);
+
+  return riscv_lookup_target_description (features);
+}
+
 /* Initialize RISC-V Linux ABI info.  */
 
 static void
@@ -555,6 +608,9 @@ riscv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_iterate_over_regset_sections
     (gdbarch, riscv_linux_iterate_over_regset_sections);
 
+  set_gdbarch_core_read_description (gdbarch,
+				     riscv_linux_core_read_description);
+
   tramp_frame_prepend_unwinder (gdbarch, &riscv_linux_sigframe);
 
   tdep->syscall_next_pc = riscv_linux_syscall_next_pc;
@@ -567,10 +623,74 @@ riscv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_get_syscall_number (gdbarch, riscv_linux_get_syscall_number);
 }
 
+#if GDB_SELF_TEST
+namespace selftests
+{
+
+/* Check that AT_HWCAP bits refine the ISA features as expected.  */
+
+static void
+riscv_apply_hwcap_test ()
+{
+  const ULONGEST hwcap_f = riscv_hwcap_isa ('f');
+  const ULONGEST hwcap_d = riscv_hwcap_isa ('d');
+  const ULONGEST hwcap_v = riscv_hwcap_isa ('v');
+
+  /* The 'd' bit implies double precision, 'f' single precision.  */
+  {
+    riscv_gdbarch_features features;
+    riscv_apply_hwcap (features, hwcap_d);
+    SELF_CHECK (features.flen == riscv_flen_d);
+  }
+  {
+    riscv_gdbarch_features features;
+    riscv_apply_hwcap (features, hwcap_f);
+    SELF_CHECK (features.flen == riscv_flen_f);
+  }
+
+  /* 'd' wins over 'f' when both are set.  */
+  {
+    riscv_gdbarch_features features;
+    riscv_apply_hwcap (features, hwcap_d | hwcap_f);
+    SELF_CHECK (features.flen == riscv_flen_d);
+  }
+
+  /* An flen already recovered from the core is not overwritten.  */
+  {
+    riscv_gdbarch_features features;
+    features.flen = riscv_flen_f;
+    riscv_apply_hwcap (features, hwcap_d);
+    SELF_CHECK (features.flen == riscv_flen_f);
+  }
+
+  /* The 'v' bit is ignored: AT_HWCAP carries no vector length.  */
+  {
+    riscv_gdbarch_features features;
+    riscv_apply_hwcap (features, hwcap_v);
+    SELF_CHECK (features.vlen == 0);
+  }
+
+  /* No relevant bits leaves the features untouched.  */
+  {
+    riscv_gdbarch_features features;
+    riscv_apply_hwcap (features, 0);
+    SELF_CHECK (features.flen == 0);
+    SELF_CHECK (features.vlen == 0);
+  }
+}
+
+} /* namespace selftests */
+#endif /* GDB_SELF_TEST */
+
 /* Initialize RISC-V Linux target support.  */
 
 INIT_GDB_FILE (riscv_linux_tdep)
 {
   gdbarch_register_osabi (bfd_arch_riscv, 0, GDB_OSABI_LINUX,
 			  riscv_linux_init_abi);
+
+#if GDB_SELF_TEST
+  selftests::register_test ("riscv-apply-hwcap",
+			    selftests::riscv_apply_hwcap_test);
+#endif
 }
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index 1af4be77091..1801b042de3 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -3924,9 +3924,6 @@ 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
@@ -3971,10 +3968,9 @@ riscv_flen_from_core_fpregset (bfd *abfd)
   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.  */
+/* See riscv-tdep.h.  */
 
-static struct riscv_gdbarch_features
+struct riscv_gdbarch_features
 riscv_features_from_bfd (bfd *abfd)
 {
   struct riscv_gdbarch_features features;
diff --git a/gdb/riscv-tdep.h b/gdb/riscv-tdep.h
index 344a995a680..5fe91b7287c 100644
--- a/gdb/riscv-tdep.h
+++ b/gdb/riscv-tdep.h
@@ -158,6 +158,15 @@ extern int riscv_abi_flen (struct gdbarch *gdbarch);
    argument registers.  */
 extern bool riscv_abi_embedded (struct gdbarch *gdbarch);
 
+/* FP register width, in bytes, implied by the D and F extensions.  */
+constexpr int riscv_flen_d = 8;
+constexpr int riscv_flen_f = 4;
+
+/* 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.  */
+extern struct riscv_gdbarch_features riscv_features_from_bfd (bfd *abfd);
+
 /* Single step based on where the current instruction will take us.  */
 extern std::vector<CORE_ADDR> riscv_software_single_step
   (struct regcache *regcache);
diff --git a/gdb/testsuite/gdb.arch/riscv-core-hwcap.core.bz2 b/gdb/testsuite/gdb.arch/riscv-core-hwcap.core.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..c557362d69cf483e16c370c0ecd3fe974b882e69
GIT binary patch
literal 15122
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
AiU0rr

literal 0
HcmV?d00001

diff --git a/gdb/testsuite/gdb.arch/riscv-core-hwcap.exp b/gdb/testsuite/gdb.arch/riscv-core-hwcap.exp
new file mode 100644
index 00000000000..84f09c04b3a
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-core-hwcap.exp
@@ -0,0 +1,72 @@
+# 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 ISA features of a core file from the
+# AT_HWCAP entry of the NT_AUXV note: the kernel publishes the
+# single-letter ISA extensions of the machine there, so a kernel core
+# opened without the executable still reveals the F and D extensions.
+#
+# The bundled core (riscv-core-hwcap.core.bz2) is a real kernel core
+# (e_flags = 0, no NT_GDB_TDESC, no RISC-V attributes) whose
+# NT_FPREGSET note has been stripped, leaving AT_HWCAP = 0x20112d
+# (rv64acdfimv) as the only evidence of the FP extension.  The F-only
+# mapping and the precedence rules are covered by the
+# "riscv-apply-hwcap" selftest.
+#
+# How to regenerate the fixture: take the riscv-core-fpregset.core.bz2
+# kernel core and remove the NT_FPREGSET note from PT_NOTE: rewrite the
+# note blob without the CORE/type-2 entry, zero-pad the segment to keep
+# file offsets stable, shrink p_filesz/p_memsz of the PT_NOTE program
+# header accordingly, and bzip2 the result.
+
+# 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-hwcap.core.bz2]
+if {$core == ""} {
+    untested "failed to decompress core file"
+    return -1
+}
+set core [gdb_remote_download host $core]
+
+clean_restart
+
+# Before the core is loaded there is no target, so nothing to prove
+# that the FP and vector registers below really come from the core.
+gdb_test "info registers \$fa0" "The program has no registers now\\." \
+    "no registers before the core is loaded"
+
+if {![gdb_core_cmd $core "load kernel core without executable"]} {
+    return -1
+}
+
+# The D bit of AT_HWCAP gives us the FP registers.
+gdb_test "info registers \$fa0" "fa0\[ \t\]+.*" \
+    "fp registers recovered from hwcap"
+
+# ... and implies FLEN = 8.
+gdb_test "print sizeof (\$fa0)" "= 8" \
+    "flen recovered from hwcap"
+
+# The V bit of AT_HWCAP is deliberately ignored: it carries no vector
+# length, so no vector registers are invented.
+gdb_test "info registers \$v0" "Invalid register .v0." \
+    "no vector registers invented from hwcap"
-- 
2.43.0


  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 ` [PATCH 1/4] gdb/riscv: recover FLEN from the NT_FPREGSET note size in core files Farid Khaidari
2026-10-25 20:07   ` Kevin Buettner
2026-10-26 10:01     ` Farid Khaidari
2026-10-22 15:44 ` Farid Khaidari [this message]
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-3-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