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