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