1 /* Target-dependent code for OpenBSD/powerpc. 2 3 Copyright (C) 2004-2020 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 "arch-utils.h" 22 #include "frame.h" 23 #include "frame-unwind.h" 24 #include "gdbtypes.h" 25 #include "osabi.h" 26 #include "regcache.h" 27 #include "regset.h" 28 #include "symtab.h" 29 #include "trad-frame.h" 30 31 #include "ppc-tdep.h" 32 #include "ppc-obsd-tdep.h" 33 #include "solib-svr4.h" 34 35 /* Register offsets from <machine/reg.h>. */ 36 struct ppc_reg_offsets ppcobsd_reg_offsets; 37 struct ppc_reg_offsets ppcobsd_fpreg_offsets; 38 39 40 /* Core file support. */ 41 42 /* Supply register REGNUM in the general-purpose register set REGSET 43 from the buffer specified by GREGS and LEN to register cache 44 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ 45 46 void 47 ppcobsd_supply_gregset (const struct regset *regset, 48 struct regcache *regcache, int regnum, 49 const void *gregs, size_t len) 50 { 51 ppc_supply_gregset (regset, regcache, regnum, gregs, len); 52 ppc_supply_fpregset (regset, regcache, regnum, gregs, len); 53 } 54 55 /* Collect register REGNUM in the general-purpose register set 56 REGSET, from register cache REGCACHE into the buffer specified by 57 GREGS and LEN. If REGNUM is -1, do this for all registers in 58 REGSET. */ 59 60 void 61 ppcobsd_collect_gregset (const struct regset *regset, 62 const struct regcache *regcache, int regnum, 63 void *gregs, size_t len) 64 { 65 ppc_collect_gregset (regset, regcache, regnum, gregs, len); 66 ppc_collect_fpregset (regset, regcache, regnum, gregs, len); 67 } 68 69 /* OpenBSD/powerpc register set. */ 70 71 const struct regset ppcobsd_gregset = 72 { 73 &ppcobsd_reg_offsets, 74 ppcobsd_supply_gregset 75 }; 76 77 const struct regset ppcobsd_fpregset = 78 { 79 &ppcobsd_fpreg_offsets, 80 ppc_supply_fpregset 81 }; 82 83 /* Iterate over core file register note sections. */ 84 85 static void 86 ppcobsd_iterate_over_regset_sections (struct gdbarch *gdbarch, 87 iterate_over_regset_sections_cb *cb, 88 void *cb_data, 89 const struct regcache *regcache) 90 { 91 cb (".reg", 412, 412, &ppcobsd_gregset, NULL, cb_data); 92 } 93 94 95 /* Signal trampolines. */ 96 97 /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page 98 in virtual memory. The randomness makes it somewhat tricky to 99 detect it, but fortunately we can rely on the fact that the start 100 of the sigtramp routine is page-aligned. We recognize the 101 trampoline by looking for the code that invokes the sigreturn 102 system call. The offset where we can find that code varies from 103 release to release. 104 105 By the way, the mapping mentioned above is read-only, so you cannot 106 place a breakpoint in the signal trampoline. */ 107 108 /* Default page size. */ 109 static const int ppcobsd_page_size = 4096; 110 111 /* Offset for sigreturn(2). */ 112 static const int ppcobsd_sigreturn_offset[] = { 113 0x98, /* OpenBSD 3.8 */ 114 0x0c, /* OpenBSD 3.2 */ 115 -1 116 }; 117 118 static int 119 ppcobsd_sigtramp_frame_sniffer (const struct frame_unwind *self, 120 struct frame_info *this_frame, 121 void **this_cache) 122 { 123 struct gdbarch *gdbarch = get_frame_arch (this_frame); 124 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 125 CORE_ADDR pc = get_frame_pc (this_frame); 126 CORE_ADDR start_pc = (pc & ~(ppcobsd_page_size - 1)); 127 const int *offset; 128 const char *name; 129 130 find_pc_partial_function (pc, &name, NULL, NULL); 131 if (name) 132 return 0; 133 134 for (offset = ppcobsd_sigreturn_offset; *offset != -1; offset++) 135 { 136 gdb_byte buf[2 * PPC_INSN_SIZE]; 137 unsigned long insn; 138 139 if (!safe_frame_unwind_memory (this_frame, start_pc + *offset, 140 buf, sizeof buf)) 141 continue; 142 143 /* Check for "li r0,SYS_sigreturn". */ 144 insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order); 145 if (insn != 0x38000067) 146 continue; 147 148 /* Check for "sc". */ 149 insn = extract_unsigned_integer (buf + PPC_INSN_SIZE, 150 PPC_INSN_SIZE, byte_order); 151 if (insn != 0x44000002) 152 continue; 153 154 return 1; 155 } 156 157 return 0; 158 } 159 160 static struct trad_frame_cache * 161 ppcobsd_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) 162 { 163 struct gdbarch *gdbarch = get_frame_arch (this_frame); 164 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 165 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 166 struct trad_frame_cache *cache; 167 CORE_ADDR addr, base, func; 168 gdb_byte buf[PPC_INSN_SIZE]; 169 unsigned long insn, sigcontext_offset; 170 int i; 171 172 if (*this_cache) 173 return (struct trad_frame_cache *) *this_cache; 174 175 cache = trad_frame_cache_zalloc (this_frame); 176 *this_cache = cache; 177 178 func = get_frame_pc (this_frame); 179 func &= ~(ppcobsd_page_size - 1); 180 if (!safe_frame_unwind_memory (this_frame, func, buf, sizeof buf)) 181 return cache; 182 183 /* Calculate the offset where we can find `struct sigcontext'. We 184 base our calculation on the amount of stack space reserved by the 185 first instruction of the signal trampoline. */ 186 insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order); 187 sigcontext_offset = (0x10000 - (insn & 0x0000ffff)) + 8; 188 189 base = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch)); 190 addr = base + sigcontext_offset + 2 * tdep->wordsize; 191 for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize) 192 { 193 int regnum = i + tdep->ppc_gp0_regnum; 194 trad_frame_set_reg_addr (cache, regnum, addr); 195 } 196 trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, addr); 197 addr += tdep->wordsize; 198 trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, addr); 199 addr += tdep->wordsize; 200 trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, addr); 201 addr += tdep->wordsize; 202 trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, addr); 203 addr += tdep->wordsize; 204 trad_frame_set_reg_addr (cache, gdbarch_pc_regnum (gdbarch), addr); 205 /* SRR0? */ 206 addr += tdep->wordsize; 207 208 /* Construct the frame ID using the function start. */ 209 trad_frame_set_id (cache, frame_id_build (base, func)); 210 211 return cache; 212 } 213 214 static void 215 ppcobsd_sigtramp_frame_this_id (struct frame_info *this_frame, 216 void **this_cache, struct frame_id *this_id) 217 { 218 struct trad_frame_cache *cache = 219 ppcobsd_sigtramp_frame_cache (this_frame, this_cache); 220 221 trad_frame_get_id (cache, this_id); 222 } 223 224 static struct value * 225 ppcobsd_sigtramp_frame_prev_register (struct frame_info *this_frame, 226 void **this_cache, int regnum) 227 { 228 struct trad_frame_cache *cache = 229 ppcobsd_sigtramp_frame_cache (this_frame, this_cache); 230 231 return trad_frame_get_register (cache, this_frame, regnum); 232 } 233 234 static const struct frame_unwind ppcobsd_sigtramp_frame_unwind = { 235 SIGTRAMP_FRAME, 236 default_frame_unwind_stop_reason, 237 ppcobsd_sigtramp_frame_this_id, 238 ppcobsd_sigtramp_frame_prev_register, 239 NULL, 240 ppcobsd_sigtramp_frame_sniffer 241 }; 242 243 244 static void 245 ppcobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 246 { 247 /* OpenBSD doesn't support the 128-bit `long double' from the psABI. */ 248 set_gdbarch_long_double_bit (gdbarch, 64); 249 set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double); 250 251 /* OpenBSD currently uses a broken GCC. */ 252 set_gdbarch_return_value (gdbarch, ppc_sysv_abi_broken_return_value); 253 254 /* OpenBSD uses SVR4-style shared libraries. */ 255 set_solib_svr4_fetch_link_map_offsets 256 (gdbarch, svr4_ilp32_fetch_link_map_offsets); 257 258 set_gdbarch_iterate_over_regset_sections 259 (gdbarch, ppcobsd_iterate_over_regset_sections); 260 261 frame_unwind_append_unwinder (gdbarch, &ppcobsd_sigtramp_frame_unwind); 262 } 263 264 void _initialize_ppcobsd_tdep (); 265 void 266 _initialize_ppcobsd_tdep () 267 { 268 gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_OPENBSD, 269 ppcobsd_init_abi); 270 gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_OPENBSD, 271 ppcobsd_init_abi); 272 273 /* Avoid initializing the register offsets again if they were 274 already initialized by ppcobsd-nat.c. */ 275 if (ppcobsd_reg_offsets.pc_offset == 0) 276 { 277 /* General-purpose registers. */ 278 ppcobsd_reg_offsets.r0_offset = 0; 279 ppcobsd_reg_offsets.gpr_size = 4; 280 ppcobsd_reg_offsets.xr_size = 4; 281 ppcobsd_reg_offsets.pc_offset = 384; 282 ppcobsd_reg_offsets.ps_offset = 388; 283 ppcobsd_reg_offsets.cr_offset = 392; 284 ppcobsd_reg_offsets.lr_offset = 396; 285 ppcobsd_reg_offsets.ctr_offset = 400; 286 ppcobsd_reg_offsets.xer_offset = 404; 287 ppcobsd_reg_offsets.mq_offset = 408; 288 289 /* Floating-point registers. */ 290 ppcobsd_reg_offsets.f0_offset = 128; 291 ppcobsd_reg_offsets.fpscr_offset = -1; 292 293 } 294 295 if (ppcobsd_fpreg_offsets.fpscr_offset == 0) 296 { 297 /* Floating-point registers. */ 298 ppcobsd_reg_offsets.f0_offset = 0; 299 ppcobsd_reg_offsets.fpscr_offset = 256; 300 ppcobsd_reg_offsets.fpscr_size = 4; 301 } 302 } 303