Move stdarg.h to common-defs.h
[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"
21#include "inferior.h"
22#include "floatformat.h"
4e052eda 23#include "regcache.h"
c906108c 24
780a49fa 25#include "gdb_assert.h"
c906108c 26#include <errno.h>
0e9f083f 27#include <string.h>
c906108c
SS
28
29#include <mach.h>
da59e081 30#include <mach_error.h>
c906108c
SS
31#include <mach/message.h>
32#include <mach/exception.h>
c906108c 33
4604bcad
MK
34#include "i386-tdep.h"
35
c906108c 36#include "gnu-nat.h"
e750d25e 37#include "i387-tdep.h"
c906108c 38
57e76fac
MS
39#ifdef HAVE_SYS_PROCFS_H
40# include <sys/procfs.h>
41# include "gregset.h"
42#endif
c906108c 43
da59e081
JM
44/* Offset to the thread_state_t location where REG is stored. */
45#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
c906108c 46
383d750b
MK
47/* At REG_OFFSET[N] is the offset to the thread_state_t location where
48 the GDB register N is stored. */
c5aa993b 49static int reg_offset[] =
c906108c 50{
c5aa993b
JM
51 REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
52 REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
53 REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
54 REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
c906108c
SS
55};
56
ecccb813
TS
57/* Offset to the greg_t location where REG is stored. */
58#define CREG_OFFSET(reg) (REG_##reg * 4)
59
60/* At CREG_OFFSET[N] is the offset to the greg_t location where
61 the GDB register N is stored. */
62static int creg_offset[] =
63{
64 CREG_OFFSET (EAX), CREG_OFFSET (ECX), CREG_OFFSET (EDX), CREG_OFFSET (EBX),
65 CREG_OFFSET (UESP), CREG_OFFSET (EBP), CREG_OFFSET (ESI), CREG_OFFSET (EDI),
66 CREG_OFFSET (EIP), CREG_OFFSET (EFL), CREG_OFFSET (CS), CREG_OFFSET (SS),
67 CREG_OFFSET (DS), CREG_OFFSET (ES), CREG_OFFSET (FS), CREG_OFFSET (GS)
68};
69
da59e081 70#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
ecccb813 71#define CREG_ADDR(state, regnum) ((const char *)(state) + creg_offset[regnum])
da59e081 72
c906108c 73\f
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;
da59e081 82 error_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 104
57e76fac
MS
105#ifdef HAVE_SYS_PROCFS_H
106/* These two calls are used by the core-regset.c code for
107 reading ELF core files. */
108void
7f7fe91e 109supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregs)
57e76fac
MS
110{
111 int i;
65e78234 112 for (i = 0; i < I386_NUM_GREGS; i++)
7f7fe91e 113 regcache_raw_supply (regcache, i, CREG_ADDR (gregs, i));
57e76fac
MS
114}
115
116void
7f7fe91e 117supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregs)
57e76fac 118{
7f7fe91e 119 i387_supply_fsave (regcache, -1, fpregs);
57e76fac
MS
120}
121#endif
122
da59e081 123/* Fetch register REGNO, or all regs if REGNO is -1. */
b4d1e8c7 124static void
85a772a5
TS
125gnu_fetch_registers (struct target_ops *ops,
126 struct regcache *regcache, int regno)
c906108c
SS
127{
128 struct proc *thread;
c5aa993b 129
da59e081 130 /* Make sure we know about new threads. */
c289427b 131 inf_update_procs (gnu_current_inf);
c906108c 132
c289427b 133 thread = inf_tid_to_thread (gnu_current_inf,
ca08a94c 134 ptid_get_lwp (inferior_ptid));
c5aa993b 135 if (!thread)
617fd3b5
PA
136 error (_("Can't fetch registers from thread %s: No such thread"),
137 target_pid_to_str (inferior_ptid));
c906108c 138
65e78234 139 if (regno < I386_NUM_GREGS || regno == -1)
c906108c 140 {
da59e081 141 thread_state_t state;
383d750b 142
da59e081
JM
143 /* This does the dirty work for us. */
144 state = proc_get_state (thread, 0);
145 if (!state)
c906108c 146 {
8a3fe4f8 147 warning (_("Couldn't fetch registers from %s"),
da59e081
JM
148 proc_string (thread));
149 return;
c906108c
SS
150 }
151
da59e081 152 if (regno == -1)
c906108c 153 {
da59e081 154 int i;
383d750b 155
da59e081 156 proc_debug (thread, "fetching all register");
383d750b 157
65e78234 158 for (i = 0; i < I386_NUM_GREGS; i++)
56be3814 159 regcache_raw_supply (regcache, i, REG_ADDR (state, i));
da59e081 160 thread->fetched_regs = ~0;
c906108c
SS
161 }
162 else
163 {
c9f4d572 164 proc_debug (thread, "fetching register %s",
875f8d0e
UW
165 gdbarch_register_name (get_regcache_arch (regcache),
166 regno));
383d750b 167
56be3814 168 regcache_raw_supply (regcache, regno,
23a6d369 169 REG_ADDR (state, regno));
da59e081 170 thread->fetched_regs |= (1 << regno);
c906108c
SS
171 }
172 }
da59e081 173
65e78234 174 if (regno >= I386_NUM_GREGS || regno == -1)
da59e081
JM
175 {
176 proc_debug (thread, "fetching floating-point registers");
383d750b 177
56be3814 178 fetch_fpregs (regcache, thread);
da59e081 179 }
c906108c
SS
180}
181\f
da59e081
JM
182
183/* Store the whole floating-point state into THREAD using information
184 from the corresponding (pseudo) registers. */
185static void
56be3814 186store_fpregs (const struct regcache *regcache, struct proc *thread, int regno)
da59e081
JM
187{
188 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
189 struct i386_float_state state;
190 error_t err;
c5aa993b 191
da59e081
JM
192 err = thread_get_state (thread->port, i386_FLOAT_STATE,
193 (thread_state_t) &state, &count);
194 if (err)
c906108c 195 {
8a3fe4f8 196 warning (_("Couldn't fetch floating-point state from %s"),
da59e081
JM
197 proc_string (thread));
198 return;
c906108c 199 }
c5aa993b 200
383d750b 201 /* FIXME: kettenis/2001-07-15: Is this right? Should we somehow
8262ee23 202 take into account DEPRECATED_REGISTER_VALID like the old code did? */
56be3814 203 i387_collect_fsave (regcache, regno, state.hw_state);
383d750b 204
da59e081
JM
205 err = thread_set_state (thread->port, i386_FLOAT_STATE,
206 (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
207 if (err)
c906108c 208 {
8a3fe4f8 209 warning (_("Couldn't store floating-point state into %s"),
da59e081
JM
210 proc_string (thread));
211 return;
c906108c 212 }
c906108c 213}
c5aa993b 214
da59e081 215/* Store at least register REGNO, or all regs if REGNO == -1. */
b4d1e8c7 216static void
85a772a5
TS
217gnu_store_registers (struct target_ops *ops,
218 struct regcache *regcache, int regno)
c5aa993b 219{
da59e081 220 struct proc *thread;
875f8d0e 221 struct gdbarch *gdbarch = get_regcache_arch (regcache);
c906108c 222
da59e081 223 /* Make sure we know about new threads. */
c289427b 224 inf_update_procs (gnu_current_inf);
c5aa993b 225
c289427b 226 thread = inf_tid_to_thread (gnu_current_inf,
ca08a94c 227 ptid_get_lwp (inferior_ptid));
c906108c 228 if (!thread)
617fd3b5
PA
229 error (_("Couldn't store registers into thread %s: No such thread"),
230 target_pid_to_str (inferior_ptid));
c906108c 231
65e78234 232 if (regno < I386_NUM_GREGS || regno == -1)
c906108c 233 {
da59e081
JM
234 thread_state_t state;
235 thread_state_data_t old_state;
236 int was_aborted = thread->aborted;
237 int was_valid = thread->state_valid;
fb557744 238 int trace;
c906108c 239
da59e081
JM
240 if (!was_aborted && was_valid)
241 memcpy (&old_state, &thread->state, sizeof (old_state));
c906108c 242
da59e081
JM
243 state = proc_get_state (thread, 1);
244 if (!state)
245 {
1777feb0
MS
246 warning (_("Couldn't store registers into %s"),
247 proc_string (thread));
da59e081
JM
248 return;
249 }
c906108c 250
fb557744
MK
251 /* Save the T bit. We might try to restore the %eflags register
252 below, but changing the T bit would seriously confuse GDB. */
253 trace = ((struct i386_thread_state *)state)->efl & 0x100;
254
da59e081
JM
255 if (!was_aborted && was_valid)
256 /* See which registers have changed after aborting the thread. */
257 {
258 int check_regno;
259
65e78234 260 for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++)
da59e081
JM
261 if ((thread->fetched_regs & (1 << check_regno))
262 && memcpy (REG_ADDR (&old_state, check_regno),
263 REG_ADDR (state, check_regno),
875f8d0e 264 register_size (gdbarch, check_regno)))
da59e081
JM
265 /* Register CHECK_REGNO has changed! Ack! */
266 {
8a3fe4f8 267 warning (_("Register %s changed after the thread was aborted"),
875f8d0e 268 gdbarch_register_name (gdbarch, check_regno));
da59e081 269 if (regno >= 0 && regno != check_regno)
383d750b 270 /* Update GDB's copy of the register. */
f6052080 271 regcache_raw_supply (regcache, check_regno,
23a6d369 272 REG_ADDR (state, check_regno));
da59e081 273 else
1777feb0
MS
274 warning (_("... also writing this register! "
275 "Suspicious..."));
da59e081
JM
276 }
277 }
c906108c 278
da59e081
JM
279 if (regno == -1)
280 {
281 int i;
383d750b 282
da59e081 283 proc_debug (thread, "storing all registers");
c5aa993b 284
65e78234 285 for (i = 0; i < I386_NUM_GREGS; i++)
672c9795 286 if (REG_VALID == regcache_register_status (regcache, i))
9b8607ce 287 regcache_raw_collect (regcache, i, REG_ADDR (state, i));
da59e081
JM
288 }
289 else
290 {
c9f4d572 291 proc_debug (thread, "storing register %s",
875f8d0e 292 gdbarch_register_name (gdbarch, regno));
c906108c 293
672c9795 294 gdb_assert (REG_VALID == regcache_register_status (regcache, regno));
ecac404d 295 regcache_raw_collect (regcache, regno, REG_ADDR (state, regno));
da59e081 296 }
fb557744
MK
297
298 /* Restore the T bit. */
299 ((struct i386_thread_state *)state)->efl &= ~0x100;
300 ((struct i386_thread_state *)state)->efl |= trace;
c906108c 301 }
c5aa993b 302
65e78234 303 if (regno >= I386_NUM_GREGS || regno == -1)
da59e081
JM
304 {
305 proc_debug (thread, "storing floating-point registers");
383d750b 306
56be3814 307 store_fpregs (regcache, thread, regno);
da59e081 308 }
c906108c 309}
b4d1e8c7
PA
310
311/* Provide a prototype to silence -Wmissing-prototypes. */
312extern initialize_file_ftype _initialize_i386gnu_nat;
313
314void
315_initialize_i386gnu_nat (void)
316{
317 struct target_ops *t;
318
319 /* Fill in the generic GNU/Hurd methods. */
320 t = gnu_target ();
321
322 t->to_fetch_registers = gnu_fetch_registers;
323 t->to_store_registers = gnu_store_registers;
324
325 /* Register the target. */
326 add_target (t);
327}
This page took 1.179825 seconds and 4 git commands to generate.