1699b0f92Schristos /* Target-dependent code for FreeBSD/amd64. 2699b0f92Schristos 3*6881a400Schristos Copyright (C) 2003-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 "osabi.h" 22699b0f92Schristos #include "regset.h" 23*6881a400Schristos #include "target.h" 24*6881a400Schristos #include "trad-frame.h" 25*6881a400Schristos #include "tramp-frame.h" 26699b0f92Schristos #include "i386-fbsd-tdep.h" 277d62b00eSchristos #include "gdbsupport/x86-xstate.h" 28699b0f92Schristos 29699b0f92Schristos #include "amd64-tdep.h" 30*6881a400Schristos #include "amd64-fbsd-tdep.h" 31699b0f92Schristos #include "fbsd-tdep.h" 32699b0f92Schristos #include "solib-svr4.h" 337d62b00eSchristos #include "inferior.h" 34699b0f92Schristos 35*6881a400Schristos /* The general-purpose regset consists of 22 64-bit slots, most of 36*6881a400Schristos which contain individual registers, but a few contain multiple 37*6881a400Schristos 16-bit segment registers. */ 38*6881a400Schristos #define AMD64_FBSD_SIZEOF_GREGSET (22 * 8) 39*6881a400Schristos 40*6881a400Schristos /* The segment base register set consists of 2 64-bit registers. */ 41*6881a400Schristos #define AMD64_FBSD_SIZEOF_SEGBASES_REGSET (2 * 8) 42*6881a400Schristos 43*6881a400Schristos /* Register maps. */ 44*6881a400Schristos 45*6881a400Schristos static const struct regcache_map_entry amd64_fbsd_gregmap[] = 46*6881a400Schristos { 47*6881a400Schristos { 1, AMD64_R15_REGNUM, 0 }, 48*6881a400Schristos { 1, AMD64_R14_REGNUM, 0 }, 49*6881a400Schristos { 1, AMD64_R13_REGNUM, 0 }, 50*6881a400Schristos { 1, AMD64_R12_REGNUM, 0 }, 51*6881a400Schristos { 1, AMD64_R11_REGNUM, 0 }, 52*6881a400Schristos { 1, AMD64_R10_REGNUM, 0 }, 53*6881a400Schristos { 1, AMD64_R9_REGNUM, 0 }, 54*6881a400Schristos { 1, AMD64_R8_REGNUM, 0 }, 55*6881a400Schristos { 1, AMD64_RDI_REGNUM, 0 }, 56*6881a400Schristos { 1, AMD64_RSI_REGNUM, 0 }, 57*6881a400Schristos { 1, AMD64_RBP_REGNUM, 0 }, 58*6881a400Schristos { 1, AMD64_RBX_REGNUM, 0 }, 59*6881a400Schristos { 1, AMD64_RDX_REGNUM, 0 }, 60*6881a400Schristos { 1, AMD64_RCX_REGNUM, 0 }, 61*6881a400Schristos { 1, AMD64_RAX_REGNUM, 0 }, 62*6881a400Schristos { 1, REGCACHE_MAP_SKIP, 4 }, /* trapno */ 63*6881a400Schristos { 1, AMD64_FS_REGNUM, 2 }, 64*6881a400Schristos { 1, AMD64_GS_REGNUM, 2 }, 65*6881a400Schristos { 1, REGCACHE_MAP_SKIP, 4 }, /* err */ 66*6881a400Schristos { 1, AMD64_ES_REGNUM, 2 }, 67*6881a400Schristos { 1, AMD64_DS_REGNUM, 2 }, 68*6881a400Schristos { 1, AMD64_RIP_REGNUM, 0 }, 69*6881a400Schristos { 1, AMD64_CS_REGNUM, 8 }, 70*6881a400Schristos { 1, AMD64_EFLAGS_REGNUM, 8 }, 71*6881a400Schristos { 1, AMD64_RSP_REGNUM, 0 }, 72*6881a400Schristos { 1, AMD64_SS_REGNUM, 8 }, 73*6881a400Schristos { 0 } 74*6881a400Schristos }; 75*6881a400Schristos 76*6881a400Schristos static const struct regcache_map_entry amd64_fbsd_segbases_regmap[] = 77*6881a400Schristos { 78*6881a400Schristos { 1, AMD64_FSBASE_REGNUM, 0 }, 79*6881a400Schristos { 1, AMD64_GSBASE_REGNUM, 0 }, 80*6881a400Schristos { 0 } 81*6881a400Schristos }; 82*6881a400Schristos 83*6881a400Schristos /* This layout including fsbase and gsbase was adopted in FreeBSD 84*6881a400Schristos 8.0. */ 85*6881a400Schristos 86*6881a400Schristos static const struct regcache_map_entry amd64_fbsd_mcregmap[] = 87*6881a400Schristos { 88*6881a400Schristos { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_onstack */ 89*6881a400Schristos { 1, AMD64_RDI_REGNUM, 0 }, 90*6881a400Schristos { 1, AMD64_RSI_REGNUM, 0 }, 91*6881a400Schristos { 1, AMD64_RDX_REGNUM, 0 }, 92*6881a400Schristos { 1, AMD64_RCX_REGNUM, 0 }, 93*6881a400Schristos { 1, AMD64_R8_REGNUM, 0 }, 94*6881a400Schristos { 1, AMD64_R9_REGNUM, 0 }, 95*6881a400Schristos { 1, AMD64_RAX_REGNUM, 0 }, 96*6881a400Schristos { 1, AMD64_RBX_REGNUM, 0 }, 97*6881a400Schristos { 1, AMD64_RBP_REGNUM, 0 }, 98*6881a400Schristos { 1, AMD64_R10_REGNUM, 0 }, 99*6881a400Schristos { 1, AMD64_R11_REGNUM, 0 }, 100*6881a400Schristos { 1, AMD64_R12_REGNUM, 0 }, 101*6881a400Schristos { 1, AMD64_R13_REGNUM, 0 }, 102*6881a400Schristos { 1, AMD64_R14_REGNUM, 0 }, 103*6881a400Schristos { 1, AMD64_R15_REGNUM, 0 }, 104*6881a400Schristos { 1, REGCACHE_MAP_SKIP, 4 }, /* mc_trapno */ 105*6881a400Schristos { 1, AMD64_FS_REGNUM, 2 }, 106*6881a400Schristos { 1, AMD64_GS_REGNUM, 2 }, 107*6881a400Schristos { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_addr */ 108*6881a400Schristos { 1, REGCACHE_MAP_SKIP, 4 }, /* mc_flags */ 109*6881a400Schristos { 1, AMD64_ES_REGNUM, 2 }, 110*6881a400Schristos { 1, AMD64_DS_REGNUM, 2 }, 111*6881a400Schristos { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_err */ 112*6881a400Schristos { 1, AMD64_RIP_REGNUM, 0 }, 113*6881a400Schristos { 1, AMD64_CS_REGNUM, 8 }, 114*6881a400Schristos { 1, AMD64_EFLAGS_REGNUM, 8 }, 115*6881a400Schristos { 1, AMD64_RSP_REGNUM, 0 }, 116*6881a400Schristos { 1, AMD64_SS_REGNUM, 8 }, 117*6881a400Schristos { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_len */ 118*6881a400Schristos { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_fpformat */ 119*6881a400Schristos { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_ownedfp */ 120*6881a400Schristos { 64, REGCACHE_MAP_SKIP, 8 }, /* mc_fpstate */ 121*6881a400Schristos { 1, AMD64_FSBASE_REGNUM, 0 }, 122*6881a400Schristos { 1, AMD64_GSBASE_REGNUM, 0 }, 123*6881a400Schristos { 0 } 124*6881a400Schristos }; 125*6881a400Schristos 126*6881a400Schristos /* Register set definitions. */ 127*6881a400Schristos 128*6881a400Schristos const struct regset amd64_fbsd_gregset = 129*6881a400Schristos { 130*6881a400Schristos amd64_fbsd_gregmap, regcache_supply_regset, regcache_collect_regset 131*6881a400Schristos }; 132*6881a400Schristos 133*6881a400Schristos const struct regset amd64_fbsd_segbases_regset = 134*6881a400Schristos { 135*6881a400Schristos amd64_fbsd_segbases_regmap, regcache_supply_regset, regcache_collect_regset 136*6881a400Schristos }; 137*6881a400Schristos 138699b0f92Schristos /* Support for signal handlers. */ 139699b0f92Schristos 140*6881a400Schristos /* In a signal frame, rsp points to a 'struct sigframe' which is 141*6881a400Schristos defined as: 142699b0f92Schristos 143*6881a400Schristos struct sigframe { 144*6881a400Schristos union { 145*6881a400Schristos __siginfohandler_t *sf_action; 146*6881a400Schristos __sighandler_t *sf_handler; 147*6881a400Schristos } sf_ahu; 148*6881a400Schristos ucontext_t sf_uc; 149*6881a400Schristos ... 150699b0f92Schristos } 151699b0f92Schristos 152*6881a400Schristos ucontext_t is defined as: 153699b0f92Schristos 154*6881a400Schristos struct __ucontext { 155*6881a400Schristos sigset_t uc_sigmask; 156*6881a400Schristos mcontext_t uc_mcontext; 157*6881a400Schristos ... 158699b0f92Schristos }; 159699b0f92Schristos 160*6881a400Schristos The mcontext_t contains the general purpose register set as well 161*6881a400Schristos as the floating point or XSAVE state. */ 162699b0f92Schristos 163*6881a400Schristos /* NB: There is an 8 byte padding hole between sf_ahu and sf_uc. */ 164*6881a400Schristos #define AMD64_SIGFRAME_UCONTEXT_OFFSET 16 165*6881a400Schristos #define AMD64_UCONTEXT_MCONTEXT_OFFSET 16 166*6881a400Schristos #define AMD64_SIZEOF_MCONTEXT_T 800 167*6881a400Schristos 168*6881a400Schristos /* Implement the "init" method of struct tramp_frame. */ 169*6881a400Schristos 170*6881a400Schristos static void 171*6881a400Schristos amd64_fbsd_sigframe_init (const struct tramp_frame *self, 172*6881a400Schristos frame_info_ptr this_frame, 173*6881a400Schristos struct trad_frame_cache *this_cache, 174*6881a400Schristos CORE_ADDR func) 175699b0f92Schristos { 176*6881a400Schristos CORE_ADDR sp = get_frame_register_unsigned (this_frame, AMD64_RSP_REGNUM); 177*6881a400Schristos CORE_ADDR mcontext_addr 178*6881a400Schristos = (sp 179*6881a400Schristos + AMD64_SIGFRAME_UCONTEXT_OFFSET 180*6881a400Schristos + AMD64_UCONTEXT_MCONTEXT_OFFSET); 181*6881a400Schristos 182*6881a400Schristos trad_frame_set_reg_regmap (this_cache, amd64_fbsd_mcregmap, mcontext_addr, 183*6881a400Schristos AMD64_SIZEOF_MCONTEXT_T); 184*6881a400Schristos 185*6881a400Schristos /* Don't bother with floating point or XSAVE state for now. The 186*6881a400Schristos current helper routines for parsing FXSAVE and XSAVE state only 187*6881a400Schristos work with regcaches. This could perhaps create a temporary 188*6881a400Schristos regcache, collect the register values from mc_fpstate and 189*6881a400Schristos mc_xfpustate, and then set register values in the trad_frame. */ 190*6881a400Schristos 191*6881a400Schristos trad_frame_set_id (this_cache, frame_id_build (sp, func)); 192*6881a400Schristos } 193*6881a400Schristos 194*6881a400Schristos static const struct tramp_frame amd64_fbsd_sigframe = 195*6881a400Schristos { 196*6881a400Schristos SIGTRAMP_FRAME, 197*6881a400Schristos 1, 198*6881a400Schristos { 199*6881a400Schristos {0x48, ULONGEST_MAX}, /* lea SIGF_UC(%rsp),%rdi */ 200*6881a400Schristos {0x8d, ULONGEST_MAX}, 201*6881a400Schristos {0x7c, ULONGEST_MAX}, 202*6881a400Schristos {0x24, ULONGEST_MAX}, 203*6881a400Schristos {0x10, ULONGEST_MAX}, 204*6881a400Schristos {0x6a, ULONGEST_MAX}, /* pushq $0 */ 205*6881a400Schristos {0x00, ULONGEST_MAX}, 206*6881a400Schristos {0x48, ULONGEST_MAX}, /* movq $SYS_sigreturn,%rax */ 207*6881a400Schristos {0xc7, ULONGEST_MAX}, 208*6881a400Schristos {0xc0, ULONGEST_MAX}, 209*6881a400Schristos {0xa1, ULONGEST_MAX}, 210*6881a400Schristos {0x01, ULONGEST_MAX}, 211*6881a400Schristos {0x00, ULONGEST_MAX}, 212*6881a400Schristos {0x00, ULONGEST_MAX}, 213*6881a400Schristos {0x0f, ULONGEST_MAX}, /* syscall */ 214*6881a400Schristos {0x05, ULONGEST_MAX}, 215*6881a400Schristos {TRAMP_SENTINEL_INSN, ULONGEST_MAX} 216*6881a400Schristos }, 217*6881a400Schristos amd64_fbsd_sigframe_init 218699b0f92Schristos }; 219699b0f92Schristos 220699b0f92Schristos /* Implement the core_read_description gdbarch method. */ 221699b0f92Schristos 222699b0f92Schristos static const struct target_desc * 223699b0f92Schristos amd64fbsd_core_read_description (struct gdbarch *gdbarch, 224699b0f92Schristos struct target_ops *target, 225699b0f92Schristos bfd *abfd) 226699b0f92Schristos { 2277f2ac410Schristos return amd64_target_description (i386fbsd_core_read_xcr0 (abfd), true); 228699b0f92Schristos } 229699b0f92Schristos 230699b0f92Schristos /* Similar to amd64_supply_fpregset, but use XSAVE extended state. */ 231699b0f92Schristos 232699b0f92Schristos static void 233699b0f92Schristos amd64fbsd_supply_xstateregset (const struct regset *regset, 234699b0f92Schristos struct regcache *regcache, int regnum, 235699b0f92Schristos const void *xstateregs, size_t len) 236699b0f92Schristos { 237699b0f92Schristos amd64_supply_xsave (regcache, regnum, xstateregs); 238699b0f92Schristos } 239699b0f92Schristos 240699b0f92Schristos /* Similar to amd64_collect_fpregset, but use XSAVE extended state. */ 241699b0f92Schristos 242699b0f92Schristos static void 243699b0f92Schristos amd64fbsd_collect_xstateregset (const struct regset *regset, 244699b0f92Schristos const struct regcache *regcache, 245699b0f92Schristos int regnum, void *xstateregs, size_t len) 246699b0f92Schristos { 247699b0f92Schristos amd64_collect_xsave (regcache, regnum, xstateregs, 1); 248699b0f92Schristos } 249699b0f92Schristos 250699b0f92Schristos static const struct regset amd64fbsd_xstateregset = 251699b0f92Schristos { 252699b0f92Schristos NULL, 253699b0f92Schristos amd64fbsd_supply_xstateregset, 254699b0f92Schristos amd64fbsd_collect_xstateregset 255699b0f92Schristos }; 256699b0f92Schristos 257699b0f92Schristos /* Iterate over core file register note sections. */ 258699b0f92Schristos 259699b0f92Schristos static void 260699b0f92Schristos amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, 261699b0f92Schristos iterate_over_regset_sections_cb *cb, 262699b0f92Schristos void *cb_data, 263699b0f92Schristos const struct regcache *regcache) 264699b0f92Schristos { 265*6881a400Schristos i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch); 266699b0f92Schristos 267*6881a400Schristos cb (".reg", AMD64_FBSD_SIZEOF_GREGSET, AMD64_FBSD_SIZEOF_GREGSET, 268*6881a400Schristos &amd64_fbsd_gregset, NULL, cb_data); 2697f2ac410Schristos cb (".reg2", tdep->sizeof_fpregset, tdep->sizeof_fpregset, &amd64_fpregset, 2707f2ac410Schristos NULL, cb_data); 271*6881a400Schristos cb (".reg-x86-segbases", AMD64_FBSD_SIZEOF_SEGBASES_REGSET, 272*6881a400Schristos AMD64_FBSD_SIZEOF_SEGBASES_REGSET, &amd64_fbsd_segbases_regset, 273*6881a400Schristos "segment bases", cb_data); 2747f2ac410Schristos cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0), X86_XSTATE_SIZE (tdep->xcr0), 275699b0f92Schristos &amd64fbsd_xstateregset, "XSAVE extended state", cb_data); 276699b0f92Schristos } 277699b0f92Schristos 2787d62b00eSchristos /* Implement the get_thread_local_address gdbarch method. */ 2797d62b00eSchristos 2807d62b00eSchristos static CORE_ADDR 2817d62b00eSchristos amd64fbsd_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid, 2827d62b00eSchristos CORE_ADDR lm_addr, CORE_ADDR offset) 2837d62b00eSchristos { 2847d62b00eSchristos struct regcache *regcache; 2857d62b00eSchristos 2867d62b00eSchristos regcache = get_thread_arch_regcache (current_inferior ()->process_target (), 2877d62b00eSchristos ptid, gdbarch); 2887d62b00eSchristos 2897d62b00eSchristos target_fetch_registers (regcache, AMD64_FSBASE_REGNUM); 2907d62b00eSchristos 2917d62b00eSchristos ULONGEST fsbase; 2927d62b00eSchristos if (regcache->cooked_read (AMD64_FSBASE_REGNUM, &fsbase) != REG_VALID) 2937d62b00eSchristos error (_("Unable to fetch %%fsbase")); 2947d62b00eSchristos 2957d62b00eSchristos CORE_ADDR dtv_addr = fsbase + gdbarch_ptr_bit (gdbarch) / 8; 2967d62b00eSchristos return fbsd_get_thread_local_address (gdbarch, dtv_addr, lm_addr, offset); 2977d62b00eSchristos } 2987d62b00eSchristos 299699b0f92Schristos static void 300699b0f92Schristos amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 301699b0f92Schristos { 302*6881a400Schristos i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch); 303699b0f92Schristos 304699b0f92Schristos /* Generic FreeBSD support. */ 305699b0f92Schristos fbsd_init_abi (info, gdbarch); 306699b0f92Schristos 307699b0f92Schristos /* Obviously FreeBSD is BSD-based. */ 308699b0f92Schristos i386bsd_init_abi (info, gdbarch); 309699b0f92Schristos 3107f2ac410Schristos amd64_init_abi (info, gdbarch, 3117f2ac410Schristos amd64_target_description (X86_XSTATE_SSE_MASK, true)); 312699b0f92Schristos 313*6881a400Schristos tramp_frame_prepend_unwinder (gdbarch, &amd64_fbsd_sigframe); 314699b0f92Schristos 315699b0f92Schristos tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET; 316699b0f92Schristos 317699b0f92Schristos /* Iterate over core file register note sections. */ 318699b0f92Schristos set_gdbarch_iterate_over_regset_sections 319699b0f92Schristos (gdbarch, amd64fbsd_iterate_over_regset_sections); 320699b0f92Schristos 321699b0f92Schristos set_gdbarch_core_read_description (gdbarch, 322699b0f92Schristos amd64fbsd_core_read_description); 323699b0f92Schristos 324699b0f92Schristos /* FreeBSD uses SVR4-style shared libraries. */ 325699b0f92Schristos set_solib_svr4_fetch_link_map_offsets 326699b0f92Schristos (gdbarch, svr4_lp64_fetch_link_map_offsets); 3277d62b00eSchristos 3287d62b00eSchristos set_gdbarch_fetch_tls_load_module_address (gdbarch, 3297d62b00eSchristos svr4_fetch_objfile_link_map); 3307d62b00eSchristos set_gdbarch_get_thread_local_address (gdbarch, 3317d62b00eSchristos amd64fbsd_get_thread_local_address); 332699b0f92Schristos } 333699b0f92Schristos 3347d62b00eSchristos void _initialize_amd64fbsd_tdep (); 335699b0f92Schristos void 3367d62b00eSchristos _initialize_amd64fbsd_tdep () 337699b0f92Schristos { 338699b0f92Schristos gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, 339699b0f92Schristos GDB_OSABI_FREEBSD, amd64fbsd_init_abi); 340699b0f92Schristos } 341