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