1*6881a400Schristos /* Target-dependent code for NetBSD/alpha. 2*6881a400Schristos 3*6881a400Schristos Copyright (C) 2002-2023 Free Software Foundation, Inc. 4*6881a400Schristos 5*6881a400Schristos Contributed by Wasabi Systems, Inc. 6*6881a400Schristos 7*6881a400Schristos This file is part of GDB. 8*6881a400Schristos 9*6881a400Schristos This program is free software; you can redistribute it and/or modify 10*6881a400Schristos it under the terms of the GNU General Public License as published by 11*6881a400Schristos the Free Software Foundation; either version 3 of the License, or 12*6881a400Schristos (at your option) any later version. 13*6881a400Schristos 14*6881a400Schristos This program is distributed in the hope that it will be useful, 15*6881a400Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 16*6881a400Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17*6881a400Schristos GNU General Public License for more details. 18*6881a400Schristos 19*6881a400Schristos You should have received a copy of the GNU General Public License 20*6881a400Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 21*6881a400Schristos 22*6881a400Schristos #include "defs.h" 23*6881a400Schristos #include "frame.h" 24*6881a400Schristos #include "gdbcore.h" 25*6881a400Schristos #include "osabi.h" 26*6881a400Schristos #include "regcache.h" 27*6881a400Schristos #include "regset.h" 28*6881a400Schristos #include "value.h" 29*6881a400Schristos 30*6881a400Schristos #include "alpha-tdep.h" 31*6881a400Schristos #include "alpha-bsd-tdep.h" 32*6881a400Schristos #include "netbsd-tdep.h" 33*6881a400Schristos #include "solib-svr4.h" 34*6881a400Schristos #include "target.h" 35*6881a400Schristos 36*6881a400Schristos /* Core file support. */ 37*6881a400Schristos 38*6881a400Schristos /* Sizeof `struct reg' in <machine/reg.h>. */ 39*6881a400Schristos #define ALPHANBSD_SIZEOF_GREGS (32 * 8) 40*6881a400Schristos 41*6881a400Schristos /* Sizeof `struct fpreg' in <machine/reg.h. */ 42*6881a400Schristos #define ALPHANBSD_SIZEOF_FPREGS ((32 * 8) + 8) 43*6881a400Schristos 44*6881a400Schristos /* Supply register REGNUM from the buffer specified by FPREGS and LEN 45*6881a400Schristos in the floating-point register set REGSET to register cache 46*6881a400Schristos REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ 47*6881a400Schristos 48*6881a400Schristos static void 49*6881a400Schristos alphanbsd_supply_fpregset (const struct regset *regset, 50*6881a400Schristos struct regcache *regcache, 51*6881a400Schristos int regnum, const void *fpregs, size_t len) 52*6881a400Schristos { 53*6881a400Schristos const gdb_byte *regs = (const gdb_byte *) fpregs; 54*6881a400Schristos int i; 55*6881a400Schristos 56*6881a400Schristos gdb_assert (len >= ALPHANBSD_SIZEOF_FPREGS); 57*6881a400Schristos 58*6881a400Schristos for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; i++) 59*6881a400Schristos { 60*6881a400Schristos if (regnum == i || regnum == -1) 61*6881a400Schristos regcache->raw_supply (i, regs + (i - ALPHA_FP0_REGNUM) * 8); 62*6881a400Schristos } 63*6881a400Schristos 64*6881a400Schristos if (regnum == ALPHA_FPCR_REGNUM || regnum == -1) 65*6881a400Schristos regcache->raw_supply (ALPHA_FPCR_REGNUM, regs + 32 * 8); 66*6881a400Schristos } 67*6881a400Schristos 68*6881a400Schristos /* Supply register REGNUM from the buffer specified by GREGS and LEN 69*6881a400Schristos in the general-purpose register set REGSET to register cache 70*6881a400Schristos REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ 71*6881a400Schristos 72*6881a400Schristos static void 73*6881a400Schristos alphanbsd_aout_supply_gregset (const struct regset *regset, 74*6881a400Schristos struct regcache *regcache, 75*6881a400Schristos int regnum, const void *gregs, size_t len) 76*6881a400Schristos { 77*6881a400Schristos const gdb_byte *regs = (const gdb_byte *) gregs; 78*6881a400Schristos int i; 79*6881a400Schristos 80*6881a400Schristos /* Table to map a GDB register number to a trapframe register index. */ 81*6881a400Schristos static const int regmap[] = 82*6881a400Schristos { 83*6881a400Schristos 0, 1, 2, 3, 84*6881a400Schristos 4, 5, 6, 7, 85*6881a400Schristos 8, 9, 10, 11, 86*6881a400Schristos 12, 13, 14, 15, 87*6881a400Schristos 30, 31, 32, 16, 88*6881a400Schristos 17, 18, 19, 20, 89*6881a400Schristos 21, 22, 23, 24, 90*6881a400Schristos 25, 29, 26 91*6881a400Schristos }; 92*6881a400Schristos 93*6881a400Schristos gdb_assert (len >= ALPHANBSD_SIZEOF_GREGS); 94*6881a400Schristos 95*6881a400Schristos for (i = 0; i < ARRAY_SIZE(regmap); i++) 96*6881a400Schristos { 97*6881a400Schristos if (regnum == i || regnum == -1) 98*6881a400Schristos regcache->raw_supply (i, regs + regmap[i] * 8); 99*6881a400Schristos } 100*6881a400Schristos 101*6881a400Schristos if (regnum == ALPHA_PC_REGNUM || regnum == -1) 102*6881a400Schristos regcache->raw_supply (ALPHA_PC_REGNUM, regs + 31 * 8); 103*6881a400Schristos 104*6881a400Schristos if (len >= ALPHANBSD_SIZEOF_GREGS + ALPHANBSD_SIZEOF_FPREGS) 105*6881a400Schristos { 106*6881a400Schristos regs += ALPHANBSD_SIZEOF_GREGS; 107*6881a400Schristos len -= ALPHANBSD_SIZEOF_GREGS; 108*6881a400Schristos alphanbsd_supply_fpregset (regset, regcache, regnum, regs, len); 109*6881a400Schristos } 110*6881a400Schristos } 111*6881a400Schristos 112*6881a400Schristos /* Supply register REGNUM from the buffer specified by GREGS and LEN 113*6881a400Schristos in the general-purpose register set REGSET to register cache 114*6881a400Schristos REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ 115*6881a400Schristos 116*6881a400Schristos static void 117*6881a400Schristos alphanbsd_supply_gregset (const struct regset *regset, 118*6881a400Schristos struct regcache *regcache, 119*6881a400Schristos int regnum, const void *gregs, size_t len) 120*6881a400Schristos { 121*6881a400Schristos const gdb_byte *regs = (const gdb_byte *) gregs; 122*6881a400Schristos int i; 123*6881a400Schristos 124*6881a400Schristos if (len >= ALPHANBSD_SIZEOF_GREGS + ALPHANBSD_SIZEOF_FPREGS) 125*6881a400Schristos { 126*6881a400Schristos alphanbsd_aout_supply_gregset (regset, regcache, regnum, gregs, len); 127*6881a400Schristos return; 128*6881a400Schristos } 129*6881a400Schristos 130*6881a400Schristos for (i = 0; i < ALPHA_ZERO_REGNUM; i++) 131*6881a400Schristos { 132*6881a400Schristos if (regnum == i || regnum == -1) 133*6881a400Schristos regcache->raw_supply (i, regs + i * 8); 134*6881a400Schristos } 135*6881a400Schristos 136*6881a400Schristos if (regnum == ALPHA_PC_REGNUM || regnum == -1) 137*6881a400Schristos regcache->raw_supply (ALPHA_PC_REGNUM, regs + 31 * 8); 138*6881a400Schristos } 139*6881a400Schristos 140*6881a400Schristos /* NetBSD/alpha register sets. */ 141*6881a400Schristos 142*6881a400Schristos static const struct regset alphanbsd_gregset = 143*6881a400Schristos { 144*6881a400Schristos NULL, 145*6881a400Schristos alphanbsd_supply_gregset, 146*6881a400Schristos NULL, 147*6881a400Schristos REGSET_VARIABLE_SIZE 148*6881a400Schristos }; 149*6881a400Schristos 150*6881a400Schristos static const struct regset alphanbsd_fpregset = 151*6881a400Schristos { 152*6881a400Schristos NULL, 153*6881a400Schristos alphanbsd_supply_fpregset 154*6881a400Schristos }; 155*6881a400Schristos 156*6881a400Schristos /* Iterate over supported core file register note sections. */ 157*6881a400Schristos 158*6881a400Schristos void 159*6881a400Schristos alphanbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, 160*6881a400Schristos iterate_over_regset_sections_cb *cb, 161*6881a400Schristos void *cb_data, 162*6881a400Schristos const struct regcache *regcache) 163*6881a400Schristos { 164*6881a400Schristos cb (".reg", ALPHANBSD_SIZEOF_GREGS, ALPHANBSD_SIZEOF_GREGS, 165*6881a400Schristos &alphanbsd_gregset, NULL, cb_data); 166*6881a400Schristos cb (".reg2", ALPHANBSD_SIZEOF_FPREGS, ALPHANBSD_SIZEOF_FPREGS, 167*6881a400Schristos &alphanbsd_fpregset, NULL, cb_data); 168*6881a400Schristos } 169*6881a400Schristos 170*6881a400Schristos 171*6881a400Schristos /* Signal trampolines. */ 172*6881a400Schristos 173*6881a400Schristos /* Under NetBSD/alpha, signal handler invocations can be identified by the 174*6881a400Schristos designated code sequence that is used to return from a signal handler. 175*6881a400Schristos In particular, the return address of a signal handler points to the 176*6881a400Schristos following code sequence: 177*6881a400Schristos 178*6881a400Schristos ldq a0, 0(sp) 179*6881a400Schristos lda sp, 16(sp) 180*6881a400Schristos lda v0, 295(zero) # __sigreturn14 181*6881a400Schristos call_pal callsys 182*6881a400Schristos 183*6881a400Schristos Each instruction has a unique encoding, so we simply attempt to match 184*6881a400Schristos the instruction the PC is pointing to with any of the above instructions. 185*6881a400Schristos If there is a hit, we know the offset to the start of the designated 186*6881a400Schristos sequence and can then check whether we really are executing in the 187*6881a400Schristos signal trampoline. If not, -1 is returned, otherwise the offset from the 188*6881a400Schristos start of the return sequence is returned. */ 189*6881a400Schristos static const gdb_byte sigtramp_retcode[] = 190*6881a400Schristos { 191*6881a400Schristos 0x00, 0x00, 0x1e, 0xa6, /* ldq a0, 0(sp) */ 192*6881a400Schristos 0x10, 0x00, 0xde, 0x23, /* lda sp, 16(sp) */ 193*6881a400Schristos 0x27, 0x01, 0x1f, 0x20, /* lda v0, 295(zero) */ 194*6881a400Schristos 0x83, 0x00, 0x00, 0x00, /* call_pal callsys */ 195*6881a400Schristos }; 196*6881a400Schristos #define RETCODE_NWORDS 4 197*6881a400Schristos #define RETCODE_SIZE (RETCODE_NWORDS * 4) 198*6881a400Schristos 199*6881a400Schristos static LONGEST 200*6881a400Schristos alphanbsd_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc) 201*6881a400Schristos { 202*6881a400Schristos gdb_byte ret[RETCODE_SIZE], w[4]; 203*6881a400Schristos LONGEST off; 204*6881a400Schristos int i; 205*6881a400Schristos 206*6881a400Schristos if (target_read_memory (pc, w, 4) != 0) 207*6881a400Schristos return -1; 208*6881a400Schristos 209*6881a400Schristos for (i = 0; i < RETCODE_NWORDS; i++) 210*6881a400Schristos { 211*6881a400Schristos if (memcmp (w, sigtramp_retcode + (i * 4), 4) == 0) 212*6881a400Schristos break; 213*6881a400Schristos } 214*6881a400Schristos if (i == RETCODE_NWORDS) 215*6881a400Schristos return (-1); 216*6881a400Schristos 217*6881a400Schristos off = i * 4; 218*6881a400Schristos pc -= off; 219*6881a400Schristos 220*6881a400Schristos if (target_read_memory (pc, ret, sizeof (ret)) != 0) 221*6881a400Schristos return -1; 222*6881a400Schristos 223*6881a400Schristos if (memcmp (ret, sigtramp_retcode, RETCODE_SIZE) == 0) 224*6881a400Schristos return off; 225*6881a400Schristos 226*6881a400Schristos return -1; 227*6881a400Schristos } 228*6881a400Schristos 229*6881a400Schristos static int 230*6881a400Schristos alphanbsd_pc_in_sigtramp (struct gdbarch *gdbarch, 231*6881a400Schristos CORE_ADDR pc, const char *func_name) 232*6881a400Schristos { 233*6881a400Schristos return (nbsd_pc_in_sigtramp (pc, func_name) 234*6881a400Schristos || alphanbsd_sigtramp_offset (gdbarch, pc) >= 0); 235*6881a400Schristos } 236*6881a400Schristos 237*6881a400Schristos static CORE_ADDR 238*6881a400Schristos alphanbsd_sigcontext_addr (frame_info_ptr frame) 239*6881a400Schristos { 240*6881a400Schristos /* FIXME: This is not correct for all versions of NetBSD/alpha. 241*6881a400Schristos We will probably need to disassemble the trampoline to figure 242*6881a400Schristos out which trampoline frame type we have. */ 243*6881a400Schristos if (!get_next_frame (frame)) 244*6881a400Schristos return 0; 245*6881a400Schristos return get_frame_base (get_next_frame (frame)); 246*6881a400Schristos } 247*6881a400Schristos 248*6881a400Schristos 249*6881a400Schristos static void 250*6881a400Schristos alphanbsd_init_abi (struct gdbarch_info info, 251*6881a400Schristos struct gdbarch *gdbarch) 252*6881a400Schristos { 253*6881a400Schristos alpha_gdbarch_tdep *tdep = gdbarch_tdep<alpha_gdbarch_tdep> (gdbarch); 254*6881a400Schristos 255*6881a400Schristos /* Hook into the DWARF CFI frame unwinder. */ 256*6881a400Schristos alpha_dwarf2_init_abi (info, gdbarch); 257*6881a400Schristos 258*6881a400Schristos /* Hook into the MDEBUG frame unwinder. */ 259*6881a400Schristos alpha_mdebug_init_abi (info, gdbarch); 260*6881a400Schristos 261*6881a400Schristos nbsd_init_abi (info, gdbarch); 262*6881a400Schristos 263*6881a400Schristos /* NetBSD/alpha does not provide single step support via ptrace(2); we 264*6881a400Schristos must use software single-stepping. */ 265*6881a400Schristos set_gdbarch_software_single_step (gdbarch, alpha_software_single_step); 266*6881a400Schristos 267*6881a400Schristos /* NetBSD/alpha has SVR4-style shared libraries. */ 268*6881a400Schristos set_solib_svr4_fetch_link_map_offsets 269*6881a400Schristos (gdbarch, svr4_lp64_fetch_link_map_offsets); 270*6881a400Schristos 271*6881a400Schristos tdep->dynamic_sigtramp_offset = alphanbsd_sigtramp_offset; 272*6881a400Schristos tdep->pc_in_sigtramp = alphanbsd_pc_in_sigtramp; 273*6881a400Schristos tdep->sigcontext_addr = alphanbsd_sigcontext_addr; 274*6881a400Schristos 275*6881a400Schristos tdep->jb_pc = 2; 276*6881a400Schristos tdep->jb_elt_size = 8; 277*6881a400Schristos 278*6881a400Schristos set_gdbarch_iterate_over_regset_sections 279*6881a400Schristos (gdbarch, alphanbsd_iterate_over_regset_sections); 280*6881a400Schristos } 281*6881a400Schristos 282*6881a400Schristos 283*6881a400Schristos void _initialize_alphanbsd_tdep (); 284*6881a400Schristos void 285*6881a400Schristos _initialize_alphanbsd_tdep () 286*6881a400Schristos { 287*6881a400Schristos /* Even though NetBSD/alpha used ELF since day one, it used the 288*6881a400Schristos traditional a.out-style core dump format before NetBSD 1.6, but 289*6881a400Schristos we don't support those. */ 290*6881a400Schristos gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_NETBSD, 291*6881a400Schristos alphanbsd_init_abi); 292*6881a400Schristos } 293