2004-07-21 Andrew Cagney <cagney@gnu.org>
[deliverable/binutils-gdb.git] / gdb / i386gnu-nat.c
CommitLineData
da59e081 1/* Low level interface to i386 running the GNU Hurd.
b6ba6518
KB
2 Copyright 1992, 1995, 1996, 1998, 2000, 2001
3 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
9 the Free Software Foundation; either version 2 of the License, or
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
JM
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
c906108c
SS
21
22#include "defs.h"
23#include "inferior.h"
24#include "floatformat.h"
4e052eda 25#include "regcache.h"
c906108c 26
780a49fa 27#include "gdb_assert.h"
c906108c 28#include <errno.h>
383d750b 29#include <stdio.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
JM
59#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
60
c906108c 61\f
da59e081
JM
62/* Get the whole floating-point state of THREAD and record the
63 values of the corresponding (pseudo) registers. */
64static void
65fetch_fpregs (struct proc *thread)
c906108c 66{
da59e081
JM
67 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
68 struct i386_float_state state;
da59e081 69 error_t err;
c906108c 70
da59e081
JM
71 err = thread_get_state (thread->port, i386_FLOAT_STATE,
72 (thread_state_t) &state, &count);
73 if (err)
c906108c 74 {
da59e081
JM
75 warning ("Couldn't fetch floating-point state from %s",
76 proc_string (thread));
77 return;
c906108c 78 }
da59e081 79
383d750b 80 if (!state.initialized)
da59e081 81 /* The floating-point state isn't initialized. */
c906108c 82 {
383d750b
MK
83 int i;
84
4604bcad 85 for (i = FP0_REGNUM; i <= FOP_REGNUM; i++)
23a6d369 86 regcache_raw_supply (current_regcache, i, NULL);
da59e081
JM
87
88 return;
c906108c 89 }
da59e081
JM
90
91 /* Supply the floating-point registers. */
41d041d6 92 i387_supply_fsave (current_regcache, -1, state.hw_state);
c906108c 93}
da59e081 94
57e76fac
MS
95#ifdef HAVE_SYS_PROCFS_H
96/* These two calls are used by the core-regset.c code for
97 reading ELF core files. */
98void
99supply_gregset (gdb_gregset_t *gregs)
100{
101 int i;
65e78234 102 for (i = 0; i < I386_NUM_GREGS; i++)
23a6d369 103 regcache_raw_supply (current_regcache, i, REG_ADDR (gregs, i));
57e76fac
MS
104}
105
106void
107supply_fpregset (gdb_fpregset_t *fpregs)
108{
41d041d6 109 i387_supply_fsave (current_regcache, -1, fpregs);
57e76fac
MS
110}
111#endif
112
da59e081 113/* Fetch register REGNO, or all regs if REGNO is -1. */
c906108c 114void
da59e081 115gnu_fetch_registers (int regno)
c906108c
SS
116{
117 struct proc *thread;
c5aa993b 118
da59e081
JM
119 /* Make sure we know about new threads. */
120 inf_update_procs (current_inferior);
c906108c 121
39f77062 122 thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
c5aa993b 123 if (!thread)
da59e081 124 error ("Can't fetch registers from thread %d: No such thread",
39f77062 125 PIDGET (inferior_ptid));
c906108c 126
65e78234 127 if (regno < I386_NUM_GREGS || regno == -1)
c906108c 128 {
da59e081 129 thread_state_t state;
383d750b 130
da59e081
JM
131 /* This does the dirty work for us. */
132 state = proc_get_state (thread, 0);
133 if (!state)
c906108c 134 {
da59e081
JM
135 warning ("Couldn't fetch registers from %s",
136 proc_string (thread));
137 return;
c906108c
SS
138 }
139
da59e081 140 if (regno == -1)
c906108c 141 {
da59e081 142 int i;
383d750b 143
da59e081 144 proc_debug (thread, "fetching all register");
383d750b 145
65e78234 146 for (i = 0; i < I386_NUM_GREGS; i++)
23a6d369 147 regcache_raw_supply (current_regcache, i, REG_ADDR (state, i));
da59e081 148 thread->fetched_regs = ~0;
c906108c
SS
149 }
150 else
151 {
da59e081 152 proc_debug (thread, "fetching register %s", REGISTER_NAME (regno));
383d750b 153
23a6d369
AC
154 regcache_raw_supply (current_regcache, regno,
155 REG_ADDR (state, regno));
da59e081 156 thread->fetched_regs |= (1 << regno);
c906108c
SS
157 }
158 }
da59e081 159
65e78234 160 if (regno >= I386_NUM_GREGS || regno == -1)
da59e081
JM
161 {
162 proc_debug (thread, "fetching floating-point registers");
383d750b 163
da59e081
JM
164 fetch_fpregs (thread);
165 }
c906108c
SS
166}
167\f
da59e081
JM
168
169/* Store the whole floating-point state into THREAD using information
170 from the corresponding (pseudo) registers. */
171static void
383d750b 172store_fpregs (struct proc *thread, int regno)
da59e081
JM
173{
174 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
175 struct i386_float_state state;
176 error_t err;
c5aa993b 177
da59e081
JM
178 err = thread_get_state (thread->port, i386_FLOAT_STATE,
179 (thread_state_t) &state, &count);
180 if (err)
c906108c 181 {
da59e081
JM
182 warning ("Couldn't fetch floating-point state from %s",
183 proc_string (thread));
184 return;
c906108c 185 }
c5aa993b 186
383d750b 187 /* FIXME: kettenis/2001-07-15: Is this right? Should we somehow
8262ee23 188 take into account DEPRECATED_REGISTER_VALID like the old code did? */
383d750b
MK
189 i387_fill_fsave (state.hw_state, regno);
190
da59e081
JM
191 err = thread_set_state (thread->port, i386_FLOAT_STATE,
192 (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
193 if (err)
c906108c 194 {
da59e081
JM
195 warning ("Couldn't store floating-point state into %s",
196 proc_string (thread));
197 return;
c906108c 198 }
c906108c 199}
c5aa993b 200
da59e081
JM
201/* Store at least register REGNO, or all regs if REGNO == -1. */
202void
203gnu_store_registers (int regno)
c5aa993b 204{
da59e081 205 struct proc *thread;
c906108c 206
da59e081
JM
207 /* Make sure we know about new threads. */
208 inf_update_procs (current_inferior);
c5aa993b 209
39f77062 210 thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
c906108c 211 if (!thread)
da59e081 212 error ("Couldn't store registers into thread %d: No such thread",
39f77062 213 PIDGET (inferior_ptid));
c906108c 214
65e78234 215 if (regno < I386_NUM_GREGS || regno == -1)
c906108c 216 {
da59e081
JM
217 thread_state_t state;
218 thread_state_data_t old_state;
219 int was_aborted = thread->aborted;
220 int was_valid = thread->state_valid;
fb557744 221 int trace;
c906108c 222
da59e081
JM
223 if (!was_aborted && was_valid)
224 memcpy (&old_state, &thread->state, sizeof (old_state));
c906108c 225
da59e081
JM
226 state = proc_get_state (thread, 1);
227 if (!state)
228 {
229 warning ("Couldn't store registers into %s", proc_string (thread));
230 return;
231 }
c906108c 232
fb557744
MK
233 /* Save the T bit. We might try to restore the %eflags register
234 below, but changing the T bit would seriously confuse GDB. */
235 trace = ((struct i386_thread_state *)state)->efl & 0x100;
236
da59e081
JM
237 if (!was_aborted && was_valid)
238 /* See which registers have changed after aborting the thread. */
239 {
240 int check_regno;
241
65e78234 242 for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++)
da59e081
JM
243 if ((thread->fetched_regs & (1 << check_regno))
244 && memcpy (REG_ADDR (&old_state, check_regno),
245 REG_ADDR (state, check_regno),
12c266ea 246 DEPRECATED_REGISTER_RAW_SIZE (check_regno)))
da59e081
JM
247 /* Register CHECK_REGNO has changed! Ack! */
248 {
249 warning ("Register %s changed after the thread was aborted",
250 REGISTER_NAME (check_regno));
251 if (regno >= 0 && regno != check_regno)
383d750b 252 /* Update GDB's copy of the register. */
23a6d369
AC
253 regcache_raw_supply (current_regcache, check_regno,
254 REG_ADDR (state, check_regno));
da59e081
JM
255 else
256 warning ("... also writing this register! Suspicious...");
257 }
258 }
c906108c 259
da59e081 260#define fill(state, regno) \
62700349 261 memcpy (REG_ADDR(state, regno), &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)], \
12c266ea 262 DEPRECATED_REGISTER_RAW_SIZE (regno))
c906108c 263
da59e081
JM
264 if (regno == -1)
265 {
266 int i;
383d750b 267
da59e081 268 proc_debug (thread, "storing all registers");
c5aa993b 269
65e78234 270 for (i = 0; i < I386_NUM_GREGS; i++)
8262ee23 271 if (deprecated_register_valid[i])
da59e081
JM
272 fill (state, i);
273 }
274 else
275 {
276 proc_debug (thread, "storing register %s", REGISTER_NAME (regno));
c906108c 277
8262ee23 278 gdb_assert (deprecated_register_valid[regno]);
da59e081
JM
279 fill (state, regno);
280 }
fb557744
MK
281
282 /* Restore the T bit. */
283 ((struct i386_thread_state *)state)->efl &= ~0x100;
284 ((struct i386_thread_state *)state)->efl |= trace;
c906108c 285 }
c5aa993b 286
da59e081 287#undef fill
c906108c 288
65e78234 289 if (regno >= I386_NUM_GREGS || regno == -1)
da59e081
JM
290 {
291 proc_debug (thread, "storing floating-point registers");
383d750b
MK
292
293 store_fpregs (thread, regno);
da59e081 294 }
c906108c 295}
This page took 0.386358 seconds and 4 git commands to generate.