17f2ac410Schristos /* Target-dependent code for GNU/Linux on RISC-V processors. 2*6881a400Schristos Copyright (C) 2018-2023 Free Software Foundation, Inc. 37f2ac410Schristos 47f2ac410Schristos This file is part of GDB. 57f2ac410Schristos 67f2ac410Schristos This program is free software; you can redistribute it and/or modify 77f2ac410Schristos it under the terms of the GNU General Public License as published by 87f2ac410Schristos the Free Software Foundation; either version 3 of the License, or 97f2ac410Schristos (at your option) any later version. 107f2ac410Schristos 117f2ac410Schristos This program is distributed in the hope that it will be useful, 127f2ac410Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 137f2ac410Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 147f2ac410Schristos GNU General Public License for more details. 157f2ac410Schristos 167f2ac410Schristos You should have received a copy of the GNU General Public License 177f2ac410Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 187f2ac410Schristos 197f2ac410Schristos #include "defs.h" 207f2ac410Schristos #include "riscv-tdep.h" 217f2ac410Schristos #include "osabi.h" 227f2ac410Schristos #include "glibc-tdep.h" 237f2ac410Schristos #include "linux-tdep.h" 247f2ac410Schristos #include "solib-svr4.h" 257f2ac410Schristos #include "regset.h" 267f2ac410Schristos #include "tramp-frame.h" 277f2ac410Schristos #include "trad-frame.h" 287d62b00eSchristos #include "gdbarch.h" 297f2ac410Schristos 30*6881a400Schristos /* The following value is derived from __NR_rt_sigreturn in 31*6881a400Schristos <include/uapi/asm-generic/unistd.h> from the Linux source tree. */ 32*6881a400Schristos 33*6881a400Schristos #define RISCV_NR_rt_sigreturn 139 34*6881a400Schristos 357f2ac410Schristos /* Define the general register mapping. The kernel puts the PC at offset 0, 367f2ac410Schristos gdb puts it at offset 32. Register x0 is always 0 and can be ignored. 377f2ac410Schristos Registers x1 to x31 are in the same place. */ 387f2ac410Schristos 397f2ac410Schristos static const struct regcache_map_entry riscv_linux_gregmap[] = 407f2ac410Schristos { 417f2ac410Schristos { 1, RISCV_PC_REGNUM, 0 }, 427f2ac410Schristos { 31, RISCV_RA_REGNUM, 0 }, /* x1 to x31 */ 437f2ac410Schristos { 0 } 447f2ac410Schristos }; 457f2ac410Schristos 467f2ac410Schristos /* Define the FP register mapping. The kernel puts the 32 FP regs first, and 477f2ac410Schristos then FCSR. */ 487f2ac410Schristos 497f2ac410Schristos static const struct regcache_map_entry riscv_linux_fregmap[] = 507f2ac410Schristos { 517f2ac410Schristos { 32, RISCV_FIRST_FP_REGNUM, 0 }, 527f2ac410Schristos { 1, RISCV_CSR_FCSR_REGNUM, 0 }, 537f2ac410Schristos { 0 } 547f2ac410Schristos }; 557f2ac410Schristos 567f2ac410Schristos /* Define the general register regset. */ 577f2ac410Schristos 587f2ac410Schristos static const struct regset riscv_linux_gregset = 597f2ac410Schristos { 60*6881a400Schristos riscv_linux_gregmap, riscv_supply_regset, regcache_collect_regset 617f2ac410Schristos }; 627f2ac410Schristos 637f2ac410Schristos /* Define the FP register regset. */ 647f2ac410Schristos 657f2ac410Schristos static const struct regset riscv_linux_fregset = 667f2ac410Schristos { 67*6881a400Schristos riscv_linux_fregmap, riscv_supply_regset, regcache_collect_regset 687f2ac410Schristos }; 697f2ac410Schristos 707f2ac410Schristos /* Define hook for core file support. */ 717f2ac410Schristos 727f2ac410Schristos static void 737f2ac410Schristos riscv_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, 747f2ac410Schristos iterate_over_regset_sections_cb *cb, 757f2ac410Schristos void *cb_data, 767f2ac410Schristos const struct regcache *regcache) 777f2ac410Schristos { 787f2ac410Schristos cb (".reg", (32 * riscv_isa_xlen (gdbarch)), (32 * riscv_isa_xlen (gdbarch)), 797f2ac410Schristos &riscv_linux_gregset, NULL, cb_data); 807f2ac410Schristos /* The kernel is adding 8 bytes for FCSR. */ 817f2ac410Schristos cb (".reg2", (32 * riscv_isa_flen (gdbarch)) + 8, 827f2ac410Schristos (32 * riscv_isa_flen (gdbarch)) + 8, 837f2ac410Schristos &riscv_linux_fregset, NULL, cb_data); 847f2ac410Schristos } 857f2ac410Schristos 867f2ac410Schristos /* Signal trampoline support. */ 877f2ac410Schristos 887f2ac410Schristos static void riscv_linux_sigframe_init (const struct tramp_frame *self, 89*6881a400Schristos frame_info_ptr this_frame, 907f2ac410Schristos struct trad_frame_cache *this_cache, 917f2ac410Schristos CORE_ADDR func); 927f2ac410Schristos 937f2ac410Schristos #define RISCV_INST_LI_A7_SIGRETURN 0x08b00893 947f2ac410Schristos #define RISCV_INST_ECALL 0x00000073 957f2ac410Schristos 967f2ac410Schristos static const struct tramp_frame riscv_linux_sigframe = { 977f2ac410Schristos SIGTRAMP_FRAME, 987f2ac410Schristos 4, 997f2ac410Schristos { 1007f2ac410Schristos { RISCV_INST_LI_A7_SIGRETURN, ULONGEST_MAX }, 1017f2ac410Schristos { RISCV_INST_ECALL, ULONGEST_MAX }, 1027f2ac410Schristos { TRAMP_SENTINEL_INSN } 1037f2ac410Schristos }, 1047f2ac410Schristos riscv_linux_sigframe_init, 1057f2ac410Schristos NULL 1067f2ac410Schristos }; 1077f2ac410Schristos 1087f2ac410Schristos /* Runtime signal frames look like this: 1097f2ac410Schristos struct rt_sigframe { 1107f2ac410Schristos struct siginfo info; 1117f2ac410Schristos struct ucontext uc; 1127f2ac410Schristos }; 1137f2ac410Schristos 1147f2ac410Schristos struct ucontext { 1157f2ac410Schristos unsigned long __uc_flags; 1167f2ac410Schristos struct ucontext *uclink; 1177f2ac410Schristos stack_t uc_stack; 1187f2ac410Schristos sigset_t uc_sigmask; 1197f2ac410Schristos char __glibc_reserved[1024 / 8 - sizeof (sigset_t)]; 1207f2ac410Schristos mcontext_t uc_mcontext; 1217f2ac410Schristos }; */ 1227f2ac410Schristos 1237f2ac410Schristos #define SIGFRAME_SIGINFO_SIZE 128 1247f2ac410Schristos #define UCONTEXT_MCONTEXT_OFFSET 176 1257f2ac410Schristos 1267f2ac410Schristos static void 1277f2ac410Schristos riscv_linux_sigframe_init (const struct tramp_frame *self, 128*6881a400Schristos frame_info_ptr this_frame, 1297f2ac410Schristos struct trad_frame_cache *this_cache, 1307f2ac410Schristos CORE_ADDR func) 1317f2ac410Schristos { 1327f2ac410Schristos struct gdbarch *gdbarch = get_frame_arch (this_frame); 1337f2ac410Schristos int xlen = riscv_isa_xlen (gdbarch); 1347f2ac410Schristos int flen = riscv_isa_flen (gdbarch); 1357f2ac410Schristos CORE_ADDR frame_sp = get_frame_sp (this_frame); 1367f2ac410Schristos CORE_ADDR mcontext_base; 1377f2ac410Schristos CORE_ADDR regs_base; 1387f2ac410Schristos 1397f2ac410Schristos mcontext_base = frame_sp + SIGFRAME_SIGINFO_SIZE + UCONTEXT_MCONTEXT_OFFSET; 1407f2ac410Schristos 1417f2ac410Schristos /* Handle the integer registers. The first one is PC, followed by x1 1427f2ac410Schristos through x31. */ 1437f2ac410Schristos regs_base = mcontext_base; 1447f2ac410Schristos trad_frame_set_reg_addr (this_cache, RISCV_PC_REGNUM, regs_base); 1457f2ac410Schristos for (int i = 1; i < 32; i++) 1467f2ac410Schristos trad_frame_set_reg_addr (this_cache, RISCV_ZERO_REGNUM + i, 1477f2ac410Schristos regs_base + (i * xlen)); 1487f2ac410Schristos 1497f2ac410Schristos /* Handle the FP registers. First comes the 32 FP registers, followed by 1507f2ac410Schristos fcsr. */ 1517f2ac410Schristos regs_base += 32 * xlen; 1527f2ac410Schristos for (int i = 0; i < 32; i++) 1537f2ac410Schristos trad_frame_set_reg_addr (this_cache, RISCV_FIRST_FP_REGNUM + i, 1547f2ac410Schristos regs_base + (i * flen)); 1557f2ac410Schristos regs_base += 32 * flen; 1567f2ac410Schristos trad_frame_set_reg_addr (this_cache, RISCV_CSR_FCSR_REGNUM, regs_base); 1577f2ac410Schristos 1587f2ac410Schristos /* Choice of the bottom of the sigframe is somewhat arbitrary. */ 1597f2ac410Schristos trad_frame_set_id (this_cache, frame_id_build (frame_sp, func)); 1607f2ac410Schristos } 1617f2ac410Schristos 162*6881a400Schristos /* When FRAME is at a syscall instruction (ECALL), return the PC of the next 163*6881a400Schristos instruction to be executed. */ 164*6881a400Schristos 165*6881a400Schristos static CORE_ADDR 166*6881a400Schristos riscv_linux_syscall_next_pc (frame_info_ptr frame) 167*6881a400Schristos { 168*6881a400Schristos const CORE_ADDR pc = get_frame_pc (frame); 169*6881a400Schristos const ULONGEST a7 = get_frame_register_unsigned (frame, RISCV_A7_REGNUM); 170*6881a400Schristos 171*6881a400Schristos if (a7 == RISCV_NR_rt_sigreturn) 172*6881a400Schristos return frame_unwind_caller_pc (frame); 173*6881a400Schristos 174*6881a400Schristos return pc + 4 /* Length of the ECALL insn. */; 175*6881a400Schristos } 176*6881a400Schristos 1777f2ac410Schristos /* Initialize RISC-V Linux ABI info. */ 1787f2ac410Schristos 1797f2ac410Schristos static void 1807f2ac410Schristos riscv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 1817f2ac410Schristos { 182*6881a400Schristos riscv_gdbarch_tdep *tdep = gdbarch_tdep<riscv_gdbarch_tdep> (gdbarch); 183*6881a400Schristos 184*6881a400Schristos linux_init_abi (info, gdbarch, 0); 1857f2ac410Schristos 1867f2ac410Schristos set_gdbarch_software_single_step (gdbarch, riscv_software_single_step); 1877f2ac410Schristos 1887f2ac410Schristos set_solib_svr4_fetch_link_map_offsets (gdbarch, 1897f2ac410Schristos (riscv_isa_xlen (gdbarch) == 4 190*6881a400Schristos ? linux_ilp32_fetch_link_map_offsets 191*6881a400Schristos : linux_lp64_fetch_link_map_offsets)); 1927f2ac410Schristos 1937f2ac410Schristos /* GNU/Linux uses SVR4-style shared libraries. */ 1947f2ac410Schristos set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); 1957f2ac410Schristos 1967f2ac410Schristos /* GNU/Linux uses the dynamic linker included in the GNU C Library. */ 1977f2ac410Schristos set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); 1987f2ac410Schristos 1997f2ac410Schristos /* Enable TLS support. */ 2007f2ac410Schristos set_gdbarch_fetch_tls_load_module_address (gdbarch, 2017f2ac410Schristos svr4_fetch_objfile_link_map); 2027f2ac410Schristos 2037f2ac410Schristos set_gdbarch_iterate_over_regset_sections 2047f2ac410Schristos (gdbarch, riscv_linux_iterate_over_regset_sections); 2057f2ac410Schristos 2067f2ac410Schristos tramp_frame_prepend_unwinder (gdbarch, &riscv_linux_sigframe); 207*6881a400Schristos 208*6881a400Schristos tdep->syscall_next_pc = riscv_linux_syscall_next_pc; 2097f2ac410Schristos } 2107f2ac410Schristos 2117f2ac410Schristos /* Initialize RISC-V Linux target support. */ 2127f2ac410Schristos 2137d62b00eSchristos void _initialize_riscv_linux_tdep (); 2147f2ac410Schristos void 2157d62b00eSchristos _initialize_riscv_linux_tdep () 2167f2ac410Schristos { 2177f2ac410Schristos gdbarch_register_osabi (bfd_arch_riscv, 0, GDB_OSABI_LINUX, 2187f2ac410Schristos riscv_linux_init_abi); 2197f2ac410Schristos } 220