* i386-linux-nat.c (OLD_CANNOT_FETCH_REGISTER,
[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++)
da59e081
JM
86 supply_register (i, NULL);
87
88 return;
c906108c 89 }
da59e081
JM
90
91 /* Supply the floating-point registers. */
383d750b 92 i387_supply_fsave (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;
102 for (i = 0; i < NUM_GREGS; i++)
103 supply_register (i, REG_ADDR (gregs, i));
104}
105
106void
107supply_fpregset (gdb_fpregset_t *fpregs)
108{
109 i387_supply_fsave ((char *) fpregs);
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
da59e081 127 if (regno < 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
da59e081
JM
146 for (i = 0; i < NUM_GREGS; i++)
147 supply_register (i, REG_ADDR (state, i));
148 thread->fetched_regs = ~0;
c906108c
SS
149 }
150 else
151 {
da59e081 152 proc_debug (thread, "fetching register %s", REGISTER_NAME (regno));
383d750b 153
da59e081
JM
154 supply_register (regno, REG_ADDR (state, regno));
155 thread->fetched_regs |= (1 << regno);
c906108c
SS
156 }
157 }
da59e081
JM
158
159 if (regno >= NUM_GREGS || regno == -1)
160 {
161 proc_debug (thread, "fetching floating-point registers");
383d750b 162
da59e081
JM
163 fetch_fpregs (thread);
164 }
c906108c
SS
165}
166\f
da59e081
JM
167
168/* Store the whole floating-point state into THREAD using information
169 from the corresponding (pseudo) registers. */
170static void
383d750b 171store_fpregs (struct proc *thread, int regno)
da59e081
JM
172{
173 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
174 struct i386_float_state state;
175 error_t err;
c5aa993b 176
da59e081
JM
177 err = thread_get_state (thread->port, i386_FLOAT_STATE,
178 (thread_state_t) &state, &count);
179 if (err)
c906108c 180 {
da59e081
JM
181 warning ("Couldn't fetch floating-point state from %s",
182 proc_string (thread));
183 return;
c906108c 184 }
c5aa993b 185
383d750b
MK
186 /* FIXME: kettenis/2001-07-15: Is this right? Should we somehow
187 take into account REGISTER_VALID like the old code did? */
188 i387_fill_fsave (state.hw_state, regno);
189
da59e081
JM
190 err = thread_set_state (thread->port, i386_FLOAT_STATE,
191 (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
192 if (err)
c906108c 193 {
da59e081
JM
194 warning ("Couldn't store floating-point state into %s",
195 proc_string (thread));
196 return;
c906108c 197 }
c906108c 198}
c5aa993b 199
da59e081
JM
200/* Store at least register REGNO, or all regs if REGNO == -1. */
201void
202gnu_store_registers (int regno)
c5aa993b 203{
da59e081 204 struct proc *thread;
c906108c 205
da59e081
JM
206 /* Make sure we know about new threads. */
207 inf_update_procs (current_inferior);
c5aa993b 208
39f77062 209 thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
c906108c 210 if (!thread)
da59e081 211 error ("Couldn't store registers into thread %d: No such thread",
39f77062 212 PIDGET (inferior_ptid));
c906108c 213
da59e081 214 if (regno < NUM_GREGS || regno == -1)
c906108c 215 {
da59e081
JM
216 thread_state_t state;
217 thread_state_data_t old_state;
218 int was_aborted = thread->aborted;
219 int was_valid = thread->state_valid;
fb557744 220 int trace;
c906108c 221
da59e081
JM
222 if (!was_aborted && was_valid)
223 memcpy (&old_state, &thread->state, sizeof (old_state));
c906108c 224
da59e081
JM
225 state = proc_get_state (thread, 1);
226 if (!state)
227 {
228 warning ("Couldn't store registers into %s", proc_string (thread));
229 return;
230 }
c906108c 231
fb557744
MK
232 /* Save the T bit. We might try to restore the %eflags register
233 below, but changing the T bit would seriously confuse GDB. */
234 trace = ((struct i386_thread_state *)state)->efl & 0x100;
235
da59e081
JM
236 if (!was_aborted && was_valid)
237 /* See which registers have changed after aborting the thread. */
238 {
239 int check_regno;
240
241 for (check_regno = 0; check_regno < NUM_GREGS; check_regno++)
242 if ((thread->fetched_regs & (1 << check_regno))
243 && memcpy (REG_ADDR (&old_state, check_regno),
244 REG_ADDR (state, check_regno),
245 REGISTER_RAW_SIZE (check_regno)))
246 /* Register CHECK_REGNO has changed! Ack! */
247 {
248 warning ("Register %s changed after the thread was aborted",
249 REGISTER_NAME (check_regno));
250 if (regno >= 0 && regno != check_regno)
383d750b 251 /* Update GDB's copy of the register. */
da59e081
JM
252 supply_register (check_regno, REG_ADDR (state, check_regno));
253 else
254 warning ("... also writing this register! Suspicious...");
255 }
256 }
c906108c 257
da59e081
JM
258#define fill(state, regno) \
259 memcpy (REG_ADDR(state, regno), &registers[REGISTER_BYTE (regno)], \
260 REGISTER_RAW_SIZE (regno))
c906108c 261
da59e081
JM
262 if (regno == -1)
263 {
264 int i;
383d750b 265
da59e081 266 proc_debug (thread, "storing all registers");
c5aa993b 267
da59e081
JM
268 for (i = 0; i < NUM_GREGS; i++)
269 if (register_valid[i])
270 fill (state, i);
271 }
272 else
273 {
274 proc_debug (thread, "storing register %s", REGISTER_NAME (regno));
c906108c 275
780a49fa 276 gdb_assert (register_valid[regno]);
da59e081
JM
277 fill (state, regno);
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
da59e081 285#undef fill
c906108c 286
da59e081
JM
287 if (regno >= NUM_GREGS || regno == -1)
288 {
289 proc_debug (thread, "storing floating-point registers");
383d750b
MK
290
291 store_fpregs (thread, regno);
da59e081 292 }
c906108c 293}
This page took 0.19116 seconds and 4 git commands to generate.