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