Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH 0/4] gdb/riscv: analyse a core file without the executable
@ 2026-10-22 15:44 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
                   ` (5 more replies)
  0 siblings, 6 replies; 16+ messages in thread
From: Farid Khaidari @ 2026-10-22 15:44 UTC (permalink / raw)
  To: gdb-patches
  Cc: Farid Khaidari, Andrew Burgess, Palmer Dabbelt, Timur Golubovich

A RISC-V core opened without its executable gets an integer-only
target description, because the core does not say how wide the FP
registers are.  Any object with no ISA attribute, a core included, is
also disassembled as plain rv64gc.

This series reads what the core does record.  The size of the
NT_FPREGSET note gives FLEN, and AT_HWCAP gives the single-letter
extensions.  The last patch passes the ISA of the resulting target
description to the disassembler when the object names none.

Patches 3 and 4 need the "arch=" disassembler option, sent to
binutils@sourceware.org as "RISC-V: add an "arch=" disassembler
option".

Vector state from the NT_RISCV_VECTOR note is left out.  GDB can read
the org.gnu.gdb.riscv.vector feature from a target description but
cannot build one, so a vlen read from the core has nowhere to go yet.
The disassembler test loads a vector description from a file instead.

Tested on x86_64-linux with a riscv64-linux-gnu target: the three new
tests give 23 passes and no failures.  The host cannot run RISC-V
binaries, so I did not run the rest of the testsuite.

Farid Khaidari (4):
  gdb/riscv: recover FLEN from the NT_FPREGSET note size in core files
  gdb/riscv: recover core file ISA features from AT_HWCAP
  gdb/riscv: test the "arch=" disassembler option
  gdb/riscv: disassemble an attribute-less object by the description ISA

 gdb/riscv-linux-tdep.c                        | 120 +++++++++++++
 gdb/riscv-tdep.c                              | 167 +++++++++++++++++-
 gdb/riscv-tdep.h                              |  14 ++
 .../gdb.arch/riscv-core-fpregset.core.bz2     | Bin 0 -> 15134 bytes
 .../gdb.arch/riscv-core-fpregset.exp          |  78 ++++++++
 .../gdb.arch/riscv-core-hwcap.core.bz2        | Bin 0 -> 15122 bytes
 gdb/testsuite/gdb.arch/riscv-core-hwcap.exp   |  72 ++++++++
 .../riscv-disasm-arch-option-vector.xml       | 123 +++++++++++++
 .../gdb.arch/riscv-disasm-arch-option.c       |  40 +++++
 .../gdb.arch/riscv-disasm-arch-option.exp     | 124 +++++++++++++
 10 files changed, 732 insertions(+), 6 deletions(-)
 create mode 100644 gdb/testsuite/gdb.arch/riscv-core-fpregset.core.bz2
 create mode 100644 gdb/testsuite/gdb.arch/riscv-core-fpregset.exp
 create mode 100644 gdb/testsuite/gdb.arch/riscv-core-hwcap.core.bz2
 create mode 100644 gdb/testsuite/gdb.arch/riscv-core-hwcap.exp
 create mode 100644 gdb/testsuite/gdb.arch/riscv-disasm-arch-option-vector.xml
 create mode 100644 gdb/testsuite/gdb.arch/riscv-disasm-arch-option.c
 create mode 100644 gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp

-- 
2.43.0


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/4] gdb/riscv: recover FLEN from the NT_FPREGSET note size in core files
  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
  2026-10-25 20:07   ` Kevin Buettner
  2026-10-22 15:44 ` [PATCH 2/4] gdb/riscv: recover core file ISA features from AT_HWCAP Farid Khaidari
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 16+ messages in thread
From: Farid Khaidari @ 2026-10-22 15:44 UTC (permalink / raw)
  To: gdb-patches
  Cc: Farid Khaidari, Andrew Burgess, Palmer Dabbelt, Timur Golubovich

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
zcmV+(JK@AaT4*^jL0KkKSw*&Nt^iEOfB*mg|NsC0|NsC0|NsC0|NsC0|NsC0|NsC0
z|NsC0|Nr1PJ;nE(13-zRg6{14Wy|Y;4k!U200A@zC)t!2u`o-s?jExla@Omm*|*&2
z4{yGu_dD0!O5bhR-JG3u)|s;#Q`x%P2KMi#fbIvgUY@JDmiKpv&mOQ;dv~3iqD|le
zKnH87?U&izL}$H$zz4M&J?!_*j{qmv4G|MSngq#;V^2iEO{NgZrju!rfiy5fOccSP
zp{7QrHBZO{z>S~{04B+hG$ip1CIW2)%~bqD8YYbzHi@(}Xab&1P-ubx0$~Y+!Wu>d
z3AEHt5$a$KOs3TJN9j-W2+&Lv^*v3sN9i_`#U|8ksM0o5LE@jOJ(V7#VrpsnQ#BfU
zRB8IALHba{G!3YFGEAB_rbf`3XeBft5QvBqCXEK8Pf4{JGGxfmG#;SP^#e5kX{MTF
z(?Ox5Mw%K1nrIC)$N*`e0004?05k!hG|<p#pfmtUsSrSuQR*6GX{6KAZ3&e0o~Nnm
zc&46_>UpGTsp&m6Hc_6a-l9DdW~sG2HAV<|N1}S3O-7mzQ1u2t(9=x}gVbmmZ9pET
zfYG1;0j5LJ89hMBMLi_M0Ay*Q>K>y_qy~UJMn=@oZ9vhr8U}y>H1!^#pa5vd27qV*
zp^zE|fChjAMu22#p!9}-000ssLI@gY&?cE0Pf6uAgv8X^F*8$5C!v(uCeul$rh!jS
zKx%4!ih7=>rc-J?F)=o#jU&mVGJ1_Xr;yb3Jx^0lY7lu(Q_~dn8aAUtPt`p#X)zh3
z84Wy<|I$npN4A(=wqb9khsPGNginns#=fpw2W4^?)~C`^`ka0)P88xZZoZ{y&NIX8
zk0ah~8!T&Ro7RPM7K2mPt74Xl^{+LjM_VP?YU75*%(r`w4uPk<(hljDYDa8EQ#C=+
z3$zhJgbD)>J?%SrUk!rIp31&wxY#t9&{k$MFq*>lqQw(ExxTO<u}E`0seL{8sAEQ;
zks=0Jxsq7RoEP+)vc?5Pda?|N3kaSn6eC!KrVH;ZxsTyK7<F8yc}rkcQ_4uZ6=lF`
zeOh5yRGf65dEo;fOpq&&mhek3ehNazORcLouSQYxOnU9G6H)+b6WR(tPMwIMmd9cB
zz9Uts;9t`Bi~2tc-KO{LG1>X9uVPur`b>~ZY)go-mSAm}efk{r;Bj=-9W;|Ot?{`q
z`Mz~g3WF<^wR|R@T|BMOZW3XAHv(FLFM3$7!}jnCZoar3EP()tAj#6Q1z->xYXU~F
z6IaHIkSLS*_=^e+>u{3kkUm@NgH^Pm`Z~<cA8L`hSz&<lVFI}~_*sEbN|5^jmIFxp
zJS7m4pV`7#v>S|DX&v+B-Av#)hTucL4sU|)4T$l>EF<h(+l2}Z|4>~W4}2ts=o^s@
zuUzgCn6fe~4iy&JChh%itMh-ai&!^U8@b;f5Lg|JWC*4zMB22*PQo{&7>!=u8D*T4
zP|A>d!h@r`(O~(q%_LjAH`;Kh?#A3*t7BJ}d}hM%$rc^paZ%g%9nWXoRvq04hF+!K
zL_i0E!WAs>t;trxRAJ&UQmll_!X1Je0;@=D*>dBG7=f{|7{hoij8UO5$`ZldKQh7)
zF4Ibbb5HNx`4Lmz&*WBiS08x9&(<K6N~cILv2i`W!)nR+?18K8ntk=AitWK5dG@#G
z?+kG#Xfhz$$I^LExt(%KUPApJfAMH^Fv#Q5AO_~skKeO~xfvPZ(o}(jB*O<r)i3FV
zV73c9gqgu1qc6h>u<*E27}Q9a0>VA^P^_hR-R0mK*_QT1P1^RcNJa$+ux~U49Y7SZ
z1uQ|>xkLjRLcw66@$83bi4|S5Meogh^_v)XmrBWbats90=x}qTH+6JYEfzi#DMicz
z1x+Zx$8BRgCo8FV62({n4YBwd^OPReSC;9*Vx#yvs7B}XN5CJSM8-G}_z;WxY`V?f
zKZt-chV}iR??%992S>RZfwIpJNpkuUcOWISf<{s<5t$XM>A6+&7|YUJvQ|82ns9Fb
zm}A6O#tXFeVAVULmwE7<wQfw4bu4xwTSKUrJQ;3eWt@FdIgqrL4WTO4qZiwiCPhh+
z63<dW!ZWSS@@Rpl{)L{nNV%suUx_CfkuYRJC&g`Y2bOX!wj;r%1KLGVDw#kbE-VXD
zq(U{sD^RGQ=hlBVW<#V53a4C~Dh~5<*SN2XY<M-wV^>3w<+`T};agTLrm9krz3f@D
zE%kRVa41O9sjVznMX6N^5|*f{d>&fXnX+?^goW6<Or(Tfp^^o}3owfml9)(5^+U2v
z`vVk`Lllw#umWO`gbB<tKmaYW7~#k8Z`1ZX`^?=Q8;QxUIS(CBJ^=!3z$>OiKnie}
zP8zcktk?q8+CfE<&LoOb0V1k-iB6lMB!_BdJ)UQAtg5mS5C}Uf?r7vv4-Ey4tQ>+{
zs9N@BW)O5cLqN`R7~0Yd7F=JnN>LM$xg?W8<}1s1RRjG|Ay}?dMR}suz9)QYY)vIG
zpxqHvk-ERLB)x_sZM=k%3wN+3di7Sio4J?#ObG??xqkjaS{9SUID$&7UX?ZXP@q^C
zW<Sjax%>L@lyy6V0njh$@*3`0%hMaUp3}B4*{09zg|Tt%AM(J_z1v+mhXL_*5G|8J
zJ1*X|k}5g}3tsF$v6)X*z2<hIQY{aq*KzVJCQ$u00>jw&Qa?QLNVe;>t+7WpwO_d6
z`ACPY>8S6V0fgiR8oTnQ{Wu90aZ+QHugOm3vkjd^Spvu%yCpk-=eoaD3*;%%N1Rb>
z8zV0Qs!q%OB_&i+^SS-j?xeRAqkzpjo@^197J7K~M$|gjW7RK&Q{=p-W)drSsPYni
zrX=68al6F7h4aq{pX7~+JAWF_m2H}}_6MQ#{$b3>HIGt>%JLL5>|a4nmB>ejUW3JS
zHMhJzgfD%5_QpBa!oM&A(WsKUyY6sn6%6{U-L$p#NGvuLXh~a9rbr0bp&W#84;Fnh
z3a@!c!9ayb4wXg#BnsoaT|)xUcT{mK&|$3tk+t}+B#?w3>#u{8{6E*ZxC<|1eqyl=
z$)Z(3K(9D}TN;w#9)Tq?6Om;wmSNmJWJm=dEP{ksMGJ@{6nP4npjpkFfWi|73na~&
z*#Og(01F@yBLI^$p^R9-SfbBZ!cI8}CTu-oKs2EO8(@U*MnC}2XsH0^6KRmLK%U9k
zZ0KQasw6LsK$@8hTe1SIB#KEkCJd0AqkE+VMwtw-D4LS$A_}Zy1Vw>&ZLQTqPB_tM
zUv8$i1O>!ptx`=4(!hm=NNU%oRp1%AlOzgoVPTMw85Gdo)Fzcen8?W(-iJ+7OHClm
zDuA-ZDydOLI$+3b;Z)g2NF%m8k<OrU;O8R`)0jeJn0<6{A#_;-Hs&7tj?85<Qq{*g
zu+<KBv}S{^t4&lvjof6gf)R?;gdm(^oex2Y;GiZ^$<HjTV28)&ov#)#2%xN4le%w*
zY9TA@iD_=4Y9lLn92m~5!~zo>BSM5-BWf+AY6yzJG$ENvj5}Y7w#$8H!Mm2Mu=sdQ
zv$xWqgdnqyZmV3;iA*gH0Xn6t#VS8?E>p-+T7ted%<^|Cl0!jl?MBoJu(v}qrV;}c
z*GWmuTN7m4ytb*eMwLXvq?ji8ozo3NVa6RWL2hyqHrK4PKAvUuRvhA7wCJep(?J97
ziKa^4+ZJKd3?$69yE-5?#?ePlK}Kbpd0>00E19Fiwp{~^*uMLh+^99vy^QU&l@;CA
z`G`mvUqizx4lu?O172Ze)u^>)o$-zD7o{(HV$4$_V_~mNje9a}P}r;>ty01{vl^{H
z&6@EGSkA`1lnxe82-?w%xX7vsLtCD8HKcZLi_w$Ha>aU;XW3D##KtH7rO<@Up)kPd
znR4Xs55?o2^@6Whgl3mlu|^83ZB3|CNz*Yj#<fPeT348wP0Qs{Q@Bb`%5z6%Mx1oa
z7t9wqY@xNiBeffQW>QVO4#uC1PUy8)jzit#U`H9g*{>X}yoM8JJel8$Q(IQlqT4vB
zV>{NF>+zJynYJ7m(1vGI@;HX&eXrIP+uRQ9ayw(JE^U4~u))VusnshqIyR;%Jmjd8
zG1Tdjgn@{itd5Ir@=+UU@4kSI<z~=pYVUS#xeh~v6|UIM(^j(~CfVbS<2S^9HUjz0
za7)mokyllMii`%uPB}cFqk*&9@k&y=>w8+fV|!;0WTP(9g#a_4WR~v3ILHlR+g`0(
zyRs*EFq(JWKxz`5wMJ+V0&E$&FGed=Tt%cOCMHSVBFGI<*@t&8r_@#&Hg+!i6nb2$
zNr<&Nvp`5@NM>VhF`H7YyIW97yUE1kPt2}q#i}|eG7e7Zm|LcpbCz9W6PmN?Y>8pl
z8{(xht({i@1o4YnDG7x4cFaBsFy%C{oLeuOU9qC^QS}sLnYP{8h-6<D-&&fpMW`v&
z;Cj<mQ%zRakhF$`%-l}0SBI@0`rkxMacdMW1q<E-Ycr0RWnA2@Yr$B%zVs%Sn2}zT
z)P~s11=vX-WR0G;bxc6a%rL<<CbzWMV@sKP7IZpm3t{Pwatk>2!yCe90YT7t`T#y4
zkUC_PpGuKvQ3<j*l8T`~gP>>walcR`m8U~Utm;gW0=6j*{+R?IPTjgl5INJ4GP02I
zkR>t_86<#sf)YbQ1kQ1)1PU=msHDY`six4Af_`B@Krk65ECL(A&45r4_Y4t`P&zaM
z_!R?|WDG{dLZJv?ObZlP4f7y#ZY=WOT2UmyfOqVGZljt*(J}<6$Vs%#@SK>Fc0?#d
zL}L+%l{iJ&gkXe_8U~Scz(sM2!}ec}#2&6(0If6{W{`VL7>r3Q$Ak&l8ZI;>TN)L4
z!q$x|@!=Q@fD6os3;~EOF$;-hmv+)f!x)jqF?sx#FZ-Vtmh>v{CC^Jfv?9p%XMUw5
zfqZrdwGaX0=?jTyW`hNS4yVi@R15{IXf#<E#D%01Z`~|}I4prTHxHoU^!Q0MFwG~}
zAQL*M0oJDdgf^K8yu%ljxiU@bIdlS;0X`D~+h!nv#w`z&Wpj(@VufGv4KZ_1(rJ)!
zq1l^lM)S@kEUB=?9Qk~M5Mlt<`7j2xg8G9IhR_CM1I+GWEseWn?8FIYFco$r8B7rj
z7K|DahM+o~7U-u8prl>4WWvz^(1kKchyu>#g&__=Oc->iNGJu<7$N+kLj)lQApj|{
z6JZT(7y<NJNF`zb=MEGCM#d6g>Wqa|NhcqtYS54|XEd7=Boyotk{=?<Op*ak;|V@1
zW<qY#6H_6r2nSTj3P3tk0Nx3cE|A?M36cWH1(F+Xk%7BHOuAYm=`_&`GGu`dG|4Vw
zP==IQFwPZDDCEL}tr$;e!>D94P?dI)LP7@6lGWF}k?DH=ZL`;+YxwK;-++k^nDx3v
zDYXlRxgIt%mQ^W$*H%cjw~Znjhse?K;qB6Y>QPb~1<469j9CXwZYx+$0bA!WE+;aa
z^K|!)2zYGFeICld%7VgS51J@{E{mhn)-O`h^giFI=z9zuu0KAx?lRZM9nWiCM@_bR
z9nL1ZA(6_}H3g<6GKoOJDBCD3lWdALAJCx?8Kh?I_0{@M*IWL>Q*^l0IuDt)dk2`W
znwH?$G1B>ZJYMxbf1BF$<2a6Ak3(qnLB@;ZLH-uY<ljrfkA2hNq;XXgnK=J1O9O@z
z9ei(RH<pYAGz?3~jR?!#QTeO&ncVe%V!`fNQQI#HMX#7R)OIiz$Y%6VMWSb<7zHU%
z6C@0PP%~BEo4ha6bPKEHJ+~wGykF*ziSMs`J03R<>@Bnh=(ah0tZWU<3X$pU>%Imd
zd>_T&*AZQ{`qTuKzy1CSK*eUDX;S|aUb95Zj#KA!9B}Ca*VGWP2WVo=Xyt(58Yv=M
zalDC9i2=*Bm(*T71=ZKwkacYuhGss_{-VITp;5h~&cljf(WSqTL4z?gn^z$zJ+X%5
ziN&%Y)jYDgBMbT~(TEi?BFPYfPEaok4lTdw9x>DuYXtVjM{dY00-$JH2ZHOq%`tMg
zyp1C?qwYxW$*9vlTAvb3W}UW4qOSrLK34?iVDYsFjxqCGd>Av38IL6hD3C}XV6%AD
zbkhB<52@Q`{8m`aYrOiM9|xRQ^eiQ%ay)?PbN0?y<@c1+n>iY}%Rloq@We~`|DFd5
zvKpjSK>DNo+7HjQ(w2kUW_(b--A-#`HAw(Kqbs-V$^yZO{c1)`1yQMNaXBPmS?xPR
ziTkk-%Q9J2%aL&)(n-CA00Qt3k#L8NQTfOmSJOrD@!bP(%k2Bfb_5Q6>6n9e@N*;|
z;qjxi78E2aQiOa?X<?YOM<vHpE_0&2Hq#M)(&hV3Fp@(4wgK|kTVnW(7yYsrUoc#_
z4zPTvUE@k^Yz7*P8pfQu;%PxZ?2HecQj1JSx-{ekbk5^{2?b09PZa$F!amMvcW9Ts
zoc&+erA~XCHSHp2TZr@}QE{Y3!i^$O+Qo~1gDRqj#?E!Wmo{k4zKZOw(+QA6NB(=;
zzSqF#ewN<&()ZgQ^W=EvBgfr@V3wQD|Eez_JpUzmlU!PVxK4d}jAEo*MDylqb>`Tf
z-a0fjuf}DutlC6=A|xg8`8)K@EwkX11CAGg5FXY55o$mPCHx@(iXs66sPouZ3Allj
zV2TeJl@dK=NfA0meR4z0rPKYRIn=m-dm)CDkoJ$4VK<tJhPFZ-C@_%qX>BzFVhT?K
z<>)N(UTTq$z(jz<Lv6PC8>3Uj9(M$}dDVWsjWsLSI@2=V60pj^!V@=h+juinInNOV
zLq(`P*<xWQlFH0K6v+;>5}@dnE7FTW;R#HliUew=UOx2E-TTiY{W;%L@V9<@4*ec#
zsuD|i&aS(6M|#QW-$7tF(>#7pZ=ub_Yx#HjtH)~_tkCD6obF?FiKSIv7njHv?|J>|
zu)hiStz(t@?;KT1wyP?eJjI(qzGKW;j?b;SQp$qYC<9R&*M1tTJOexV;x%%FLoLm1
z<$~abC8xDv&L6)-xp^F4<?lJkqal>~e;3j$Umv-DSucS*GmB%O=p9sjk6tHBOSd*u
zrnL47_J-g2cBABB^2fP4(`D5c(|r}Ei=#<s7@7nVdO?GVQ^?=1`fL6^95hzrRr$H#
zdAwPi_Xkw_VXBj+@Nu`hepRbEw!?9A{MkF_o;qV_#wN!qC5K1DyS6y~?4X)K@O@AZ
z^r5qu)<A+I&=zPwvIBikBwy~57G}#{fzGwfjiy`$r1o1C0{|73Tb9+?QM^?FnT`t&
zh|09jLZf{JV~Q}pY#(cX?kDYI{vJ%b(JSxYB1%P}EUaWr8nfd-4PKN<12Q96L&#`p
zbT&Hd8(#lQ!xi$=_VremK8L5NJy+t#%+X@7-KUKgvO|~I9eIlA8WD6D>drT}|4r2C
zD*q|rLAuz}X6)#>IvC5%CepW^UGj*F734ywHGuQjZWtYnLWP{rj#)g3KuP%zaMxp1
z$t~d0LJT(<4@HGSJ|#)`A<NY7yXK1gT2sL}`kXG%?ZS4x-^UvZgy*-i3xla4^c}Sz
zG*Lvlp#zPMvGr(keioy&@kKdj#M^cw$HG(X(*MCFQ?8xCzu#(J>m#8$@&YH*m$9pX
z$KYyda=aezpT|v)n%L|#{*NUu>mxJuo!P3--FX2(d!vH|3#{Tj-(}>DWnNUTA800N
zPiuK3Xc&>Hno{WzJmc8$DExc^q(SaPsE302)4cZf?62?MF1t8O36DdIOx?kAf(c2)
z-;(rIa*6w>n$U`3>80jPU;P?}wyMvft8=^8?D?IH6x_y7=BuQPvc_LH7k_{4=F!1n
zsW}^IiT)=Z59h7y)x&$>WqG`OCnwb%tEtIoqW!V*zh>w28X55?#KYgEaGH4_LJY`&
zROJXw@!q6%(W|7Xn?9Nay=TeUTk9_h;Zamk@#Ln@n*4?bm!3cv_S83kL_C~7bvrhO
zwXdp=o()$O3bQ4ONeoB^0Y`glbUnv>KJBorv*uxwR$&6<Wz>f1>iKjY59<vPMGvRy
z{Pma`D;ilSosHmia@`+BFU#(@^s#n%?PYzJ&*`PoWct3`XztPe9@@(9>OW^S^-2p2
zZHLkSCL?b%U>No25TVK(e5s+2`d{}WHWi*c$GQq#hADOc88-lCM`dw9OnfA}mlI#f
zxAwjidfMA5ohE}>`oQTaZj-w4&&+6@<9T_0hV!i-!qL-0_ABu@JGBIr59!s6$mjZ*
z%4&Sp4o6Rb_t<?MY=5hG@fn;r;t}RV;eH4to6ZMXkQy6P=_=?FKAs!Gci-aI<r~DI
zAbux$I%N<H>+Zt1L;tbXFx&n(_)ANSyv_0RJF>gs_CMctcZCU!sEMApLdDYoghWCJ
z?4i@3H*^Gw3PL2|L6!YpU0i`JkP`~Ey057<RDgD4Fxp*f&RAX7do*>EHj*>m^CrW6
z%z`I+KH-prHjfKvjsGfQXzFdWJvVTi!(eUXQARr{=u(UrFwu?4m&q`*1BB0gf!0_4
z?Dx3)=V!{)=2>JX=_bVY|0hR8?h#r4qx5^!d(;L^k`{h+h#=u87evcX(Yl^)g~sx?
zOb#^mvlK$z=+%OZNY6lWm~?l?=J|XK;Zp;HZx$MHIboRPSk<3x;TF~68BhF(Wak7i
zwTm1_kwa66GY#=224%u9I9a~3Nta_uZVto#!>=#X(u;ZfV)Iw@4GLJ-8W3$VrWo|z
zzPn2-U8Sb)E_Q1-cd?2ml4$j`HRs5{_q0Q~RAXGdv`OfJqT55qqnOqCV7e-_CrJnn
zfd7IJx39`Rl8~;KQ&vK$bH3n=99#>U>r|2+j#qLJA8prW;fU@8Fb<B7vKjj$B)P{_
z3;Uz+8R={6aP>Cn>`=uN8(Lt$Hz`Gy)u5k;b^0*mc}wJC<Q4{Y8pEn5w-7c31<eYC
z*$9QL9lmA^_B?B7eQ!Brw(qt$7<ftP&w*dZ?R2|5$6bjXIMjxQdE-U<2!I!u5$ntL
zx@7bg%!E?HhZ2F{!|&!J@6F}CGd;198BZTB>!YzkU1Z|Np#@L9Yf<%J`&uMGcxRjB
z&UMuRa#~!{(I%(IKr$2JBdi$(;dqO_ph%dJ??2)cCU~vPv`6ne=lao0hak*dPbFxJ
zTm$r_qStG;Jlon+NZH+P>Cn;G@2u%3#V)a;8W?f<hzSoFqJfd6*K%ibMwRz;Zg4p2
zI``JI4<gh_C$}%uy2c&x@1nhuna?cF3Y}{Vi`@2X7!Be9yqBBg(`E+m(p?vO&`mik
z`ui;O;K+PLL>xUsKfL%A93CLTq&1_2#vU)}>o^p5w5rA6Ii=T1Wa(0y$b$~k$FBh8
z|Ek!T8@|r`^UXbe^G~pW>X5>1`tX9yw~1qkfs3X?2*BcWzY}Pv10nHbARsAKl92}4
z{mxDnMNBO^urBAzjDL3tem0P5_n&q_kMTL=OIWc=3*!jen8taIL=LCQoAZGUl;9w>
zUJG{3`qTs5d)>QzJLNS8v9=sUU>Uq8-J#E()65l*Fx_d1b#V4Bvp6UDx4?I`R6-^g
zLc4_zUjc|viN78WyFmsGcoE3KFp+fE0Am{Z-+YYgk#*&krG@-X>h^bo8#t!EGm*1|
zxesbJPmly>v@G_Q4*HF7wbAywezWn0!iAw3)eSGM)*r)#(3MQ@rcfQ`^A=&jX&+iq
z**=ZQ(^WAM-BCGz*r4e+U4I*Y@iFK}t88p6YP`3b+5>349BhoRG~mq&tl9|7w-B+l
z>Q{}=yY!soU>eu^1_p?Y@8}L7P66DA4PzIW6m^q`#?|q2`FGskY;~v9vU<3haIxju
zjO&tFMB&aMrp);jq_Y{(u%|Ap6oX3P-qA^taJ)$zixxm{1NvT|0|7$<5}~YifN@`2
z4*s(wuERL^!yL(=mrxUK%>nRdBxj+tnU#YeVgs+^eNuA^8HH0z@z#X7T0#M|4XIH?
zOb{|GG-|;hQgz&rx?yVjqm<n8uut#-q)U%m`@6x*Qd^P4vwJ8HBe#yLp<WVL5>84H
zBohoT&5zklvkiyvfgxZ@1{;`kg+g6Z6~U-1@>dHJP2f@5)WyNf-}og9ki3jCBZtkF
zFn{@~X)`;-NT3PdO<^1(@TOr^*rLsFq2KrYYNb0t)g>mRwiEKc^8hfc8ifjh<X>Q)
zwzT1}G<szjQMYLR;hZhE=<D&Wj~cI8t<iij^0+-M%1}wAdEH-=Xvw0L@dY%XHAQOK
zkhmfcM$kp88o(FYL6AXWZdaS6m*m85TdpBA=0%cSew$HW+?DHpL<9znWthUj&Vu5m
z0P099D#S&osWmfv-d^U9^lmeA{08mfD#QZ8YY#9Mz(N4kkn&fx^KM{J7-k2zyw(!a
zFL43t{_$G=Yp~|(<Bp3{1LnI8eT(6@Whi06ttmt}7bi)XM8a&#d|$B?l)xMIh1K)W
zP2G(D9%TFGjzi42bMc7qnF=|!i47_pKII~ef}>^;nN7ajkTsT-OfEDaor6S89#8;k
z6CRotQeHbNYK+XiDU|O%N^I~_6k6z>J_kncDVK2S_gcFL!y8(f|I~NFufgNdQQMD$
z2+w&05`O3<?ikyR5oBY77KM>ySQHEE-HkWh)WQLm?1Bf3XT!G%9MfEth^$r5NfqC}
z-^CV3zK|@z&~zqAh;;@TPC<G`+>27&j6}Xf<S8&z3FJ5M=>!NcjQnEjWnlJFHoAq<
zr#HgkHRap`Yz#00@g{*558kQ+(&2T8ZV%xvjgXCvAgb`s4_{+qPksz`cRsLG42;aj
zpphL38KkY-zdAGn8Vv(sqt!)RA#~Dg2v1vUc)Pi{8@Y}(a}X5Wko!Ryi}4LWA4b<N
z__X6p=@hsJx=h)Fr^6)>)!|_zW02vW$Kd|r;@%*U<<dH{VaRpqRV$;7(cb6GkF)o1
z;6KNhyw#1De>IrNY{)sj{?x9Ro4M_(>Q-D4;fOS%486c;7FmJC9CIjtG&^u)sJ!6>
zxX`@H5J@&Rs?fsJXu>3T2D)o~Ky-|-^vx?RBkaA$yfUPXAP+JX?#lEh!0bL}^A*d^
zw1DER@N0Oqm{qGSHZAw9(Eoi^2e6L!rXw)WmtbdVIh1Aqod6a8GH6f8nWm)?U}A}}
zK1kW167=RTn9DL9XvQo6Rhc9Gh<yjXXFz*Kz@)JZcqi28@5Mo8Qj+Ev+$OSkpezn4
z#$QFSHbXnJ)aUM4yUqv#p8Ftx#wapu@<}Kct?d5Y{wDtC(3h_@0S;55N`yAcR^IDH
zDK?0XV`C{B;RVG6W^gD&GlLIif)EyKNlEIy@9+DcO5Mh>iVgx!Mo51Uwt@;_OCWa4
zJCF+xKrDalnMHrAN+(olRJ1J|ZL7g(O)z&_!)BdT-tVt?0`!;6;o%o@z}3_ty&fP|
z+`(<ewv>rQvZoNerFW88mb#+5GpSf)HsH)3Y<kD`N{N?aGY23klEqS%X#u+Oq-0`g
z$q!kLEu1rL&W1=!$lhwZxz~Amt9`Ih?DmU%&~Jtwq0t9Mc6T>)c8TXeO;j95Z}e;A
zX!K`Ko-*^<@XPSaM?4p#gZ*lOp^c$@Bw5-jyo%+*;<`IEfmIqy7ojDK@RyugNpz^i
zFE<vi(OkbPBv4};T%#W$XNeMM0ElPJTn=M4kFVSfwvaX?F^Fsiz#U5?wmF-U^Sy@4
zS5u0R3ypLjYRBauw6c+vjnMBfx!DYs!}B&cV)BB^*)Z7a!VV%5$w(1!)6Ulet*i{0
z{RYjRkI7#QK~PyEW!a^@mZ_qBufVNZg{1cBZO?;G`F(#=*6MyrtBhyTeh}SGl9*nF
zF$yyK1?CCBH4fnd-e}H%ft+%*=-%|yHqCNTS<IC^Jb&_uy1RN*pZ-g4EyXG2y&qEx
z8j{~>+$!IeBRr;_b8b{R%samRdbRLX&qp@@iO}wbKYdUR%{wu@mS#5gt|22WxOjT*
zIBnOmQjtgX7o8(=R9UbsxMg~fZT}+!z3S8mcK{QBz(tq7v)#!dsv|TZ2qGNk1XA<%
zEIF*B_TP8!L$P)u5g0QE1OxBIB1t^osycE<^uE)9_W~iIAUxxZ^CWGNOcc{g6O$q7
zDW&FQl7|C=IOb}n@G=<*63r}aPS9vH{PicAX`PwEig{N&A`l@o1XOGy8D)xj-mB`o
z<Fn69lsOcSQVh?6`@#8Jnq~n4q3P(V)mCAAKQ&rrnZ}!JLhLid(xj3n91_)n1*}O7
zFu?>3G#`>VXJLTHl>G8fE0Dtr^1&@xW}(+vlvS@o5W>qMr8LUag;}X1orvnR%i$yd
z5!9(oE>v=wXojOKvkWxRL{%tqXstOy*8A(8SEs2`2W4_d>MkE-K~i<dEczY)U+&p6
znP$&|ilqyxDUfwrM?l#ew4_tb6rm55Jw9R%y);1Qoqyaud*)ltinUxA(7?YVG}7uI
z^+Nvs4k&Nw>omZ$ISa|(Yu<-&bOt#1mO|Gjy<4Z8=bbTbj*;=w^s7XAt4{uAjcDJe
z_H6Qxed^x*Jw9&NFsn$2c5bhaJ<wmw|Gs-s+Il%D{hpGwgnQfH;LQ4h$7^2y-1m6V
zt$RVMCO!QyHMCR_c_v8Y<j`_rXr!Ryn+C-~Yf<VaPA3;Bl9!k%&x9U@zCeyk*OGTU
zz`pnoDM(=2#N8I}ItzB3U0CRUUc{7(gGrT59x_$f`?Tb(0In+pQa?@DbAQ=f^kj<#
zXy@1-o6CF;uifA3jd53CLm8$uT9i<YPNXO$M#oek@au&fY^10{s<SxqXCZY-9C`D~
z7ude9{Y%2Wx3YF}?NF~>;J;VFi_E+DKdJV=OV}NEh|qcdkJHeT#}Ub!I7mlkz0~%!
z7*e`Hj7BHV@C#?p^LzvNNzz?T8hL|iKT+EhgNm~d&6_kZ4DMl&Ky6>2cH-KHqwq#R
z3}PPh?HBOwGvw8=dKIle*pmhT(I~wdX0XYB?G&u8Jrqtz<DlMU)KHk%=1|QoQjw`D
zGg4AMw&dw@&M^DL+aPa^nH7;9iwr*(SbMxSK+kxHdt)Hof<NxkL2mUsjqIdSnD0c#
zcpS&OEz;Scc^s{LB{pnc+|i{14Zkh82{4(^Dk8A(^6Ys~i-39dlHI&?ge+ZDiluFB
zo4i91AbFX-X>1RB^Dj~8nr>@|3wH2ols=kjE(VE=k1HyQ5u!J7_hcnzL-*1<>YA}|
z)&@hra*N%g*$cHR!b3t8??l4Sd@)_}9NUwT63t1eYeBnTMRwd}QX@}}$$E|vpvoYW
zKzIg19vy_NF1>ixY(o@_y$q}&2!(sXB>-_Fo%-UH-lpd(3Ei@~S{$u_AQ@xvdqDQ+
z_qdVLzrK9FzL{d2MIp-j(u*1WUGZ$#jXU`p4{RHwuJHO3<dk|@nc0Eh@<qCfh9KV&
zDahLE?s}VSqRdYU0Fgb~5I~Z-ahpb7yO*;kP?AW?bv`9MLZK_x>8E<dQRdfv%h)JM
z6-@TVD(`if*VpRDqW#lZGfY1Zy{FM#)>Ho*@tNu8_08Y|uVC|Hijs}(EQ=TFd|ZC>
zgMsLKZ-Lw%&K+U%+~1&tC#0tHHRhRYB4s^X#4}mWmE{#z<#ljx89%3GE4#6YjkBl$
zQX)`^fDGira5d_KwfeCTet6&h_wIC%nw9KV&*Kd}n1y_cqgZ%7Q{M&{pLNWqAohvf
zHjk0_TJ<~!SwhmbT|sY7Xapu8F+TC2{J-MGFT=lJlK^DVVYIzM>{X#IID96=K;JaD
z%U{0FYSb2oLEhSWZ5v8kcIaAw|8oY{k$o--uJPHgzW1{Jb!yg~kppcD!MQj7K$}az
zj`BGm449Ij{(vbEIpA0U|44JdDFz@q@A6#gs$A1?$rI(vQGMFiO0l4E!lreOS;p+=
z{a{8PxT6oQDX3tmb<bbrpcTLXV9T}ldf7C>zOW+Hg8`5nS&;|B!aHAs-OUR2w*idY
z|J_q9iy7No>D;d{i-S;8#t;lp;W%V;)0y4$=Q4{EN?Rnj&?php2`X|Vh&4$3Vv0p8
zvP=S^&;-n*?Z?pz76k7FUiy7McG7O1!Ukwgd9prUW~ttuu6!q`t=2E!g^S=yzH*(#
zGkqw3Wo+%1FM=WkXnNV^Uf0xo-R9I(i|twzS6Lo7P*L4VmzXWJs}5)1A6DKrugZ2O
zcRLR%L?HIw@#BwL?9KKmHz7F1^s?HkeV+mqhF7s_OZhU7SKsTy7gI&NdT<~Fch6xw
zSrW%fcMAsO(C8Hr0GpC+ayk~$&2g38K^7DNS#f}u5?#WQ@b(A~C4r|Yyl^C0mZy*d
zQ+61`NT@Y97B7x0yRz_XukiVKThPHlkj&}FJk<;>0MWASkCA|Ko+c8}nNBnpmSYw!
zNXKW5KuHzw)@~tO{7lQY0F~Pt5%fMh9dp;az8Mw#l{Jx__I;Z^S7Bpokz)!|F@!mz
z8i>s`Spf9mj83AHil~*<L~5rsO?{kZtQymiMcc=EhIXi6j71s(ljP3Z(0BTFy(9PI
z#F}!M+p{a1VUm)~(<HpOY%O4e#di!lvgFk@#K<ck$7I1BRdI{f@oEVT0ba(BJgFJ%
zl1_T(+*j<jru{vJj>i53UfJq>#GG^Hk%)J5c$PY_>^nUCD8b&KYScOP{VsK#ZllR}
zz@f&D?n?(Fc501|sl^B$b!CLIk9R)+e=)nyZ2&lfAFt6VJ<ZH)Q83tx<ISdf1dFG8
z6cA|IUxD=SSB&p-VPiduF2K;l34ra|)ikKlk?_icU_IennX^phv6x?K*OAq*%Asw_
z=r+soe@4A_x)<kId-R{#s@kJj+k(Q}1@d<`St+(bRzw+r;kkhU_A0J<0e-|X0X$;_
zyU&eIt<i!><KGd-y0|Q{3rs#bo!nq`ckh+X>4(wF@O2dJ<%$3i5FkcxyBkl(1JFe4
zqk)mj+y2zFvIl+-ILg@@qW<+Bi0c3_VCJiQW4&?{itzT1o0Z|=+3V469`yY@IEjI=
z$vGsrwyfI^r=a{TS1e;nMyhZU7wRhMf^m2O-kpg@Zf4lE^eXxupI$=e-Kfe;ZNjbw
zLRXaa!1wtufwWHs5r*J=5I+?H6cCIf#|a0Wr82&0WBBr6ZFN7Z!ox3V2rsiLq5ev7
zoVLd$weCfE@dSZtG*SpKgpbI`s+o(@Rc}%8{Zf0LcT6;@sk<jef6MZr`C0GqDBH>k
z06MYxO|rUotK(qa4!F^c$Wwe63LoW81Be!C^vCXu;ixHmqD!2@0K+!K4ms6A>k=0w
z4UmEfTiM%;g%iEVC7hZFGV6!kpZ0zdjxY5OI!l}*R#`Nx;S?S@Ek;S_$k__WYzH3P
zyUvzeg_Tmc>l*O5O-^gfXU=nH8FCSevJycDT6G)m250aa!1@sV6o5XwN(1ri9JWKP
z1Djl_q!`YbdwZ^feyGW1u<<d2zp)JUE<0I_qk~0(W5Kt_1Q2`aUYaQ<<C_Ts2Y7DK
zC|Dy6PZfeeD6i0cl6|`#Tj1K=+3;;ZHUPC(+<mN~1*MDL<?PpIQkoa}Vkn11rTnY>
z(?rs6Pxm6Fd;8k1+f}N(f)ZQ9!)7ZWJhgE4K6NqqX^SboJoyJTMq^cn3E~J>p|=`}
z)zW?lgCg2(#}?8i+Rg%tC^9JAI-K!JZw{T^0xfH^Vvz+CC{13AK}u^@&S>shSt+nJ
zi7%J6Fm5&NTUo(PdCQ!gs8qPvX<Op!T}QFA+b>+Xl8{5N+~-={j87_J^hVZpd-}e7
z&N#xOzS<vJ3MWkoljCeHnI&hTco6|;Ah`N=DzVE2u*~Gs8tAZAfa$oahEl_FOJUk}
zt!`oD4eA(8DO-C=Ib)`}Nwz?ct)wxRPfh9>OeEG%%UZ@~YSFp0ayPOX=n@5!MB@mM
z<wKn>NG~Ldld(W+YS80wnQ{3Siz29?j8IWwp1PLTvZW-+#-pa%33EuPhGk|;vSUoM
z6gEydFm7_Ca_rk6PZ39Ssk2+1-olaFi_?Z4s{=F%hM0D$Y^UCsCcQY8Yht5S1W{gP
z8)eHjiZ+b1fiu%pT{J>dGeX5IN@-0I%uTl0*xB&LU0PveD4CvcRv>WD<wvVEYss4T
zW~9ZKl6OK>yRc|kGrcrVI=>uq;%Rkc&BHeQsQ6IKqhb_42`quV#?_3rY7Xw~Z!L7L
z?`x5(f^$!X-42@eV(?`eq~)qcRdj~w-tDQa_oj!PIn2Gm)TU-?le8H{(n7<Ss=ITo
z2GMACB8=d)6LN!e3zi(B%;n>gXgOA#x7FRZ9N`O#8|j&53ziC?DprLW2h7r^5ez$y
zaeCC2rg>nIQt@^zO-9x*zgzSA^V4=`t1dKZ&6kS=GlY1@n{f99YVU5)Xg+sHbElwC
zDux?$>=T92RtT`L&V5YI?!m%*ZYG$2CG@1atx-N1;NVX0b`W5mTz&NRjag{x)o5*W
z@0x!?#ZvFOFJozle=l%I;(R$Qb@gyl`Bvlf?3WVdY)1-!Wktkp_|tBstfN6U&hRQH
zA+74H2e=I(t@{pSf7BVhSK_f!Jo(aMjV<d;JFW{-4Rb5mWq_maYlq~zuY+hH#EVLM
zBL!faWgcrDBi0NIjPed2JHfn)!7cW1B?f~q%r;vFLcD<rbzFq#BLg^*fO6Dl6y6w)
z1K=dC1Bw-ME$_)D+$j+XcSF_=4FT2<vlzW*s<ZXt90(q_Ih!)K^~+7z_Y%X=<l*Zu
z*6{Ev8a$>?G?^!f5WGL?;c^wd9xJz9?QwE#Sz}}2M<?Rk$)qY7v+qaN4L!payuDUL
z5CBXIh)ZRQx=VHS=42?YA#pi4pl_)r@e~qU3-62OWjf6pZ7+XdtAW*+z#I{u<2znX
zitkJyzyQn($o@Tn5-jFQ0-IzQIdbjX$$oqQ+oRh`d9Wa%ujlMY4?~oLc|sqMF9=yM
zt)ygVhvt^|NEt_GgaA9C@;x%Y8=BS-=DaFIQM-;gM)*{93(<oJfbLtBs^tVO>;xAF
z|5kvP^CuI>21Xppup(qW?vw}<>-QfhzJ!qU-ogjrLKy)&ZRRl2%xtof>Y7ryRhD8H
zj|_H&Y*#peEdc`v`k#ZLpO+*V!_z;EV(F4nl(1yWE;QQ1mP@~fs+WGr`a~f6oNNTz
z@DCryxjxCDKWAcAv6cAo%{x9<YlDL;kC$ZZ984AfjC(B?K>CCKk(TA`XYf6Vdj2L(
zT-7;zDSH7>hEObC-f;a5s>-dg+(5nk^;p^}1?p=zQnbTn%~;D#X<V8su)b(64Iq`S
z+E%;2Mp>A~DVk`?jv(FK$%Ks~0Mhol4ThIt#P~VAMs}M!>SW}8?Y#tD(UUP!!-|Lv
zmRI}84S_Zy1;m&r3`CK{8KSVv7lq+?UK8FI!Y_;B@Nixih2dab7ev=P+1$;mU%Bq1
zB?ir^X`+!c?c-HkpIgQG{;PI%L!KnH(=$iUf6l|-S|C=%Ok32|UHZ(p-Sc38G9nwh
zrS=aqM@%L!Zzl8GfwX9Q1{M{@B93>{0FviJpi%O8ehK^%?fc3LYwYX>$hAOqjX`V3
zT<~e(co5|aWrFDI7Y-ip*G&m`g}}B4DRQ{xeV=;b&6wwRgcGHpRG=UjGcqqx#-pE9
z@@X*lbQX9F-0rA5uaXMQQ?KItZ&mlZ+(XZcqymJrL7mp911d6%T@<c2MFzbOT6n^W
zA#w+~%XxI91QTk9wM>}3UxJ}S2jY$vKMSUYY70itdfjepH0?ukcbe*3^p`?}E=mFK
zlhHJRmU}>uq`IV8;ZTzpV8H;4$so&?3|n;5w<$H7=vVo-^!n8bpx!QEmx4%*aBviu
z;VCPBG(3hEj<heSL9Rf4WDD5ZBB%3Y#0kfjJTD~MVB((jSdtLyhpRqF(@r?2L_6pq
zuIE2tUU4s3O5ox$-bl}lqp0u5B)?0oB1k@&L+TJQyW*-&NCr>gn5?X~7CI|B7vjK`
zcyVa}4G2L#m@e#c2k0J0L#&_orr46#XyRCG1r$s}K;rU%2!#2OAm5G5#XnDs(ElZu
z%&S{f^S^X&uKUm9%jDJUsjT-i#kH@qHGXmkXFT=2_Qx^zb3O+5_BBuuYcg^ovGD6d
zzl{;a7KYBWMUHlSsH;QXTJ72mnD|>e$#RQuO*7i5ryZ}3l2_yg<W?^CsEiD0D#>d`
zw6DJ5PDTgZ^83Db=`+l*)OfMSi)uRiFgE;;xnOOC1NBiVO9l&R_Xam+QG8546U>|C
z%+>vJ_0=L`x>3!LBl1jmrjrbr69xtu+oImTgV$?nf5u%#dgrzs_XU{NQb>&4sWmnA
zGUyK`&Le^Mijdin4p(uZsg63a;c_|14Nw2e*7ao=vGQ6I3K5C2Nrq3k+@uy8Q)G2>
z;MrZF6&=ge;#9F}n6e>sI$0!TXALY$%lL7*r4`4(#K%Dlm7=^b-LD3}8Y~tp%XY3G
z5QKToG!3DAbHHQJFj|4xL6)n~UB6!&3lmLe9|jD2*!cJFUb|xNOSJPlbQSfv;X!zX
z;gBtXd*fuJv<3D8K-1p6a>ck?j=n}VpGqHAA}sR*+L;AcK%ZEO3?Rs2)Q1$o;bAn%
zds$IcybaMq-#5?2(bqf&YydG=NgP8g>-@*ACbW%xE~kvu=Ei4jD7yUW==j+%i>)-|
zU~6;@?4dA*8H>80Rq`K-9u|ScU<2kbZXcY@Qfxoix+Ap)p<DzyGq{Kj7?_K%>io>V
z$?$%M>g%)l`$=}-)^{jKl(_0#pkz2^)**Qhk!$jKFapqM0<mXwlLH~5GL5_JJSUY@
zh-+wcx4NLXVl8`i0oBOR1%dYbUlx9IZC{Cv&rGtk492c-JCL*!Q8eZQ0SK}Ss2`w_
z8n%>km#>tIx~w0+$s>SYoG|Py_S?2wt(eVW8R3Mecrq|%IpiZ|A%k%oCr!%G^J_tJ
zG?3x)F@``-7_fplC9@Iatvw#in8qu>JfIX0X|vj?L@R?;D7~lSy{JHM45&<b+X6NG
z0EX#jWXBl?o}SVzMN9+W!+Y)d0T*`X)MP$OU}o4ZhE}n8(h78`%H?`kLq^_K8q;Af
zBYe+qv#*=;1Mz-jLg^C-=PAI16&R)iH4^%eGeHpm&e=3z%qmZ2zp06yAfrcll!`ve
zy?(y0XIx=s?IG2k>tSyX8pS)O2*ZTKO_ES_yHH|E670B$R0SlCKCcCDTtM?6uS`D4
zu+L`w5y^{n0tq;2-wqstw{d<U0z#Rdq5|%{fW@erNIB{(mEnD(2LM7VJUT3er2g!n
ziAatQOb91R|H5<ZYw-Xrk5|%>9A)Sq#4bRd>P*)uvjXygs~>q^&2V=s%mZj-7NCJ`
z=8O0<<%_U4O0@dsxz7>=V*gJ|z<iIEeGjDn9}`=8e;eE0|F4I$z9AWE`p5SwIr|D8
z?*!Y1;J)N)A}^Q5_I%7k=B`0{(kA5p?aB3*!O=F-qSiGV%}vB@bVzqMU|>h$?jpl6
zjJrYwG!MlWZ)PrdBnud!vd*=&Wa(nQrX&l>7}`k!5JR!iB3s~|fwA|N_QZ|;Nglj(
za=Fi-FB%d>l|JFFROu);=M19+$Sq3o!pI}jcZrYQ9Tg$YYWv@wXPl{qk2LE`vk}px
z5V_QNo=l1cj%Z+rV#q;aGIE}G!`v??mG#H!n4Rf_o;x6;5>I9-o}>Co2(k)5R6+_Y
z6p;`Siijg5EQJh<ASkh9B9bTqk}(t%SP^2uLPTOA1~Cu;VHAW}2@#A)3k3jBkz|Un
zB8wp+G7)4X6ai$A7Dy>1ibzEkMUo0gi2-2&Ko&{)><LVP6pIB2i2xBK6e5IDMIyzL
z0J212i2^936d)rADv@MVn@No}l!O&*VHZT8-~H(9hkaTQ1^6SvgWVjqi<jktEZlA@
z02I@+Drelo4{a4LpwlOQMI>So5Po=JjHD1jkOAjjhrvW4W!1yuM&JOViS#6hfYpmN
zdVHRvH}ds8PS!pRa9OAr-DeNVqqvdt+?lhVSFBULWh3JA>`WM=s6^u0Zz6<C-9P+Y
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


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 2/4] gdb/riscv: recover core file ISA features from AT_HWCAP
  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-22 15:44 ` Farid Khaidari
  2026-10-22 15:44 ` [PATCH 3/4] gdb/riscv: test the "arch=" disassembler option Farid Khaidari
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 16+ messages in thread
From: Farid Khaidari @ 2026-10-22 15:44 UTC (permalink / raw)
  To: gdb-patches
  Cc: Farid Khaidari, Andrew Burgess, Palmer Dabbelt, Timur Golubovich

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


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 3/4] gdb/riscv: test the "arch=" disassembler option
  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-22 15:44 ` [PATCH 2/4] gdb/riscv: recover core file ISA features from AT_HWCAP Farid Khaidari
@ 2026-10-22 15:44 ` Farid Khaidari
  2026-10-22 15:44 ` [PATCH 4/4] gdb/riscv: disassemble an attribute-less object by the description ISA Farid Khaidari
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 16+ messages in thread
From: Farid Khaidari @ 2026-10-22 15:44 UTC (permalink / raw)
  To: gdb-patches
  Cc: Farid Khaidari, Andrew Burgess, Palmer Dabbelt, Timur Golubovich

The test puts vector instructions into an executable built for rv64gc.
They disassemble as raw .insn words until "arch=" names an ISA with V.
The check is repeated on a copy with the architecture attribute
stripped.

One "disassemble" command uses a single disassembler for the whole
function, so the expected output covers more than the first
instruction: an option lost after it would show there.  Mapping
symbols are left to objdump tests, since GDB cannot exercise them.

Signed-off-by: Farid Khaidari <khaidari.fg@gmail.com>
---
 .../gdb.arch/riscv-disasm-arch-option.c       | 40 +++++++++
 .../gdb.arch/riscv-disasm-arch-option.exp     | 84 +++++++++++++++++++
 2 files changed, 124 insertions(+)
 create mode 100644 gdb/testsuite/gdb.arch/riscv-disasm-arch-option.c
 create mode 100644 gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp

diff --git a/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.c b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.c
new file mode 100644
index 00000000000..75857442b7e
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.c
@@ -0,0 +1,40 @@
+/* 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/>.  */
+
+/* Plant the encodings of two vector instructions in an ordinary
+   function.  The file is compiled without the vector extension, so the
+   ELF carries an rv64gc architecture attribute and the instructions
+   only decode once the disassembler is told about the vector extension
+   through the "arch=" option.  ".insn" is used rather than the
+   mnemonics because assembling those would require the vector
+   extension, which would then appear in the architecture attribute of
+   the ELF and leave the option with nothing to prove.  */
+
+void
+vector_insns (void)
+{
+  /* vsetvli t0,a0,e8,m1,ta,ma */
+  asm volatile (".insn 4, 0x0c0572d7");
+  /* vxor.vv v1,v2,v3 */
+  asm volatile (".insn 4, 0x2e2180d7");
+}
+
+int
+main (void)
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp
new file mode 100644
index 00000000000..1e6698b2e5d
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp
@@ -0,0 +1,84 @@
+# 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 the "arch=" disassembler option against an executable.  The
+# option names the ISA to disassemble for, in place of the one the
+# object records, so the test needs an object both with and without an
+# architecture attribute.
+#
+# A single "disassemble" prints the whole function through one
+# disassembler, so an ISA that survived only the first instruction would
+# show up from the second on: the expected output names both.
+
+require {istarget "riscv64-*-*"}
+
+standard_testfile
+
+# Compile without the vector extension: the executable carries an rv64gc
+# architecture attribute, and the vector instructions planted in it only
+# decode once the disassembler is told about the vector extension.
+set compile_flags {debug}
+lappend compile_flags "additional_flags=-march=rv64gc"
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile $compile_flags]} {
+    return -1
+}
+
+gdb_test "disassemble vector_insns" "\\.insn\[ \t\]+4, 0x0c0572d7.*" \
+    "vector instructions not decoded with the ISA of the object"
+
+gdb_test_no_output "set disassembler-options arch=rv64gcv" \
+    "set the arch to one with vector"
+
+gdb_test "disassemble vector_insns" \
+    "vsetvli\[ \t\]+t0,a0,e8,m1,ta,ma.*vxor\\.vv\[ \t\]+v1,v2,v3.*" \
+    "arch= overrides the ISA of the object"
+
+# Each "disassemble" builds its own disassembler, so this repetition
+# only checks that the option is still in effect for the next command,
+# not that it survived within one.
+gdb_test "disassemble vector_insns" \
+    "vsetvli\[ \t\]+t0,a0,e8,m1,ta,ma.*vxor\\.vv\[ \t\]+v1,v2,v3.*" \
+    "arch=rv64gcv still in effect for the next command"
+
+# Clearing the option returns to the ISA of the object.
+gdb_test_no_output "set disassembler-options" "clear disassembler options"
+
+gdb_test "disassemble vector_insns" "\\.insn\[ \t\]+4, 0x0c0572d7.*" \
+    "vector instructions not decoded after clearing the option"
+
+# An object that records no ISA is the case GDB supplies the option for
+# on its own.  Strip the attribute to get one that still has a symbol
+# table, which a core file cannot stand in for.
+set stripped ${testfile}-no-attributes
+set objcopy [gdb_find_objcopy]
+
+if {[run_on_host "strip the architecture attribute" $objcopy \
+	 "--remove-section=.riscv.attributes $binfile \
+	      [standard_output_file $stripped]"]} {
+    return -1
+}
+
+clean_restart $stripped
+
+gdb_test "info symbol vector_insns" "vector_insns in section .*" \
+    "the stripped binary still carries a symbol table"
+
+gdb_test_no_output "set disassembler-options arch=rv64gcv" \
+    "set the arch on an object without an attribute"
+
+gdb_test "disassemble vector_insns" \
+    "vsetvli\[ \t\]+t0,a0,e8,m1,ta,ma.*vxor\\.vv\[ \t\]+v1,v2,v3.*" \
+    "vector instructions decoded with arch=rv64gcv"
-- 
2.43.0


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 4/4] gdb/riscv: disassemble an attribute-less object by the description ISA
  2026-10-22 15:44 [PATCH 0/4] gdb/riscv: analyse a core file without the executable Farid Khaidari
                   ` (2 preceding siblings ...)
  2026-10-22 15:44 ` [PATCH 3/4] gdb/riscv: test the "arch=" disassembler option Farid Khaidari
@ 2026-10-22 15:44 ` Farid Khaidari
  2026-10-25 20:50   ` Kevin Buettner
  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
  5 siblings, 1 reply; 16+ messages in thread
From: Farid Khaidari @ 2026-10-22 15:44 UTC (permalink / raw)
  To: gdb-patches
  Cc: Farid Khaidari, Andrew Burgess, Palmer Dabbelt, Timur Golubovich

An object without a RISC-V architecture attribute is disassembled as
rv64gc, whatever the target description says.  A core file is such an
object, so its vector instructions print as raw .insn words even when
the description has vector registers.

For such objects, pass the ISA implied by the target description to
the disassembler as "arch=".  An object that records its own ISA keeps
using it.  The test checks both cases: with a vector description
loaded, an rv64gc executable must not decode the planted words as
vector instructions, and the same executable with the attribute
stripped must.

The option is set in print_insn, not through
gdbarch_disassembler_options_implicit as mips-tdep.c does.  A gdbarch
is shared by all objects with matching features, and only print_insn
knows which object it is disassembling.

User options are appended to the string for every instruction.
libopcodes clears disassembler_options after parsing and resets any
option missing from a later string, so they would be lost from the
second instruction on.

The test loads the vector description from a file.  In practice such a
description comes from a core, but a core only matches the executable
that produced it.  Only RV64 is tested; the RV32 ISA string was checked
by reading the code.

Signed-off-by: Farid Khaidari <khaidari.fg@gmail.com>
---
 gdb/riscv-tdep.c                              |  76 +++++++++++
 gdb/riscv-tdep.h                              |   5 +
 .../riscv-disasm-arch-option-vector.xml       | 123 ++++++++++++++++++
 .../gdb.arch/riscv-disasm-arch-option.exp     |  42 +++++-
 4 files changed, 245 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.arch/riscv-disasm-arch-option-vector.xml

diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index 1801b042de3..a1132b86b43 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -39,6 +39,7 @@
 #include "elf-bfd.h"
 #include "symcat.h"
 #include "dis-asm.h"
+#include "disasm.h"
 #include "frame-unwind.h"
 #include "frame-base.h"
 #include "trad-frame.h"
@@ -4201,6 +4202,44 @@ riscv_gnu_triplet_regexp (struct gdbarch *gdbarch)
   return "riscv(32|64)?";
 }
 
+/* Return true if the object owning the section being disassembled
+   records a RISC-V ISA string attribute.  */
+
+static bool
+riscv_disasm_bfd_has_isa_attribute (struct disassemble_info *info)
+{
+  if (info->section == nullptr)
+    return false;
+
+  auto *abfd = info->section->owner;
+  if (abfd == nullptr || bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+    return false;
+
+  return elf_known_obj_attributes_proc (abfd)[Tag_RISCV_arch].s != nullptr;
+}
+
+/* X register width, in bytes, implied by the RV32 base integer ISA.  */
+constexpr int riscv_xlen_32 = 4;
+
+/* Build an ISA string for the "arch=" disassembler option from
+   FEATURES, the target description of the architecture.  The option
+   replaces the rv64gc default of libopcodes, so the extension set is
+   that same default, widened by V once the target description sizes
+   the vector registers.  Naming the extensions the description does
+   know about instead would decode less than the default it replaces:
+   an ISA without G implies neither Zicsr nor Zifencei, which would
+   drop "csrr" and "fence.i" from a target that merely describes no FP
+   registers.  */
+
+static std::string
+riscv_isa_for_disassembler (const struct riscv_gdbarch_features &features)
+{
+  std::string isa = features.xlen == riscv_xlen_32 ? "rv32gc" : "rv64gc";
+  if (features.vlen > 0)
+    isa += "v";
+  return isa;
+}
+
 /* Implement the "print_insn" gdbarch method.  */
 
 static int
@@ -4212,6 +4251,37 @@ riscv_print_insn (bfd_vma addr, struct disassemble_info *info)
   if (s != nullptr)
     info->section = s->the_bfd_section;
 
+  /* An object that records its own ISA is disassembled according to
+     that ISA.  One that does not, such as a core file loaded without an
+     executable, is disassembled according to the target description;
+     libopcodes would otherwise fall back to plain rv64gc.  ARCH_OPTION
+     must outlive the default_print_insn call below, which parses it.
+
+     The user options are read from the gdbarch and appended here.
+     libopcodes clears INFO->DISASSEMBLER_OPTIONS once it has parsed
+     them, so the string has to be supplied again for the next
+     instruction; each parse first resets every option it does not see
+     back to its default, which is why the user ones have to be
+     repeated rather than parsed once.  They come last and so take
+     precedence.  */
+  std::string arch_option;
+  auto *di = static_cast<gdb_disassemble_info *> (info->application_data);
+  if (di != nullptr && !riscv_disasm_bfd_has_isa_attribute (info))
+    {
+      gdbarch *arch = di->arch ();
+      riscv_gdbarch_tdep *tdep = gdbarch_tdep<riscv_gdbarch_tdep> (arch);
+
+      arch_option = tdep->disassembler_options_arch;
+
+      const char *user_options = get_disassembler_options (arch);
+      if (user_options != nullptr && *user_options != '\0')
+	{
+	  arch_option += ',';
+	  arch_option += user_options;
+	}
+      info->disassembler_options = arch_option.c_str ();
+    }
+
   return default_print_insn (addr, info);
 }
 
@@ -4343,6 +4413,12 @@ riscv_gdbarch_init (struct gdbarch_info info,
   tdep->isa_features = features;
   tdep->abi_features = abi_features;
 
+  /* Supplied to the disassembler for an object that records no ISA of
+     its own, such as a core file loaded without an executable, which
+     libopcodes would otherwise disassemble as plain rv64gc.  */
+  std::string isa = riscv_isa_for_disassembler (features);
+  tdep->disassembler_options_arch = "arch=" + isa;
+
   /* Target data types.  */
   set_gdbarch_short_bit (gdbarch, 16);
   set_gdbarch_int_bit (gdbarch, 32);
diff --git a/gdb/riscv-tdep.h b/gdb/riscv-tdep.h
index 5fe91b7287c..d9a696fccb7 100644
--- a/gdb/riscv-tdep.h
+++ b/gdb/riscv-tdep.h
@@ -94,6 +94,11 @@ struct riscv_gdbarch_tdep : gdbarch_tdep_base
   /* ISA-specific data types.  */
   struct type *riscv_fpreg_d_type = nullptr;
 
+  /* The "arch=" disassembler option naming the ISA of ISA_FEATURES,
+     supplied to the disassembler for an object that records no ISA of
+     its own.  */
+  std::string disassembler_options_arch;
+
   /* The location of these registers, set to -2 by default so we don't
      match against -1 which is frequently used to mean "all registers",
      e.g. in the regcache supply/collect code.  */
diff --git a/gdb/testsuite/gdb.arch/riscv-disasm-arch-option-vector.xml b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option-vector.xml
new file mode 100644
index 00000000000..7f514803d51
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option-vector.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2026 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>riscv</architecture>
+  <feature name="org.gnu.gdb.riscv.cpu">
+    <reg name="zero" bitsize="64" type="int"/>
+    <reg name="ra" bitsize="64" type="code_ptr"/>
+    <reg name="sp" bitsize="64" type="data_ptr"/>
+    <reg name="gp" bitsize="64" type="data_ptr"/>
+    <reg name="tp" bitsize="64" type="data_ptr"/>
+    <reg name="t0" bitsize="64" type="int"/>
+    <reg name="t1" bitsize="64" type="int"/>
+    <reg name="t2" bitsize="64" type="int"/>
+    <reg name="fp" bitsize="64" type="data_ptr"/>
+    <reg name="s1" bitsize="64" type="int"/>
+    <reg name="a0" bitsize="64" type="int"/>
+    <reg name="a1" bitsize="64" type="int"/>
+    <reg name="a2" bitsize="64" type="int"/>
+    <reg name="a3" bitsize="64" type="int"/>
+    <reg name="a4" bitsize="64" type="int"/>
+    <reg name="a5" bitsize="64" type="int"/>
+    <reg name="a6" bitsize="64" type="int"/>
+    <reg name="a7" bitsize="64" type="int"/>
+    <reg name="s2" bitsize="64" type="int"/>
+    <reg name="s3" bitsize="64" type="int"/>
+    <reg name="s4" bitsize="64" type="int"/>
+    <reg name="s5" bitsize="64" type="int"/>
+    <reg name="s6" bitsize="64" type="int"/>
+    <reg name="s7" bitsize="64" type="int"/>
+    <reg name="s8" bitsize="64" type="int"/>
+    <reg name="s9" bitsize="64" type="int"/>
+    <reg name="s10" bitsize="64" type="int"/>
+    <reg name="s11" bitsize="64" type="int"/>
+    <reg name="t3" bitsize="64" type="int"/>
+    <reg name="t4" bitsize="64" type="int"/>
+    <reg name="t5" bitsize="64" type="int"/>
+    <reg name="t6" bitsize="64" type="int"/>
+    <reg name="pc" bitsize="64" type="code_ptr"/>
+  </feature>
+  <feature name="org.gnu.gdb.riscv.fpu">
+
+    <union id="riscv_double">
+      <field name="float" type="ieee_single"/>
+      <field name="double" type="ieee_double"/>
+    </union>
+
+    <reg name="ft0" bitsize="64" type="riscv_double" regnum="33"/>
+    <reg name="ft1" bitsize="64" type="riscv_double"/>
+    <reg name="ft2" bitsize="64" type="riscv_double"/>
+    <reg name="ft3" bitsize="64" type="riscv_double"/>
+    <reg name="ft4" bitsize="64" type="riscv_double"/>
+    <reg name="ft5" bitsize="64" type="riscv_double"/>
+    <reg name="ft6" bitsize="64" type="riscv_double"/>
+    <reg name="ft7" bitsize="64" type="riscv_double"/>
+    <reg name="fs0" bitsize="64" type="riscv_double"/>
+    <reg name="fs1" bitsize="64" type="riscv_double"/>
+    <reg name="fa0" bitsize="64" type="riscv_double"/>
+    <reg name="fa1" bitsize="64" type="riscv_double"/>
+    <reg name="fa2" bitsize="64" type="riscv_double"/>
+    <reg name="fa3" bitsize="64" type="riscv_double"/>
+    <reg name="fa4" bitsize="64" type="riscv_double"/>
+    <reg name="fa5" bitsize="64" type="riscv_double"/>
+    <reg name="fa6" bitsize="64" type="riscv_double"/>
+    <reg name="fa7" bitsize="64" type="riscv_double"/>
+    <reg name="fs2" bitsize="64" type="riscv_double"/>
+    <reg name="fs3" bitsize="64" type="riscv_double"/>
+    <reg name="fs4" bitsize="64" type="riscv_double"/>
+    <reg name="fs5" bitsize="64" type="riscv_double"/>
+    <reg name="fs6" bitsize="64" type="riscv_double"/>
+    <reg name="fs7" bitsize="64" type="riscv_double"/>
+    <reg name="fs8" bitsize="64" type="riscv_double"/>
+    <reg name="fs9" bitsize="64" type="riscv_double"/>
+    <reg name="fs10" bitsize="64" type="riscv_double"/>
+    <reg name="fs11" bitsize="64" type="riscv_double"/>
+    <reg name="ft8" bitsize="64" type="riscv_double"/>
+    <reg name="ft9" bitsize="64" type="riscv_double"/>
+    <reg name="ft10" bitsize="64" type="riscv_double"/>
+    <reg name="ft11" bitsize="64" type="riscv_double"/>
+
+    <reg name="fcsr" bitsize="32" type="int" regnum="68"/>
+  </feature>
+  <feature name="org.gnu.gdb.riscv.vector">
+    <vector id="bytes16" type="uint8" count="16"/>
+    <reg name="v0" bitsize="128" type="bytes16"/>
+    <reg name="v1" bitsize="128" type="bytes16"/>
+    <reg name="v2" bitsize="128" type="bytes16"/>
+    <reg name="v3" bitsize="128" type="bytes16"/>
+    <reg name="v4" bitsize="128" type="bytes16"/>
+    <reg name="v5" bitsize="128" type="bytes16"/>
+    <reg name="v6" bitsize="128" type="bytes16"/>
+    <reg name="v7" bitsize="128" type="bytes16"/>
+    <reg name="v8" bitsize="128" type="bytes16"/>
+    <reg name="v9" bitsize="128" type="bytes16"/>
+    <reg name="v10" bitsize="128" type="bytes16"/>
+    <reg name="v11" bitsize="128" type="bytes16"/>
+    <reg name="v12" bitsize="128" type="bytes16"/>
+    <reg name="v13" bitsize="128" type="bytes16"/>
+    <reg name="v14" bitsize="128" type="bytes16"/>
+    <reg name="v15" bitsize="128" type="bytes16"/>
+    <reg name="v16" bitsize="128" type="bytes16"/>
+    <reg name="v17" bitsize="128" type="bytes16"/>
+    <reg name="v18" bitsize="128" type="bytes16"/>
+    <reg name="v19" bitsize="128" type="bytes16"/>
+    <reg name="v20" bitsize="128" type="bytes16"/>
+    <reg name="v21" bitsize="128" type="bytes16"/>
+    <reg name="v22" bitsize="128" type="bytes16"/>
+    <reg name="v23" bitsize="128" type="bytes16"/>
+    <reg name="v24" bitsize="128" type="bytes16"/>
+    <reg name="v25" bitsize="128" type="bytes16"/>
+    <reg name="v26" bitsize="128" type="bytes16"/>
+    <reg name="v27" bitsize="128" type="bytes16"/>
+    <reg name="v28" bitsize="128" type="bytes16"/>
+    <reg name="v29" bitsize="128" type="bytes16"/>
+    <reg name="v30" bitsize="128" type="bytes16"/>
+    <reg name="v31" bitsize="128" type="bytes16"/>
+  </feature>
+</target>
diff --git a/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp
index 1e6698b2e5d..49500408f72 100644
--- a/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp
+++ b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp
@@ -16,7 +16,8 @@
 # Check the "arch=" disassembler option against an executable.  The
 # option names the ISA to disassemble for, in place of the one the
 # object records, so the test needs an object both with and without an
-# architecture attribute.
+# architecture attribute.  GDB supplies the option itself for the object
+# that records nothing, which the test checks as well.
 #
 # A single "disassemble" prints the whole function through one
 # disassembler, so an ISA that survived only the first instruction would
@@ -82,3 +83,42 @@ gdb_test_no_output "set disassembler-options arch=rv64gcv" \
 gdb_test "disassemble vector_insns" \
     "vsetvli\[ \t\]+t0,a0,e8,m1,ta,ma.*vxor\\.vv\[ \t\]+v1,v2,v3.*" \
     "vector instructions decoded with arch=rv64gcv"
+
+# For an object that records no ISA, GDB names one on its own, out of the
+# target description.  In practice a description that sizes the vector
+# registers is the one recovered from a core file, but a core only pairs
+# with the executable it was dumped from, and the instructions of this
+# one would be nowhere in the memory such a core dumped.  A description
+# loaded from a file sizes the registers the same way and pairs with any
+# executable.
+set tdesc_file "${srcdir}/${subdir}/${testfile}-vector.xml"
+
+if {[is_remote host]} {
+    set tdesc_file [remote_download host $tdesc_file]
+}
+
+# Restarting drops the option set above: what decodes the instructions
+# here is the ISA GDB supplies itself.
+clean_restart $stripped
+
+gdb_test_no_output "set tdesc filename $tdesc_file" \
+    "load a description with vector registers, object without an attribute"
+
+gdb_test "disassemble vector_insns" \
+    "vsetvli\[ \t\]+t0,a0,e8,m1,ta,ma.*vxor\\.vv\[ \t\]+v1,v2,v3.*" \
+    "the description ISA reaches the disassembler on its own"
+
+# The same description against the executable that does record rv64gc:
+# the attribute has to keep winning, so the planted encodings stay raw
+# words.  Were the description supplied here anyway, they would decode as
+# vector instructions.
+clean_restart $testfile
+
+gdb_test_no_output "set tdesc filename $tdesc_file" \
+    "load a description with vector registers"
+
+gdb_test "print sizeof (\$v0)" " = 16" \
+    "the description sizes the vector registers"
+
+gdb_test "disassemble vector_insns" "\\.insn\[ \t\]+4, 0x0c0572d7.*" \
+    "the attribute of the object outranks the description ISA"
-- 
2.43.0


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/4] gdb/riscv: recover FLEN from the NT_FPREGSET note size in core files
  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
  0 siblings, 1 reply; 16+ messages in thread
From: Kevin Buettner @ 2026-10-25 20:07 UTC (permalink / raw)
  To: Farid Khaidari, gdb-patches

Hi Farid,

On 10/22/26 8:44 AM, Farid Khaidari wrote:
> 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 +++++++++++++++++-

I don't think that riscv-tdep.c is the correct place to add knowledge
about linux specific features.  It seems to me that much of what you've
done here ought to be placed in gdb/riscv-linux-tdep.c.

If it's not truly linux-specific, but would be of benefit to other riscv
platforms, then this should be explained in the commit log as well as in
the code comments too.

Kevin


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 0/4] gdb/riscv: analyse a core file without the executable
  2026-10-22 15:44 [PATCH 0/4] gdb/riscv: analyse a core file without the executable Farid Khaidari
                   ` (3 preceding siblings ...)
  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:17 ` Kevin Buettner
  2026-10-26  9:56 ` [PATCH v2 " Farid Khaidari
  5 siblings, 0 replies; 16+ messages in thread
From: Kevin Buettner @ 2026-10-25 20:17 UTC (permalink / raw)
  To: Farid Khaidari, gdb-patches



On 10/22/26 8:44 AM, Farid Khaidari wrote:
> A RISC-V core opened without its executable gets an integer-only
> target description, because the core does not say how wide the FP
> registers are.  Any object with no ISA attribute, a core included, is
> also disassembled as plain rv64gc.
> 
> This series reads what the core does record.  The size of the
> NT_FPREGSET note gives FLEN, and AT_HWCAP gives the single-letter
> extensions.  The last patch passes the ISA of the resulting target
> description to the disassembler when the object names none.
> 
> Patches 3 and 4 need the "arch=" disassembler option, sent to
> binutils@sourceware.org as "RISC-V: add an "arch=" disassembler
> option".
> 
> Vector state from the NT_RISCV_VECTOR note is left out.  GDB can read
> the org.gnu.gdb.riscv.vector feature from a target description but
> cannot build one, so a vlen read from the core has nowhere to go yet.
> The disassembler test loads a vector description from a file instead.
> 
> Tested on x86_64-linux with a riscv64-linux-gnu target: the three new
> tests give 23 passes and no failures.  The host cannot run RISC-V
> binaries, so I did not run the rest of the testsuite.
> 
> Farid Khaidari (4):
>   gdb/riscv: recover FLEN from the NT_FPREGSET note size in core files
>   gdb/riscv: recover core file ISA features from AT_HWCAP
>   gdb/riscv: test the "arch=" disassembler option
>   gdb/riscv: disassemble an attribute-less object by the description ISA
> 
>  gdb/riscv-linux-tdep.c                        | 120 +++++++++++++
>  gdb/riscv-tdep.c                              | 167 +++++++++++++++++-
>  gdb/riscv-tdep.h                              |  14 ++
>  .../gdb.arch/riscv-core-fpregset.core.bz2     | Bin 0 -> 15134 bytes
>  .../gdb.arch/riscv-core-fpregset.exp          |  78 ++++++++
>  .../gdb.arch/riscv-core-hwcap.core.bz2        | Bin 0 -> 15122 bytes
>  gdb/testsuite/gdb.arch/riscv-core-hwcap.exp   |  72 ++++++++
>  .../riscv-disasm-arch-option-vector.xml       | 123 +++++++++++++
>  .../gdb.arch/riscv-disasm-arch-option.c       |  40 +++++
>  .../gdb.arch/riscv-disasm-arch-option.exp     | 124 +++++++++++++
>  10 files changed, 732 insertions(+), 6 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.arch/riscv-core-fpregset.core.bz2
>  create mode 100644 gdb/testsuite/gdb.arch/riscv-core-fpregset.exp
>  create mode 100644 gdb/testsuite/gdb.arch/riscv-core-hwcap.core.bz2
>  create mode 100644 gdb/testsuite/gdb.arch/riscv-core-hwcap.exp
>  create mode 100644 gdb/testsuite/gdb.arch/riscv-disasm-arch-option-vector.xml
>  create mode 100644 gdb/testsuite/gdb.arch/riscv-disasm-arch-option.c
>  create mode 100644 gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp

I ran this series, including the companion changes sent to the binutils
list, through an AI code review which included testing on a RISC-V Linux
machine.  No regressions were found; this series does what it claims.

I am replying to concerns found regarding individual patches.

Kevin


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 4/4] gdb/riscv: disassemble an attribute-less object by the description ISA
  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
  0 siblings, 1 reply; 16+ messages in thread
From: Kevin Buettner @ 2026-10-25 20:50 UTC (permalink / raw)
  To: Farid Khaidari, gdb-patches

Hi Farid,

A nit...

On 10/22/26 8:44 AM, Farid Khaidari wrote:

>  static int
> @@ -4212,6 +4251,37 @@ riscv_print_insn (bfd_vma addr, struct disassemble_info *info)
>    if (s != nullptr)
>      info->section = s->the_bfd_section;
>  
> +  /* An object that records its own ISA is disassembled according to
> +     that ISA.  One that does not, such as a core file loaded without an
> +     executable, is disassembled according to the target description;
> +     libopcodes would otherwise fall back to plain rv64gc.  ARCH_OPTION
> +     must outlive the default_print_insn call below, which parses it.
> +
> +     The user options are read from the gdbarch and appended here.
> +     libopcodes clears INFO->DISASSEMBLER_OPTIONS once it has parsed
> +     them, so the string has to be supplied again for the next
> +     instruction; each parse first resets every option it does not see
> +     back to its default, which is why the user ones have to be
> +     repeated rather than parsed once.  They come last and so take
> +     precedence.  */
> +  std::string arch_option;
> +  auto *di = static_cast<gdb_disassemble_info *> (info->application_data);
> +  if (di != nullptr && !riscv_disasm_bfd_has_isa_attribute (info))
> +    {
> +      gdbarch *arch = di->arch ();
> +      riscv_gdbarch_tdep *tdep = gdbarch_tdep<riscv_gdbarch_tdep> (arch);
> +
> +      arch_option = tdep->disassembler_options_arch;
> +
> +      const char *user_options = get_disassembler_options (arch);
> +      if (user_options != nullptr && *user_options != '\0')
> +	{
> +	  arch_option += ',';
> +	  arch_option += user_options;
> +	}
> +      info->disassembler_options = arch_option.c_str ();

This points info->disassembler_options at storage owned by a local
std::string, which is destroyed when riscv_print_insn returns.  It
only works because print_insn_riscv() sets disassembler_options to
NULL after parsing them.  (There is an early return before that, when
riscv_init_disasm_info fails, but that function currently always
returns true.)  Relying on that libopcodes behaviour seems fragile:
if print_insn_riscv ever stops clearing the field, or returns early
before doing so, the next instruction will see a dangling pointer.

Kevin


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2 0/4] gdb/riscv: analyse a core file without the executable
  2026-10-22 15:44 [PATCH 0/4] gdb/riscv: analyse a core file without the executable Farid Khaidari
                   ` (4 preceding siblings ...)
  2026-10-25 20:17 ` [PATCH 0/4] gdb/riscv: analyse a core file without the executable Kevin Buettner
@ 2026-10-26  9:56 ` 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
                     ` (4 more replies)
  5 siblings, 5 replies; 16+ messages in thread
From: Farid Khaidari @ 2026-10-26  9:56 UTC (permalink / raw)
  To: gdb-patches
  Cc: Andrew Burgess, Palmer Dabbelt, Timur Golubovich, Kevin Buettner

A RISC-V core opened without its executable gets an integer-only
target description and is disassembled as plain rv64gc.  This series
takes FLEN from the size of the NT_FPREGSET note and the single-letter
extensions from AT_HWCAP, and passes the resulting ISA to the
disassembler when the object names none.  Vector state is left out:
GDB cannot build a vector target description yet.

Patches 3 and 4 need "[PATCH v2] RISC-V: add an "arch=" disassembler
option" on binutils@sourceware.org.

Changes in v2:

- The core file code moves to riscv-linux-tdep.c as a
  core_read_description hook (patches 1 and 2).
- riscv_print_insn restores disassembler_options after each
  instruction (patch 4).
- The test core files were regenerated on a stock Linux 6.8 kernel.

Tested on x86_64-linux with a riscv64-linux-gnu target: 22 passes, no
failures, and each patch builds and passes its tests on its own.

Farid Khaidari (4):
  gdb/riscv: recover FLEN from the NT_FPREGSET note size in core files
  gdb/riscv: recover core file ISA features from AT_HWCAP
  gdb/riscv: test the "arch=" disassembler option
  gdb/riscv: disassemble an attribute-less object by the description ISA

 gdb/riscv-linux-tdep.c                        | 161 +++++++++++++++++-
 gdb/riscv-tdep.c                              |  78 ++++++++-
 gdb/riscv-tdep.h                              |  10 ++
 .../gdb.arch/riscv-core-fpregset.core.bz2     | Bin 0 -> 3204 bytes
 .../gdb.arch/riscv-core-fpregset.exp          |  73 ++++++++
 .../gdb.arch/riscv-core-hwcap.core.bz2        | Bin 0 -> 3229 bytes
 gdb/testsuite/gdb.arch/riscv-core-hwcap.exp   |  67 ++++++++
 .../riscv-disasm-arch-option-vector.xml       | 123 +++++++++++++
 .../gdb.arch/riscv-disasm-arch-option.c       |  40 +++++
 .../gdb.arch/riscv-disasm-arch-option.exp     | 119 +++++++++++++
 10 files changed, 663 insertions(+), 8 deletions(-)
 create mode 100644 gdb/testsuite/gdb.arch/riscv-core-fpregset.core.bz2
 create mode 100644 gdb/testsuite/gdb.arch/riscv-core-fpregset.exp
 create mode 100644 gdb/testsuite/gdb.arch/riscv-core-hwcap.core.bz2
 create mode 100644 gdb/testsuite/gdb.arch/riscv-core-hwcap.exp
 create mode 100644 gdb/testsuite/gdb.arch/riscv-disasm-arch-option-vector.xml
 create mode 100644 gdb/testsuite/gdb.arch/riscv-disasm-arch-option.c
 create mode 100644 gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp

-- 
2.43.0


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2 1/4] gdb/riscv: recover FLEN from the NT_FPREGSET note size in core files
  2026-10-26  9:56 ` [PATCH v2 " Farid Khaidari
@ 2026-10-26  9:56   ` Farid Khaidari
  2026-10-26  9:56   ` [PATCH v2 2/4] gdb/riscv: recover core file ISA features from AT_HWCAP Farid Khaidari
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 16+ messages in thread
From: Farid Khaidari @ 2026-10-26  9:56 UTC (permalink / raw)
  To: gdb-patches
  Cc: Andrew Burgess, Palmer Dabbelt, Timur Golubovich, Kevin Buettner

A core dumped by the Linux kernel 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.

Add a core_read_description hook for RISC-V Linux.  When e_flags says
nothing, it takes FLEN from the size of the NT_FPREGSET note: 32
registers of FLEN bytes plus fcsr padded to 8 bytes.  The size formula
moves out of riscv_linux_iterate_over_regset_sections into a helper
that both use.  The
layout is Linux-specific (FreeBSD, for one, always uses 16-byte slots),
so the hook lives in riscv-linux-tdep.c.  If the note gives nothing,
the hook returns no description and GDB behaves as before.
riscv_features_from_bfd is exported for it.

The test core is a real Linux core dump with a 264-byte NT_FPREGSET,
i.e. FLEN = 8.

Signed-off-by: Farid Khaidari <khaidari.fg@gmail.com>
---
 gdb/riscv-linux-tdep.c                        |  93 +++++++++++++++++-
 gdb/riscv-tdep.c                              |   9 +-
 gdb/riscv-tdep.h                              |  10 ++
 .../gdb.arch/riscv-core-fpregset.core.bz2     | Bin 0 -> 3204 bytes
 .../gdb.arch/riscv-core-fpregset.exp          |  73 ++++++++++++++
 5 files changed, 177 insertions(+), 8 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-linux-tdep.c b/gdb/riscv-linux-tdep.c
index fcfa5f98ea4..594f6a36f89 100644
--- a/gdb/riscv-linux-tdep.c
+++ b/gdb/riscv-linux-tdep.c
@@ -31,6 +31,7 @@
 #include "linux-record.h"
 #include "riscv-linux-tdep.h"
 #include "inferior.h"
+#include "gdbsupport/selftest.h"
 
 extern unsigned int record_debug;
 
@@ -74,6 +75,16 @@ static const struct regset riscv_linux_fregset =
   riscv_linux_fregmap, riscv_supply_regset, regcache_collect_regset
 };
 
+/* Return the size of the FP register regset for FP registers of FLEN
+   bytes: 32 registers followed by FCSR, which the kernel pads to 8
+   bytes.  */
+
+static constexpr int
+riscv_linux_fregset_size (int flen)
+{
+  return 32 * flen + 8;
+}
+
 /* Define hook for core file support.  */
 
 static void
@@ -84,9 +95,8 @@ riscv_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   cb (".reg", (32 * riscv_isa_xlen (gdbarch)), (32 * riscv_isa_xlen (gdbarch)),
       &riscv_linux_gregset, NULL, cb_data);
-  /* The kernel is adding 8 bytes for FCSR.  */
-  cb (".reg2", (32 * riscv_isa_flen (gdbarch)) + 8,
-      (32 * riscv_isa_flen (gdbarch)) + 8,
+  cb (".reg2", riscv_linux_fregset_size (riscv_isa_flen (gdbarch)),
+      riscv_linux_fregset_size (riscv_isa_flen (gdbarch)),
       &riscv_linux_fregset, NULL, cb_data);
 }
 
@@ -523,6 +533,52 @@ riscv_linux_get_syscall_number (struct gdbarch *gdbarch, thread_info *thread)
   return ret;
 }
 
+/* Return the FLEN implied by SIZE, the size of an NT_FPREGSET note, or 0
+   if SIZE matches no known layout.  This inverts
+   riscv_linux_fregset_size.  */
+
+static int
+riscv_linux_flen_from_fpregset_size (bfd_size_type size)
+{
+  for (int flen : { riscv_flen_d, riscv_flen_f })
+    if (size == riscv_linux_fregset_size (flen))
+      return flen;
+
+  return 0;
+}
+
+/* Implement the "core_read_description" gdbarch method.
+
+   A core dumped by the Linux kernel has no float ABI in its e_flags, so
+   if ABFD has an NT_FPREGSET note (the ".reg2" pseudo-section), recover
+   the FLEN from its size.  A core with an NT_GDB_TDESC note never gets
+   here; the core target uses that note directly.  */
+
+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);
+
+  asection *fpregs = bfd_get_section_by_name (abfd, ".reg2");
+  if (features.flen == 0 && fpregs != nullptr)
+    {
+      bfd_size_type size = bfd_section_size (fpregs);
+      features.flen = riscv_linux_flen_from_fpregset_size (size);
+      if (features.flen == 0)
+	warning (_("unrecognized .reg2 note size %s in core file; "
+		   "FLEN left unknown"),
+		 pulongest (size));
+    }
+
+  /* Nothing was learnt beyond the ELF header.  Let GDB fall back to its
+     default description, which also takes the executable into account.  */
+  if (features.flen == 0)
+    return nullptr;
+
+  return riscv_lookup_target_description (features);
+}
+
 /* Initialize RISC-V Linux ABI info.  */
 
 static void
@@ -555,6 +611,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 +626,38 @@ 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 an NT_FPREGSET note size maps to the right FLEN.  */
+
+static void
+riscv_linux_flen_from_fpregset_size_test ()
+{
+  for (int flen : { riscv_flen_d, riscv_flen_f })
+    SELF_CHECK (riscv_linux_flen_from_fpregset_size
+		  (riscv_linux_fregset_size (flen)) == flen);
+
+  /* Anything else leaves the FLEN unknown.  */
+  SELF_CHECK (riscv_linux_flen_from_fpregset_size (0) == 0);
+  SELF_CHECK (riscv_linux_flen_from_fpregset_size (32 * 8) == 0);
+  SELF_CHECK (riscv_linux_flen_from_fpregset_size (32 * 16 + 8) == 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-linux-flen-from-fpregset-size",
+     selftests::riscv_linux_flen_from_fpregset_size_test);
+#endif
 }
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index 68c56fbafb3..0a997231abc 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -3923,10 +3923,9 @@ static const struct frame_unwind_legacy riscv_frame_unwind (
   /*.prev_arch     =*/ NULL
 );
 
-/* 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 (const bfd *abfd)
 {
   struct riscv_gdbarch_features features;
@@ -3950,9 +3949,9 @@ 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;
 
       if (e_flags & EF_RISCV_RVE)
 	{
diff --git a/gdb/riscv-tdep.h b/gdb/riscv-tdep.h
index 344a995a680..01cb515dfbd 100644
--- a/gdb/riscv-tdep.h
+++ b/gdb/riscv-tdep.h
@@ -158,6 +158,16 @@ 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
+  (const 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-fpregset.core.bz2 b/gdb/testsuite/gdb.arch/riscv-core-fpregset.core.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..497db069ac76a81e74b7ba676b3ddf3e3a64a014
GIT binary patch
literal 3204
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

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..57e63756f77
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-core-fpregset.exp
@@ -0,0 +1,73 @@
+# 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 core file dumped by
+# the Linux kernel and opened without the executable.  Such a 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) was dumped by a stock
+# Linux 6.8 kernel.  Its PT_NOTE carries NT_FPREGSET (264 bytes) but
+# neither NT_GDB_TDESC nor any RISC-V attributes, and its 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-linux-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 Linux core and the FLEN assertions are
+# RV64-specific.
+require {istarget "riscv64-*-linux*"}
+
+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 core without executable"] != 1} {
+    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


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2 2/4] gdb/riscv: recover core file ISA features from AT_HWCAP
  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   ` Farid Khaidari
  2026-10-26  9:56   ` [PATCH v2 3/4] gdb/riscv: test the "arch=" disassembler option Farid Khaidari
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 16+ messages in thread
From: Farid Khaidari @ 2026-10-26  9:56 UTC (permalink / raw)
  To: gdb-patches
  Cc: Andrew Burgess, Palmer Dabbelt, Timur Golubovich, Kevin Buettner

When a core has neither a float ABI in e_flags nor an NT_FPREGSET
note, the RISC-V Linux core_read_description hook now reads AT_HWCAP
from the core's auxv and takes FLEN from the F and D bits.

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

The test core is a real Linux core 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                        |  72 +++++++++++++++++-
 .../gdb.arch/riscv-core-hwcap.core.bz2        | Bin 0 -> 3229 bytes
 gdb/testsuite/gdb.arch/riscv-core-hwcap.exp   |  67 ++++++++++++++++
 3 files changed, 137 insertions(+), 2 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 594f6a36f89..707852e8f54 100644
--- a/gdb/riscv-linux-tdep.c
+++ b/gdb/riscv-linux-tdep.c
@@ -31,6 +31,7 @@
 #include "linux-record.h"
 #include "riscv-linux-tdep.h"
 #include "inferior.h"
+#include "auxv.h"
 #include "gdbsupport/selftest.h"
 
 extern unsigned int record_debug;
@@ -547,12 +548,43 @@ riscv_linux_flen_from_fpregset_size (bfd_size_type size)
   return 0;
 }
 
+/* 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.  */
+
+static void
+riscv_apply_hwcap (struct riscv_gdbarch_features &features, ULONGEST hwcap)
+{
+  if (features.flen != 0)
+    return;
+
+  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.
 
    A core dumped by the Linux kernel has no float ABI in its e_flags, so
    if ABFD has an NT_FPREGSET note (the ".reg2" pseudo-section), recover
-   the FLEN from its size.  A core with an NT_GDB_TDESC note never gets
-   here; the core target uses that note directly.  */
+   the FLEN from its size; failing that, from AT_HWCAP in the core's
+   auxv.  A core with an NT_GDB_TDESC note never gets here; the core
+   target uses that note directly.  */
 
 static const struct target_desc *
 riscv_linux_core_read_description (struct gdbarch *gdbarch,
@@ -571,6 +603,9 @@ riscv_linux_core_read_description (struct gdbarch *gdbarch,
 		 pulongest (size));
     }
 
+  auto auxv = target_read_auxv_raw (target);
+  riscv_apply_hwcap (features, linux_get_hwcap (auxv, target, gdbarch));
+
   /* Nothing was learnt beyond the ELF header.  Let GDB fall back to its
      default description, which also takes the executable into account.  */
   if (features.flen == 0)
@@ -645,6 +680,37 @@ riscv_linux_flen_from_fpregset_size_test ()
   SELF_CHECK (riscv_linux_flen_from_fpregset_size (32 * 16 + 8) == 0);
 }
 
+/* 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');
+
+  /* Return features with FLEN set, refined by HWCAP.  */
+  auto apply = [] (ULONGEST hwcap, int flen = 0)
+    {
+      riscv_gdbarch_features features;
+      features.flen = flen;
+      riscv_apply_hwcap (features, hwcap);
+      return features;
+    };
+
+  /* 'd' implies double precision, 'f' single, and 'd' wins.  */
+  SELF_CHECK (apply (hwcap_d).flen == riscv_flen_d);
+  SELF_CHECK (apply (hwcap_f).flen == riscv_flen_f);
+  SELF_CHECK (apply (hwcap_d | hwcap_f).flen == riscv_flen_d);
+  SELF_CHECK (apply (0).flen == 0);
+
+  /* An FLEN already recovered from the core is not overwritten.  */
+  SELF_CHECK (apply (hwcap_d, riscv_flen_f).flen == riscv_flen_f);
+
+  /* The 'v' bit is ignored: AT_HWCAP carries no vector length.  */
+  SELF_CHECK (apply (hwcap_v).vlen == 0);
+}
+
 } /* namespace selftests */
 #endif /* GDB_SELF_TEST */
 
@@ -659,5 +725,7 @@ INIT_GDB_FILE (riscv_linux_tdep)
   selftests::register_test
     ("riscv-linux-flen-from-fpregset-size",
      selftests::riscv_linux_flen_from_fpregset_size_test);
+  selftests::register_test ("riscv-apply-hwcap",
+			    selftests::riscv_apply_hwcap_test);
 #endif
 }
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..9ced8e4c9a16d0afa823f3bde8e31288f463945a
GIT binary patch
literal 3229
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
P@BCfK6yZWb9KvM$m8QOX

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..3655cb047a0
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-core-hwcap.exp
@@ -0,0 +1,67 @@
+# 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 core it dumps
+# opened without the executable still reveals the F and D extensions.
+#
+# The bundled core (riscv-core-hwcap.core.bz2) is a real Linux 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
+# 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 of the PT_NOTE program
+# header accordingly, and bzip2 the result.
+
+# The fixture is an ELF64 Linux core and the FLEN assertions are
+# RV64-specific.
+require {istarget "riscv64-*-linux*"}
+
+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 core without executable"] != 1} {
+    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


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2 3/4] gdb/riscv: test the "arch=" disassembler option
  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   ` 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
  4 siblings, 0 replies; 16+ messages in thread
From: Farid Khaidari @ 2026-10-26  9:56 UTC (permalink / raw)
  To: gdb-patches
  Cc: Andrew Burgess, Palmer Dabbelt, Timur Golubovich, Kevin Buettner

The test puts vector instructions into an executable built for rv64gc.
They disassemble as raw .insn words until "arch=" names an ISA with V.
The check is repeated on a copy with the architecture attribute
stripped.

One "disassemble" command uses a single disassembler for the whole
function, so the expected output covers more than the first
instruction: an option lost after it would show there.  Mapping
symbols are left to objdump tests, since GDB cannot exercise them.

Signed-off-by: Farid Khaidari <khaidari.fg@gmail.com>
---
 .../gdb.arch/riscv-disasm-arch-option.c       | 40 ++++++++++
 .../gdb.arch/riscv-disasm-arch-option.exp     | 80 +++++++++++++++++++
 2 files changed, 120 insertions(+)
 create mode 100644 gdb/testsuite/gdb.arch/riscv-disasm-arch-option.c
 create mode 100644 gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp

diff --git a/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.c b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.c
new file mode 100644
index 00000000000..75857442b7e
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.c
@@ -0,0 +1,40 @@
+/* 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/>.  */
+
+/* Plant the encodings of two vector instructions in an ordinary
+   function.  The file is compiled without the vector extension, so the
+   ELF carries an rv64gc architecture attribute and the instructions
+   only decode once the disassembler is told about the vector extension
+   through the "arch=" option.  ".insn" is used rather than the
+   mnemonics because assembling those would require the vector
+   extension, which would then appear in the architecture attribute of
+   the ELF and leave the option with nothing to prove.  */
+
+void
+vector_insns (void)
+{
+  /* vsetvli t0,a0,e8,m1,ta,ma */
+  asm volatile (".insn 4, 0x0c0572d7");
+  /* vxor.vv v1,v2,v3 */
+  asm volatile (".insn 4, 0x2e2180d7");
+}
+
+int
+main (void)
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp
new file mode 100644
index 00000000000..2dd7a998eeb
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp
@@ -0,0 +1,80 @@
+# 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 the "arch=" disassembler option against an executable.  The
+# option names the ISA to disassemble for, in place of the one the
+# object records, so the test needs an object both with and without an
+# architecture attribute.
+#
+# A single "disassemble" prints the whole function through one
+# disassembler, so an ISA that survived only the first instruction would
+# show up from the second on: the expected output names both.
+
+require {istarget "riscv64-*-*"}
+
+standard_testfile
+
+# Compile without the vector extension: the executable carries an rv64gc
+# architecture attribute, and the vector instructions planted in it only
+# decode once the disassembler is told about the vector extension.
+set compile_flags {debug}
+lappend compile_flags "additional_flags=-march=rv64gc"
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile \
+	 $compile_flags]} {
+    return -1
+}
+
+# The planted words decoded as vector instructions, and left raw.
+set vector_re "vsetvli\[ \t\]+t0,a0,e8,m1,ta,ma.*vxor\\.vv\[ \t\]+v1,v2,v3.*"
+set raw_re "\\.insn\[ \t\]+4, 0x0c0572d7.*"
+
+gdb_test "disassemble vector_insns" $raw_re \
+    "vector instructions not decoded with the ISA of the object"
+
+gdb_test_no_output "set disassembler-options arch=rv64gcv" \
+    "set the arch to one with vector"
+
+gdb_test "disassemble vector_insns" $vector_re \
+    "arch= overrides the ISA of the object"
+
+# Clearing the option returns to the ISA of the object.
+gdb_test_no_output "set disassembler-options" "clear disassembler options"
+
+gdb_test "disassemble vector_insns" $raw_re \
+    "vector instructions not decoded after clearing the option"
+
+# An object that records no ISA is the case GDB supplies the option for
+# on its own.  Strip the attribute to get one that still has a symbol
+# table, which a core file cannot stand in for.
+set stripped ${testfile}-no-attributes
+set objcopy [gdb_find_objcopy]
+
+if {[run_on_host "strip the architecture attribute" $objcopy \
+	 "--remove-section=.riscv.attributes $binfile \
+	      [standard_output_file $stripped]"]} {
+    return -1
+}
+
+clean_restart $stripped
+
+gdb_test "info symbol vector_insns" "vector_insns in section .*" \
+    "the stripped binary still carries a symbol table"
+
+gdb_test_no_output "set disassembler-options arch=rv64gcv" \
+    "set the arch on an object without an attribute"
+
+gdb_test "disassemble vector_insns" $vector_re \
+    "vector instructions decoded with arch=rv64gcv"
-- 
2.43.0


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2 4/4] gdb/riscv: disassemble an attribute-less object by the description ISA
  2026-10-26  9:56 ` [PATCH v2 " Farid Khaidari
                     ` (2 preceding siblings ...)
  2026-10-26  9:56   ` [PATCH v2 3/4] gdb/riscv: test the "arch=" disassembler option Farid Khaidari
@ 2026-10-26  9:56   ` Farid Khaidari
  2026-10-27 14:31   ` [PATCH v2 0/4] gdb/riscv: analyse a core file without the executable Farid Khaidari
  4 siblings, 0 replies; 16+ messages in thread
From: Farid Khaidari @ 2026-10-26  9:56 UTC (permalink / raw)
  To: gdb-patches
  Cc: Andrew Burgess, Palmer Dabbelt, Timur Golubovich, Kevin Buettner

An object without a RISC-V architecture attribute is disassembled as
rv64gc, whatever the target description says.  A core file is such an
object, so its vector instructions print as raw .insn words even when
the description has vector registers.

For such objects, pass the ISA implied by the target description to
the disassembler as "arch=".  An object that records its own ISA keeps
using it.  The test checks both cases: with a vector description
loaded, an rv64gc executable must not decode the planted words as
vector instructions, and the same executable with the attribute
stripped must.

The option is set in print_insn, not through
gdbarch_disassembler_options_implicit as mips-tdep.c does.  A gdbarch
is shared by all objects with matching features, and only print_insn
knows which object it is disassembling.

User options are appended to the string for every instruction.
libopcodes clears disassembler_options after parsing and resets any
option missing from a later string, so they would be lost from the
second instruction on.  The string is local to print_insn, and the
previous disassembler_options value is restored after the call, so no
pointer to it outlives print_insn.

The test loads the vector description from a file.  In practice such a
description comes from a core, but a core only matches the executable
that produced it.  Only RV64 is tested; the RV32 ISA string was checked
by reading the code.

Signed-off-by: Farid Khaidari <khaidari.fg@gmail.com>
---
 gdb/riscv-tdep.c                              |  69 ++++++++++
 .../riscv-disasm-arch-option-vector.xml       | 123 ++++++++++++++++++
 .../gdb.arch/riscv-disasm-arch-option.exp     |  41 +++++-
 3 files changed, 232 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.arch/riscv-disasm-arch-option-vector.xml

diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index 0a997231abc..606bd371676 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -39,6 +39,7 @@
 #include "elf-bfd.h"
 #include "symcat.h"
 #include "dis-asm.h"
+#include "disasm.h"
 #include "frame-unwind.h"
 #include "frame-base.h"
 #include "trad-frame.h"
@@ -56,6 +57,7 @@
 #include "arch/riscv.h"
 #include "record-full.h"
 #include "riscv-ravenscar-thread.h"
+#include "gdbsupport/scope-exit.h"
 
 #include <vector>
 
@@ -4151,6 +4153,45 @@ riscv_gnu_triplet_regexp (struct gdbarch *gdbarch)
   return "riscv(32|64)?";
 }
 
+/* Return true if the object owning the section being disassembled
+   records a RISC-V ISA string attribute.  */
+
+static bool
+riscv_disasm_bfd_has_isa_attribute (struct disassemble_info *info)
+{
+  if (info->section == nullptr)
+    return false;
+
+  auto *abfd = info->section->owner;
+  if (abfd == nullptr || bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+    return false;
+
+  return elf_known_obj_attributes_proc (abfd)[Tag_RISCV_arch].s != nullptr;
+}
+
+/* X register width, in bytes, implied by the RV32 base integer ISA.  */
+constexpr int riscv_xlen_32 = 4;
+
+/* Build an ISA string for the "arch=" disassembler option from
+   FEATURES, the target description of the architecture.  The option
+   replaces the rv64gc default of libopcodes, so the extension set is
+   that same default, widened by V once the target description sizes
+   the vector registers.  Naming the extensions the description does
+   know about instead would decode less than the default it replaces:
+   an ISA without G implies neither Zicsr nor Zifencei, which would
+   drop "csrr" and "fence.i" from a target that merely describes no FP
+   registers.  An RV32E target gets rv32gc for the same reason: E only
+   removes registers, so rv32gc decodes every RV32E instruction.  */
+
+static std::string
+riscv_isa_for_disassembler (const struct riscv_gdbarch_features &features)
+{
+  std::string isa = features.xlen == riscv_xlen_32 ? "rv32gc" : "rv64gc";
+  if (features.vlen > 0)
+    isa += "v";
+  return isa;
+}
+
 /* Implement the "print_insn" gdbarch method.  */
 
 static int
@@ -4162,6 +4203,34 @@ riscv_print_insn (bfd_vma addr, struct disassemble_info *info)
   if (s != nullptr)
     info->section = s->the_bfd_section;
 
+  /* An object that records its own ISA is disassembled according to
+     that ISA.  One that does not, such as a core file loaded without an
+     executable, is disassembled according to the target description;
+     libopcodes would otherwise fall back to plain rv64gc.
+
+     The option is supplied for each instruction, since the object can
+     change between them.  Each parse resets the options it does not
+     see, so the user ones are appended, last so that they win.  INFO
+     points at the local string only for this call.  */
+  auto *di = static_cast<gdb_disassemble_info *> (info->application_data);
+  if (di == nullptr || riscv_disasm_bfd_has_isa_attribute (info))
+    return default_print_insn (addr, info);
+
+  gdbarch *arch = di->arch ();
+  riscv_gdbarch_tdep *tdep = gdbarch_tdep<riscv_gdbarch_tdep> (arch);
+  std::string options
+    = "arch=" + riscv_isa_for_disassembler (tdep->isa_features);
+
+  const char *user_options = get_disassembler_options (arch);
+  if (user_options != nullptr && *user_options != '\0')
+    {
+      options += ',';
+      options += user_options;
+    }
+
+  const char *saved_options = info->disassembler_options;
+  info->disassembler_options = options.c_str ();
+  SCOPE_EXIT { info->disassembler_options = saved_options; };
   return default_print_insn (addr, info);
 }
 
diff --git a/gdb/testsuite/gdb.arch/riscv-disasm-arch-option-vector.xml b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option-vector.xml
new file mode 100644
index 00000000000..7f514803d51
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option-vector.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2026 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>riscv</architecture>
+  <feature name="org.gnu.gdb.riscv.cpu">
+    <reg name="zero" bitsize="64" type="int"/>
+    <reg name="ra" bitsize="64" type="code_ptr"/>
+    <reg name="sp" bitsize="64" type="data_ptr"/>
+    <reg name="gp" bitsize="64" type="data_ptr"/>
+    <reg name="tp" bitsize="64" type="data_ptr"/>
+    <reg name="t0" bitsize="64" type="int"/>
+    <reg name="t1" bitsize="64" type="int"/>
+    <reg name="t2" bitsize="64" type="int"/>
+    <reg name="fp" bitsize="64" type="data_ptr"/>
+    <reg name="s1" bitsize="64" type="int"/>
+    <reg name="a0" bitsize="64" type="int"/>
+    <reg name="a1" bitsize="64" type="int"/>
+    <reg name="a2" bitsize="64" type="int"/>
+    <reg name="a3" bitsize="64" type="int"/>
+    <reg name="a4" bitsize="64" type="int"/>
+    <reg name="a5" bitsize="64" type="int"/>
+    <reg name="a6" bitsize="64" type="int"/>
+    <reg name="a7" bitsize="64" type="int"/>
+    <reg name="s2" bitsize="64" type="int"/>
+    <reg name="s3" bitsize="64" type="int"/>
+    <reg name="s4" bitsize="64" type="int"/>
+    <reg name="s5" bitsize="64" type="int"/>
+    <reg name="s6" bitsize="64" type="int"/>
+    <reg name="s7" bitsize="64" type="int"/>
+    <reg name="s8" bitsize="64" type="int"/>
+    <reg name="s9" bitsize="64" type="int"/>
+    <reg name="s10" bitsize="64" type="int"/>
+    <reg name="s11" bitsize="64" type="int"/>
+    <reg name="t3" bitsize="64" type="int"/>
+    <reg name="t4" bitsize="64" type="int"/>
+    <reg name="t5" bitsize="64" type="int"/>
+    <reg name="t6" bitsize="64" type="int"/>
+    <reg name="pc" bitsize="64" type="code_ptr"/>
+  </feature>
+  <feature name="org.gnu.gdb.riscv.fpu">
+
+    <union id="riscv_double">
+      <field name="float" type="ieee_single"/>
+      <field name="double" type="ieee_double"/>
+    </union>
+
+    <reg name="ft0" bitsize="64" type="riscv_double" regnum="33"/>
+    <reg name="ft1" bitsize="64" type="riscv_double"/>
+    <reg name="ft2" bitsize="64" type="riscv_double"/>
+    <reg name="ft3" bitsize="64" type="riscv_double"/>
+    <reg name="ft4" bitsize="64" type="riscv_double"/>
+    <reg name="ft5" bitsize="64" type="riscv_double"/>
+    <reg name="ft6" bitsize="64" type="riscv_double"/>
+    <reg name="ft7" bitsize="64" type="riscv_double"/>
+    <reg name="fs0" bitsize="64" type="riscv_double"/>
+    <reg name="fs1" bitsize="64" type="riscv_double"/>
+    <reg name="fa0" bitsize="64" type="riscv_double"/>
+    <reg name="fa1" bitsize="64" type="riscv_double"/>
+    <reg name="fa2" bitsize="64" type="riscv_double"/>
+    <reg name="fa3" bitsize="64" type="riscv_double"/>
+    <reg name="fa4" bitsize="64" type="riscv_double"/>
+    <reg name="fa5" bitsize="64" type="riscv_double"/>
+    <reg name="fa6" bitsize="64" type="riscv_double"/>
+    <reg name="fa7" bitsize="64" type="riscv_double"/>
+    <reg name="fs2" bitsize="64" type="riscv_double"/>
+    <reg name="fs3" bitsize="64" type="riscv_double"/>
+    <reg name="fs4" bitsize="64" type="riscv_double"/>
+    <reg name="fs5" bitsize="64" type="riscv_double"/>
+    <reg name="fs6" bitsize="64" type="riscv_double"/>
+    <reg name="fs7" bitsize="64" type="riscv_double"/>
+    <reg name="fs8" bitsize="64" type="riscv_double"/>
+    <reg name="fs9" bitsize="64" type="riscv_double"/>
+    <reg name="fs10" bitsize="64" type="riscv_double"/>
+    <reg name="fs11" bitsize="64" type="riscv_double"/>
+    <reg name="ft8" bitsize="64" type="riscv_double"/>
+    <reg name="ft9" bitsize="64" type="riscv_double"/>
+    <reg name="ft10" bitsize="64" type="riscv_double"/>
+    <reg name="ft11" bitsize="64" type="riscv_double"/>
+
+    <reg name="fcsr" bitsize="32" type="int" regnum="68"/>
+  </feature>
+  <feature name="org.gnu.gdb.riscv.vector">
+    <vector id="bytes16" type="uint8" count="16"/>
+    <reg name="v0" bitsize="128" type="bytes16"/>
+    <reg name="v1" bitsize="128" type="bytes16"/>
+    <reg name="v2" bitsize="128" type="bytes16"/>
+    <reg name="v3" bitsize="128" type="bytes16"/>
+    <reg name="v4" bitsize="128" type="bytes16"/>
+    <reg name="v5" bitsize="128" type="bytes16"/>
+    <reg name="v6" bitsize="128" type="bytes16"/>
+    <reg name="v7" bitsize="128" type="bytes16"/>
+    <reg name="v8" bitsize="128" type="bytes16"/>
+    <reg name="v9" bitsize="128" type="bytes16"/>
+    <reg name="v10" bitsize="128" type="bytes16"/>
+    <reg name="v11" bitsize="128" type="bytes16"/>
+    <reg name="v12" bitsize="128" type="bytes16"/>
+    <reg name="v13" bitsize="128" type="bytes16"/>
+    <reg name="v14" bitsize="128" type="bytes16"/>
+    <reg name="v15" bitsize="128" type="bytes16"/>
+    <reg name="v16" bitsize="128" type="bytes16"/>
+    <reg name="v17" bitsize="128" type="bytes16"/>
+    <reg name="v18" bitsize="128" type="bytes16"/>
+    <reg name="v19" bitsize="128" type="bytes16"/>
+    <reg name="v20" bitsize="128" type="bytes16"/>
+    <reg name="v21" bitsize="128" type="bytes16"/>
+    <reg name="v22" bitsize="128" type="bytes16"/>
+    <reg name="v23" bitsize="128" type="bytes16"/>
+    <reg name="v24" bitsize="128" type="bytes16"/>
+    <reg name="v25" bitsize="128" type="bytes16"/>
+    <reg name="v26" bitsize="128" type="bytes16"/>
+    <reg name="v27" bitsize="128" type="bytes16"/>
+    <reg name="v28" bitsize="128" type="bytes16"/>
+    <reg name="v29" bitsize="128" type="bytes16"/>
+    <reg name="v30" bitsize="128" type="bytes16"/>
+    <reg name="v31" bitsize="128" type="bytes16"/>
+  </feature>
+</target>
diff --git a/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp
index 2dd7a998eeb..2c7a85bf70c 100644
--- a/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp
+++ b/gdb/testsuite/gdb.arch/riscv-disasm-arch-option.exp
@@ -16,7 +16,8 @@
 # Check the "arch=" disassembler option against an executable.  The
 # option names the ISA to disassemble for, in place of the one the
 # object records, so the test needs an object both with and without an
-# architecture attribute.
+# architecture attribute.  GDB supplies the option itself for the object
+# that records nothing, which the test checks as well.
 #
 # A single "disassemble" prints the whole function through one
 # disassembler, so an ISA that survived only the first instruction would
@@ -78,3 +79,41 @@ gdb_test_no_output "set disassembler-options arch=rv64gcv" \
 
 gdb_test "disassemble vector_insns" $vector_re \
     "vector instructions decoded with arch=rv64gcv"
+
+# For an object that records no ISA, GDB names one on its own, out of the
+# target description.  In practice a description that sizes the vector
+# registers is the one recovered from a core file, but a core only pairs
+# with the executable it was dumped from, and the instructions of this
+# one would be nowhere in the memory such a core dumped.  A description
+# loaded from a file sizes the registers the same way and pairs with any
+# executable.
+set tdesc_file "${srcdir}/${subdir}/${testfile}-vector.xml"
+
+if {[is_remote host]} {
+    set tdesc_file [remote_download host $tdesc_file]
+}
+
+# Restarting drops the option set above: what decodes the instructions
+# here is the ISA GDB supplies itself.
+clean_restart $stripped
+
+gdb_test_no_output "set tdesc filename $tdesc_file" \
+    "load a description with vector registers, object without an attribute"
+
+gdb_test "disassemble vector_insns" $vector_re \
+    "the description ISA reaches the disassembler on its own"
+
+# The same description against the executable that does record rv64gc:
+# the attribute has to keep winning, so the planted encodings stay raw
+# words.  Were the description supplied here anyway, they would decode as
+# vector instructions.
+clean_restart $testfile
+
+gdb_test_no_output "set tdesc filename $tdesc_file" \
+    "load a description with vector registers"
+
+gdb_test "print sizeof (\$v0)" " = 16" \
+    "the description sizes the vector registers"
+
+gdb_test "disassemble vector_insns" $raw_re \
+    "the attribute of the object outranks the description ISA"
-- 
2.43.0


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/4] gdb/riscv: recover FLEN from the NT_FPREGSET note size in core files
  2026-10-25 20:07   ` Kevin Buettner
@ 2026-10-26 10:01     ` Farid Khaidari
  0 siblings, 0 replies; 16+ messages in thread
From: Farid Khaidari @ 2026-10-26 10:01 UTC (permalink / raw)
  To: Kevin Buettner; +Cc: gdb-patches

Hi Kevin,

On 10/25/26 23:07, Kevin Buettner wrote:
> I don't think that riscv-tdep.c is the correct place to add knowledge
> about linux specific features.  It seems to me that much of what you've
> done here ought to be placed in gdb/riscv-linux-tdep.c.

Thanks for the review.  It is Linux-specific: FreeBSD lays out
NT_FPREGSET in 16-byte slots, so its size says nothing about FLEN
there.  v2 moves the code to riscv-linux-tdep.c as a
core_read_description hook.

Farid

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 4/4] gdb/riscv: disassemble an attribute-less object by the description ISA
  2026-10-25 20:50   ` Kevin Buettner
@ 2026-10-26 10:01     ` Farid Khaidari
  0 siblings, 0 replies; 16+ messages in thread
From: Farid Khaidari @ 2026-10-26 10:01 UTC (permalink / raw)
  To: Kevin Buettner; +Cc: gdb-patches

Hi Kevin,

On 10/25/26 23:50, Kevin Buettner wrote:
> Relying on that libopcodes behaviour seems fragile:
> if print_insn_riscv ever stops clearing the field, or returns early
> before doing so, the next instruction will see a dangling pointer.

Agreed.  v2 saves disassembler_options and restores it with
SCOPE_EXIT, so no pointer to the local string outlives the call.

Farid

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2 0/4] gdb/riscv: analyse a core file without the executable
  2026-10-26  9:56 ` [PATCH v2 " Farid Khaidari
                     ` (3 preceding siblings ...)
  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   ` Farid Khaidari
  4 siblings, 0 replies; 16+ messages in thread
From: Farid Khaidari @ 2026-10-27 14:31 UTC (permalink / raw)
  To: gdb-patches

The opcodes "arch=" disassembler option that patches 3/4 and 4/4 depend
on is now in master as commit 6f52aa942cb.  The series applies cleanly
on top of current master.

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2026-10-27 14:32 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox