xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/amd64-fbsd-tdep.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
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