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