1 /* Target-dependent code for NetBSD/hppa 2 3 Copyright (C) 2008-2023 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "defs.h" 21 #include "osabi.h" 22 #include "regcache.h" 23 #include "regset.h" 24 25 #include "trad-frame.h" 26 #include "tramp-frame.h" 27 28 #include "hppa-tdep.h" 29 #include "hppa-bsd-tdep.h" 30 #include "netbsd-tdep.h" 31 #include "gdbarch.h" 32 33 /* From <machine/mcontext.h>. */ 34 static int hppanbsd_mc_reg_offset[] = 35 { 36 /* r0 ... r31 */ 37 -1, 1 * 4, 2 * 4, 3 * 4, 38 4 * 4, 5 * 4, 6 * 4, 7 * 4, 39 8 * 4, 9 * 4, 10 * 4, 11 * 4, 40 12 * 4, 13 * 4, 14 * 4, 15 * 4, 41 16 * 4, 17 * 4, 18 * 4, 19 * 4, 42 20 * 4, 21 * 4, 22 * 4, 23 * 4, 43 24 * 4, 25 * 4, 26 * 4, 27 * 4, 44 28 * 4, 29 * 4, 30 * 4, 31 * 4, 45 46 32 * 4, /* HPPA_SAR_REGNUM */ 47 35 * 4, /* HPPA_PCOQ_HEAD_REGNUM */ 48 33 * 4, /* HPPA_PCSQ_HEAD_REGNUM */ 49 36 * 4, /* HPPA_PCOQ_TAIL_REGNUM */ 50 34 * 4, /* HPPA_PCSQ_TAIL_REGNUM */ 51 -1, /* HPPA_EIEM_REGNUM */ 52 -1, /* HPPA_IIR_REGNUM */ 53 -1, /* HPPA_ISR_REGNUM */ 54 -1, /* HPPA_IOR_REGNUM */ 55 0 * 4, /* HPPA_IPSW_REGNUM */ 56 -1, /* spare? */ 57 41 * 4, /* HPPA_SR4_REGNUM */ 58 37 * 4, /* sr0 */ 59 38 * 4, /* sr1 */ 60 39 * 4, /* sr2 */ 61 40 * 4, /* sr3 */ 62 -1, /* 48 */ 63 -1, /* 49 */ 64 -1, /* 50 */ 65 -1, /* 51 */ 66 -1, /* 52 */ 67 -1, /* 53 */ 68 -1, /* 54 */ 69 -1, /* 55 */ 70 -1, /* 56 */ 71 -1, /* 57 CR24 */ 72 -1, /* 58 CR25 */ 73 -1, /* 59 CR26 */ 74 43 * 4, /* HPPA_CR27_REGNUM */ 75 76 /* more tbd */ 77 }; 78 79 static void hppanbsd_sigtramp_cache_init (const struct tramp_frame *, 80 frame_info_ptr, 81 struct trad_frame_cache *, 82 CORE_ADDR); 83 84 static const struct tramp_frame hppanbsd_sigtramp_si4 = 85 { 86 SIGTRAMP_FRAME, 87 4, 88 { 89 { 0xc7d7c012, ULONGEST_MAX }, /* bb,>=,n %arg3, 30, 1f */ 90 { 0xd6e01c1e, ULONGEST_MAX }, /* depwi 0,31,2,%arg3 */ 91 { 0x0ee81093, ULONGEST_MAX }, /* ldw 4(%arg3), %r19 */ 92 { 0x0ee01097, ULONGEST_MAX }, /* ldw 0(%arg3), %arg3 */ 93 /* 1: */ 94 { 0xe8404000, ULONGEST_MAX }, /* blr %r0, %rp */ 95 { 0xeae0c002, ULONGEST_MAX }, /* bv,n %r0(%arg3) */ 96 { 0x08000240, ULONGEST_MAX }, /* nop */ 97 98 { 0x0803025a, ULONGEST_MAX }, /* copy %r3, %arg0 */ 99 { 0x20200801, ULONGEST_MAX }, /* ldil -40000000, %r1 */ 100 { 0xe420e008, ULONGEST_MAX }, /* be,l 4(%sr7, %r1), %sr0, %r31 */ 101 { 0x34160268, ULONGEST_MAX }, /* ldi 134, %t1 ; SYS_setcontext */ 102 103 { 0x081c025a, ULONGEST_MAX }, /* copy ret0, %arg0 */ 104 { 0x20200801, ULONGEST_MAX }, /* ldil -40000000, %r1 */ 105 { 0xe420e008, ULONGEST_MAX }, /* be,l 4(%sr7, %r1), %sr0, %r31 */ 106 { 0x34160002, ULONGEST_MAX }, /* ldi 1, %t1 ; SYS_exit */ 107 { TRAMP_SENTINEL_INSN, ULONGEST_MAX } 108 }, 109 hppanbsd_sigtramp_cache_init 110 }; 111 112 113 static void 114 hppanbsd_sigtramp_cache_init (const struct tramp_frame *self, 115 frame_info_ptr this_frame, 116 struct trad_frame_cache *this_cache, 117 CORE_ADDR func) 118 { 119 CORE_ADDR sp = get_frame_register_unsigned (this_frame, HPPA_SP_REGNUM); 120 CORE_ADDR base; 121 int *reg_offset; 122 int num_regs; 123 int i; 124 125 reg_offset = hppanbsd_mc_reg_offset; 126 num_regs = ARRAY_SIZE (hppanbsd_mc_reg_offset); 127 128 /* frame pointer */ 129 base = sp - 0x280; 130 /* offsetof(struct sigframe_siginfo, sf_uc) = 128 */ 131 base += 128; 132 /* offsetof(ucontext_t, uc_mcontext) == 40 */ 133 base += 40; 134 135 for (i = 0; i < num_regs; i++) 136 if (reg_offset[i] != -1) 137 trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]); 138 139 /* Construct the frame ID using the function start. */ 140 trad_frame_set_id (this_cache, frame_id_build (sp, func)); 141 } 142 143 /* Core file support. */ 144 145 /* Sizeof `struct reg' in <machine/reg.h>. */ 146 #define HPPANBSD_SIZEOF_GREGS (47 * 4) 147 148 static int hppanbsd_reg_offset[] = 149 { 150 /* r0 ... r31 */ 151 -1, 1 * 4, 2 * 4, 3 * 4, 152 4 * 4, 5 * 4, 6 * 4, 7 * 4, 153 8 * 4, 9 * 4, 10 * 4, 11 * 4, 154 12 * 4, 13 * 4, 14 * 4, 15 * 4, 155 16 * 4, 17 * 4, 18 * 4, 19 * 4, 156 20 * 4, 21 * 4, 22 * 4, 23 * 4, 157 24 * 4, 25 * 4, 26 * 4, 27 * 4, 158 28 * 4, 29 * 4, 30 * 4, 31 * 4, 159 160 32 * 4, /* HPPA_SAR_REGNUM */ 161 35 * 4, /* HPPA_PCOQ_HEAD_REGNUM */ 162 33 * 4, /* HPPA_PCSQ_HEAD_REGNUM */ 163 36 * 4, /* HPPA_PCOQ_TAIL_REGNUM */ 164 34 * 4, /* HPPA_PCSQ_TAIL_REGNUM */ 165 -1, /* HPPA_EIEM_REGNUM */ 166 -1, /* HPPA_IIR_REGNUM */ 167 -1, /* HPPA_ISR_REGNUM */ 168 -1, /* HPPA_IOR_REGNUM */ 169 0 * 4, /* HPPA_IPSW_REGNUM */ 170 -1, /* spare? */ 171 41 * 4, /* HPPA_SR4_REGNUM */ 172 37 * 4, /* sr0 */ 173 38 * 4, /* sr1 */ 174 39 * 4, /* sr2 */ 175 40 * 4, /* sr3 */ 176 -1, /* 48 */ 177 -1, /* 49 */ 178 -1, /* 50 */ 179 -1, /* 51 */ 180 -1, /* 52 */ 181 -1, /* 53 */ 182 -1, /* 54 */ 183 -1, /* 55 */ 184 -1, /* 56 */ 185 -1, /* 57 */ 186 -1, /* 58 */ 187 -1, /* 59 */ 188 46 * 4, /* HPPA_CR27_REGNUM */ 189 }; 190 191 /* Supply register REGNUM from the buffer specified by GREGS and LEN 192 in the general-purpose register set REGSET to register cache 193 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ 194 195 static void 196 hppanbsd_supply_gregset (const struct regset *regset, 197 struct regcache *regcache, 198 int regnum, const void *gregs, size_t len) 199 { 200 const gdb_byte *regs = (const gdb_byte *) gregs; 201 int i; 202 203 gdb_assert (len >= HPPANBSD_SIZEOF_GREGS); 204 205 for (i = 0; i < ARRAY_SIZE (hppanbsd_reg_offset); i++) 206 if (hppanbsd_reg_offset[i] != -1) 207 if (regnum == -1 || regnum == i) 208 regcache->raw_supply (i, regs + hppanbsd_reg_offset[i]); 209 } 210 211 /* NetBSD/hppa register set. */ 212 213 static const struct regset hppanbsd_gregset = 214 { 215 NULL, 216 hppanbsd_supply_gregset 217 }; 218 219 /* Iterate over supported core file register note sections. */ 220 221 static void 222 hppanbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, 223 iterate_over_regset_sections_cb *cb, 224 void *cb_data, 225 const struct regcache *regcache) 226 { 227 cb (".reg", HPPANBSD_SIZEOF_GREGS, HPPANBSD_SIZEOF_GREGS, &hppanbsd_gregset, 228 NULL, cb_data); 229 } 230 231 static void 232 hppanbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 233 { 234 /* Obviously NetBSD is BSD-based. */ 235 hppabsd_init_abi (info, gdbarch); 236 237 nbsd_init_abi (info, gdbarch); 238 239 /* Core file support. */ 240 set_gdbarch_iterate_over_regset_sections 241 (gdbarch, hppanbsd_iterate_over_regset_sections); 242 243 tramp_frame_prepend_unwinder (gdbarch, &hppanbsd_sigtramp_si4); 244 } 245 246 void _initialize_hppanbsd_tdep (); 247 void 248 _initialize_hppanbsd_tdep () 249 { 250 gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_NETBSD, 251 hppanbsd_init_abi); 252 } 253