gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / i386-gnu-nat.c
CommitLineData
da59e081 1/* Low level interface to i386 running the GNU Hurd.
f6052080 2
b811d2c2 3 Copyright (C) 1992-2020 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. */
2d0a338c
TS
108void
109i386_gnu_nat_target::fetch_registers (struct regcache *regcache, int regno)
c906108c
SS
110{
111 struct proc *thread;
222312d3 112 ptid_t ptid = regcache->ptid ();
c5aa993b 113
da59e081 114 /* Make sure we know about new threads. */
c289427b 115 inf_update_procs (gnu_current_inf);
c906108c 116
e38504b3 117 thread = inf_tid_to_thread (gnu_current_inf, ptid.lwp ());
c5aa993b 118 if (!thread)
617fd3b5 119 error (_("Can't fetch registers from thread %s: No such thread"),
a068643d 120 target_pid_to_str (ptid).c_str ());
c906108c 121
65e78234 122 if (regno < I386_NUM_GREGS || regno == -1)
c906108c 123 {
da59e081 124 thread_state_t state;
383d750b 125
da59e081
JM
126 /* This does the dirty work for us. */
127 state = proc_get_state (thread, 0);
128 if (!state)
c906108c 129 {
8a3fe4f8 130 warning (_("Couldn't fetch registers from %s"),
da59e081
JM
131 proc_string (thread));
132 return;
c906108c
SS
133 }
134
da59e081 135 if (regno == -1)
c906108c 136 {
da59e081 137 int i;
383d750b 138
da59e081 139 proc_debug (thread, "fetching all register");
383d750b 140
65e78234 141 for (i = 0; i < I386_NUM_GREGS; i++)
73e1c03f 142 regcache->raw_supply (i, REG_ADDR (state, i));
da59e081 143 thread->fetched_regs = ~0;
c906108c
SS
144 }
145 else
146 {
c9f4d572 147 proc_debug (thread, "fetching register %s",
ac7936df 148 gdbarch_register_name (regcache->arch (),
875f8d0e 149 regno));
383d750b 150
73e1c03f 151 regcache->raw_supply (regno, REG_ADDR (state, regno));
da59e081 152 thread->fetched_regs |= (1 << regno);
c906108c
SS
153 }
154 }
da59e081 155
65e78234 156 if (regno >= I386_NUM_GREGS || regno == -1)
da59e081
JM
157 {
158 proc_debug (thread, "fetching floating-point registers");
383d750b 159
56be3814 160 fetch_fpregs (regcache, thread);
da59e081 161 }
c906108c
SS
162}
163\f
da59e081
JM
164
165/* Store the whole floating-point state into THREAD using information
166 from the corresponding (pseudo) registers. */
167static void
56be3814 168store_fpregs (const struct regcache *regcache, struct proc *thread, int regno)
da59e081
JM
169{
170 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
171 struct i386_float_state state;
0947023d 172 kern_return_t err;
c5aa993b 173
da59e081
JM
174 err = thread_get_state (thread->port, i386_FLOAT_STATE,
175 (thread_state_t) &state, &count);
176 if (err)
c906108c 177 {
8a3fe4f8 178 warning (_("Couldn't fetch floating-point state from %s"),
da59e081
JM
179 proc_string (thread));
180 return;
c906108c 181 }
c5aa993b 182
383d750b 183 /* FIXME: kettenis/2001-07-15: Is this right? Should we somehow
8262ee23 184 take into account DEPRECATED_REGISTER_VALID like the old code did? */
56be3814 185 i387_collect_fsave (regcache, regno, state.hw_state);
383d750b 186
da59e081
JM
187 err = thread_set_state (thread->port, i386_FLOAT_STATE,
188 (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
189 if (err)
c906108c 190 {
8a3fe4f8 191 warning (_("Couldn't store floating-point state into %s"),
da59e081
JM
192 proc_string (thread));
193 return;
c906108c 194 }
c906108c 195}
c5aa993b 196
da59e081 197/* Store at least register REGNO, or all regs if REGNO == -1. */
2d0a338c
TS
198void
199i386_gnu_nat_target::store_registers (struct regcache *regcache, int regno)
c5aa993b 200{
da59e081 201 struct proc *thread;
ac7936df 202 struct gdbarch *gdbarch = regcache->arch ();
222312d3 203 ptid_t ptid = regcache->ptid ();
c906108c 204
da59e081 205 /* Make sure we know about new threads. */
c289427b 206 inf_update_procs (gnu_current_inf);
c5aa993b 207
e38504b3 208 thread = inf_tid_to_thread (gnu_current_inf, ptid.lwp ());
c906108c 209 if (!thread)
617fd3b5 210 error (_("Couldn't store registers into thread %s: No such thread"),
a068643d 211 target_pid_to_str (ptid).c_str ());
c906108c 212
65e78234 213 if (regno < I386_NUM_GREGS || regno == -1)
c906108c 214 {
da59e081
JM
215 thread_state_t state;
216 thread_state_data_t old_state;
217 int was_aborted = thread->aborted;
218 int was_valid = thread->state_valid;
fb557744 219 int trace;
c906108c 220
da59e081
JM
221 if (!was_aborted && was_valid)
222 memcpy (&old_state, &thread->state, sizeof (old_state));
c906108c 223
da59e081
JM
224 state = proc_get_state (thread, 1);
225 if (!state)
226 {
1777feb0
MS
227 warning (_("Couldn't store registers into %s"),
228 proc_string (thread));
da59e081
JM
229 return;
230 }
c906108c 231
fb557744
MK
232 /* Save the T bit. We might try to restore the %eflags register
233 below, but changing the T bit would seriously confuse GDB. */
234 trace = ((struct i386_thread_state *)state)->efl & 0x100;
235
da59e081
JM
236 if (!was_aborted && was_valid)
237 /* See which registers have changed after aborting the thread. */
238 {
239 int check_regno;
240
65e78234 241 for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++)
da59e081
JM
242 if ((thread->fetched_regs & (1 << check_regno))
243 && memcpy (REG_ADDR (&old_state, check_regno),
244 REG_ADDR (state, check_regno),
875f8d0e 245 register_size (gdbarch, check_regno)))
da59e081
JM
246 /* Register CHECK_REGNO has changed! Ack! */
247 {
8a3fe4f8 248 warning (_("Register %s changed after the thread was aborted"),
875f8d0e 249 gdbarch_register_name (gdbarch, check_regno));
da59e081 250 if (regno >= 0 && regno != check_regno)
383d750b 251 /* Update GDB's copy of the register. */
73e1c03f
SM
252 regcache->raw_supply (check_regno,
253 REG_ADDR (state, check_regno));
da59e081 254 else
1777feb0
MS
255 warning (_("... also writing this register! "
256 "Suspicious..."));
da59e081
JM
257 }
258 }
c906108c 259
da59e081
JM
260 if (regno == -1)
261 {
262 int i;
383d750b 263
da59e081 264 proc_debug (thread, "storing all registers");
c5aa993b 265
65e78234 266 for (i = 0; i < I386_NUM_GREGS; i++)
0ec9f114 267 if (REG_VALID == regcache->get_register_status (i))
34a79281 268 regcache->raw_collect (i, REG_ADDR (state, i));
da59e081
JM
269 }
270 else
271 {
c9f4d572 272 proc_debug (thread, "storing register %s",
875f8d0e 273 gdbarch_register_name (gdbarch, regno));
c906108c 274
0ec9f114 275 gdb_assert (REG_VALID == regcache->get_register_status (regno));
34a79281 276 regcache->raw_collect (regno, REG_ADDR (state, regno));
da59e081 277 }
fb557744
MK
278
279 /* Restore the T bit. */
280 ((struct i386_thread_state *)state)->efl &= ~0x100;
281 ((struct i386_thread_state *)state)->efl |= trace;
c906108c 282 }
c5aa993b 283
65e78234 284 if (regno >= I386_NUM_GREGS || regno == -1)
da59e081
JM
285 {
286 proc_debug (thread, "storing floating-point registers");
383d750b 287
56be3814 288 store_fpregs (regcache, thread, regno);
da59e081 289 }
c906108c 290}
b4d1e8c7 291
05db5edd
ST
292\f
293/* Support for debug registers. */
294
295#ifdef i386_DEBUG_STATE
296/* Get debug registers for thread THREAD. */
297
298static void
299i386_gnu_dr_get (struct i386_debug_state *regs, struct proc *thread)
300{
301 mach_msg_type_number_t count = i386_DEBUG_STATE_COUNT;
0947023d 302 kern_return_t err;
05db5edd
ST
303
304 err = thread_get_state (thread->port, i386_DEBUG_STATE,
305 (thread_state_t) regs, &count);
306 if (err != 0 || count != i386_DEBUG_STATE_COUNT)
307 warning (_("Couldn't fetch debug state from %s"),
308 proc_string (thread));
309}
310
311/* Set debug registers for thread THREAD. */
312
313static void
314i386_gnu_dr_set (const struct i386_debug_state *regs, struct proc *thread)
315{
0947023d 316 kern_return_t err;
05db5edd
ST
317
318 err = thread_set_state (thread->port, i386_DEBUG_STATE,
319 (thread_state_t) regs, i386_DEBUG_STATE_COUNT);
320 if (err != 0)
321 warning (_("Couldn't store debug state into %s"),
322 proc_string (thread));
323}
324
325/* Set DR_CONTROL in THREAD. */
326
327static void
328i386_gnu_dr_set_control_one (struct proc *thread, void *arg)
329{
e9e431d1 330 unsigned long *control = (unsigned long *) arg;
05db5edd
ST
331 struct i386_debug_state regs;
332
333 i386_gnu_dr_get (&regs, thread);
334 regs.dr[DR_CONTROL] = *control;
335 i386_gnu_dr_set (&regs, thread);
336}
337
338/* Set DR_CONTROL to CONTROL in all threads. */
339
340static void
341i386_gnu_dr_set_control (unsigned long control)
342{
343 inf_update_procs (gnu_current_inf);
344 inf_threads (gnu_current_inf, i386_gnu_dr_set_control_one, &control);
345}
346
347/* Parameters to set a debugging address. */
348
349struct reg_addr
350{
351 int regnum; /* Register number (zero based). */
352 CORE_ADDR addr; /* Address. */
353};
354
355/* Set address REGNUM (zero based) to ADDR in THREAD. */
356
357static void
358i386_gnu_dr_set_addr_one (struct proc *thread, void *arg)
359{
e9e431d1 360 struct reg_addr *reg_addr = (struct reg_addr *) arg;
05db5edd
ST
361 struct i386_debug_state regs;
362
363 i386_gnu_dr_get (&regs, thread);
364 regs.dr[reg_addr->regnum] = reg_addr->addr;
365 i386_gnu_dr_set (&regs, thread);
366}
367
368/* Set address REGNUM (zero based) to ADDR in all threads. */
369
370static void
371i386_gnu_dr_set_addr (int regnum, CORE_ADDR addr)
372{
373 struct reg_addr reg_addr;
374
375 gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
376
377 reg_addr.regnum = regnum;
378 reg_addr.addr = addr;
379
380 inf_update_procs (gnu_current_inf);
381 inf_threads (gnu_current_inf, i386_gnu_dr_set_addr_one, &reg_addr);
382}
383
384/* Get debug register REGNUM value from only the one LWP of PTID. */
385
386static unsigned long
387i386_gnu_dr_get_reg (ptid_t ptid, int regnum)
388{
389 struct i386_debug_state regs;
390 struct proc *thread;
391
392 /* Make sure we know about new threads. */
393 inf_update_procs (gnu_current_inf);
394
e38504b3 395 thread = inf_tid_to_thread (gnu_current_inf, ptid.lwp ());
05db5edd
ST
396 i386_gnu_dr_get (&regs, thread);
397
398 return regs.dr[regnum];
399}
400
401/* Return the inferior's debug register REGNUM. */
402
403static CORE_ADDR
404i386_gnu_dr_get_addr (int regnum)
405{
406 gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
407
408 return i386_gnu_dr_get_reg (inferior_ptid, regnum);
409}
410
411/* Get DR_STATUS from only the one thread of INFERIOR_PTID. */
412
413static unsigned long
414i386_gnu_dr_get_status (void)
415{
416 return i386_gnu_dr_get_reg (inferior_ptid, DR_STATUS);
417}
418
419/* Return the inferior's DR7 debug control register. */
420
421static unsigned long
422i386_gnu_dr_get_control (void)
423{
424 return i386_gnu_dr_get_reg (inferior_ptid, DR_CONTROL);
425}
426#endif /* i386_DEBUG_STATE */
427
6c265988 428void _initialize_i386gnu_nat ();
b4d1e8c7 429void
6c265988 430_initialize_i386gnu_nat ()
b4d1e8c7 431{
05db5edd 432#ifdef i386_DEBUG_STATE
05db5edd
ST
433 x86_dr_low.set_control = i386_gnu_dr_set_control;
434 gdb_assert (DR_FIRSTADDR == 0 && DR_LASTADDR < i386_DEBUG_STATE_COUNT);
435 x86_dr_low.set_addr = i386_gnu_dr_set_addr;
436 x86_dr_low.get_addr = i386_gnu_dr_get_addr;
437 x86_dr_low.get_status = i386_gnu_dr_get_status;
438 x86_dr_low.get_control = i386_gnu_dr_get_control;
439 x86_set_debug_register_length (4);
440#endif /* i386_DEBUG_STATE */
441
53dff92c
ST
442 gnu_target = &the_i386_gnu_nat_target;
443
b4d1e8c7 444 /* Register the target. */
d9f719f1 445 add_inf_child_target (&the_i386_gnu_nat_target);
b4d1e8c7 446}
This page took 1.61711 seconds and 4 git commands to generate.