]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/i386gnu-nat.c
gdb/
[thirdparty/binutils-gdb.git] / gdb / i386gnu-nat.c
CommitLineData
da59e081 1/* Low level interface to i386 running the GNU Hurd.
f6052080 2
0b302171
JB
3 Copyright (C) 1992, 1995-1996, 1998, 2000-2001, 2004, 2007-2012 Free
4 Software Foundation, Inc.
c906108c 5
c5aa993b 6 This file is part of GDB.
c906108c 7
c5aa993b
JM
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
c5aa993b 11 (at your option) any later version.
c906108c 12
c5aa993b
JM
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
c906108c 17
c5aa993b 18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
20
21#include "defs.h"
22#include "inferior.h"
23#include "floatformat.h"
4e052eda 24#include "regcache.h"
c906108c 25
780a49fa 26#include "gdb_assert.h"
c906108c 27#include <errno.h>
383d750b 28#include <stdio.h>
3303a276 29#include "gdb_string.h"
c906108c
SS
30
31#include <mach.h>
da59e081 32#include <mach_error.h>
c906108c
SS
33#include <mach/message.h>
34#include <mach/exception.h>
c906108c 35
4604bcad
MK
36#include "i386-tdep.h"
37
c906108c 38#include "gnu-nat.h"
e750d25e 39#include "i387-tdep.h"
c906108c 40
57e76fac
MS
41#ifdef HAVE_SYS_PROCFS_H
42# include <sys/procfs.h>
43# include "gregset.h"
44#endif
c906108c 45
da59e081
JM
46/* Offset to the thread_state_t location where REG is stored. */
47#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
c906108c 48
383d750b
MK
49/* At REG_OFFSET[N] is the offset to the thread_state_t location where
50 the GDB register N is stored. */
c5aa993b 51static int reg_offset[] =
c906108c 52{
c5aa993b
JM
53 REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
54 REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
55 REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
56 REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
c906108c
SS
57};
58
da59e081 59#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
7f7fe91e 60#define CREG_ADDR(state, regnum) ((const char *)(state) + reg_offset[regnum])
da59e081 61
c906108c 62\f
3303a276
MK
63/* Get the whole floating-point state of THREAD and record the values
64 of the corresponding (pseudo) registers. */
65
da59e081 66static void
56be3814 67fetch_fpregs (struct regcache *regcache, struct proc *thread)
c906108c 68{
da59e081
JM
69 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
70 struct i386_float_state state;
da59e081 71 error_t err;
c906108c 72
da59e081
JM
73 err = thread_get_state (thread->port, i386_FLOAT_STATE,
74 (thread_state_t) &state, &count);
75 if (err)
c906108c 76 {
8a3fe4f8 77 warning (_("Couldn't fetch floating-point state from %s"),
da59e081
JM
78 proc_string (thread));
79 return;
c906108c 80 }
da59e081 81
383d750b 82 if (!state.initialized)
c906108c 83 {
3303a276 84 /* The floating-point state isn't initialized. */
56be3814 85 i387_supply_fsave (regcache, -1, NULL);
3303a276
MK
86 }
87 else
88 {
89 /* Supply the floating-point registers. */
56be3814 90 i387_supply_fsave (regcache, -1, state.hw_state);
c906108c
SS
91 }
92}
da59e081 93
57e76fac
MS
94#ifdef HAVE_SYS_PROCFS_H
95/* These two calls are used by the core-regset.c code for
96 reading ELF core files. */
97void
7f7fe91e 98supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregs)
57e76fac
MS
99{
100 int i;
65e78234 101 for (i = 0; i < I386_NUM_GREGS; i++)
7f7fe91e 102 regcache_raw_supply (regcache, i, CREG_ADDR (gregs, i));
57e76fac
MS
103}
104
105void
7f7fe91e 106supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregs)
57e76fac 107{
7f7fe91e 108 i387_supply_fsave (regcache, -1, fpregs);
57e76fac
MS
109}
110#endif
111
da59e081 112/* Fetch register REGNO, or all regs if REGNO is -1. */
b4d1e8c7 113static void
85a772a5
TS
114gnu_fetch_registers (struct target_ops *ops,
115 struct regcache *regcache, int regno)
c906108c
SS
116{
117 struct proc *thread;
c5aa993b 118
da59e081 119 /* Make sure we know about new threads. */
c289427b 120 inf_update_procs (gnu_current_inf);
c906108c 121
c289427b 122 thread = inf_tid_to_thread (gnu_current_inf,
617fd3b5 123 ptid_get_tid (inferior_ptid));
c5aa993b 124 if (!thread)
617fd3b5
PA
125 error (_("Can't fetch registers from thread %s: No such thread"),
126 target_pid_to_str (inferior_ptid));
c906108c 127
65e78234 128 if (regno < I386_NUM_GREGS || regno == -1)
c906108c 129 {
da59e081 130 thread_state_t state;
383d750b 131
da59e081
JM
132 /* This does the dirty work for us. */
133 state = proc_get_state (thread, 0);
134 if (!state)
c906108c 135 {
8a3fe4f8 136 warning (_("Couldn't fetch registers from %s"),
da59e081
JM
137 proc_string (thread));
138 return;
c906108c
SS
139 }
140
da59e081 141 if (regno == -1)
c906108c 142 {
da59e081 143 int i;
383d750b 144
da59e081 145 proc_debug (thread, "fetching all register");
383d750b 146
65e78234 147 for (i = 0; i < I386_NUM_GREGS; i++)
56be3814 148 regcache_raw_supply (regcache, i, REG_ADDR (state, i));
da59e081 149 thread->fetched_regs = ~0;
c906108c
SS
150 }
151 else
152 {
c9f4d572 153 proc_debug (thread, "fetching register %s",
875f8d0e
UW
154 gdbarch_register_name (get_regcache_arch (regcache),
155 regno));
383d750b 156
56be3814 157 regcache_raw_supply (regcache, regno,
23a6d369 158 REG_ADDR (state, regno));
da59e081 159 thread->fetched_regs |= (1 << regno);
c906108c
SS
160 }
161 }
da59e081 162
65e78234 163 if (regno >= I386_NUM_GREGS || regno == -1)
da59e081
JM
164 {
165 proc_debug (thread, "fetching floating-point registers");
383d750b 166
56be3814 167 fetch_fpregs (regcache, thread);
da59e081 168 }
c906108c
SS
169}
170\f
da59e081
JM
171
172/* Store the whole floating-point state into THREAD using information
173 from the corresponding (pseudo) registers. */
174static void
56be3814 175store_fpregs (const struct regcache *regcache, struct proc *thread, int regno)
da59e081
JM
176{
177 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
178 struct i386_float_state state;
179 error_t err;
c5aa993b 180
da59e081
JM
181 err = thread_get_state (thread->port, i386_FLOAT_STATE,
182 (thread_state_t) &state, &count);
183 if (err)
c906108c 184 {
8a3fe4f8 185 warning (_("Couldn't fetch floating-point state from %s"),
da59e081
JM
186 proc_string (thread));
187 return;
c906108c 188 }
c5aa993b 189
383d750b 190 /* FIXME: kettenis/2001-07-15: Is this right? Should we somehow
8262ee23 191 take into account DEPRECATED_REGISTER_VALID like the old code did? */
56be3814 192 i387_collect_fsave (regcache, regno, state.hw_state);
383d750b 193
da59e081
JM
194 err = thread_set_state (thread->port, i386_FLOAT_STATE,
195 (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
196 if (err)
c906108c 197 {
8a3fe4f8 198 warning (_("Couldn't store floating-point state into %s"),
da59e081
JM
199 proc_string (thread));
200 return;
c906108c 201 }
c906108c 202}
c5aa993b 203
da59e081 204/* Store at least register REGNO, or all regs if REGNO == -1. */
b4d1e8c7 205static void
85a772a5
TS
206gnu_store_registers (struct target_ops *ops,
207 struct regcache *regcache, int regno)
c5aa993b 208{
da59e081 209 struct proc *thread;
875f8d0e 210 struct gdbarch *gdbarch = get_regcache_arch (regcache);
c906108c 211
da59e081 212 /* Make sure we know about new threads. */
c289427b 213 inf_update_procs (gnu_current_inf);
c5aa993b 214
c289427b 215 thread = inf_tid_to_thread (gnu_current_inf,
617fd3b5 216 ptid_get_tid (inferior_ptid));
c906108c 217 if (!thread)
617fd3b5
PA
218 error (_("Couldn't store registers into thread %s: No such thread"),
219 target_pid_to_str (inferior_ptid));
c906108c 220
65e78234 221 if (regno < I386_NUM_GREGS || regno == -1)
c906108c 222 {
da59e081
JM
223 thread_state_t state;
224 thread_state_data_t old_state;
225 int was_aborted = thread->aborted;
226 int was_valid = thread->state_valid;
fb557744 227 int trace;
c906108c 228
da59e081
JM
229 if (!was_aborted && was_valid)
230 memcpy (&old_state, &thread->state, sizeof (old_state));
c906108c 231
da59e081
JM
232 state = proc_get_state (thread, 1);
233 if (!state)
234 {
1777feb0
MS
235 warning (_("Couldn't store registers into %s"),
236 proc_string (thread));
da59e081
JM
237 return;
238 }
c906108c 239
fb557744
MK
240 /* Save the T bit. We might try to restore the %eflags register
241 below, but changing the T bit would seriously confuse GDB. */
242 trace = ((struct i386_thread_state *)state)->efl & 0x100;
243
da59e081
JM
244 if (!was_aborted && was_valid)
245 /* See which registers have changed after aborting the thread. */
246 {
247 int check_regno;
248
65e78234 249 for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++)
da59e081
JM
250 if ((thread->fetched_regs & (1 << check_regno))
251 && memcpy (REG_ADDR (&old_state, check_regno),
252 REG_ADDR (state, check_regno),
875f8d0e 253 register_size (gdbarch, check_regno)))
da59e081
JM
254 /* Register CHECK_REGNO has changed! Ack! */
255 {
8a3fe4f8 256 warning (_("Register %s changed after the thread was aborted"),
875f8d0e 257 gdbarch_register_name (gdbarch, check_regno));
da59e081 258 if (regno >= 0 && regno != check_regno)
383d750b 259 /* Update GDB's copy of the register. */
f6052080 260 regcache_raw_supply (regcache, check_regno,
23a6d369 261 REG_ADDR (state, check_regno));
da59e081 262 else
1777feb0
MS
263 warning (_("... also writing this register! "
264 "Suspicious..."));
da59e081
JM
265 }
266 }
c906108c 267
da59e081
JM
268 if (regno == -1)
269 {
270 int i;
383d750b 271
da59e081 272 proc_debug (thread, "storing all registers");
c5aa993b 273
65e78234 274 for (i = 0; i < I386_NUM_GREGS; i++)
672c9795 275 if (REG_VALID == regcache_register_status (regcache, i))
9b8607ce 276 regcache_raw_collect (regcache, i, REG_ADDR (state, i));
da59e081
JM
277 }
278 else
279 {
c9f4d572 280 proc_debug (thread, "storing register %s",
875f8d0e 281 gdbarch_register_name (gdbarch, regno));
c906108c 282
672c9795 283 gdb_assert (REG_VALID == regcache_register_status (regcache, regno));
ecac404d 284 regcache_raw_collect (regcache, regno, REG_ADDR (state, regno));
da59e081 285 }
fb557744
MK
286
287 /* Restore the T bit. */
288 ((struct i386_thread_state *)state)->efl &= ~0x100;
289 ((struct i386_thread_state *)state)->efl |= trace;
c906108c 290 }
c5aa993b 291
65e78234 292 if (regno >= I386_NUM_GREGS || regno == -1)
da59e081
JM
293 {
294 proc_debug (thread, "storing floating-point registers");
383d750b 295
56be3814 296 store_fpregs (regcache, thread, regno);
da59e081 297 }
c906108c 298}
b4d1e8c7
PA
299
300/* Provide a prototype to silence -Wmissing-prototypes. */
301extern initialize_file_ftype _initialize_i386gnu_nat;
302
303void
304_initialize_i386gnu_nat (void)
305{
306 struct target_ops *t;
307
308 /* Fill in the generic GNU/Hurd methods. */
309 t = gnu_target ();
310
311 t->to_fetch_registers = gnu_fetch_registers;
312 t->to_store_registers = gnu_store_registers;
313
314 /* Register the target. */
315 add_target (t);
316}