1 1.1 christos /* Target-dependent code for FreeBSD/mips. 2 1.1 christos 3 1.1.1.5 christos Copyright (C) 2017-2024 Free Software Foundation, Inc. 4 1.1 christos 5 1.1 christos This file is part of GDB. 6 1.1 christos 7 1.1 christos This program is free software; you can redistribute it and/or modify 8 1.1 christos it under the terms of the GNU General Public License as published by 9 1.1 christos the Free Software Foundation; either version 3 of the License, or 10 1.1 christos (at your option) any later version. 11 1.1 christos 12 1.1 christos This program is distributed in the hope that it will be useful, 13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 1.1 christos GNU General Public License for more details. 16 1.1 christos 17 1.1 christos You should have received a copy of the GNU General Public License 18 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 1.1 christos 20 1.1.1.5 christos #include "extract-store-integer.h" 21 1.1 christos #include "osabi.h" 22 1.1 christos #include "regset.h" 23 1.1 christos #include "trad-frame.h" 24 1.1 christos #include "tramp-frame.h" 25 1.1 christos 26 1.1 christos #include "fbsd-tdep.h" 27 1.1 christos #include "mips-tdep.h" 28 1.1 christos #include "mips-fbsd-tdep.h" 29 1.1 christos 30 1.1 christos #include "solib-svr4.h" 31 1.1 christos 32 1.1 christos /* Core file support. */ 33 1.1 christos 34 1.1 christos /* Number of registers in `struct reg' from <machine/reg.h>. The 35 1.1 christos first 38 follow the standard MIPS layout. The 39th holds 36 1.1 christos IC_INT_REG on RM7K and RM9K processors. The 40th is a dummy for 37 1.1 christos padding. */ 38 1.1 christos #define MIPS_FBSD_NUM_GREGS 40 39 1.1 christos 40 1.1 christos /* Number of registers in `struct fpreg' from <machine/reg.h>. The 41 1.1 christos first 32 hold floating point registers. 33 holds the FSR. The 42 1.1.1.2 christos 34th holds FIR on FreeBSD 12.0 and newer kernels. On older kernels 43 1.1.1.2 christos it was a zero-filled dummy for padding. */ 44 1.1 christos #define MIPS_FBSD_NUM_FPREGS 34 45 1.1 christos 46 1.1.1.2 christos /* Supply a single register. The register size might not match, so use 47 1.1.1.2 christos regcache->raw_supply_integer (). */ 48 1.1 christos 49 1.1 christos static void 50 1.1 christos mips_fbsd_supply_reg (struct regcache *regcache, int regnum, const void *addr, 51 1.1 christos size_t len) 52 1.1 christos { 53 1.1.1.2 christos regcache->raw_supply_integer (regnum, (const gdb_byte *) addr, len, true); 54 1.1 christos } 55 1.1 christos 56 1.1.1.2 christos /* Collect a single register. The register size might not match, so use 57 1.1.1.2 christos regcache->raw_collect_integer (). */ 58 1.1 christos 59 1.1 christos static void 60 1.1 christos mips_fbsd_collect_reg (const struct regcache *regcache, int regnum, void *addr, 61 1.1 christos size_t len) 62 1.1 christos { 63 1.1.1.2 christos regcache->raw_collect_integer (regnum, (gdb_byte *) addr, len, true); 64 1.1 christos } 65 1.1 christos 66 1.1 christos /* Supply the floating-point registers stored in FPREGS to REGCACHE. 67 1.1 christos Each floating-point register in FPREGS is REGSIZE bytes in 68 1.1 christos length. */ 69 1.1 christos 70 1.1 christos void 71 1.1 christos mips_fbsd_supply_fpregs (struct regcache *regcache, int regnum, 72 1.1 christos const void *fpregs, size_t regsize) 73 1.1 christos { 74 1.1.1.2 christos struct gdbarch *gdbarch = regcache->arch (); 75 1.1 christos const gdb_byte *regs = (const gdb_byte *) fpregs; 76 1.1.1.2 christos int i, fp0num; 77 1.1 christos 78 1.1.1.2 christos fp0num = mips_regnum (gdbarch)->fp0; 79 1.1.1.2 christos for (i = 0; i <= 32; i++) 80 1.1.1.2 christos if (regnum == fp0num + i || regnum == -1) 81 1.1.1.2 christos mips_fbsd_supply_reg (regcache, fp0num + i, 82 1.1.1.2 christos regs + i * regsize, regsize); 83 1.1.1.2 christos if (regnum == mips_regnum (gdbarch)->fp_control_status || regnum == -1) 84 1.1.1.2 christos mips_fbsd_supply_reg (regcache, mips_regnum (gdbarch)->fp_control_status, 85 1.1.1.2 christos regs + 32 * regsize, regsize); 86 1.1.1.2 christos if ((regnum == mips_regnum (gdbarch)->fp_implementation_revision 87 1.1.1.2 christos || regnum == -1) 88 1.1.1.2 christos && extract_unsigned_integer (regs + 33 * regsize, regsize, 89 1.1.1.2 christos gdbarch_byte_order (gdbarch)) != 0) 90 1.1.1.2 christos mips_fbsd_supply_reg (regcache, 91 1.1.1.2 christos mips_regnum (gdbarch)->fp_implementation_revision, 92 1.1.1.2 christos regs + 33 * regsize, regsize); 93 1.1 christos } 94 1.1 christos 95 1.1 christos /* Supply the general-purpose registers stored in GREGS to REGCACHE. 96 1.1 christos Each general-purpose register in GREGS is REGSIZE bytes in 97 1.1 christos length. */ 98 1.1 christos 99 1.1 christos void 100 1.1 christos mips_fbsd_supply_gregs (struct regcache *regcache, int regnum, 101 1.1 christos const void *gregs, size_t regsize) 102 1.1 christos { 103 1.1.1.2 christos struct gdbarch *gdbarch = regcache->arch (); 104 1.1 christos const gdb_byte *regs = (const gdb_byte *) gregs; 105 1.1 christos int i; 106 1.1 christos 107 1.1.1.2 christos for (i = 0; i <= mips_regnum (gdbarch)->pc; i++) 108 1.1 christos if (regnum == i || regnum == -1) 109 1.1 christos mips_fbsd_supply_reg (regcache, i, regs + i * regsize, regsize); 110 1.1 christos } 111 1.1 christos 112 1.1 christos /* Collect the floating-point registers from REGCACHE and store them 113 1.1 christos in FPREGS. Each floating-point register in FPREGS is REGSIZE bytes 114 1.1 christos in length. */ 115 1.1 christos 116 1.1 christos void 117 1.1 christos mips_fbsd_collect_fpregs (const struct regcache *regcache, int regnum, 118 1.1 christos void *fpregs, size_t regsize) 119 1.1 christos { 120 1.1.1.2 christos struct gdbarch *gdbarch = regcache->arch (); 121 1.1 christos gdb_byte *regs = (gdb_byte *) fpregs; 122 1.1.1.2 christos int i, fp0num; 123 1.1 christos 124 1.1.1.2 christos fp0num = mips_regnum (gdbarch)->fp0; 125 1.1.1.2 christos for (i = 0; i < 32; i++) 126 1.1.1.2 christos if (regnum == fp0num + i || regnum == -1) 127 1.1.1.2 christos mips_fbsd_collect_reg (regcache, fp0num + i, 128 1.1.1.2 christos regs + i * regsize, regsize); 129 1.1.1.2 christos if (regnum == mips_regnum (gdbarch)->fp_control_status || regnum == -1) 130 1.1.1.2 christos mips_fbsd_collect_reg (regcache, mips_regnum (gdbarch)->fp_control_status, 131 1.1.1.2 christos regs + 32 * regsize, regsize); 132 1.1.1.2 christos if (regnum == mips_regnum (gdbarch)->fp_implementation_revision 133 1.1.1.2 christos || regnum == -1) 134 1.1.1.2 christos mips_fbsd_collect_reg (regcache, 135 1.1.1.2 christos mips_regnum (gdbarch)->fp_implementation_revision, 136 1.1.1.2 christos regs + 33 * regsize, regsize); 137 1.1 christos } 138 1.1 christos 139 1.1 christos /* Collect the general-purpose registers from REGCACHE and store them 140 1.1 christos in GREGS. Each general-purpose register in GREGS is REGSIZE bytes 141 1.1 christos in length. */ 142 1.1 christos 143 1.1 christos void 144 1.1 christos mips_fbsd_collect_gregs (const struct regcache *regcache, int regnum, 145 1.1 christos void *gregs, size_t regsize) 146 1.1 christos { 147 1.1.1.2 christos struct gdbarch *gdbarch = regcache->arch (); 148 1.1 christos gdb_byte *regs = (gdb_byte *) gregs; 149 1.1 christos int i; 150 1.1 christos 151 1.1.1.2 christos for (i = 0; i <= mips_regnum (gdbarch)->pc; i++) 152 1.1 christos if (regnum == i || regnum == -1) 153 1.1 christos mips_fbsd_collect_reg (regcache, i, regs + i * regsize, regsize); 154 1.1 christos } 155 1.1 christos 156 1.1 christos /* Supply register REGNUM from the buffer specified by FPREGS and LEN 157 1.1 christos in the floating-point register set REGSET to register cache 158 1.1 christos REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ 159 1.1 christos 160 1.1 christos static void 161 1.1 christos mips_fbsd_supply_fpregset (const struct regset *regset, 162 1.1 christos struct regcache *regcache, 163 1.1 christos int regnum, const void *fpregs, size_t len) 164 1.1 christos { 165 1.1.1.2 christos size_t regsize = mips_abi_regsize (regcache->arch ()); 166 1.1 christos 167 1.1 christos gdb_assert (len >= MIPS_FBSD_NUM_FPREGS * regsize); 168 1.1 christos 169 1.1 christos mips_fbsd_supply_fpregs (regcache, regnum, fpregs, regsize); 170 1.1 christos } 171 1.1 christos 172 1.1 christos /* Collect register REGNUM from the register cache REGCACHE and store 173 1.1 christos it in the buffer specified by FPREGS and LEN in the floating-point 174 1.1 christos register set REGSET. If REGNUM is -1, do this for all registers in 175 1.1 christos REGSET. */ 176 1.1 christos 177 1.1 christos static void 178 1.1 christos mips_fbsd_collect_fpregset (const struct regset *regset, 179 1.1 christos const struct regcache *regcache, 180 1.1 christos int regnum, void *fpregs, size_t len) 181 1.1 christos { 182 1.1.1.2 christos size_t regsize = mips_abi_regsize (regcache->arch ()); 183 1.1 christos 184 1.1 christos gdb_assert (len >= MIPS_FBSD_NUM_FPREGS * regsize); 185 1.1 christos 186 1.1 christos mips_fbsd_collect_fpregs (regcache, regnum, fpregs, regsize); 187 1.1 christos } 188 1.1 christos 189 1.1 christos /* Supply register REGNUM from the buffer specified by GREGS and LEN 190 1.1 christos in the general-purpose register set REGSET to register cache 191 1.1 christos REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ 192 1.1 christos 193 1.1 christos static void 194 1.1 christos mips_fbsd_supply_gregset (const struct regset *regset, 195 1.1 christos struct regcache *regcache, int regnum, 196 1.1 christos const void *gregs, size_t len) 197 1.1 christos { 198 1.1.1.2 christos size_t regsize = mips_abi_regsize (regcache->arch ()); 199 1.1 christos 200 1.1 christos gdb_assert (len >= MIPS_FBSD_NUM_GREGS * regsize); 201 1.1 christos 202 1.1 christos mips_fbsd_supply_gregs (regcache, regnum, gregs, regsize); 203 1.1 christos } 204 1.1 christos 205 1.1 christos /* Collect register REGNUM from the register cache REGCACHE and store 206 1.1 christos it in the buffer specified by GREGS and LEN in the general-purpose 207 1.1 christos register set REGSET. If REGNUM is -1, do this for all registers in 208 1.1 christos REGSET. */ 209 1.1 christos 210 1.1 christos static void 211 1.1 christos mips_fbsd_collect_gregset (const struct regset *regset, 212 1.1 christos const struct regcache *regcache, 213 1.1 christos int regnum, void *gregs, size_t len) 214 1.1 christos { 215 1.1.1.2 christos size_t regsize = mips_abi_regsize (regcache->arch ()); 216 1.1 christos 217 1.1 christos gdb_assert (len >= MIPS_FBSD_NUM_GREGS * regsize); 218 1.1 christos 219 1.1 christos mips_fbsd_collect_gregs (regcache, regnum, gregs, regsize); 220 1.1 christos } 221 1.1 christos 222 1.1 christos /* FreeBSD/mips register sets. */ 223 1.1 christos 224 1.1 christos static const struct regset mips_fbsd_gregset = 225 1.1 christos { 226 1.1 christos NULL, 227 1.1 christos mips_fbsd_supply_gregset, 228 1.1 christos mips_fbsd_collect_gregset, 229 1.1 christos }; 230 1.1 christos 231 1.1 christos static const struct regset mips_fbsd_fpregset = 232 1.1 christos { 233 1.1 christos NULL, 234 1.1 christos mips_fbsd_supply_fpregset, 235 1.1 christos mips_fbsd_collect_fpregset, 236 1.1 christos }; 237 1.1 christos 238 1.1 christos /* Iterate over core file register note sections. */ 239 1.1 christos 240 1.1 christos static void 241 1.1 christos mips_fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, 242 1.1 christos iterate_over_regset_sections_cb *cb, 243 1.1 christos void *cb_data, 244 1.1 christos const struct regcache *regcache) 245 1.1 christos { 246 1.1 christos size_t regsize = mips_abi_regsize (gdbarch); 247 1.1 christos 248 1.1.1.2 christos cb (".reg", MIPS_FBSD_NUM_GREGS * regsize, MIPS_FBSD_NUM_GREGS * regsize, 249 1.1.1.2 christos &mips_fbsd_gregset, NULL, cb_data); 250 1.1.1.2 christos cb (".reg2", MIPS_FBSD_NUM_FPREGS * regsize, MIPS_FBSD_NUM_FPREGS * regsize, 251 1.1.1.2 christos &mips_fbsd_fpregset, NULL, cb_data); 252 1.1 christos } 253 1.1 christos 254 1.1 christos /* Signal trampoline support. */ 255 1.1 christos 256 1.1 christos #define FBSD_SYS_sigreturn 417 257 1.1 christos 258 1.1 christos #define MIPS_INST_LI_V0_SIGRETURN 0x24020000 + FBSD_SYS_sigreturn 259 1.1 christos #define MIPS_INST_SYSCALL 0x0000000c 260 1.1 christos #define MIPS_INST_BREAK 0x0000000d 261 1.1 christos 262 1.1 christos #define O32_SIGFRAME_UCONTEXT_OFFSET (16) 263 1.1 christos #define O32_SIGSET_T_SIZE (16) 264 1.1 christos 265 1.1 christos #define O32_UCONTEXT_ONSTACK (O32_SIGSET_T_SIZE) 266 1.1 christos #define O32_UCONTEXT_PC (O32_UCONTEXT_ONSTACK + 4) 267 1.1 christos #define O32_UCONTEXT_REGS (O32_UCONTEXT_PC + 4) 268 1.1 christos #define O32_UCONTEXT_SR (O32_UCONTEXT_REGS + 4 * 32) 269 1.1 christos #define O32_UCONTEXT_LO (O32_UCONTEXT_SR + 4) 270 1.1 christos #define O32_UCONTEXT_HI (O32_UCONTEXT_LO + 4) 271 1.1 christos #define O32_UCONTEXT_FPUSED (O32_UCONTEXT_HI + 4) 272 1.1 christos #define O32_UCONTEXT_FPREGS (O32_UCONTEXT_FPUSED + 4) 273 1.1 christos 274 1.1 christos #define O32_UCONTEXT_REG_SIZE 4 275 1.1 christos 276 1.1 christos static void 277 1.1 christos mips_fbsd_sigframe_init (const struct tramp_frame *self, 278 1.1.1.5 christos const frame_info_ptr &this_frame, 279 1.1 christos struct trad_frame_cache *cache, 280 1.1 christos CORE_ADDR func) 281 1.1 christos { 282 1.1 christos struct gdbarch *gdbarch = get_frame_arch (this_frame); 283 1.1 christos enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 284 1.1 christos CORE_ADDR sp, ucontext_addr, addr; 285 1.1 christos int regnum; 286 1.1 christos gdb_byte buf[4]; 287 1.1 christos 288 1.1 christos /* We find the appropriate instance of `ucontext_t' at a 289 1.1 christos fixed offset in the signal frame. */ 290 1.1 christos sp = get_frame_register_signed (this_frame, 291 1.1 christos MIPS_SP_REGNUM + gdbarch_num_regs (gdbarch)); 292 1.1 christos ucontext_addr = sp + O32_SIGFRAME_UCONTEXT_OFFSET; 293 1.1 christos 294 1.1 christos /* PC. */ 295 1.1 christos regnum = mips_regnum (gdbarch)->pc; 296 1.1 christos trad_frame_set_reg_addr (cache, 297 1.1 christos regnum + gdbarch_num_regs (gdbarch), 298 1.1 christos ucontext_addr + O32_UCONTEXT_PC); 299 1.1 christos 300 1.1 christos /* GPRs. */ 301 1.1 christos for (regnum = MIPS_ZERO_REGNUM, addr = ucontext_addr + O32_UCONTEXT_REGS; 302 1.1 christos regnum <= MIPS_RA_REGNUM; regnum++, addr += O32_UCONTEXT_REG_SIZE) 303 1.1 christos trad_frame_set_reg_addr (cache, 304 1.1 christos regnum + gdbarch_num_regs (gdbarch), 305 1.1 christos addr); 306 1.1 christos 307 1.1 christos regnum = MIPS_PS_REGNUM; 308 1.1 christos trad_frame_set_reg_addr (cache, 309 1.1 christos regnum + gdbarch_num_regs (gdbarch), 310 1.1 christos ucontext_addr + O32_UCONTEXT_SR); 311 1.1 christos 312 1.1 christos /* HI and LO. */ 313 1.1 christos regnum = mips_regnum (gdbarch)->lo; 314 1.1 christos trad_frame_set_reg_addr (cache, 315 1.1 christos regnum + gdbarch_num_regs (gdbarch), 316 1.1 christos ucontext_addr + O32_UCONTEXT_LO); 317 1.1 christos regnum = mips_regnum (gdbarch)->hi; 318 1.1 christos trad_frame_set_reg_addr (cache, 319 1.1 christos regnum + gdbarch_num_regs (gdbarch), 320 1.1 christos ucontext_addr + O32_UCONTEXT_HI); 321 1.1 christos 322 1.1 christos if (target_read_memory (ucontext_addr + O32_UCONTEXT_FPUSED, buf, 4) == 0 323 1.1 christos && extract_unsigned_integer (buf, 4, byte_order) != 0) 324 1.1 christos { 325 1.1 christos for (regnum = 0, addr = ucontext_addr + O32_UCONTEXT_FPREGS; 326 1.1 christos regnum < 32; regnum++, addr += O32_UCONTEXT_REG_SIZE) 327 1.1 christos trad_frame_set_reg_addr (cache, 328 1.1 christos regnum + gdbarch_fp0_regnum (gdbarch), 329 1.1 christos addr); 330 1.1 christos trad_frame_set_reg_addr (cache, mips_regnum (gdbarch)->fp_control_status, 331 1.1 christos addr); 332 1.1 christos } 333 1.1 christos 334 1.1 christos trad_frame_set_id (cache, frame_id_build (sp, func)); 335 1.1 christos } 336 1.1 christos 337 1.1 christos #define MIPS_INST_ADDIU_A0_SP_O32 (0x27a40000 \ 338 1.1 christos + O32_SIGFRAME_UCONTEXT_OFFSET) 339 1.1 christos 340 1.1 christos static const struct tramp_frame mips_fbsd_sigframe = 341 1.1 christos { 342 1.1 christos SIGTRAMP_FRAME, 343 1.1 christos MIPS_INSN32_SIZE, 344 1.1 christos { 345 1.1.1.2 christos { MIPS_INST_ADDIU_A0_SP_O32, ULONGEST_MAX }, /* addiu a0, sp, SIGF_UC */ 346 1.1.1.2 christos { MIPS_INST_LI_V0_SIGRETURN, ULONGEST_MAX }, /* li v0, SYS_sigreturn */ 347 1.1.1.2 christos { MIPS_INST_SYSCALL, ULONGEST_MAX }, /* syscall */ 348 1.1.1.2 christos { MIPS_INST_BREAK, ULONGEST_MAX }, /* break */ 349 1.1.1.2 christos { TRAMP_SENTINEL_INSN, ULONGEST_MAX } 350 1.1 christos }, 351 1.1 christos mips_fbsd_sigframe_init 352 1.1 christos }; 353 1.1 christos 354 1.1 christos #define N64_SIGFRAME_UCONTEXT_OFFSET (32) 355 1.1 christos #define N64_SIGSET_T_SIZE (16) 356 1.1 christos 357 1.1 christos #define N64_UCONTEXT_ONSTACK (N64_SIGSET_T_SIZE) 358 1.1 christos #define N64_UCONTEXT_PC (N64_UCONTEXT_ONSTACK + 8) 359 1.1 christos #define N64_UCONTEXT_REGS (N64_UCONTEXT_PC + 8) 360 1.1 christos #define N64_UCONTEXT_SR (N64_UCONTEXT_REGS + 8 * 32) 361 1.1 christos #define N64_UCONTEXT_LO (N64_UCONTEXT_SR + 8) 362 1.1 christos #define N64_UCONTEXT_HI (N64_UCONTEXT_LO + 8) 363 1.1 christos #define N64_UCONTEXT_FPUSED (N64_UCONTEXT_HI + 8) 364 1.1 christos #define N64_UCONTEXT_FPREGS (N64_UCONTEXT_FPUSED + 8) 365 1.1 christos 366 1.1 christos #define N64_UCONTEXT_REG_SIZE 8 367 1.1 christos 368 1.1 christos static void 369 1.1 christos mips64_fbsd_sigframe_init (const struct tramp_frame *self, 370 1.1.1.5 christos const frame_info_ptr &this_frame, 371 1.1 christos struct trad_frame_cache *cache, 372 1.1 christos CORE_ADDR func) 373 1.1 christos { 374 1.1 christos struct gdbarch *gdbarch = get_frame_arch (this_frame); 375 1.1 christos enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 376 1.1 christos CORE_ADDR sp, ucontext_addr, addr; 377 1.1 christos int regnum; 378 1.1 christos gdb_byte buf[4]; 379 1.1 christos 380 1.1 christos /* We find the appropriate instance of `ucontext_t' at a 381 1.1 christos fixed offset in the signal frame. */ 382 1.1 christos sp = get_frame_register_signed (this_frame, 383 1.1 christos MIPS_SP_REGNUM + gdbarch_num_regs (gdbarch)); 384 1.1 christos ucontext_addr = sp + N64_SIGFRAME_UCONTEXT_OFFSET; 385 1.1 christos 386 1.1 christos /* PC. */ 387 1.1 christos regnum = mips_regnum (gdbarch)->pc; 388 1.1 christos trad_frame_set_reg_addr (cache, 389 1.1 christos regnum + gdbarch_num_regs (gdbarch), 390 1.1 christos ucontext_addr + N64_UCONTEXT_PC); 391 1.1 christos 392 1.1 christos /* GPRs. */ 393 1.1 christos for (regnum = MIPS_ZERO_REGNUM, addr = ucontext_addr + N64_UCONTEXT_REGS; 394 1.1 christos regnum <= MIPS_RA_REGNUM; regnum++, addr += N64_UCONTEXT_REG_SIZE) 395 1.1 christos trad_frame_set_reg_addr (cache, 396 1.1 christos regnum + gdbarch_num_regs (gdbarch), 397 1.1 christos addr); 398 1.1 christos 399 1.1 christos regnum = MIPS_PS_REGNUM; 400 1.1 christos trad_frame_set_reg_addr (cache, 401 1.1 christos regnum + gdbarch_num_regs (gdbarch), 402 1.1 christos ucontext_addr + N64_UCONTEXT_SR); 403 1.1 christos 404 1.1 christos /* HI and LO. */ 405 1.1 christos regnum = mips_regnum (gdbarch)->lo; 406 1.1 christos trad_frame_set_reg_addr (cache, 407 1.1 christos regnum + gdbarch_num_regs (gdbarch), 408 1.1 christos ucontext_addr + N64_UCONTEXT_LO); 409 1.1 christos regnum = mips_regnum (gdbarch)->hi; 410 1.1 christos trad_frame_set_reg_addr (cache, 411 1.1 christos regnum + gdbarch_num_regs (gdbarch), 412 1.1 christos ucontext_addr + N64_UCONTEXT_HI); 413 1.1 christos 414 1.1 christos if (target_read_memory (ucontext_addr + N64_UCONTEXT_FPUSED, buf, 4) == 0 415 1.1 christos && extract_unsigned_integer (buf, 4, byte_order) != 0) 416 1.1 christos { 417 1.1 christos for (regnum = 0, addr = ucontext_addr + N64_UCONTEXT_FPREGS; 418 1.1 christos regnum < 32; regnum++, addr += N64_UCONTEXT_REG_SIZE) 419 1.1 christos trad_frame_set_reg_addr (cache, 420 1.1 christos regnum + gdbarch_fp0_regnum (gdbarch), 421 1.1 christos addr); 422 1.1 christos trad_frame_set_reg_addr (cache, mips_regnum (gdbarch)->fp_control_status, 423 1.1 christos addr); 424 1.1 christos } 425 1.1 christos 426 1.1 christos trad_frame_set_id (cache, frame_id_build (sp, func)); 427 1.1 christos } 428 1.1 christos 429 1.1.1.2 christos #define MIPS_INST_ADDIU_A0_SP_N32 (0x27a40000 \ 430 1.1.1.2 christos + N64_SIGFRAME_UCONTEXT_OFFSET) 431 1.1.1.2 christos 432 1.1.1.2 christos static const struct tramp_frame mipsn32_fbsd_sigframe = 433 1.1.1.2 christos { 434 1.1.1.2 christos SIGTRAMP_FRAME, 435 1.1.1.2 christos MIPS_INSN32_SIZE, 436 1.1.1.2 christos { 437 1.1.1.2 christos { MIPS_INST_ADDIU_A0_SP_N32, ULONGEST_MAX }, /* addiu a0, sp, SIGF_UC */ 438 1.1.1.2 christos { MIPS_INST_LI_V0_SIGRETURN, ULONGEST_MAX }, /* li v0, SYS_sigreturn */ 439 1.1.1.2 christos { MIPS_INST_SYSCALL, ULONGEST_MAX }, /* syscall */ 440 1.1.1.2 christos { MIPS_INST_BREAK, ULONGEST_MAX }, /* break */ 441 1.1.1.2 christos { TRAMP_SENTINEL_INSN, ULONGEST_MAX } 442 1.1.1.2 christos }, 443 1.1.1.2 christos mips64_fbsd_sigframe_init 444 1.1.1.2 christos }; 445 1.1.1.2 christos 446 1.1 christos #define MIPS_INST_DADDIU_A0_SP_N64 (0x67a40000 \ 447 1.1 christos + N64_SIGFRAME_UCONTEXT_OFFSET) 448 1.1 christos 449 1.1 christos static const struct tramp_frame mips64_fbsd_sigframe = 450 1.1 christos { 451 1.1 christos SIGTRAMP_FRAME, 452 1.1 christos MIPS_INSN32_SIZE, 453 1.1 christos { 454 1.1.1.2 christos { MIPS_INST_DADDIU_A0_SP_N64, ULONGEST_MAX }, /* daddiu a0, sp, SIGF_UC */ 455 1.1.1.2 christos { MIPS_INST_LI_V0_SIGRETURN, ULONGEST_MAX }, /* li v0, SYS_sigreturn */ 456 1.1.1.2 christos { MIPS_INST_SYSCALL, ULONGEST_MAX }, /* syscall */ 457 1.1.1.2 christos { MIPS_INST_BREAK, ULONGEST_MAX }, /* break */ 458 1.1.1.2 christos { TRAMP_SENTINEL_INSN, ULONGEST_MAX } 459 1.1 christos }, 460 1.1 christos mips64_fbsd_sigframe_init 461 1.1 christos }; 462 1.1 christos 463 1.1 christos /* Shared library support. */ 464 1.1 christos 465 1.1.1.3 christos /* FreeBSD/mips can use an alternate routine in the runtime linker to 466 1.1.1.3 christos resolve functions. */ 467 1.1.1.3 christos 468 1.1.1.3 christos static CORE_ADDR 469 1.1.1.3 christos mips_fbsd_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc) 470 1.1.1.3 christos { 471 1.1.1.6 christos bound_minimal_symbol msym 472 1.1.1.6 christos = lookup_minimal_symbol (current_program_space, "_mips_rtld_bind"); 473 1.1.1.4 christos if (msym.minsym != nullptr && msym.value_address () == pc) 474 1.1.1.3 christos return frame_unwind_caller_pc (get_current_frame ()); 475 1.1.1.3 christos 476 1.1.1.3 christos return fbsd_skip_solib_resolver (gdbarch, pc); 477 1.1.1.3 christos } 478 1.1.1.3 christos 479 1.1 christos /* FreeBSD/mips uses a slightly different `struct link_map' than the 480 1.1 christos other FreeBSD platforms as it includes an additional `l_off' 481 1.1 christos member. */ 482 1.1 christos 483 1.1 christos static struct link_map_offsets * 484 1.1 christos mips_fbsd_ilp32_fetch_link_map_offsets (void) 485 1.1 christos { 486 1.1 christos static struct link_map_offsets lmo; 487 1.1 christos static struct link_map_offsets *lmp = NULL; 488 1.1 christos 489 1.1 christos if (lmp == NULL) 490 1.1 christos { 491 1.1 christos lmp = &lmo; 492 1.1 christos 493 1.1 christos lmo.r_version_offset = 0; 494 1.1 christos lmo.r_version_size = 4; 495 1.1 christos lmo.r_map_offset = 4; 496 1.1 christos lmo.r_brk_offset = 8; 497 1.1 christos lmo.r_ldsomap_offset = -1; 498 1.1.1.4 christos lmo.r_next_offset = -1; 499 1.1 christos 500 1.1 christos lmo.link_map_size = 24; 501 1.1 christos lmo.l_addr_offset = 0; 502 1.1 christos lmo.l_name_offset = 8; 503 1.1 christos lmo.l_ld_offset = 12; 504 1.1 christos lmo.l_next_offset = 16; 505 1.1 christos lmo.l_prev_offset = 20; 506 1.1 christos } 507 1.1 christos 508 1.1 christos return lmp; 509 1.1 christos } 510 1.1 christos 511 1.1 christos static struct link_map_offsets * 512 1.1 christos mips_fbsd_lp64_fetch_link_map_offsets (void) 513 1.1 christos { 514 1.1 christos static struct link_map_offsets lmo; 515 1.1 christos static struct link_map_offsets *lmp = NULL; 516 1.1 christos 517 1.1 christos if (lmp == NULL) 518 1.1 christos { 519 1.1 christos lmp = &lmo; 520 1.1 christos 521 1.1 christos lmo.r_version_offset = 0; 522 1.1 christos lmo.r_version_size = 4; 523 1.1 christos lmo.r_map_offset = 8; 524 1.1 christos lmo.r_brk_offset = 16; 525 1.1 christos lmo.r_ldsomap_offset = -1; 526 1.1.1.4 christos lmo.r_next_offset = -1; 527 1.1 christos 528 1.1 christos lmo.link_map_size = 48; 529 1.1 christos lmo.l_addr_offset = 0; 530 1.1 christos lmo.l_name_offset = 16; 531 1.1 christos lmo.l_ld_offset = 24; 532 1.1 christos lmo.l_next_offset = 32; 533 1.1 christos lmo.l_prev_offset = 40; 534 1.1 christos } 535 1.1 christos 536 1.1 christos return lmp; 537 1.1 christos } 538 1.1 christos 539 1.1 christos static void 540 1.1 christos mips_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 541 1.1 christos { 542 1.1 christos enum mips_abi abi = mips_abi (gdbarch); 543 1.1 christos 544 1.1 christos /* Generic FreeBSD support. */ 545 1.1 christos fbsd_init_abi (info, gdbarch); 546 1.1 christos 547 1.1 christos set_gdbarch_software_single_step (gdbarch, mips_software_single_step); 548 1.1 christos 549 1.1 christos switch (abi) 550 1.1 christos { 551 1.1 christos case MIPS_ABI_O32: 552 1.1 christos tramp_frame_prepend_unwinder (gdbarch, &mips_fbsd_sigframe); 553 1.1 christos break; 554 1.1 christos case MIPS_ABI_N32: 555 1.1.1.2 christos tramp_frame_prepend_unwinder (gdbarch, &mipsn32_fbsd_sigframe); 556 1.1 christos break; 557 1.1 christos case MIPS_ABI_N64: 558 1.1 christos tramp_frame_prepend_unwinder (gdbarch, &mips64_fbsd_sigframe); 559 1.1 christos break; 560 1.1 christos } 561 1.1 christos 562 1.1 christos set_gdbarch_iterate_over_regset_sections 563 1.1 christos (gdbarch, mips_fbsd_iterate_over_regset_sections); 564 1.1 christos 565 1.1.1.3 christos set_gdbarch_skip_solib_resolver (gdbarch, mips_fbsd_skip_solib_resolver); 566 1.1.1.3 christos 567 1.1 christos /* FreeBSD/mips has SVR4-style shared libraries. */ 568 1.1 christos set_solib_svr4_fetch_link_map_offsets 569 1.1 christos (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ? 570 1.1 christos mips_fbsd_ilp32_fetch_link_map_offsets : 571 1.1 christos mips_fbsd_lp64_fetch_link_map_offsets)); 572 1.1 christos } 573 1.1 christos 574 1.1.1.3 christos void _initialize_mips_fbsd_tdep (); 575 1.1 christos void 576 1.1.1.3 christos _initialize_mips_fbsd_tdep () 577 1.1 christos { 578 1.1 christos gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_FREEBSD, 579 1.1 christos mips_fbsd_init_abi); 580 1.1 christos } 581