i386-gnu-nat.c revision 1.1.1.4 1 1.1 christos /* Low level interface to i386 running the GNU Hurd.
2 1.1 christos
3 1.1.1.4 christos Copyright (C) 1992-2023 Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos This file is part of GDB.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 1.1 christos
20 1.1.1.2 christos /* Include this first, to pick up the <mach.h> 'thread_info' diversion. */
21 1.1.1.2 christos #include "gnu-nat.h"
22 1.1.1.2 christos
23 1.1 christos /* Mach/Hurd headers are not yet ready for C++ compilation. */
24 1.1 christos extern "C"
25 1.1 christos {
26 1.1 christos #include <mach.h>
27 1.1 christos #include <mach_error.h>
28 1.1 christos #include <mach/message.h>
29 1.1 christos #include <mach/exception.h>
30 1.1 christos }
31 1.1 christos
32 1.1 christos #include "defs.h"
33 1.1 christos #include "x86-nat.h"
34 1.1 christos #include "inferior.h"
35 1.1 christos #include "floatformat.h"
36 1.1 christos #include "regcache.h"
37 1.1 christos
38 1.1 christos #include "i386-tdep.h"
39 1.1 christos
40 1.1 christos #include "inf-child.h"
41 1.1 christos #include "i387-tdep.h"
42 1.1 christos
43 1.1 christos /* Offset to the thread_state_t location where REG is stored. */
44 1.1 christos #define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
45 1.1 christos
46 1.1 christos /* At REG_OFFSET[N] is the offset to the thread_state_t location where
47 1.1 christos the GDB register N is stored. */
48 1.1 christos static int reg_offset[] =
49 1.1 christos {
50 1.1 christos REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
51 1.1 christos REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
52 1.1 christos REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
53 1.1 christos REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
54 1.1 christos };
55 1.1 christos
56 1.1 christos #define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
57 1.1 christos
58 1.1 christos
59 1.1.1.2 christos
61 1.1.1.2 christos /* The i386 GNU Hurd target. */
62 1.1.1.2 christos
63 1.1.1.2 christos #ifdef i386_DEBUG_STATE
64 1.1.1.2 christos using gnu_base_target = x86_nat_target<gnu_nat_target>;
65 1.1.1.2 christos #else
66 1.1.1.2 christos using gnu_base_target = gnu_nat_target;
67 1.1.1.2 christos #endif
68 1.1.1.2 christos
69 1.1.1.2 christos struct i386_gnu_nat_target final : public gnu_base_target
70 1.1.1.2 christos {
71 1.1.1.2 christos void fetch_registers (struct regcache *, int) override;
72 1.1.1.2 christos void store_registers (struct regcache *, int) override;
73 1.1.1.2 christos };
74 1.1.1.2 christos
75 1.1.1.2 christos static i386_gnu_nat_target the_i386_gnu_nat_target;
76 1.1 christos
77 1.1 christos /* Get the whole floating-point state of THREAD and record the values
78 1.1 christos of the corresponding (pseudo) registers. */
79 1.1 christos
80 1.1 christos static void
81 1.1 christos fetch_fpregs (struct regcache *regcache, struct proc *thread)
82 1.1 christos {
83 1.1 christos mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
84 1.1 christos struct i386_float_state state;
85 1.1 christos kern_return_t err;
86 1.1 christos
87 1.1 christos err = thread_get_state (thread->port, i386_FLOAT_STATE,
88 1.1 christos (thread_state_t) &state, &count);
89 1.1 christos if (err)
90 1.1 christos {
91 1.1 christos warning (_("Couldn't fetch floating-point state from %s"),
92 1.1 christos proc_string (thread));
93 1.1 christos return;
94 1.1 christos }
95 1.1 christos
96 1.1 christos if (!state.initialized)
97 1.1 christos {
98 1.1 christos /* The floating-point state isn't initialized. */
99 1.1 christos i387_supply_fsave (regcache, -1, NULL);
100 1.1 christos }
101 1.1 christos else
102 1.1 christos {
103 1.1 christos /* Supply the floating-point registers. */
104 1.1 christos i387_supply_fsave (regcache, -1, state.hw_state);
105 1.1 christos }
106 1.1 christos }
107 1.1 christos
108 1.1.1.2 christos /* Fetch register REGNO, or all regs if REGNO is -1. */
109 1.1.1.2 christos void
110 1.1 christos i386_gnu_nat_target::fetch_registers (struct regcache *regcache, int regno)
111 1.1 christos {
112 1.1.1.2 christos struct proc *thread;
113 1.1 christos ptid_t ptid = regcache->ptid ();
114 1.1 christos
115 1.1 christos /* Make sure we know about new threads. */
116 1.1 christos inf_update_procs (gnu_current_inf);
117 1.1.1.2 christos
118 1.1 christos thread = inf_tid_to_thread (gnu_current_inf, ptid.lwp ());
119 1.1 christos if (!thread)
120 1.1.1.3 christos error (_("Can't fetch registers from thread %s: No such thread"),
121 1.1 christos target_pid_to_str (ptid).c_str ());
122 1.1 christos
123 1.1 christos if (regno < I386_NUM_GREGS || regno == -1)
124 1.1 christos {
125 1.1 christos thread_state_t state;
126 1.1 christos
127 1.1 christos /* This does the dirty work for us. */
128 1.1 christos state = proc_get_state (thread, 0);
129 1.1 christos if (!state)
130 1.1 christos {
131 1.1 christos warning (_("Couldn't fetch registers from %s"),
132 1.1 christos proc_string (thread));
133 1.1 christos return;
134 1.1 christos }
135 1.1 christos
136 1.1 christos if (regno == -1)
137 1.1 christos {
138 1.1 christos int i;
139 1.1 christos
140 1.1 christos proc_debug (thread, "fetching all register");
141 1.1 christos
142 1.1.1.2 christos for (i = 0; i < I386_NUM_GREGS; i++)
143 1.1 christos regcache->raw_supply (i, REG_ADDR (state, i));
144 1.1 christos thread->fetched_regs = ~0;
145 1.1 christos }
146 1.1 christos else
147 1.1 christos {
148 1.1.1.2 christos proc_debug (thread, "fetching register %s",
149 1.1 christos gdbarch_register_name (regcache->arch (),
150 1.1 christos regno));
151 1.1.1.2 christos
152 1.1 christos regcache->raw_supply (regno, REG_ADDR (state, regno));
153 1.1 christos thread->fetched_regs |= (1 << regno);
154 1.1 christos }
155 1.1 christos }
156 1.1 christos
157 1.1 christos if (regno >= I386_NUM_GREGS || regno == -1)
158 1.1 christos {
159 1.1 christos proc_debug (thread, "fetching floating-point registers");
160 1.1 christos
161 1.1 christos fetch_fpregs (regcache, thread);
162 1.1 christos }
163 1.1 christos }
164 1.1 christos
165 1.1 christos
167 1.1 christos /* Store the whole floating-point state into THREAD using information
168 1.1 christos from the corresponding (pseudo) registers. */
169 1.1 christos static void
170 1.1 christos store_fpregs (const struct regcache *regcache, struct proc *thread, int regno)
171 1.1 christos {
172 1.1 christos mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
173 1.1 christos struct i386_float_state state;
174 1.1 christos kern_return_t err;
175 1.1 christos
176 1.1 christos err = thread_get_state (thread->port, i386_FLOAT_STATE,
177 1.1 christos (thread_state_t) &state, &count);
178 1.1 christos if (err)
179 1.1 christos {
180 1.1 christos warning (_("Couldn't fetch floating-point state from %s"),
181 1.1 christos proc_string (thread));
182 1.1 christos return;
183 1.1 christos }
184 1.1 christos
185 1.1 christos /* FIXME: kettenis/2001-07-15: Is this right? Should we somehow
186 1.1 christos take into account DEPRECATED_REGISTER_VALID like the old code did? */
187 1.1 christos i387_collect_fsave (regcache, regno, state.hw_state);
188 1.1 christos
189 1.1 christos err = thread_set_state (thread->port, i386_FLOAT_STATE,
190 1.1 christos (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
191 1.1 christos if (err)
192 1.1 christos {
193 1.1 christos warning (_("Couldn't store floating-point state into %s"),
194 1.1 christos proc_string (thread));
195 1.1 christos return;
196 1.1 christos }
197 1.1 christos }
198 1.1.1.2 christos
199 1.1.1.2 christos /* Store at least register REGNO, or all regs if REGNO == -1. */
200 1.1 christos void
201 1.1 christos i386_gnu_nat_target::store_registers (struct regcache *regcache, int regno)
202 1.1.1.2 christos {
203 1.1.1.2 christos struct proc *thread;
204 1.1 christos struct gdbarch *gdbarch = regcache->arch ();
205 1.1 christos ptid_t ptid = regcache->ptid ();
206 1.1 christos
207 1.1 christos /* Make sure we know about new threads. */
208 1.1.1.2 christos inf_update_procs (gnu_current_inf);
209 1.1 christos
210 1.1 christos thread = inf_tid_to_thread (gnu_current_inf, ptid.lwp ());
211 1.1.1.3 christos if (!thread)
212 1.1 christos error (_("Couldn't store registers into thread %s: No such thread"),
213 1.1 christos target_pid_to_str (ptid).c_str ());
214 1.1 christos
215 1.1 christos if (regno < I386_NUM_GREGS || regno == -1)
216 1.1 christos {
217 1.1 christos thread_state_t state;
218 1.1 christos thread_state_data_t old_state;
219 1.1 christos int was_aborted = thread->aborted;
220 1.1 christos int was_valid = thread->state_valid;
221 1.1 christos int trace;
222 1.1 christos
223 1.1 christos if (!was_aborted && was_valid)
224 1.1 christos memcpy (&old_state, &thread->state, sizeof (old_state));
225 1.1 christos
226 1.1 christos state = proc_get_state (thread, 1);
227 1.1 christos if (!state)
228 1.1 christos {
229 1.1 christos warning (_("Couldn't store registers into %s"),
230 1.1 christos proc_string (thread));
231 1.1 christos return;
232 1.1 christos }
233 1.1.1.4 christos
234 1.1 christos /* Save the T bit. We might try to restore the %eflags register
235 1.1 christos below, but changing the T bit would seriously confuse GDB. */
236 1.1 christos trace = ((struct i386_thread_state *)state)->efl & 0x100;
237 1.1 christos
238 1.1 christos if (!was_aborted && was_valid)
239 1.1 christos /* See which registers have changed after aborting the thread. */
240 1.1 christos {
241 1.1 christos int check_regno;
242 1.1 christos
243 1.1 christos for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++)
244 1.1 christos if ((thread->fetched_regs & (1 << check_regno))
245 1.1 christos && memcpy (REG_ADDR (&old_state, check_regno),
246 1.1 christos REG_ADDR (state, check_regno),
247 1.1 christos register_size (gdbarch, check_regno)))
248 1.1 christos /* Register CHECK_REGNO has changed! Ack! */
249 1.1 christos {
250 1.1 christos warning (_("Register %s changed after the thread was aborted"),
251 1.1 christos gdbarch_register_name (gdbarch, check_regno));
252 1.1.1.2 christos if (regno >= 0 && regno != check_regno)
253 1.1.1.2 christos /* Update GDB's copy of the register. */
254 1.1 christos regcache->raw_supply (check_regno,
255 1.1 christos REG_ADDR (state, check_regno));
256 1.1 christos else
257 1.1 christos warning (_("... also writing this register! "
258 1.1 christos "Suspicious..."));
259 1.1 christos }
260 1.1 christos }
261 1.1 christos
262 1.1 christos if (regno == -1)
263 1.1 christos {
264 1.1 christos int i;
265 1.1 christos
266 1.1 christos proc_debug (thread, "storing all registers");
267 1.1.1.2 christos
268 1.1.1.2 christos for (i = 0; i < I386_NUM_GREGS; i++)
269 1.1 christos if (REG_VALID == regcache->get_register_status (i))
270 1.1 christos regcache->raw_collect (i, REG_ADDR (state, i));
271 1.1 christos }
272 1.1 christos else
273 1.1 christos {
274 1.1 christos proc_debug (thread, "storing register %s",
275 1.1.1.2 christos gdbarch_register_name (gdbarch, regno));
276 1.1.1.2 christos
277 1.1 christos gdb_assert (REG_VALID == regcache->get_register_status (regno));
278 1.1 christos regcache->raw_collect (regno, REG_ADDR (state, regno));
279 1.1 christos }
280 1.1 christos
281 1.1 christos /* Restore the T bit. */
282 1.1 christos ((struct i386_thread_state *)state)->efl &= ~0x100;
283 1.1 christos ((struct i386_thread_state *)state)->efl |= trace;
284 1.1 christos }
285 1.1 christos
286 1.1 christos if (regno >= I386_NUM_GREGS || regno == -1)
287 1.1 christos {
288 1.1 christos proc_debug (thread, "storing floating-point registers");
289 1.1 christos
290 1.1 christos store_fpregs (regcache, thread, regno);
291 1.1 christos }
292 1.1 christos }
293 1.1 christos
294 1.1 christos
295 1.1 christos /* Support for debug registers. */
297 1.1 christos
298 1.1 christos #ifdef i386_DEBUG_STATE
299 1.1 christos /* Get debug registers for thread THREAD. */
300 1.1 christos
301 1.1 christos static void
302 1.1 christos i386_gnu_dr_get (struct i386_debug_state *regs, struct proc *thread)
303 1.1 christos {
304 1.1 christos mach_msg_type_number_t count = i386_DEBUG_STATE_COUNT;
305 1.1 christos kern_return_t err;
306 1.1 christos
307 1.1 christos err = thread_get_state (thread->port, i386_DEBUG_STATE,
308 1.1 christos (thread_state_t) regs, &count);
309 1.1 christos if (err != 0 || count != i386_DEBUG_STATE_COUNT)
310 1.1 christos warning (_("Couldn't fetch debug state from %s"),
311 1.1 christos proc_string (thread));
312 1.1 christos }
313 1.1 christos
314 1.1 christos /* Set debug registers for thread THREAD. */
315 1.1 christos
316 1.1 christos static void
317 1.1 christos i386_gnu_dr_set (const struct i386_debug_state *regs, struct proc *thread)
318 1.1 christos {
319 1.1 christos kern_return_t err;
320 1.1 christos
321 1.1 christos err = thread_set_state (thread->port, i386_DEBUG_STATE,
322 1.1 christos (thread_state_t) regs, i386_DEBUG_STATE_COUNT);
323 1.1 christos if (err != 0)
324 1.1 christos warning (_("Couldn't store debug state into %s"),
325 1.1 christos proc_string (thread));
326 1.1 christos }
327 1.1 christos
328 1.1 christos /* Set DR_CONTROL in THREAD. */
329 1.1 christos
330 1.1 christos static void
331 1.1 christos i386_gnu_dr_set_control_one (struct proc *thread, void *arg)
332 1.1 christos {
333 1.1 christos unsigned long *control = (unsigned long *) arg;
334 1.1 christos struct i386_debug_state regs;
335 1.1 christos
336 1.1 christos i386_gnu_dr_get (®s, thread);
337 1.1 christos regs.dr[DR_CONTROL] = *control;
338 1.1 christos i386_gnu_dr_set (®s, thread);
339 1.1 christos }
340 1.1 christos
341 1.1 christos /* Set DR_CONTROL to CONTROL in all threads. */
342 1.1 christos
343 1.1 christos static void
344 1.1 christos i386_gnu_dr_set_control (unsigned long control)
345 1.1 christos {
346 1.1 christos inf_update_procs (gnu_current_inf);
347 1.1 christos inf_threads (gnu_current_inf, i386_gnu_dr_set_control_one, &control);
348 1.1 christos }
349 1.1 christos
350 1.1 christos /* Parameters to set a debugging address. */
351 1.1 christos
352 1.1 christos struct reg_addr
353 1.1 christos {
354 1.1 christos int regnum; /* Register number (zero based). */
355 1.1 christos CORE_ADDR addr; /* Address. */
356 1.1 christos };
357 1.1 christos
358 1.1 christos /* Set address REGNUM (zero based) to ADDR in THREAD. */
359 1.1 christos
360 1.1 christos static void
361 1.1 christos i386_gnu_dr_set_addr_one (struct proc *thread, void *arg)
362 1.1 christos {
363 1.1 christos struct reg_addr *reg_addr = (struct reg_addr *) arg;
364 1.1 christos struct i386_debug_state regs;
365 1.1 christos
366 1.1 christos i386_gnu_dr_get (®s, thread);
367 1.1 christos regs.dr[reg_addr->regnum] = reg_addr->addr;
368 1.1 christos i386_gnu_dr_set (®s, thread);
369 1.1 christos }
370 1.1 christos
371 1.1 christos /* Set address REGNUM (zero based) to ADDR in all threads. */
372 1.1 christos
373 1.1 christos static void
374 1.1 christos i386_gnu_dr_set_addr (int regnum, CORE_ADDR addr)
375 1.1 christos {
376 1.1 christos struct reg_addr reg_addr;
377 1.1 christos
378 1.1 christos gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
379 1.1 christos
380 1.1 christos reg_addr.regnum = regnum;
381 1.1 christos reg_addr.addr = addr;
382 1.1 christos
383 1.1 christos inf_update_procs (gnu_current_inf);
384 1.1 christos inf_threads (gnu_current_inf, i386_gnu_dr_set_addr_one, ®_addr);
385 1.1 christos }
386 1.1 christos
387 1.1 christos /* Get debug register REGNUM value from only the one LWP of PTID. */
388 1.1 christos
389 1.1 christos static unsigned long
390 1.1 christos i386_gnu_dr_get_reg (ptid_t ptid, int regnum)
391 1.1 christos {
392 1.1 christos struct i386_debug_state regs;
393 1.1 christos struct proc *thread;
394 1.1 christos
395 1.1.1.2 christos /* Make sure we know about new threads. */
396 1.1 christos inf_update_procs (gnu_current_inf);
397 1.1 christos
398 1.1 christos thread = inf_tid_to_thread (gnu_current_inf, ptid.lwp ());
399 1.1 christos i386_gnu_dr_get (®s, thread);
400 1.1 christos
401 1.1 christos return regs.dr[regnum];
402 1.1 christos }
403 1.1 christos
404 1.1 christos /* Return the inferior's debug register REGNUM. */
405 1.1 christos
406 1.1 christos static CORE_ADDR
407 1.1 christos i386_gnu_dr_get_addr (int regnum)
408 1.1 christos {
409 1.1 christos gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
410 1.1 christos
411 1.1 christos return i386_gnu_dr_get_reg (inferior_ptid, regnum);
412 1.1 christos }
413 1.1 christos
414 1.1 christos /* Get DR_STATUS from only the one thread of INFERIOR_PTID. */
415 1.1 christos
416 1.1 christos static unsigned long
417 1.1 christos i386_gnu_dr_get_status (void)
418 1.1 christos {
419 1.1 christos return i386_gnu_dr_get_reg (inferior_ptid, DR_STATUS);
420 1.1 christos }
421 1.1 christos
422 1.1 christos /* Return the inferior's DR7 debug control register. */
423 1.1 christos
424 1.1 christos static unsigned long
425 1.1 christos i386_gnu_dr_get_control (void)
426 1.1 christos {
427 1.1 christos return i386_gnu_dr_get_reg (inferior_ptid, DR_CONTROL);
428 1.1.1.3 christos }
429 1.1 christos #endif /* i386_DEBUG_STATE */
430 1.1.1.3 christos
431 1.1 christos void _initialize_i386gnu_nat ();
432 1.1 christos void
433 1.1 christos _initialize_i386gnu_nat ()
434 1.1 christos {
435 1.1 christos #ifdef i386_DEBUG_STATE
436 1.1 christos x86_dr_low.set_control = i386_gnu_dr_set_control;
437 1.1 christos gdb_assert (DR_FIRSTADDR == 0 && DR_LASTADDR < i386_DEBUG_STATE_COUNT);
438 1.1 christos x86_dr_low.set_addr = i386_gnu_dr_set_addr;
439 1.1 christos x86_dr_low.get_addr = i386_gnu_dr_get_addr;
440 1.1 christos x86_dr_low.get_status = i386_gnu_dr_get_status;
441 1.1 christos x86_dr_low.get_control = i386_gnu_dr_get_control;
442 1.1.1.3 christos x86_set_debug_register_length (4);
443 1.1.1.3 christos #endif /* i386_DEBUG_STATE */
444 1.1 christos
445 1.1.1.2 christos gnu_target = &the_i386_gnu_nat_target;
446 1.1 christos
447 /* Register the target. */
448 add_inf_child_target (&the_i386_gnu_nat_target);
449 }
450