1699b0f92Schristos /* Target-dependent code for PowerPC systems running FreeBSD. 2699b0f92Schristos 3*6881a400Schristos Copyright (C) 2013-2023 Free Software Foundation, Inc. 4699b0f92Schristos 5699b0f92Schristos This file is part of GDB. 6699b0f92Schristos 7699b0f92Schristos This program is free software; you can redistribute it and/or modify 8699b0f92Schristos it under the terms of the GNU General Public License as published by 9699b0f92Schristos the Free Software Foundation; either version 3 of the License, or 10699b0f92Schristos (at your option) any later version. 11699b0f92Schristos 12699b0f92Schristos This program is distributed in the hope that it will be useful, 13699b0f92Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 14699b0f92Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15699b0f92Schristos GNU General Public License for more details. 16699b0f92Schristos 17699b0f92Schristos You should have received a copy of the GNU General Public License 18699b0f92Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19699b0f92Schristos 20699b0f92Schristos #include "defs.h" 21699b0f92Schristos #include "arch-utils.h" 22699b0f92Schristos #include "frame.h" 23699b0f92Schristos #include "gdbcore.h" 24699b0f92Schristos #include "frame-unwind.h" 25699b0f92Schristos #include "gdbtypes.h" 26699b0f92Schristos #include "osabi.h" 27699b0f92Schristos #include "regcache.h" 28699b0f92Schristos #include "regset.h" 29699b0f92Schristos #include "symtab.h" 30699b0f92Schristos #include "target.h" 31699b0f92Schristos #include "trad-frame.h" 32699b0f92Schristos 33699b0f92Schristos #include "ppc-tdep.h" 34699b0f92Schristos #include "ppc64-tdep.h" 35699b0f92Schristos #include "ppc-fbsd-tdep.h" 36699b0f92Schristos #include "fbsd-tdep.h" 37699b0f92Schristos #include "solib-svr4.h" 387d62b00eSchristos #include "inferior.h" 39699b0f92Schristos 40699b0f92Schristos 41699b0f92Schristos /* 32-bit regset descriptions. */ 42699b0f92Schristos 43699b0f92Schristos static const struct ppc_reg_offsets ppc32_fbsd_reg_offsets = 44699b0f92Schristos { 45699b0f92Schristos /* General-purpose registers. */ 46699b0f92Schristos /* .r0_offset = */ 0, 47699b0f92Schristos /* .gpr_size = */ 4, 48699b0f92Schristos /* .xr_size = */ 4, 49699b0f92Schristos /* .pc_offset = */ 144, 50699b0f92Schristos /* .ps_offset = */ -1, 51699b0f92Schristos /* .cr_offset = */ 132, 52699b0f92Schristos /* .lr_offset = */ 128, 53699b0f92Schristos /* .ctr_offset = */ 140, 54699b0f92Schristos /* .xer_offset = */ 136, 55699b0f92Schristos /* .mq_offset = */ -1, 56699b0f92Schristos 57699b0f92Schristos /* Floating-point registers. */ 58699b0f92Schristos /* .f0_offset = */ 0, 59699b0f92Schristos /* .fpscr_offset = */ 256, 607f2ac410Schristos /* .fpscr_size = */ 8 61699b0f92Schristos }; 62699b0f92Schristos 63699b0f92Schristos /* 64-bit regset descriptions. */ 64699b0f92Schristos 65699b0f92Schristos static const struct ppc_reg_offsets ppc64_fbsd_reg_offsets = 66699b0f92Schristos { 67699b0f92Schristos /* General-purpose registers. */ 68699b0f92Schristos /* .r0_offset = */ 0, 69699b0f92Schristos /* .gpr_size = */ 8, 70699b0f92Schristos /* .xr_size = */ 8, 71699b0f92Schristos /* .pc_offset = */ 288, 72699b0f92Schristos /* .ps_offset = */ -1, 73699b0f92Schristos /* .cr_offset = */ 264, 74699b0f92Schristos /* .lr_offset = */ 256, 75699b0f92Schristos /* .ctr_offset = */ 280, 76699b0f92Schristos /* .xer_offset = */ 272, 77699b0f92Schristos /* .mq_offset = */ -1, 78699b0f92Schristos 79699b0f92Schristos /* Floating-point registers. */ 80699b0f92Schristos /* .f0_offset = */ 0, 81699b0f92Schristos /* .fpscr_offset = */ 256, 827f2ac410Schristos /* .fpscr_size = */ 8 83699b0f92Schristos }; 84699b0f92Schristos 85699b0f92Schristos /* 32-bit general-purpose register set. */ 86699b0f92Schristos 87699b0f92Schristos static const struct regset ppc32_fbsd_gregset = { 88699b0f92Schristos &ppc32_fbsd_reg_offsets, 89699b0f92Schristos ppc_supply_gregset, 90699b0f92Schristos ppc_collect_gregset 91699b0f92Schristos }; 92699b0f92Schristos 93699b0f92Schristos /* 64-bit general-purpose register set. */ 94699b0f92Schristos 95699b0f92Schristos static const struct regset ppc64_fbsd_gregset = { 96699b0f92Schristos &ppc64_fbsd_reg_offsets, 97699b0f92Schristos ppc_supply_gregset, 98699b0f92Schristos ppc_collect_gregset 99699b0f92Schristos }; 100699b0f92Schristos 101699b0f92Schristos /* 32-/64-bit floating-point register set. */ 102699b0f92Schristos 103699b0f92Schristos static const struct regset ppc32_fbsd_fpregset = { 104699b0f92Schristos &ppc32_fbsd_reg_offsets, 105699b0f92Schristos ppc_supply_fpregset, 106699b0f92Schristos ppc_collect_fpregset 107699b0f92Schristos }; 108699b0f92Schristos 109699b0f92Schristos const struct regset * 110699b0f92Schristos ppc_fbsd_gregset (int wordsize) 111699b0f92Schristos { 112699b0f92Schristos return wordsize == 8 ? &ppc64_fbsd_gregset : &ppc32_fbsd_gregset; 113699b0f92Schristos } 114699b0f92Schristos 115699b0f92Schristos const struct regset * 116699b0f92Schristos ppc_fbsd_fpregset (void) 117699b0f92Schristos { 118699b0f92Schristos return &ppc32_fbsd_fpregset; 119699b0f92Schristos } 120699b0f92Schristos 121699b0f92Schristos /* Iterate over core file register note sections. */ 122699b0f92Schristos 123699b0f92Schristos static void 124699b0f92Schristos ppcfbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, 125699b0f92Schristos iterate_over_regset_sections_cb *cb, 126699b0f92Schristos void *cb_data, 127699b0f92Schristos const struct regcache *regcache) 128699b0f92Schristos { 129*6881a400Schristos ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch); 130699b0f92Schristos 131699b0f92Schristos if (tdep->wordsize == 4) 1327f2ac410Schristos cb (".reg", 148, 148, &ppc32_fbsd_gregset, NULL, cb_data); 133699b0f92Schristos else 1347f2ac410Schristos cb (".reg", 296, 296, &ppc64_fbsd_gregset, NULL, cb_data); 1357f2ac410Schristos cb (".reg2", 264, 264, &ppc32_fbsd_fpregset, NULL, cb_data); 136699b0f92Schristos } 137699b0f92Schristos 138699b0f92Schristos /* Default page size. */ 139699b0f92Schristos 140699b0f92Schristos static const int ppcfbsd_page_size = 4096; 141699b0f92Schristos 142699b0f92Schristos /* Offset for sigreturn(2). */ 143699b0f92Schristos 144699b0f92Schristos static const int ppcfbsd_sigreturn_offset[] = { 145699b0f92Schristos 0xc, /* FreeBSD 32-bit */ 146699b0f92Schristos -1 147699b0f92Schristos }; 148699b0f92Schristos 149699b0f92Schristos /* Signal trampolines. */ 150699b0f92Schristos 151699b0f92Schristos static int 152699b0f92Schristos ppcfbsd_sigtramp_frame_sniffer (const struct frame_unwind *self, 153*6881a400Schristos frame_info_ptr this_frame, 154699b0f92Schristos void **this_cache) 155699b0f92Schristos { 156699b0f92Schristos struct gdbarch *gdbarch = get_frame_arch (this_frame); 157699b0f92Schristos enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 158699b0f92Schristos CORE_ADDR pc = get_frame_pc (this_frame); 159699b0f92Schristos CORE_ADDR start_pc = (pc & ~(ppcfbsd_page_size - 1)); 160699b0f92Schristos const int *offset; 161699b0f92Schristos const char *name; 162699b0f92Schristos 163699b0f92Schristos /* A stack trampoline is detected if no name is associated 164699b0f92Schristos to the current pc and if it points inside a trampoline 165699b0f92Schristos sequence. */ 166699b0f92Schristos 167699b0f92Schristos find_pc_partial_function (pc, &name, NULL, NULL); 168699b0f92Schristos 169699b0f92Schristos /* If we have a name, we have no trampoline, return. */ 170699b0f92Schristos if (name) 171699b0f92Schristos return 0; 172699b0f92Schristos 173699b0f92Schristos for (offset = ppcfbsd_sigreturn_offset; *offset != -1; offset++) 174699b0f92Schristos { 175699b0f92Schristos gdb_byte buf[2 * PPC_INSN_SIZE]; 176699b0f92Schristos unsigned long insn; 177699b0f92Schristos 178699b0f92Schristos if (!safe_frame_unwind_memory (this_frame, start_pc + *offset, 179*6881a400Schristos {buf, sizeof buf})) 180699b0f92Schristos continue; 181699b0f92Schristos 182699b0f92Schristos /* Check for "li r0,SYS_sigreturn". */ 183699b0f92Schristos insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order); 184699b0f92Schristos if (insn != 0x380001a1) 185699b0f92Schristos continue; 186699b0f92Schristos 187699b0f92Schristos /* Check for "sc". */ 188699b0f92Schristos insn = extract_unsigned_integer (buf + PPC_INSN_SIZE, 189699b0f92Schristos PPC_INSN_SIZE, byte_order); 190699b0f92Schristos if (insn != 0x44000002) 191699b0f92Schristos continue; 192699b0f92Schristos 193699b0f92Schristos return 1; 194699b0f92Schristos } 195699b0f92Schristos 196699b0f92Schristos return 0; 197699b0f92Schristos } 198699b0f92Schristos 199699b0f92Schristos static struct trad_frame_cache * 200*6881a400Schristos ppcfbsd_sigtramp_frame_cache (frame_info_ptr this_frame, void **this_cache) 201699b0f92Schristos { 202699b0f92Schristos struct gdbarch *gdbarch = get_frame_arch (this_frame); 203*6881a400Schristos ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch); 204699b0f92Schristos struct trad_frame_cache *cache; 205699b0f92Schristos CORE_ADDR addr, base, func; 206699b0f92Schristos gdb_byte buf[PPC_INSN_SIZE]; 207699b0f92Schristos int i; 208699b0f92Schristos 209699b0f92Schristos if (*this_cache) 210699b0f92Schristos return (struct trad_frame_cache *) *this_cache; 211699b0f92Schristos 212699b0f92Schristos cache = trad_frame_cache_zalloc (this_frame); 213699b0f92Schristos *this_cache = cache; 214699b0f92Schristos 215699b0f92Schristos func = get_frame_pc (this_frame); 216699b0f92Schristos func &= ~(ppcfbsd_page_size - 1); 217*6881a400Schristos if (!safe_frame_unwind_memory (this_frame, func, {buf, sizeof buf})) 218699b0f92Schristos return cache; 219699b0f92Schristos 220699b0f92Schristos base = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch)); 221699b0f92Schristos addr = base + 0x10 + 2 * tdep->wordsize; 222699b0f92Schristos for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize) 223699b0f92Schristos { 224699b0f92Schristos int regnum = i + tdep->ppc_gp0_regnum; 225699b0f92Schristos trad_frame_set_reg_addr (cache, regnum, addr); 226699b0f92Schristos } 227699b0f92Schristos trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, addr); 228699b0f92Schristos addr += tdep->wordsize; 229699b0f92Schristos trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, addr); 230699b0f92Schristos addr += tdep->wordsize; 231699b0f92Schristos trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, addr); 232699b0f92Schristos addr += tdep->wordsize; 233699b0f92Schristos trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, addr); 234699b0f92Schristos addr += tdep->wordsize; 235699b0f92Schristos trad_frame_set_reg_addr (cache, gdbarch_pc_regnum (gdbarch), addr); 236699b0f92Schristos /* SRR0? */ 237699b0f92Schristos addr += tdep->wordsize; 238699b0f92Schristos 239699b0f92Schristos /* Construct the frame ID using the function start. */ 240699b0f92Schristos trad_frame_set_id (cache, frame_id_build (base, func)); 241699b0f92Schristos 242699b0f92Schristos return cache; 243699b0f92Schristos } 244699b0f92Schristos 245699b0f92Schristos static void 246*6881a400Schristos ppcfbsd_sigtramp_frame_this_id (frame_info_ptr this_frame, 247699b0f92Schristos void **this_cache, struct frame_id *this_id) 248699b0f92Schristos { 249699b0f92Schristos struct trad_frame_cache *cache = 250699b0f92Schristos ppcfbsd_sigtramp_frame_cache (this_frame, this_cache); 251699b0f92Schristos 252699b0f92Schristos trad_frame_get_id (cache, this_id); 253699b0f92Schristos } 254699b0f92Schristos 255699b0f92Schristos static struct value * 256*6881a400Schristos ppcfbsd_sigtramp_frame_prev_register (frame_info_ptr this_frame, 257699b0f92Schristos void **this_cache, int regnum) 258699b0f92Schristos { 259699b0f92Schristos struct trad_frame_cache *cache = 260699b0f92Schristos ppcfbsd_sigtramp_frame_cache (this_frame, this_cache); 261699b0f92Schristos 262699b0f92Schristos return trad_frame_get_register (cache, this_frame, regnum); 263699b0f92Schristos } 264699b0f92Schristos 265699b0f92Schristos static const struct frame_unwind ppcfbsd_sigtramp_frame_unwind = { 266*6881a400Schristos "ppc freebsd sigtramp", 267699b0f92Schristos SIGTRAMP_FRAME, 268699b0f92Schristos default_frame_unwind_stop_reason, 269699b0f92Schristos ppcfbsd_sigtramp_frame_this_id, 270699b0f92Schristos ppcfbsd_sigtramp_frame_prev_register, 271699b0f92Schristos NULL, 272699b0f92Schristos ppcfbsd_sigtramp_frame_sniffer 273699b0f92Schristos }; 274699b0f92Schristos 275699b0f92Schristos static enum return_value_convention 276699b0f92Schristos ppcfbsd_return_value (struct gdbarch *gdbarch, struct value *function, 277699b0f92Schristos struct type *valtype, struct regcache *regcache, 278699b0f92Schristos gdb_byte *readbuf, const gdb_byte *writebuf) 279699b0f92Schristos { 280699b0f92Schristos return ppc_sysv_abi_broken_return_value (gdbarch, function, valtype, 281699b0f92Schristos regcache, readbuf, writebuf); 282699b0f92Schristos } 283699b0f92Schristos 2847d62b00eSchristos /* Implement the "get_thread_local_address" gdbarch method. */ 2857d62b00eSchristos 2867d62b00eSchristos static CORE_ADDR 2877d62b00eSchristos ppcfbsd_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid, 2887d62b00eSchristos CORE_ADDR lm_addr, CORE_ADDR offset) 2897d62b00eSchristos { 290*6881a400Schristos ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch); 2917d62b00eSchristos struct regcache *regcache; 2927d62b00eSchristos int tp_offset, tp_regnum; 2937d62b00eSchristos 2947d62b00eSchristos regcache = get_thread_arch_regcache (current_inferior ()->process_target (), 2957d62b00eSchristos ptid, gdbarch); 2967d62b00eSchristos 2977d62b00eSchristos if (tdep->wordsize == 4) 2987d62b00eSchristos { 2997d62b00eSchristos tp_offset = 0x7008; 3007d62b00eSchristos tp_regnum = PPC_R0_REGNUM + 2; 3017d62b00eSchristos } 3027d62b00eSchristos else 3037d62b00eSchristos { 3047d62b00eSchristos tp_offset = 0x7010; 3057d62b00eSchristos tp_regnum = PPC_R0_REGNUM + 13; 3067d62b00eSchristos } 3077d62b00eSchristos target_fetch_registers (regcache, tp_regnum); 3087d62b00eSchristos 3097d62b00eSchristos ULONGEST tp; 3107d62b00eSchristos if (regcache->cooked_read (tp_regnum, &tp) != REG_VALID) 3117d62b00eSchristos error (_("Unable to fetch tcb pointer")); 3127d62b00eSchristos 3137d62b00eSchristos /* tp points to the end of the TCB block. The first member of the 3147d62b00eSchristos TCB is the pointer to the DTV array. */ 3157d62b00eSchristos CORE_ADDR dtv_addr = tp - tp_offset; 3167d62b00eSchristos return fbsd_get_thread_local_address (gdbarch, dtv_addr, lm_addr, offset); 3177d62b00eSchristos } 318699b0f92Schristos 319699b0f92Schristos static void 320699b0f92Schristos ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 321699b0f92Schristos { 322*6881a400Schristos ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch); 323699b0f92Schristos 324699b0f92Schristos /* Generic FreeBSD support. */ 325699b0f92Schristos fbsd_init_abi (info, gdbarch); 326699b0f92Schristos 327699b0f92Schristos /* FreeBSD doesn't support the 128-bit `long double' from the psABI. */ 328699b0f92Schristos set_gdbarch_long_double_bit (gdbarch, 64); 329699b0f92Schristos set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double); 330699b0f92Schristos 331699b0f92Schristos if (tdep->wordsize == 4) 332699b0f92Schristos { 333699b0f92Schristos set_gdbarch_return_value (gdbarch, ppcfbsd_return_value); 334699b0f92Schristos 335699b0f92Schristos set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); 336699b0f92Schristos set_solib_svr4_fetch_link_map_offsets (gdbarch, 337699b0f92Schristos svr4_ilp32_fetch_link_map_offsets); 338699b0f92Schristos 339699b0f92Schristos frame_unwind_append_unwinder (gdbarch, &ppcfbsd_sigtramp_frame_unwind); 340699b0f92Schristos set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc"); 341699b0f92Schristos } 342699b0f92Schristos 343699b0f92Schristos if (tdep->wordsize == 8) 344699b0f92Schristos { 345699b0f92Schristos set_gdbarch_convert_from_func_ptr_addr 346699b0f92Schristos (gdbarch, ppc64_convert_from_func_ptr_addr); 347699b0f92Schristos set_gdbarch_elf_make_msymbol_special (gdbarch, 348699b0f92Schristos ppc64_elf_make_msymbol_special); 349699b0f92Schristos 350699b0f92Schristos set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code); 351699b0f92Schristos set_solib_svr4_fetch_link_map_offsets (gdbarch, 352699b0f92Schristos svr4_lp64_fetch_link_map_offsets); 353699b0f92Schristos set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpc"); 354699b0f92Schristos } 355699b0f92Schristos 356699b0f92Schristos set_gdbarch_iterate_over_regset_sections 357699b0f92Schristos (gdbarch, ppcfbsd_iterate_over_regset_sections); 358699b0f92Schristos 359699b0f92Schristos set_gdbarch_fetch_tls_load_module_address (gdbarch, 360699b0f92Schristos svr4_fetch_objfile_link_map); 3617d62b00eSchristos set_gdbarch_get_thread_local_address (gdbarch, 3627d62b00eSchristos ppcfbsd_get_thread_local_address); 363699b0f92Schristos } 364699b0f92Schristos 3657d62b00eSchristos void _initialize_ppcfbsd_tdep (); 366699b0f92Schristos void 3677d62b00eSchristos _initialize_ppcfbsd_tdep () 368699b0f92Schristos { 369699b0f92Schristos gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc, GDB_OSABI_FREEBSD, 370699b0f92Schristos ppcfbsd_init_abi); 371699b0f92Schristos gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc64, GDB_OSABI_FREEBSD, 372699b0f92Schristos ppcfbsd_init_abi); 373699b0f92Schristos gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_FREEBSD, 374699b0f92Schristos ppcfbsd_init_abi); 375699b0f92Schristos } 376