xref: /netbsd-src/external/gpl3/gdb/dist/gdb/nat/riscv-linux-tdesc.c (revision f8cf1a9151c7af1cb0bd8b09c13c66bca599c027)
1 /* GNU/Linux/RISC-V native target description support for GDB.
2    Copyright (C) 2020-2024 Free Software Foundation, Inc.
3 
4    This file is part of GDB.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18 
19 
20 #include "gdb_proc_service.h"
21 #include "arch/riscv.h"
22 #include "elf/common.h"
23 #include "nat/gdb_ptrace.h"
24 #include "nat/riscv-linux-tdesc.h"
25 
26 #include <sys/uio.h>
27 
28 /* Work around glibc header breakage causing ELF_NFPREG not to be usable.  */
29 #ifndef NFPREG
30 # define NFPREG 33
31 #endif
32 
33 /* See nat/riscv-linux-tdesc.h.  */
34 
35 struct riscv_gdbarch_features
36 riscv_linux_read_features (int tid)
37 {
38   struct riscv_gdbarch_features features;
39   elf_fpregset_t regs;
40   int flen;
41 
42   /* Figuring out xlen is easy.  */
43   features.xlen = sizeof (elf_greg_t);
44 
45   /* Start with no f-registers.  */
46   features.flen = 0;
47 
48   /* How much worth of f-registers can we fetch if any?  */
49   for (flen = sizeof (regs.__f.__f[0]); ; flen *= 2)
50     {
51       size_t regset_size;
52       struct iovec iov;
53 
54       /* Regsets have a uniform slot size, so we count FSCR like
55 	 an FP data register.  */
56       regset_size = ELF_NFPREG * flen;
57       if (regset_size > sizeof (regs))
58 	break;
59 
60       iov.iov_base = &regs;
61       iov.iov_len = regset_size;
62       if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET,
63 		  (PTRACE_TYPE_ARG3) &iov) == -1)
64 	{
65 	  switch (errno)
66 	    {
67 	    case EINVAL:
68 	      continue;
69 	    case EIO:
70 	      break;
71 	    default:
72 	      perror_with_name (_("Couldn't get registers"));
73 	      break;
74 	    }
75 	}
76       else
77 	features.flen = flen;
78       break;
79     }
80 
81   return features;
82 }
83