17f2ac410Schristos /* Target-dependent code for FreeBSD/arm. 27f2ac410Schristos 3*6881a400Schristos Copyright (C) 2017-2023 Free Software Foundation, Inc. 47f2ac410Schristos 57f2ac410Schristos This file is part of GDB. 67f2ac410Schristos 77f2ac410Schristos This program is free software; you can redistribute it and/or modify 87f2ac410Schristos it under the terms of the GNU General Public License as published by 97f2ac410Schristos the Free Software Foundation; either version 3 of the License, or 107f2ac410Schristos (at your option) any later version. 117f2ac410Schristos 127f2ac410Schristos This program is distributed in the hope that it will be useful, 137f2ac410Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 147f2ac410Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 157f2ac410Schristos GNU General Public License for more details. 167f2ac410Schristos 177f2ac410Schristos You should have received a copy of the GNU General Public License 187f2ac410Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 197f2ac410Schristos 207f2ac410Schristos #include "defs.h" 217f2ac410Schristos 227f2ac410Schristos #include "elf/common.h" 237d62b00eSchristos #include "target-descriptions.h" 247d62b00eSchristos #include "aarch32-tdep.h" 257f2ac410Schristos #include "arm-tdep.h" 267f2ac410Schristos #include "arm-fbsd-tdep.h" 277f2ac410Schristos #include "auxv.h" 287f2ac410Schristos #include "fbsd-tdep.h" 297f2ac410Schristos #include "gdbcore.h" 30*6881a400Schristos #include "inferior.h" 317f2ac410Schristos #include "osabi.h" 327f2ac410Schristos #include "solib-svr4.h" 337f2ac410Schristos #include "trad-frame.h" 347f2ac410Schristos #include "tramp-frame.h" 357f2ac410Schristos 367f2ac410Schristos /* Register maps. */ 377f2ac410Schristos 387f2ac410Schristos static const struct regcache_map_entry arm_fbsd_gregmap[] = 397f2ac410Schristos { 407f2ac410Schristos { 13, ARM_A1_REGNUM, 4 }, /* r0 ... r12 */ 417f2ac410Schristos { 1, ARM_SP_REGNUM, 4 }, 427f2ac410Schristos { 1, ARM_LR_REGNUM, 4 }, 437f2ac410Schristos { 1, ARM_PC_REGNUM, 4 }, 447f2ac410Schristos { 1, ARM_PS_REGNUM, 4 }, 457f2ac410Schristos { 0 } 467f2ac410Schristos }; 477f2ac410Schristos 487f2ac410Schristos static const struct regcache_map_entry arm_fbsd_vfpregmap[] = 497f2ac410Schristos { 507f2ac410Schristos { 32, ARM_D0_REGNUM, 8 }, /* d0 ... d31 */ 517f2ac410Schristos { 1, ARM_FPSCR_REGNUM, 4 }, 527f2ac410Schristos { 0 } 537f2ac410Schristos }; 547f2ac410Schristos 55*6881a400Schristos /* Register numbers are relative to tdep->tls_regnum. */ 56*6881a400Schristos 57*6881a400Schristos static const struct regcache_map_entry arm_fbsd_tls_regmap[] = 58*6881a400Schristos { 59*6881a400Schristos { 1, 0, 4 }, /* tpidruro */ 60*6881a400Schristos { 0 } 61*6881a400Schristos }; 62*6881a400Schristos 637f2ac410Schristos /* In a signal frame, sp points to a 'struct sigframe' which is 647f2ac410Schristos defined as: 657f2ac410Schristos 667f2ac410Schristos struct sigframe { 677f2ac410Schristos siginfo_t sf_si; 687f2ac410Schristos ucontext_t sf_uc; 697f2ac410Schristos mcontext_vfp_t sf_vfp; 707f2ac410Schristos }; 717f2ac410Schristos 727f2ac410Schristos ucontext_t is defined as: 737f2ac410Schristos 747f2ac410Schristos struct __ucontext { 757f2ac410Schristos sigset_t uc_sigmask; 767f2ac410Schristos mcontext_t uc_mcontext; 777f2ac410Schristos ... 787f2ac410Schristos }; 797f2ac410Schristos 807f2ac410Schristos mcontext_t is defined as: 817f2ac410Schristos 827f2ac410Schristos struct { 837f2ac410Schristos unsigned int __gregs[17]; 847f2ac410Schristos size_t mc_vfp_size; 857f2ac410Schristos void *mc_vfp_ptr; 867f2ac410Schristos ... 877f2ac410Schristos }; 887f2ac410Schristos 897f2ac410Schristos mcontext_vfp_t is defined as: 907f2ac410Schristos 917f2ac410Schristos struct { 927f2ac410Schristos uint64_t mcv_reg[32]; 937f2ac410Schristos uint32_t mcv_fpscr; 947f2ac410Schristos }; 957f2ac410Schristos 967f2ac410Schristos If the VFP state is valid, then mc_vfp_ptr will point to sf_vfp in 977f2ac410Schristos the sigframe, otherwise it is NULL. There is no non-VFP floating 987f2ac410Schristos point register state saved in the signal frame. */ 997f2ac410Schristos 1007f2ac410Schristos #define ARM_SIGFRAME_UCONTEXT_OFFSET 64 1017f2ac410Schristos #define ARM_UCONTEXT_MCONTEXT_OFFSET 16 1027f2ac410Schristos #define ARM_MCONTEXT_VFP_PTR_OFFSET 72 1037f2ac410Schristos 1047f2ac410Schristos /* Implement the "init" method of struct tramp_frame. */ 1057f2ac410Schristos 1067f2ac410Schristos static void 1077f2ac410Schristos arm_fbsd_sigframe_init (const struct tramp_frame *self, 108*6881a400Schristos frame_info_ptr this_frame, 1097f2ac410Schristos struct trad_frame_cache *this_cache, 1107f2ac410Schristos CORE_ADDR func) 1117f2ac410Schristos { 1127f2ac410Schristos struct gdbarch *gdbarch = get_frame_arch (this_frame); 1137f2ac410Schristos enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 1147f2ac410Schristos CORE_ADDR sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM); 1157f2ac410Schristos CORE_ADDR mcontext_addr = (sp 1167f2ac410Schristos + ARM_SIGFRAME_UCONTEXT_OFFSET 1177f2ac410Schristos + ARM_UCONTEXT_MCONTEXT_OFFSET); 1187f2ac410Schristos ULONGEST mcontext_vfp_addr; 1197f2ac410Schristos 1207f2ac410Schristos trad_frame_set_reg_regmap (this_cache, arm_fbsd_gregmap, mcontext_addr, 1217f2ac410Schristos regcache_map_entry_size (arm_fbsd_gregmap)); 1227f2ac410Schristos 1237f2ac410Schristos if (safe_read_memory_unsigned_integer (mcontext_addr 1247f2ac410Schristos + ARM_MCONTEXT_VFP_PTR_OFFSET, 4, 1257f2ac410Schristos byte_order, 1267f2ac410Schristos &mcontext_vfp_addr) 1277f2ac410Schristos && mcontext_vfp_addr != 0) 1287f2ac410Schristos trad_frame_set_reg_regmap (this_cache, arm_fbsd_vfpregmap, mcontext_vfp_addr, 1297f2ac410Schristos regcache_map_entry_size (arm_fbsd_vfpregmap)); 1307f2ac410Schristos 1317f2ac410Schristos trad_frame_set_id (this_cache, frame_id_build (sp, func)); 1327f2ac410Schristos } 1337f2ac410Schristos 1347f2ac410Schristos static const struct tramp_frame arm_fbsd_sigframe = 1357f2ac410Schristos { 1367f2ac410Schristos SIGTRAMP_FRAME, 1377f2ac410Schristos 4, 1387f2ac410Schristos { 1397f2ac410Schristos {0xe1a0000d, ULONGEST_MAX}, /* mov r0, sp */ 1407f2ac410Schristos {0xe2800040, ULONGEST_MAX}, /* add r0, r0, #SIGF_UC */ 1417f2ac410Schristos {0xe59f700c, ULONGEST_MAX}, /* ldr r7, [pc, #12] */ 1427f2ac410Schristos {0xef0001a1, ULONGEST_MAX}, /* swi SYS_sigreturn */ 1437f2ac410Schristos {TRAMP_SENTINEL_INSN, ULONGEST_MAX} 1447f2ac410Schristos }, 1457f2ac410Schristos arm_fbsd_sigframe_init 1467f2ac410Schristos }; 1477f2ac410Schristos 1487f2ac410Schristos /* Register set definitions. */ 1497f2ac410Schristos 1507f2ac410Schristos const struct regset arm_fbsd_gregset = 1517f2ac410Schristos { 1527f2ac410Schristos arm_fbsd_gregmap, 1537f2ac410Schristos regcache_supply_regset, regcache_collect_regset 1547f2ac410Schristos }; 1557f2ac410Schristos 1567f2ac410Schristos const struct regset arm_fbsd_vfpregset = 1577f2ac410Schristos { 1587f2ac410Schristos arm_fbsd_vfpregmap, 1597f2ac410Schristos regcache_supply_regset, regcache_collect_regset 1607f2ac410Schristos }; 1617f2ac410Schristos 162*6881a400Schristos static void 163*6881a400Schristos arm_fbsd_supply_tls_regset (const struct regset *regset, 164*6881a400Schristos struct regcache *regcache, 165*6881a400Schristos int regnum, const void *buf, size_t size) 166*6881a400Schristos { 167*6881a400Schristos struct gdbarch *gdbarch = regcache->arch (); 168*6881a400Schristos arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch); 169*6881a400Schristos 170*6881a400Schristos regcache->supply_regset (regset, tdep->tls_regnum, regnum, buf, size); 171*6881a400Schristos } 172*6881a400Schristos 173*6881a400Schristos static void 174*6881a400Schristos arm_fbsd_collect_tls_regset (const struct regset *regset, 175*6881a400Schristos const struct regcache *regcache, 176*6881a400Schristos int regnum, void *buf, size_t size) 177*6881a400Schristos { 178*6881a400Schristos struct gdbarch *gdbarch = regcache->arch (); 179*6881a400Schristos arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch); 180*6881a400Schristos 181*6881a400Schristos regcache->collect_regset (regset, tdep->tls_regnum, regnum, buf, size); 182*6881a400Schristos } 183*6881a400Schristos 184*6881a400Schristos const struct regset arm_fbsd_tls_regset = 185*6881a400Schristos { 186*6881a400Schristos arm_fbsd_tls_regmap, 187*6881a400Schristos arm_fbsd_supply_tls_regset, arm_fbsd_collect_tls_regset 188*6881a400Schristos }; 189*6881a400Schristos 1907d62b00eSchristos /* Implement the "iterate_over_regset_sections" gdbarch method. */ 1917f2ac410Schristos 1927f2ac410Schristos static void 1937f2ac410Schristos arm_fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, 1947f2ac410Schristos iterate_over_regset_sections_cb *cb, 1957f2ac410Schristos void *cb_data, 1967f2ac410Schristos const struct regcache *regcache) 1977f2ac410Schristos { 198*6881a400Schristos arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch); 1997f2ac410Schristos 2007f2ac410Schristos cb (".reg", ARM_FBSD_SIZEOF_GREGSET, ARM_FBSD_SIZEOF_GREGSET, 2017f2ac410Schristos &arm_fbsd_gregset, NULL, cb_data); 2027f2ac410Schristos 203*6881a400Schristos if (tdep->tls_regnum > 0) 204*6881a400Schristos cb (".reg-aarch-tls", ARM_FBSD_SIZEOF_TLSREGSET, ARM_FBSD_SIZEOF_TLSREGSET, 205*6881a400Schristos &arm_fbsd_tls_regset, NULL, cb_data); 206*6881a400Schristos 2077f2ac410Schristos /* While FreeBSD/arm cores do contain a NT_FPREGSET / ".reg2" 2087f2ac410Schristos register set, it is not populated with register values by the 2097f2ac410Schristos kernel but just contains all zeroes. */ 2107f2ac410Schristos if (tdep->vfp_register_count > 0) 2117f2ac410Schristos cb (".reg-arm-vfp", ARM_FBSD_SIZEOF_VFPREGSET, ARM_FBSD_SIZEOF_VFPREGSET, 2127f2ac410Schristos &arm_fbsd_vfpregset, "VFP floating-point", cb_data); 2137f2ac410Schristos } 2147f2ac410Schristos 215*6881a400Schristos /* See arm-fbsd-tdep.h. */ 2167f2ac410Schristos 2177f2ac410Schristos const struct target_desc * 218*6881a400Schristos arm_fbsd_read_description_auxv (const gdb::optional<gdb::byte_vector> &auxv, 219*6881a400Schristos target_ops *target, gdbarch *gdbarch, bool tls) 2207f2ac410Schristos { 2217f2ac410Schristos CORE_ADDR arm_hwcap = 0; 2227f2ac410Schristos 223*6881a400Schristos if (!auxv.has_value () 224*6881a400Schristos || target_auxv_search (*auxv, target, gdbarch, AT_FREEBSD_HWCAP, 225*6881a400Schristos &arm_hwcap) != 1) 226*6881a400Schristos return arm_read_description (ARM_FP_TYPE_NONE, tls); 2277f2ac410Schristos 2287f2ac410Schristos if (arm_hwcap & HWCAP_VFP) 2297f2ac410Schristos { 2307f2ac410Schristos if (arm_hwcap & HWCAP_NEON) 2317d62b00eSchristos return aarch32_read_description (); 2327f2ac410Schristos else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPD32)) 2337f2ac410Schristos == (HWCAP_VFPv3 | HWCAP_VFPD32)) 234*6881a400Schristos return arm_read_description (ARM_FP_TYPE_VFPV3, tls); 2357f2ac410Schristos else 236*6881a400Schristos return arm_read_description (ARM_FP_TYPE_VFPV2, tls); 2377f2ac410Schristos } 2387f2ac410Schristos 239*6881a400Schristos return arm_read_description (ARM_FP_TYPE_NONE, tls); 240*6881a400Schristos } 241*6881a400Schristos 242*6881a400Schristos /* See arm-fbsd-tdep.h. */ 243*6881a400Schristos 244*6881a400Schristos const struct target_desc * 245*6881a400Schristos arm_fbsd_read_description_auxv (bool tls) 246*6881a400Schristos { 247*6881a400Schristos gdb::optional<gdb::byte_vector> auxv = target_read_auxv (); 248*6881a400Schristos return arm_fbsd_read_description_auxv (auxv, 249*6881a400Schristos current_inferior ()->top_target (), 250*6881a400Schristos current_inferior ()->gdbarch, 251*6881a400Schristos tls); 2527f2ac410Schristos } 2537f2ac410Schristos 2547f2ac410Schristos /* Implement the "core_read_description" gdbarch method. */ 2557f2ac410Schristos 2567f2ac410Schristos static const struct target_desc * 2577f2ac410Schristos arm_fbsd_core_read_description (struct gdbarch *gdbarch, 2587f2ac410Schristos struct target_ops *target, 2597f2ac410Schristos bfd *abfd) 2607f2ac410Schristos { 261*6881a400Schristos asection *tls = bfd_get_section_by_name (abfd, ".reg-aarch-tls"); 262*6881a400Schristos 263*6881a400Schristos gdb::optional<gdb::byte_vector> auxv = target_read_auxv_raw (target); 264*6881a400Schristos return arm_fbsd_read_description_auxv (auxv, target, gdbarch, tls != nullptr); 265*6881a400Schristos } 266*6881a400Schristos 267*6881a400Schristos /* Implement the get_thread_local_address gdbarch method. */ 268*6881a400Schristos 269*6881a400Schristos static CORE_ADDR 270*6881a400Schristos arm_fbsd_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid, 271*6881a400Schristos CORE_ADDR lm_addr, CORE_ADDR offset) 272*6881a400Schristos { 273*6881a400Schristos arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch); 274*6881a400Schristos struct regcache *regcache; 275*6881a400Schristos 276*6881a400Schristos regcache = get_thread_arch_regcache (current_inferior ()->process_target (), 277*6881a400Schristos ptid, gdbarch); 278*6881a400Schristos 279*6881a400Schristos target_fetch_registers (regcache, tdep->tls_regnum); 280*6881a400Schristos 281*6881a400Schristos ULONGEST tpidruro; 282*6881a400Schristos if (regcache->cooked_read (tdep->tls_regnum, &tpidruro) != REG_VALID) 283*6881a400Schristos error (_("Unable to fetch %%tpidruro")); 284*6881a400Schristos 285*6881a400Schristos /* %tpidruro points to the TCB whose first member is the dtv 286*6881a400Schristos pointer. */ 287*6881a400Schristos CORE_ADDR dtv_addr = tpidruro; 288*6881a400Schristos return fbsd_get_thread_local_address (gdbarch, dtv_addr, lm_addr, offset); 2897f2ac410Schristos } 2907f2ac410Schristos 2917f2ac410Schristos /* Implement the 'init_osabi' method of struct gdb_osabi_handler. */ 2927f2ac410Schristos 2937f2ac410Schristos static void 2947f2ac410Schristos arm_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 2957f2ac410Schristos { 296*6881a400Schristos arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch); 2977f2ac410Schristos 2987f2ac410Schristos /* Generic FreeBSD support. */ 2997f2ac410Schristos fbsd_init_abi (info, gdbarch); 3007f2ac410Schristos 3017f2ac410Schristos if (tdep->fp_model == ARM_FLOAT_AUTO) 3027f2ac410Schristos tdep->fp_model = ARM_FLOAT_SOFT_VFP; 3037f2ac410Schristos 3047f2ac410Schristos tramp_frame_prepend_unwinder (gdbarch, &arm_fbsd_sigframe); 3057f2ac410Schristos 3067f2ac410Schristos set_solib_svr4_fetch_link_map_offsets 3077f2ac410Schristos (gdbarch, svr4_ilp32_fetch_link_map_offsets); 3087f2ac410Schristos 3097f2ac410Schristos tdep->jb_pc = 24; 3107f2ac410Schristos tdep->jb_elt_size = 4; 3117f2ac410Schristos 3127f2ac410Schristos set_gdbarch_iterate_over_regset_sections 3137f2ac410Schristos (gdbarch, arm_fbsd_iterate_over_regset_sections); 3147f2ac410Schristos set_gdbarch_core_read_description (gdbarch, arm_fbsd_core_read_description); 3157f2ac410Schristos 316*6881a400Schristos if (tdep->tls_regnum > 0) 317*6881a400Schristos { 318*6881a400Schristos set_gdbarch_fetch_tls_load_module_address (gdbarch, 319*6881a400Schristos svr4_fetch_objfile_link_map); 320*6881a400Schristos set_gdbarch_get_thread_local_address (gdbarch, 321*6881a400Schristos arm_fbsd_get_thread_local_address); 322*6881a400Schristos } 323*6881a400Schristos 3247f2ac410Schristos /* Single stepping. */ 3257f2ac410Schristos set_gdbarch_software_single_step (gdbarch, arm_software_single_step); 3267f2ac410Schristos } 3277f2ac410Schristos 3287d62b00eSchristos void _initialize_arm_fbsd_tdep (); 3297f2ac410Schristos void 3307d62b00eSchristos _initialize_arm_fbsd_tdep () 3317f2ac410Schristos { 3327f2ac410Schristos gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_FREEBSD, 3337f2ac410Schristos arm_fbsd_init_abi); 3347f2ac410Schristos } 335