Rename fprintf_symbol_filtered
[binutils-gdb.git] / gdb / i386-fbsd-nat.c
1 /* Native-dependent code for FreeBSD/i386.
2
3 Copyright (C) 2001-2022 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 "inferior.h"
22 #include "regcache.h"
23 #include "target.h"
24
25 #include <sys/types.h>
26 #include <sys/ptrace.h>
27 #include <sys/sysctl.h>
28 #include <sys/user.h>
29
30 #include "i386-tdep.h"
31 #include "i386-fbsd-tdep.h"
32 #include "i387-tdep.h"
33 #include "x86-nat.h"
34 #include "gdbsupport/x86-xstate.h"
35 #include "x86-fbsd-nat.h"
36
37 class i386_fbsd_nat_target final : public x86_fbsd_nat_target
38 {
39 public:
40 void fetch_registers (struct regcache *, int) override;
41 void store_registers (struct regcache *, int) override;
42
43 const struct target_desc *read_description () override;
44
45 void resume (ptid_t, int, enum gdb_signal) override;
46 };
47
48 static i386_fbsd_nat_target the_i386_fbsd_nat_target;
49
50 #ifdef PT_GETXSTATE_INFO
51 static size_t xsave_len;
52 #endif
53
54 static int have_ptrace_xmmregs;
55
56 /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
57 for all registers. */
58
59 void
60 i386_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
61 {
62 struct gdbarch *gdbarch = regcache->arch ();
63 #if defined(PT_GETFSBASE) || defined(PT_GETGSBASE)
64 const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
65 #endif
66 pid_t pid = get_ptrace_pid (regcache->ptid ());
67
68 if (fetch_register_set<struct reg> (regcache, regnum, PT_GETREGS,
69 &i386_fbsd_gregset))
70 {
71 if (regnum != -1)
72 return;
73 }
74
75 #ifdef PT_GETFSBASE
76 if (regnum == -1 || regnum == I386_FSBASE_REGNUM)
77 {
78 register_t base;
79
80 if (ptrace (PT_GETFSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
81 perror_with_name (_("Couldn't get segment register fs_base"));
82
83 regcache->raw_supply (I386_FSBASE_REGNUM, &base);
84 if (regnum != -1)
85 return;
86 }
87 #endif
88 #ifdef PT_GETGSBASE
89 if (regnum == -1 || regnum == I386_GSBASE_REGNUM)
90 {
91 register_t base;
92
93 if (ptrace (PT_GETGSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
94 perror_with_name (_("Couldn't get segment register gs_base"));
95
96 regcache->raw_supply (I386_GSBASE_REGNUM, &base);
97 if (regnum != -1)
98 return;
99 }
100 #endif
101
102 /* There is no i386_fxsave_supplies or i386_xsave_supplies.
103 Instead, the earlier register sets return early if the request
104 was for a specific register that was already satisified to avoid
105 fetching the FPU/XSAVE state unnecessarily. */
106
107 #ifdef PT_GETXSTATE_INFO
108 if (xsave_len != 0)
109 {
110 void *xstateregs = alloca (xsave_len);
111
112 if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
113 perror_with_name (_("Couldn't get extended state status"));
114
115 i387_supply_xsave (regcache, regnum, xstateregs);
116 return;
117 }
118 #endif
119 if (have_ptrace_xmmregs != 0)
120 {
121 char xmmregs[I387_SIZEOF_FXSAVE];
122
123 if (ptrace(PT_GETXMMREGS, pid, (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
124 perror_with_name (_("Couldn't get XMM registers"));
125
126 i387_supply_fxsave (regcache, regnum, xmmregs);
127 return;
128 }
129
130 struct fpreg fpregs;
131
132 if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
133 perror_with_name (_("Couldn't get floating point status"));
134
135 i387_supply_fsave (regcache, regnum, &fpregs);
136 }
137
138 /* Store register REGNUM back into the inferior. If REGNUM is -1, do
139 this for all registers. */
140
141 void
142 i386_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
143 {
144 struct gdbarch *gdbarch = regcache->arch ();
145 #if defined(PT_GETFSBASE) || defined(PT_GETGSBASE)
146 const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
147 #endif
148 pid_t pid = get_ptrace_pid (regcache->ptid ());
149
150 if (store_register_set<struct reg> (regcache, regnum, PT_GETREGS, PT_SETREGS,
151 &i386_fbsd_gregset))
152 {
153 if (regnum != -1)
154 return;
155 }
156
157 #ifdef PT_SETFSBASE
158 if (regnum == -1 || regnum == I386_FSBASE_REGNUM)
159 {
160 register_t base;
161
162 regcache->raw_collect (I386_FSBASE_REGNUM, &base);
163
164 if (ptrace (PT_SETFSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
165 perror_with_name (_("Couldn't write segment register fs_base"));
166 if (regnum != -1)
167 return;
168 }
169 #endif
170 #ifdef PT_SETGSBASE
171 if (regnum == -1 || regnum == I386_GSBASE_REGNUM)
172 {
173 register_t base;
174
175 regcache->raw_collect (I386_GSBASE_REGNUM, &base);
176
177 if (ptrace (PT_SETGSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
178 perror_with_name (_("Couldn't write segment register gs_base"));
179 if (regnum != -1)
180 return;
181 }
182 #endif
183
184 /* There is no i386_fxsave_supplies or i386_xsave_supplies.
185 Instead, the earlier register sets return early if the request
186 was for a specific register that was already satisified to avoid
187 fetching the FPU/XSAVE state unnecessarily. */
188
189 #ifdef PT_GETXSTATE_INFO
190 if (xsave_len != 0)
191 {
192 void *xstateregs = alloca (xsave_len);
193
194 if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
195 perror_with_name (_("Couldn't get extended state status"));
196
197 i387_collect_xsave (regcache, regnum, xstateregs, 0);
198
199 if (ptrace (PT_SETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, xsave_len)
200 == -1)
201 perror_with_name (_("Couldn't write extended state status"));
202 return;
203 }
204 #endif
205 if (have_ptrace_xmmregs != 0)
206 {
207 char xmmregs[I387_SIZEOF_FXSAVE];
208
209 if (ptrace(PT_GETXMMREGS, pid, (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
210 perror_with_name (_("Couldn't get XMM registers"));
211
212 i387_collect_fxsave (regcache, regnum, xmmregs);
213
214 if (ptrace (PT_SETXMMREGS, pid, (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
215 perror_with_name (_("Couldn't write XMM registers"));
216 return;
217 }
218
219 struct fpreg fpregs;
220
221 if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
222 perror_with_name (_("Couldn't get floating point status"));
223
224 i387_collect_fsave (regcache, regnum, &fpregs);
225
226 if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
227 perror_with_name (_("Couldn't write floating point status"));
228 }
229
230 /* Resume execution of the inferior process. If STEP is nonzero,
231 single-step it. If SIGNAL is nonzero, give it that signal. */
232
233 void
234 i386_fbsd_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
235 {
236 pid_t pid = ptid.pid ();
237 int request = PT_STEP;
238
239 if (pid == -1)
240 /* Resume all threads. This only gets used in the non-threaded
241 case, where "resume all threads" and "resume inferior_ptid" are
242 the same. */
243 pid = inferior_ptid.pid ();
244
245 if (!step)
246 {
247 struct regcache *regcache = get_current_regcache ();
248 ULONGEST eflags;
249
250 /* Workaround for a bug in FreeBSD. Make sure that the trace
251 flag is off when doing a continue. There is a code path
252 through the kernel which leaves the flag set when it should
253 have been cleared. If a process has a signal pending (such
254 as SIGALRM) and we do a PT_STEP, the process never really has
255 a chance to run because the kernel needs to notify the
256 debugger that a signal is being sent. Therefore, the process
257 never goes through the kernel's trap() function which would
258 normally clear it. */
259
260 regcache_cooked_read_unsigned (regcache, I386_EFLAGS_REGNUM,
261 &eflags);
262 if (eflags & 0x0100)
263 regcache_cooked_write_unsigned (regcache, I386_EFLAGS_REGNUM,
264 eflags & ~0x0100);
265
266 request = PT_CONTINUE;
267 }
268
269 /* An addres of (caddr_t) 1 tells ptrace to continue from where it
270 was. (If GDB wanted it to start some other way, we have already
271 written a new PC value to the child.) */
272 if (ptrace (request, pid, (caddr_t) 1,
273 gdb_signal_to_host (signal)) == -1)
274 perror_with_name (("ptrace"));
275 }
276 \f
277
278 /* Support for debugging kernel virtual memory images. */
279
280 #include <machine/pcb.h>
281
282 #include "bsd-kvm.h"
283
284 static int
285 i386fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
286 {
287 /* The following is true for FreeBSD 4.7:
288
289 The pcb contains %eip, %ebx, %esp, %ebp, %esi, %edi and %gs.
290 This accounts for all callee-saved registers specified by the
291 psABI and then some. Here %esp contains the stack pointer at the
292 point just after the call to cpu_switch(). From this information
293 we reconstruct the register state as it would look when we just
294 returned from cpu_switch(). */
295
296 /* The stack pointer shouldn't be zero. */
297 if (pcb->pcb_esp == 0)
298 return 0;
299
300 pcb->pcb_esp += 4;
301 regcache->raw_supply (I386_EDI_REGNUM, &pcb->pcb_edi);
302 regcache->raw_supply (I386_ESI_REGNUM, &pcb->pcb_esi);
303 regcache->raw_supply (I386_EBP_REGNUM, &pcb->pcb_ebp);
304 regcache->raw_supply (I386_ESP_REGNUM, &pcb->pcb_esp);
305 regcache->raw_supply (I386_EBX_REGNUM, &pcb->pcb_ebx);
306 regcache->raw_supply (I386_EIP_REGNUM, &pcb->pcb_eip);
307 regcache->raw_supply (I386_GS_REGNUM, &pcb->pcb_gs);
308
309 return 1;
310 }
311 \f
312
313 /* Implement the read_description method. */
314
315 const struct target_desc *
316 i386_fbsd_nat_target::read_description ()
317 {
318 #ifdef PT_GETXSTATE_INFO
319 static int xsave_probed;
320 static uint64_t xcr0;
321 #endif
322 static int xmm_probed;
323
324 #ifdef PT_GETXSTATE_INFO
325 if (!xsave_probed)
326 {
327 struct ptrace_xstate_info info;
328
329 if (ptrace (PT_GETXSTATE_INFO, inferior_ptid.pid (),
330 (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0)
331 {
332 xsave_len = info.xsave_len;
333 xcr0 = info.xsave_mask;
334 }
335 xsave_probed = 1;
336 }
337
338 if (xsave_len != 0)
339 return i386_target_description (xcr0, true);
340 #endif
341
342 if (!xmm_probed)
343 {
344 char xmmregs[I387_SIZEOF_FXSAVE];
345
346 if (ptrace (PT_GETXMMREGS, inferior_ptid.pid (),
347 (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
348 have_ptrace_xmmregs = 1;
349 xmm_probed = 1;
350 }
351
352 if (have_ptrace_xmmregs)
353 return i386_target_description (X86_XSTATE_SSE_MASK, true);
354
355 return i386_target_description (X86_XSTATE_X87_MASK, true);
356 }
357
358 void _initialize_i386fbsd_nat ();
359 void
360 _initialize_i386fbsd_nat ()
361 {
362 add_inf_child_target (&the_i386_fbsd_nat_target);
363
364 /* Support debugging kernel virtual memory images. */
365 bsd_kvm_add_target (i386fbsd_supply_pcb);
366 }