1 /* Target-dependent code for FreeBSD/amd64. 2 3 Copyright (C) 2003-2023 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 "osabi.h" 22 #include "regset.h" 23 #include "target.h" 24 #include "trad-frame.h" 25 #include "tramp-frame.h" 26 #include "i386-fbsd-tdep.h" 27 #include "gdbsupport/x86-xstate.h" 28 29 #include "amd64-tdep.h" 30 #include "amd64-fbsd-tdep.h" 31 #include "fbsd-tdep.h" 32 #include "solib-svr4.h" 33 #include "inferior.h" 34 35 /* The general-purpose regset consists of 22 64-bit slots, most of 36 which contain individual registers, but a few contain multiple 37 16-bit segment registers. */ 38 #define AMD64_FBSD_SIZEOF_GREGSET (22 * 8) 39 40 /* The segment base register set consists of 2 64-bit registers. */ 41 #define AMD64_FBSD_SIZEOF_SEGBASES_REGSET (2 * 8) 42 43 /* Register maps. */ 44 45 static const struct regcache_map_entry amd64_fbsd_gregmap[] = 46 { 47 { 1, AMD64_R15_REGNUM, 0 }, 48 { 1, AMD64_R14_REGNUM, 0 }, 49 { 1, AMD64_R13_REGNUM, 0 }, 50 { 1, AMD64_R12_REGNUM, 0 }, 51 { 1, AMD64_R11_REGNUM, 0 }, 52 { 1, AMD64_R10_REGNUM, 0 }, 53 { 1, AMD64_R9_REGNUM, 0 }, 54 { 1, AMD64_R8_REGNUM, 0 }, 55 { 1, AMD64_RDI_REGNUM, 0 }, 56 { 1, AMD64_RSI_REGNUM, 0 }, 57 { 1, AMD64_RBP_REGNUM, 0 }, 58 { 1, AMD64_RBX_REGNUM, 0 }, 59 { 1, AMD64_RDX_REGNUM, 0 }, 60 { 1, AMD64_RCX_REGNUM, 0 }, 61 { 1, AMD64_RAX_REGNUM, 0 }, 62 { 1, REGCACHE_MAP_SKIP, 4 }, /* trapno */ 63 { 1, AMD64_FS_REGNUM, 2 }, 64 { 1, AMD64_GS_REGNUM, 2 }, 65 { 1, REGCACHE_MAP_SKIP, 4 }, /* err */ 66 { 1, AMD64_ES_REGNUM, 2 }, 67 { 1, AMD64_DS_REGNUM, 2 }, 68 { 1, AMD64_RIP_REGNUM, 0 }, 69 { 1, AMD64_CS_REGNUM, 8 }, 70 { 1, AMD64_EFLAGS_REGNUM, 8 }, 71 { 1, AMD64_RSP_REGNUM, 0 }, 72 { 1, AMD64_SS_REGNUM, 8 }, 73 { 0 } 74 }; 75 76 static const struct regcache_map_entry amd64_fbsd_segbases_regmap[] = 77 { 78 { 1, AMD64_FSBASE_REGNUM, 0 }, 79 { 1, AMD64_GSBASE_REGNUM, 0 }, 80 { 0 } 81 }; 82 83 /* This layout including fsbase and gsbase was adopted in FreeBSD 84 8.0. */ 85 86 static const struct regcache_map_entry amd64_fbsd_mcregmap[] = 87 { 88 { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_onstack */ 89 { 1, AMD64_RDI_REGNUM, 0 }, 90 { 1, AMD64_RSI_REGNUM, 0 }, 91 { 1, AMD64_RDX_REGNUM, 0 }, 92 { 1, AMD64_RCX_REGNUM, 0 }, 93 { 1, AMD64_R8_REGNUM, 0 }, 94 { 1, AMD64_R9_REGNUM, 0 }, 95 { 1, AMD64_RAX_REGNUM, 0 }, 96 { 1, AMD64_RBX_REGNUM, 0 }, 97 { 1, AMD64_RBP_REGNUM, 0 }, 98 { 1, AMD64_R10_REGNUM, 0 }, 99 { 1, AMD64_R11_REGNUM, 0 }, 100 { 1, AMD64_R12_REGNUM, 0 }, 101 { 1, AMD64_R13_REGNUM, 0 }, 102 { 1, AMD64_R14_REGNUM, 0 }, 103 { 1, AMD64_R15_REGNUM, 0 }, 104 { 1, REGCACHE_MAP_SKIP, 4 }, /* mc_trapno */ 105 { 1, AMD64_FS_REGNUM, 2 }, 106 { 1, AMD64_GS_REGNUM, 2 }, 107 { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_addr */ 108 { 1, REGCACHE_MAP_SKIP, 4 }, /* mc_flags */ 109 { 1, AMD64_ES_REGNUM, 2 }, 110 { 1, AMD64_DS_REGNUM, 2 }, 111 { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_err */ 112 { 1, AMD64_RIP_REGNUM, 0 }, 113 { 1, AMD64_CS_REGNUM, 8 }, 114 { 1, AMD64_EFLAGS_REGNUM, 8 }, 115 { 1, AMD64_RSP_REGNUM, 0 }, 116 { 1, AMD64_SS_REGNUM, 8 }, 117 { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_len */ 118 { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_fpformat */ 119 { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_ownedfp */ 120 { 64, REGCACHE_MAP_SKIP, 8 }, /* mc_fpstate */ 121 { 1, AMD64_FSBASE_REGNUM, 0 }, 122 { 1, AMD64_GSBASE_REGNUM, 0 }, 123 { 0 } 124 }; 125 126 /* Register set definitions. */ 127 128 const struct regset amd64_fbsd_gregset = 129 { 130 amd64_fbsd_gregmap, regcache_supply_regset, regcache_collect_regset 131 }; 132 133 const struct regset amd64_fbsd_segbases_regset = 134 { 135 amd64_fbsd_segbases_regmap, regcache_supply_regset, regcache_collect_regset 136 }; 137 138 /* Support for signal handlers. */ 139 140 /* In a signal frame, rsp points to a 'struct sigframe' which is 141 defined as: 142 143 struct sigframe { 144 union { 145 __siginfohandler_t *sf_action; 146 __sighandler_t *sf_handler; 147 } sf_ahu; 148 ucontext_t sf_uc; 149 ... 150 } 151 152 ucontext_t is defined as: 153 154 struct __ucontext { 155 sigset_t uc_sigmask; 156 mcontext_t uc_mcontext; 157 ... 158 }; 159 160 The mcontext_t contains the general purpose register set as well 161 as the floating point or XSAVE state. */ 162 163 /* NB: There is an 8 byte padding hole between sf_ahu and sf_uc. */ 164 #define AMD64_SIGFRAME_UCONTEXT_OFFSET 16 165 #define AMD64_UCONTEXT_MCONTEXT_OFFSET 16 166 #define AMD64_SIZEOF_MCONTEXT_T 800 167 168 /* Implement the "init" method of struct tramp_frame. */ 169 170 static void 171 amd64_fbsd_sigframe_init (const struct tramp_frame *self, 172 frame_info_ptr this_frame, 173 struct trad_frame_cache *this_cache, 174 CORE_ADDR func) 175 { 176 CORE_ADDR sp = get_frame_register_unsigned (this_frame, AMD64_RSP_REGNUM); 177 CORE_ADDR mcontext_addr 178 = (sp 179 + AMD64_SIGFRAME_UCONTEXT_OFFSET 180 + AMD64_UCONTEXT_MCONTEXT_OFFSET); 181 182 trad_frame_set_reg_regmap (this_cache, amd64_fbsd_mcregmap, mcontext_addr, 183 AMD64_SIZEOF_MCONTEXT_T); 184 185 /* Don't bother with floating point or XSAVE state for now. The 186 current helper routines for parsing FXSAVE and XSAVE state only 187 work with regcaches. This could perhaps create a temporary 188 regcache, collect the register values from mc_fpstate and 189 mc_xfpustate, and then set register values in the trad_frame. */ 190 191 trad_frame_set_id (this_cache, frame_id_build (sp, func)); 192 } 193 194 static const struct tramp_frame amd64_fbsd_sigframe = 195 { 196 SIGTRAMP_FRAME, 197 1, 198 { 199 {0x48, ULONGEST_MAX}, /* lea SIGF_UC(%rsp),%rdi */ 200 {0x8d, ULONGEST_MAX}, 201 {0x7c, ULONGEST_MAX}, 202 {0x24, ULONGEST_MAX}, 203 {0x10, ULONGEST_MAX}, 204 {0x6a, ULONGEST_MAX}, /* pushq $0 */ 205 {0x00, ULONGEST_MAX}, 206 {0x48, ULONGEST_MAX}, /* movq $SYS_sigreturn,%rax */ 207 {0xc7, ULONGEST_MAX}, 208 {0xc0, ULONGEST_MAX}, 209 {0xa1, ULONGEST_MAX}, 210 {0x01, ULONGEST_MAX}, 211 {0x00, ULONGEST_MAX}, 212 {0x00, ULONGEST_MAX}, 213 {0x0f, ULONGEST_MAX}, /* syscall */ 214 {0x05, ULONGEST_MAX}, 215 {TRAMP_SENTINEL_INSN, ULONGEST_MAX} 216 }, 217 amd64_fbsd_sigframe_init 218 }; 219 220 /* Implement the core_read_description gdbarch method. */ 221 222 static const struct target_desc * 223 amd64fbsd_core_read_description (struct gdbarch *gdbarch, 224 struct target_ops *target, 225 bfd *abfd) 226 { 227 return amd64_target_description (i386fbsd_core_read_xcr0 (abfd), true); 228 } 229 230 /* Similar to amd64_supply_fpregset, but use XSAVE extended state. */ 231 232 static void 233 amd64fbsd_supply_xstateregset (const struct regset *regset, 234 struct regcache *regcache, int regnum, 235 const void *xstateregs, size_t len) 236 { 237 amd64_supply_xsave (regcache, regnum, xstateregs); 238 } 239 240 /* Similar to amd64_collect_fpregset, but use XSAVE extended state. */ 241 242 static void 243 amd64fbsd_collect_xstateregset (const struct regset *regset, 244 const struct regcache *regcache, 245 int regnum, void *xstateregs, size_t len) 246 { 247 amd64_collect_xsave (regcache, regnum, xstateregs, 1); 248 } 249 250 static const struct regset amd64fbsd_xstateregset = 251 { 252 NULL, 253 amd64fbsd_supply_xstateregset, 254 amd64fbsd_collect_xstateregset 255 }; 256 257 /* Iterate over core file register note sections. */ 258 259 static void 260 amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, 261 iterate_over_regset_sections_cb *cb, 262 void *cb_data, 263 const struct regcache *regcache) 264 { 265 i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch); 266 267 cb (".reg", AMD64_FBSD_SIZEOF_GREGSET, AMD64_FBSD_SIZEOF_GREGSET, 268 &amd64_fbsd_gregset, NULL, cb_data); 269 cb (".reg2", tdep->sizeof_fpregset, tdep->sizeof_fpregset, &amd64_fpregset, 270 NULL, cb_data); 271 cb (".reg-x86-segbases", AMD64_FBSD_SIZEOF_SEGBASES_REGSET, 272 AMD64_FBSD_SIZEOF_SEGBASES_REGSET, &amd64_fbsd_segbases_regset, 273 "segment bases", cb_data); 274 cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0), X86_XSTATE_SIZE (tdep->xcr0), 275 &amd64fbsd_xstateregset, "XSAVE extended state", cb_data); 276 } 277 278 /* Implement the get_thread_local_address gdbarch method. */ 279 280 static CORE_ADDR 281 amd64fbsd_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid, 282 CORE_ADDR lm_addr, CORE_ADDR offset) 283 { 284 struct regcache *regcache; 285 286 regcache = get_thread_arch_regcache (current_inferior ()->process_target (), 287 ptid, gdbarch); 288 289 target_fetch_registers (regcache, AMD64_FSBASE_REGNUM); 290 291 ULONGEST fsbase; 292 if (regcache->cooked_read (AMD64_FSBASE_REGNUM, &fsbase) != REG_VALID) 293 error (_("Unable to fetch %%fsbase")); 294 295 CORE_ADDR dtv_addr = fsbase + gdbarch_ptr_bit (gdbarch) / 8; 296 return fbsd_get_thread_local_address (gdbarch, dtv_addr, lm_addr, offset); 297 } 298 299 static void 300 amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 301 { 302 i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch); 303 304 /* Generic FreeBSD support. */ 305 fbsd_init_abi (info, gdbarch); 306 307 /* Obviously FreeBSD is BSD-based. */ 308 i386bsd_init_abi (info, gdbarch); 309 310 amd64_init_abi (info, gdbarch, 311 amd64_target_description (X86_XSTATE_SSE_MASK, true)); 312 313 tramp_frame_prepend_unwinder (gdbarch, &amd64_fbsd_sigframe); 314 315 tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET; 316 317 /* Iterate over core file register note sections. */ 318 set_gdbarch_iterate_over_regset_sections 319 (gdbarch, amd64fbsd_iterate_over_regset_sections); 320 321 set_gdbarch_core_read_description (gdbarch, 322 amd64fbsd_core_read_description); 323 324 /* FreeBSD uses SVR4-style shared libraries. */ 325 set_solib_svr4_fetch_link_map_offsets 326 (gdbarch, svr4_lp64_fetch_link_map_offsets); 327 328 set_gdbarch_fetch_tls_load_module_address (gdbarch, 329 svr4_fetch_objfile_link_map); 330 set_gdbarch_get_thread_local_address (gdbarch, 331 amd64fbsd_get_thread_local_address); 332 } 333 334 void _initialize_amd64fbsd_tdep (); 335 void 336 _initialize_amd64fbsd_tdep () 337 { 338 gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, 339 GDB_OSABI_FREEBSD, amd64fbsd_init_abi); 340 } 341