14b169a6bSchristos /* GNU/Linux/OR1K specific low level interface for the GDB server. 2*64f917f5Schristos Copyright (C) 2021-2024 Free Software Foundation, Inc. 34b169a6bSchristos 44b169a6bSchristos This file is part of GDB. 54b169a6bSchristos 64b169a6bSchristos This program is free software; you can redistribute it and/or modify 74b169a6bSchristos it under the terms of the GNU General Public License as published by 84b169a6bSchristos the Free Software Foundation; either version 3 of the License, or 94b169a6bSchristos (at your option) any later version. 104b169a6bSchristos 114b169a6bSchristos This program is distributed in the hope that it will be useful, 124b169a6bSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 134b169a6bSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 144b169a6bSchristos GNU General Public License for more details. 154b169a6bSchristos 164b169a6bSchristos You should have received a copy of the GNU General Public License 174b169a6bSchristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 184b169a6bSchristos 194b169a6bSchristos #include "linux-low.h" 204b169a6bSchristos #include "elf/common.h" 214b169a6bSchristos #include "nat/gdb_ptrace.h" 224b169a6bSchristos #include <endian.h> 234b169a6bSchristos #include "gdb_proc_service.h" 244b169a6bSchristos #include <asm/ptrace.h> 254b169a6bSchristos 264b169a6bSchristos #ifndef PTRACE_GET_THREAD_AREA 274b169a6bSchristos #define PTRACE_GET_THREAD_AREA 25 284b169a6bSchristos #endif 294b169a6bSchristos 304b169a6bSchristos /* Linux target op definitions for the OpenRISC architecture. */ 314b169a6bSchristos 324b169a6bSchristos class or1k_target : public linux_process_target 334b169a6bSchristos { 344b169a6bSchristos public: 354b169a6bSchristos 364b169a6bSchristos const regs_info *get_regs_info () override; 374b169a6bSchristos 384b169a6bSchristos const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override; 394b169a6bSchristos 404b169a6bSchristos protected: 414b169a6bSchristos 424b169a6bSchristos void low_arch_setup () override; 434b169a6bSchristos 444b169a6bSchristos bool low_cannot_fetch_register (int regno) override; 454b169a6bSchristos 464b169a6bSchristos bool low_cannot_store_register (int regno) override; 474b169a6bSchristos 484b169a6bSchristos bool low_supports_breakpoints () override; 494b169a6bSchristos 504b169a6bSchristos CORE_ADDR low_get_pc (regcache *regcache) override; 514b169a6bSchristos 524b169a6bSchristos void low_set_pc (regcache *regcache, CORE_ADDR newpc) override; 534b169a6bSchristos 544b169a6bSchristos bool low_breakpoint_at (CORE_ADDR pc) override; 554b169a6bSchristos }; 564b169a6bSchristos 574b169a6bSchristos /* The singleton target ops object. */ 584b169a6bSchristos 594b169a6bSchristos static or1k_target the_or1k_target; 604b169a6bSchristos 614b169a6bSchristos bool 624b169a6bSchristos or1k_target::low_supports_breakpoints () 634b169a6bSchristos { 644b169a6bSchristos return true; 654b169a6bSchristos } 664b169a6bSchristos 674b169a6bSchristos CORE_ADDR 684b169a6bSchristos or1k_target::low_get_pc (regcache *regcache) 694b169a6bSchristos { 704b169a6bSchristos return linux_get_pc_32bit (regcache); 714b169a6bSchristos } 724b169a6bSchristos 734b169a6bSchristos void 744b169a6bSchristos or1k_target::low_set_pc (regcache *regcache, CORE_ADDR pc) 754b169a6bSchristos { 764b169a6bSchristos linux_set_pc_32bit (regcache, pc); 774b169a6bSchristos } 784b169a6bSchristos 794b169a6bSchristos /* The following definition must agree with the number of registers 804b169a6bSchristos defined in "struct user_regs" in GLIBC 814b169a6bSchristos (sysdeps/unix/sysv/linux/or1k/sys/ucontext.h), and also with 824b169a6bSchristos OR1K_NUM_REGS in GDB proper. */ 834b169a6bSchristos 844b169a6bSchristos #define or1k_num_regs 35 854b169a6bSchristos 864b169a6bSchristos /* Defined in auto-generated file or1k-linux.c. */ 874b169a6bSchristos 884b169a6bSchristos void init_registers_or1k_linux (void); 894b169a6bSchristos extern const struct target_desc *tdesc_or1k_linux; 904b169a6bSchristos 914b169a6bSchristos /* This union is used to convert between int and byte buffer 924b169a6bSchristos representations of register contents. */ 934b169a6bSchristos 944b169a6bSchristos union or1k_register 954b169a6bSchristos { 964b169a6bSchristos unsigned char buf[4]; 974b169a6bSchristos int reg32; 984b169a6bSchristos }; 994b169a6bSchristos 1004b169a6bSchristos /* Return the ptrace ``address'' of register REGNO. */ 1014b169a6bSchristos 1024b169a6bSchristos static int or1k_regmap[] = { 1034b169a6bSchristos -1, 1, 2, 3, 4, 5, 6, 7, 1044b169a6bSchristos 8, 9, 10, 11, 12, 13, 14, 15, 1054b169a6bSchristos 16, 17, 18, 19, 20, 21, 22, 23, 1064b169a6bSchristos 24, 25, 26, 27, 28, 29, 30, 31, 1074b169a6bSchristos -1, /* PC */ 1084b169a6bSchristos -1, /* ORIGINAL R11 */ 1094b169a6bSchristos -1 /* SYSCALL NO */ 1104b169a6bSchristos }; 1114b169a6bSchristos 1124b169a6bSchristos /* Implement the low_arch_setup linux target ops method. */ 1134b169a6bSchristos 1144b169a6bSchristos void 1154b169a6bSchristos or1k_target::low_arch_setup () 1164b169a6bSchristos { 1174b169a6bSchristos current_process ()->tdesc = tdesc_or1k_linux; 1184b169a6bSchristos } 1194b169a6bSchristos 1204b169a6bSchristos /* Implement the low_cannot_fetch_register linux target ops method. */ 1214b169a6bSchristos 1224b169a6bSchristos bool 1234b169a6bSchristos or1k_target::low_cannot_fetch_register (int regno) 1244b169a6bSchristos { 1254b169a6bSchristos return (or1k_regmap[regno] == -1); 1264b169a6bSchristos } 1274b169a6bSchristos 1284b169a6bSchristos /* Implement the low_cannot_store_register linux target ops method. */ 1294b169a6bSchristos 1304b169a6bSchristos bool 1314b169a6bSchristos or1k_target::low_cannot_store_register (int regno) 1324b169a6bSchristos { 1334b169a6bSchristos return (or1k_regmap[regno] == -1); 1344b169a6bSchristos } 1354b169a6bSchristos 1364b169a6bSchristos /* Breakpoint support. */ 1374b169a6bSchristos 1384b169a6bSchristos static const unsigned int or1k_breakpoint = 0x21000001; 1394b169a6bSchristos #define or1k_breakpoint_len 4 1404b169a6bSchristos 1414b169a6bSchristos /* Implementation of target ops method "sw_breakpoint_from_kind". */ 1424b169a6bSchristos 1434b169a6bSchristos const gdb_byte * 1444b169a6bSchristos or1k_target::sw_breakpoint_from_kind (int kind, int *size) 1454b169a6bSchristos { 1464b169a6bSchristos *size = or1k_breakpoint_len; 1474b169a6bSchristos return (const gdb_byte *) &or1k_breakpoint; 1484b169a6bSchristos } 1494b169a6bSchristos 1504b169a6bSchristos /* Implement the low_breakpoint_at linux target ops method. */ 1514b169a6bSchristos 1524b169a6bSchristos bool 1534b169a6bSchristos or1k_target::low_breakpoint_at (CORE_ADDR where) 1544b169a6bSchristos { 1554b169a6bSchristos unsigned int insn; 1564b169a6bSchristos 1574b169a6bSchristos read_memory (where, (unsigned char *) &insn, or1k_breakpoint_len); 1584b169a6bSchristos if (insn == or1k_breakpoint) 1594b169a6bSchristos return true; 1604b169a6bSchristos return false; 1614b169a6bSchristos } 1624b169a6bSchristos 1634b169a6bSchristos /* Fetch the thread-local storage pointer for libthread_db. */ 1644b169a6bSchristos 1654b169a6bSchristos ps_err_e 1664b169a6bSchristos ps_get_thread_area (struct ps_prochandle *ph, 1674b169a6bSchristos lwpid_t lwpid, int idx, void **base) 1684b169a6bSchristos { 1694b169a6bSchristos if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0) 1704b169a6bSchristos return PS_ERR; 1714b169a6bSchristos 1724b169a6bSchristos /* IDX is the bias from the thread pointer to the beginning of the 1734b169a6bSchristos thread descriptor. It has to be subtracted due to implementation 1744b169a6bSchristos quirks in libthread_db. */ 1754b169a6bSchristos *base = (void *) ((char *) *base - idx); 1764b169a6bSchristos 1774b169a6bSchristos return PS_OK; 1784b169a6bSchristos } 1794b169a6bSchristos 1804b169a6bSchristos /* Helper functions to collect/supply a single register REGNO. */ 1814b169a6bSchristos 1824b169a6bSchristos static void 1834b169a6bSchristos or1k_collect_register (struct regcache *regcache, int regno, 1844b169a6bSchristos union or1k_register *reg) 1854b169a6bSchristos { 1864b169a6bSchristos union or1k_register tmp_reg; 1874b169a6bSchristos 1884b169a6bSchristos collect_register (regcache, regno, &tmp_reg.reg32); 1894b169a6bSchristos reg->reg32 = tmp_reg.reg32; 1904b169a6bSchristos } 1914b169a6bSchristos 1924b169a6bSchristos static void 1934b169a6bSchristos or1k_supply_register (struct regcache *regcache, int regno, 1944b169a6bSchristos const union or1k_register *reg) 1954b169a6bSchristos { 1964b169a6bSchristos supply_register (regcache, regno, reg->buf); 1974b169a6bSchristos } 1984b169a6bSchristos 1994b169a6bSchristos /* We have only a single register set on OpenRISC. */ 2004b169a6bSchristos 2014b169a6bSchristos static void 2024b169a6bSchristos or1k_fill_gregset (struct regcache *regcache, void *buf) 2034b169a6bSchristos { 2044b169a6bSchristos union or1k_register *regset = (union or1k_register *) buf; 2054b169a6bSchristos int i; 2064b169a6bSchristos 2074b169a6bSchristos for (i = 1; i < or1k_num_regs; i++) 2084b169a6bSchristos or1k_collect_register (regcache, i, regset + i); 2094b169a6bSchristos } 2104b169a6bSchristos 2114b169a6bSchristos static void 2124b169a6bSchristos or1k_store_gregset (struct regcache *regcache, const void *buf) 2134b169a6bSchristos { 2144b169a6bSchristos const union or1k_register *regset = (union or1k_register *) buf; 2154b169a6bSchristos int i; 2164b169a6bSchristos 2174b169a6bSchristos for (i = 0; i < or1k_num_regs; i++) 2184b169a6bSchristos or1k_supply_register (regcache, i, regset + i); 2194b169a6bSchristos } 2204b169a6bSchristos 2214b169a6bSchristos static struct regset_info or1k_regsets[] = 2224b169a6bSchristos { 2234b169a6bSchristos { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS, 2244b169a6bSchristos or1k_num_regs * 4, GENERAL_REGS, 2254b169a6bSchristos or1k_fill_gregset, or1k_store_gregset }, 2264b169a6bSchristos NULL_REGSET 2274b169a6bSchristos }; 2284b169a6bSchristos 2294b169a6bSchristos static struct regsets_info or1k_regsets_info = 2304b169a6bSchristos { 2314b169a6bSchristos or1k_regsets, /* regsets */ 2324b169a6bSchristos 0, /* num_regsets */ 2334b169a6bSchristos NULL, /* disabled_regsets */ 2344b169a6bSchristos }; 2354b169a6bSchristos 2364b169a6bSchristos static struct usrregs_info or1k_usrregs_info = 2374b169a6bSchristos { 2384b169a6bSchristos or1k_num_regs, 2394b169a6bSchristos or1k_regmap, 2404b169a6bSchristos }; 2414b169a6bSchristos 2424b169a6bSchristos static struct regs_info or1k_regs = 2434b169a6bSchristos { 2444b169a6bSchristos NULL, /* regset_bitmap */ 2454b169a6bSchristos &or1k_usrregs_info, 2464b169a6bSchristos &or1k_regsets_info 2474b169a6bSchristos }; 2484b169a6bSchristos 2494b169a6bSchristos const regs_info * 2504b169a6bSchristos or1k_target::get_regs_info () 2514b169a6bSchristos { 2524b169a6bSchristos return &or1k_regs; 2534b169a6bSchristos } 2544b169a6bSchristos 2554b169a6bSchristos /* The linux target ops object. */ 2564b169a6bSchristos 2574b169a6bSchristos linux_process_target *the_linux_target = &the_or1k_target; 2584b169a6bSchristos 2594b169a6bSchristos void 2604b169a6bSchristos initialize_low_arch (void) 2614b169a6bSchristos { 2624b169a6bSchristos init_registers_or1k_linux (); 2634b169a6bSchristos 2644b169a6bSchristos initialize_regsets_info (&or1k_regsets_info); 2654b169a6bSchristos } 266