1 /* GNU/Linux/OR1K specific low level interface for the GDB server. 2 Copyright (C) 2021-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 #include "linux-low.h" 20 #include "elf/common.h" 21 #include "nat/gdb_ptrace.h" 22 #include <endian.h> 23 #include "gdb_proc_service.h" 24 #include <asm/ptrace.h> 25 26 #ifndef PTRACE_GET_THREAD_AREA 27 #define PTRACE_GET_THREAD_AREA 25 28 #endif 29 30 /* Linux target op definitions for the OpenRISC architecture. */ 31 32 class or1k_target : public linux_process_target 33 { 34 public: 35 36 const regs_info *get_regs_info () override; 37 38 const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override; 39 40 protected: 41 42 void low_arch_setup () override; 43 44 bool low_cannot_fetch_register (int regno) override; 45 46 bool low_cannot_store_register (int regno) override; 47 48 bool low_supports_breakpoints () override; 49 50 CORE_ADDR low_get_pc (regcache *regcache) override; 51 52 void low_set_pc (regcache *regcache, CORE_ADDR newpc) override; 53 54 bool low_breakpoint_at (CORE_ADDR pc) override; 55 }; 56 57 /* The singleton target ops object. */ 58 59 static or1k_target the_or1k_target; 60 61 bool 62 or1k_target::low_supports_breakpoints () 63 { 64 return true; 65 } 66 67 CORE_ADDR 68 or1k_target::low_get_pc (regcache *regcache) 69 { 70 return linux_get_pc_32bit (regcache); 71 } 72 73 void 74 or1k_target::low_set_pc (regcache *regcache, CORE_ADDR pc) 75 { 76 linux_set_pc_32bit (regcache, pc); 77 } 78 79 /* The following definition must agree with the number of registers 80 defined in "struct user_regs" in GLIBC 81 (sysdeps/unix/sysv/linux/or1k/sys/ucontext.h), and also with 82 OR1K_NUM_REGS in GDB proper. */ 83 84 #define or1k_num_regs 35 85 86 /* Defined in auto-generated file or1k-linux.c. */ 87 88 void init_registers_or1k_linux (void); 89 extern const struct target_desc *tdesc_or1k_linux; 90 91 /* This union is used to convert between int and byte buffer 92 representations of register contents. */ 93 94 union or1k_register 95 { 96 unsigned char buf[4]; 97 int reg32; 98 }; 99 100 /* Return the ptrace ``address'' of register REGNO. */ 101 102 static int or1k_regmap[] = { 103 -1, 1, 2, 3, 4, 5, 6, 7, 104 8, 9, 10, 11, 12, 13, 14, 15, 105 16, 17, 18, 19, 20, 21, 22, 23, 106 24, 25, 26, 27, 28, 29, 30, 31, 107 -1, /* PC */ 108 -1, /* ORIGINAL R11 */ 109 -1 /* SYSCALL NO */ 110 }; 111 112 /* Implement the low_arch_setup linux target ops method. */ 113 114 void 115 or1k_target::low_arch_setup () 116 { 117 current_process ()->tdesc = tdesc_or1k_linux; 118 } 119 120 /* Implement the low_cannot_fetch_register linux target ops method. */ 121 122 bool 123 or1k_target::low_cannot_fetch_register (int regno) 124 { 125 return (or1k_regmap[regno] == -1); 126 } 127 128 /* Implement the low_cannot_store_register linux target ops method. */ 129 130 bool 131 or1k_target::low_cannot_store_register (int regno) 132 { 133 return (or1k_regmap[regno] == -1); 134 } 135 136 /* Breakpoint support. */ 137 138 static const unsigned int or1k_breakpoint = 0x21000001; 139 #define or1k_breakpoint_len 4 140 141 /* Implementation of target ops method "sw_breakpoint_from_kind". */ 142 143 const gdb_byte * 144 or1k_target::sw_breakpoint_from_kind (int kind, int *size) 145 { 146 *size = or1k_breakpoint_len; 147 return (const gdb_byte *) &or1k_breakpoint; 148 } 149 150 /* Implement the low_breakpoint_at linux target ops method. */ 151 152 bool 153 or1k_target::low_breakpoint_at (CORE_ADDR where) 154 { 155 unsigned int insn; 156 157 read_memory (where, (unsigned char *) &insn, or1k_breakpoint_len); 158 if (insn == or1k_breakpoint) 159 return true; 160 return false; 161 } 162 163 /* Fetch the thread-local storage pointer for libthread_db. */ 164 165 ps_err_e 166 ps_get_thread_area (struct ps_prochandle *ph, 167 lwpid_t lwpid, int idx, void **base) 168 { 169 if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0) 170 return PS_ERR; 171 172 /* IDX is the bias from the thread pointer to the beginning of the 173 thread descriptor. It has to be subtracted due to implementation 174 quirks in libthread_db. */ 175 *base = (void *) ((char *) *base - idx); 176 177 return PS_OK; 178 } 179 180 /* Helper functions to collect/supply a single register REGNO. */ 181 182 static void 183 or1k_collect_register (struct regcache *regcache, int regno, 184 union or1k_register *reg) 185 { 186 union or1k_register tmp_reg; 187 188 collect_register (regcache, regno, &tmp_reg.reg32); 189 reg->reg32 = tmp_reg.reg32; 190 } 191 192 static void 193 or1k_supply_register (struct regcache *regcache, int regno, 194 const union or1k_register *reg) 195 { 196 supply_register (regcache, regno, reg->buf); 197 } 198 199 /* We have only a single register set on OpenRISC. */ 200 201 static void 202 or1k_fill_gregset (struct regcache *regcache, void *buf) 203 { 204 union or1k_register *regset = (union or1k_register *) buf; 205 int i; 206 207 for (i = 1; i < or1k_num_regs; i++) 208 or1k_collect_register (regcache, i, regset + i); 209 } 210 211 static void 212 or1k_store_gregset (struct regcache *regcache, const void *buf) 213 { 214 const union or1k_register *regset = (union or1k_register *) buf; 215 int i; 216 217 for (i = 0; i < or1k_num_regs; i++) 218 or1k_supply_register (regcache, i, regset + i); 219 } 220 221 static struct regset_info or1k_regsets[] = 222 { 223 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS, 224 or1k_num_regs * 4, GENERAL_REGS, 225 or1k_fill_gregset, or1k_store_gregset }, 226 NULL_REGSET 227 }; 228 229 static struct regsets_info or1k_regsets_info = 230 { 231 or1k_regsets, /* regsets */ 232 0, /* num_regsets */ 233 NULL, /* disabled_regsets */ 234 }; 235 236 static struct usrregs_info or1k_usrregs_info = 237 { 238 or1k_num_regs, 239 or1k_regmap, 240 }; 241 242 static struct regs_info or1k_regs = 243 { 244 NULL, /* regset_bitmap */ 245 &or1k_usrregs_info, 246 &or1k_regsets_info 247 }; 248 249 const regs_info * 250 or1k_target::get_regs_info () 251 { 252 return &or1k_regs; 253 } 254 255 /* The linux target ops object. */ 256 257 linux_process_target *the_linux_target = &the_or1k_target; 258 259 void 260 initialize_low_arch (void) 261 { 262 init_registers_or1k_linux (); 263 264 initialize_regsets_info (&or1k_regsets_info); 265 } 266