]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/i386-gnu-nat.c
Remove regcache_raw_supply
[thirdparty/binutils-gdb.git] / gdb / i386-gnu-nat.c
CommitLineData
da59e081 1/* Low level interface to i386 running the GNU Hurd.
f6052080 2
e2882c85 3 Copyright (C) 1992-2018 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
21389b7f
TS
20/* Mach/Hurd headers are not yet ready for C++ compilation. */
21extern "C"
22{
23#include <mach.h>
24#include <mach_error.h>
25#include <mach/message.h>
26#include <mach/exception.h>
27}
28
c906108c 29#include "defs.h"
05db5edd 30#include "x86-nat.h"
c906108c
SS
31#include "inferior.h"
32#include "floatformat.h"
4e052eda 33#include "regcache.h"
c906108c 34
4604bcad
MK
35#include "i386-tdep.h"
36
c906108c 37#include "gnu-nat.h"
05db5edd 38#include "inf-child.h"
e750d25e 39#include "i387-tdep.h"
c906108c 40
da59e081
JM
41/* Offset to the thread_state_t location where REG is stored. */
42#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
c906108c 43
383d750b
MK
44/* At REG_OFFSET[N] is the offset to the thread_state_t location where
45 the GDB register N is stored. */
c5aa993b 46static int reg_offset[] =
c906108c 47{
c5aa993b
JM
48 REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
49 REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
50 REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
51 REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
c906108c
SS
52};
53
da59e081
JM
54#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
55
c906108c 56\f
f6ac5f3d
PA
57
58/* The i386 GNU Hurd target. */
59
60#ifdef i386_DEBUG_STATE
61using gnu_base_target = x86_nat_target<gnu_nat_target>;
62#else
63using gnu_base_target = gnu_nat_target;
64#endif
65
66struct i386_gnu_nat_target final : public gnu_base_target
67{
68 void fetch_registers (struct regcache *, int) override;
69 void store_registers (struct regcache *, int) override;
70};
71
72static i386_gnu_nat_target the_i386_gnu_nat_target;
73
3303a276
MK
74/* Get the whole floating-point state of THREAD and record the values
75 of the corresponding (pseudo) registers. */
76
da59e081 77static void
56be3814 78fetch_fpregs (struct regcache *regcache, struct proc *thread)
c906108c 79{
da59e081
JM
80 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
81 struct i386_float_state state;
0947023d 82 kern_return_t err;
c906108c 83
da59e081
JM
84 err = thread_get_state (thread->port, i386_FLOAT_STATE,
85 (thread_state_t) &state, &count);
86 if (err)
c906108c 87 {
8a3fe4f8 88 warning (_("Couldn't fetch floating-point state from %s"),
da59e081
JM
89 proc_string (thread));
90 return;
c906108c 91 }
da59e081 92
383d750b 93 if (!state.initialized)
c906108c 94 {
3303a276 95 /* The floating-point state isn't initialized. */
56be3814 96 i387_supply_fsave (regcache, -1, NULL);
3303a276
MK
97 }
98 else
99 {
100 /* Supply the floating-point registers. */
56be3814 101 i387_supply_fsave (regcache, -1, state.hw_state);
c906108c
SS
102 }
103}
da59e081
JM
104
105/* Fetch register REGNO, or all regs if REGNO is -1. */
b4d1e8c7 106static void
85a772a5
TS
107gnu_fetch_registers (struct target_ops *ops,
108 struct regcache *regcache, int regno)
c906108c
SS
109{
110 struct proc *thread;
222312d3 111 ptid_t ptid = regcache->ptid ();
c5aa993b 112
da59e081 113 /* Make sure we know about new threads. */
c289427b 114 inf_update_procs (gnu_current_inf);
c906108c 115
d9cb6cdc 116 thread = inf_tid_to_thread (gnu_current_inf, ptid_get_lwp (ptid));
c5aa993b 117 if (!thread)
617fd3b5 118 error (_("Can't fetch registers from thread %s: No such thread"),
d9cb6cdc 119 target_pid_to_str (ptid));
c906108c 120
65e78234 121 if (regno < I386_NUM_GREGS || regno == -1)
c906108c 122 {
da59e081 123 thread_state_t state;
383d750b 124
da59e081
JM
125 /* This does the dirty work for us. */
126 state = proc_get_state (thread, 0);
127 if (!state)
c906108c 128 {
8a3fe4f8 129 warning (_("Couldn't fetch registers from %s"),
da59e081
JM
130 proc_string (thread));
131 return;
c906108c
SS
132 }
133
da59e081 134 if (regno == -1)
c906108c 135 {
da59e081 136 int i;
383d750b 137
da59e081 138 proc_debug (thread, "fetching all register");
383d750b 139
65e78234 140 for (i = 0; i < I386_NUM_GREGS; i++)
73e1c03f 141 regcache->raw_supply (i, REG_ADDR (state, i));
da59e081 142 thread->fetched_regs = ~0;
c906108c
SS
143 }
144 else
145 {
c9f4d572 146 proc_debug (thread, "fetching register %s",
ac7936df 147 gdbarch_register_name (regcache->arch (),
875f8d0e 148 regno));
383d750b 149
73e1c03f 150 regcache->raw_supply (regno, REG_ADDR (state, regno));
da59e081 151 thread->fetched_regs |= (1 << regno);
c906108c
SS
152 }
153 }
da59e081 154
65e78234 155 if (regno >= I386_NUM_GREGS || regno == -1)
da59e081
JM
156 {
157 proc_debug (thread, "fetching floating-point registers");
383d750b 158
56be3814 159 fetch_fpregs (regcache, thread);
da59e081 160 }
c906108c
SS
161}
162\f
da59e081
JM
163
164/* Store the whole floating-point state into THREAD using information
165 from the corresponding (pseudo) registers. */
166static void
56be3814 167store_fpregs (const struct regcache *regcache, struct proc *thread, int regno)
da59e081
JM
168{
169 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
170 struct i386_float_state state;
0947023d 171 kern_return_t err;
c5aa993b 172
da59e081
JM
173 err = thread_get_state (thread->port, i386_FLOAT_STATE,
174 (thread_state_t) &state, &count);
175 if (err)
c906108c 176 {
8a3fe4f8 177 warning (_("Couldn't fetch floating-point state from %s"),
da59e081
JM
178 proc_string (thread));
179 return;
c906108c 180 }
c5aa993b 181
383d750b 182 /* FIXME: kettenis/2001-07-15: Is this right? Should we somehow
8262ee23 183 take into account DEPRECATED_REGISTER_VALID like the old code did? */
56be3814 184 i387_collect_fsave (regcache, regno, state.hw_state);
383d750b 185
da59e081
JM
186 err = thread_set_state (thread->port, i386_FLOAT_STATE,
187 (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
188 if (err)
c906108c 189 {
8a3fe4f8 190 warning (_("Couldn't store floating-point state into %s"),
da59e081
JM
191 proc_string (thread));
192 return;
c906108c 193 }
c906108c 194}
c5aa993b 195
da59e081 196/* Store at least register REGNO, or all regs if REGNO == -1. */
b4d1e8c7 197static void
85a772a5
TS
198gnu_store_registers (struct target_ops *ops,
199 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
d9cb6cdc 208 thread = inf_tid_to_thread (gnu_current_inf, ptid_get_lwp (ptid));
c906108c 209 if (!thread)
617fd3b5 210 error (_("Couldn't store registers into thread %s: No such thread"),
d9cb6cdc 211 target_pid_to_str (ptid));
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))
9b8607ce 268 regcache_raw_collect (regcache, 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));
ecac404d 276 regcache_raw_collect (regcache, 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
395 thread = inf_tid_to_thread (gnu_current_inf, ptid_get_lwp (ptid));
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
b4d1e8c7
PA
428void
429_initialize_i386gnu_nat (void)
430{
05db5edd 431#ifdef i386_DEBUG_STATE
05db5edd
ST
432 x86_dr_low.set_control = i386_gnu_dr_set_control;
433 gdb_assert (DR_FIRSTADDR == 0 && DR_LASTADDR < i386_DEBUG_STATE_COUNT);
434 x86_dr_low.set_addr = i386_gnu_dr_set_addr;
435 x86_dr_low.get_addr = i386_gnu_dr_get_addr;
436 x86_dr_low.get_status = i386_gnu_dr_get_status;
437 x86_dr_low.get_control = i386_gnu_dr_get_control;
438 x86_set_debug_register_length (4);
439#endif /* i386_DEBUG_STATE */
440
b4d1e8c7 441 /* Register the target. */
d9f719f1 442 add_inf_child_target (&the_i386_gnu_nat_target);
b4d1e8c7 443}