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