gas/ChangeLog
[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
SS
35
36#include "gnu-nat.h"
383d750b 37#include "i387-nat.h"
c906108c 38
c906108c 39
da59e081
JM
40/* Offset to the thread_state_t location where REG is stored. */
41#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
c906108c 42
383d750b
MK
43/* At REG_OFFSET[N] is the offset to the thread_state_t location where
44 the GDB register N is stored. */
c5aa993b 45static int reg_offset[] =
c906108c 46{
c5aa993b
JM
47 REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
48 REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
49 REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
50 REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
c906108c
SS
51};
52
da59e081
JM
53#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
54
c906108c 55\f
da59e081
JM
56/* Get the whole floating-point state of THREAD and record the
57 values of the corresponding (pseudo) registers. */
58static void
59fetch_fpregs (struct proc *thread)
c906108c 60{
da59e081
JM
61 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
62 struct i386_float_state state;
da59e081 63 error_t err;
c906108c 64
da59e081
JM
65 err = thread_get_state (thread->port, i386_FLOAT_STATE,
66 (thread_state_t) &state, &count);
67 if (err)
c906108c 68 {
da59e081
JM
69 warning ("Couldn't fetch floating-point state from %s",
70 proc_string (thread));
71 return;
c906108c 72 }
da59e081 73
383d750b 74 if (!state.initialized)
da59e081 75 /* The floating-point state isn't initialized. */
c906108c 76 {
383d750b
MK
77 int i;
78
da59e081
JM
79 for (i = FP0_REGNUM; i <= FP7_REGNUM; i++)
80 supply_register (i, NULL);
383d750b 81 for (i = FCTRL_REGNUM; i <= FOP_REGNUM; i++)
da59e081
JM
82 supply_register (i, NULL);
83
84 return;
c906108c 85 }
da59e081
JM
86
87 /* Supply the floating-point registers. */
383d750b 88 i387_supply_fsave (state.hw_state);
c906108c 89}
da59e081
JM
90
91/* Fetch register REGNO, or all regs if REGNO is -1. */
c906108c 92void
da59e081 93gnu_fetch_registers (int regno)
c906108c
SS
94{
95 struct proc *thread;
c5aa993b 96
da59e081
JM
97 /* Make sure we know about new threads. */
98 inf_update_procs (current_inferior);
c906108c 99
39f77062 100 thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
c5aa993b 101 if (!thread)
da59e081 102 error ("Can't fetch registers from thread %d: No such thread",
39f77062 103 PIDGET (inferior_ptid));
c906108c 104
da59e081 105 if (regno < NUM_GREGS || regno == -1)
c906108c 106 {
da59e081 107 thread_state_t state;
383d750b 108
da59e081
JM
109 /* This does the dirty work for us. */
110 state = proc_get_state (thread, 0);
111 if (!state)
c906108c 112 {
da59e081
JM
113 warning ("Couldn't fetch registers from %s",
114 proc_string (thread));
115 return;
c906108c
SS
116 }
117
da59e081 118 if (regno == -1)
c906108c 119 {
da59e081 120 int i;
383d750b 121
da59e081 122 proc_debug (thread, "fetching all register");
383d750b 123
da59e081
JM
124 for (i = 0; i < NUM_GREGS; i++)
125 supply_register (i, REG_ADDR (state, i));
126 thread->fetched_regs = ~0;
c906108c
SS
127 }
128 else
129 {
da59e081 130 proc_debug (thread, "fetching register %s", REGISTER_NAME (regno));
383d750b 131
da59e081
JM
132 supply_register (regno, REG_ADDR (state, regno));
133 thread->fetched_regs |= (1 << regno);
c906108c
SS
134 }
135 }
da59e081
JM
136
137 if (regno >= NUM_GREGS || regno == -1)
138 {
139 proc_debug (thread, "fetching floating-point registers");
383d750b 140
da59e081
JM
141 fetch_fpregs (thread);
142 }
c906108c
SS
143}
144\f
da59e081
JM
145
146/* Store the whole floating-point state into THREAD using information
147 from the corresponding (pseudo) registers. */
148static void
383d750b 149store_fpregs (struct proc *thread, int regno)
da59e081
JM
150{
151 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
152 struct i386_float_state state;
153 error_t err;
c5aa993b 154
da59e081
JM
155 err = thread_get_state (thread->port, i386_FLOAT_STATE,
156 (thread_state_t) &state, &count);
157 if (err)
c906108c 158 {
da59e081
JM
159 warning ("Couldn't fetch floating-point state from %s",
160 proc_string (thread));
161 return;
c906108c 162 }
c5aa993b 163
383d750b
MK
164 /* FIXME: kettenis/2001-07-15: Is this right? Should we somehow
165 take into account REGISTER_VALID like the old code did? */
166 i387_fill_fsave (state.hw_state, regno);
167
da59e081
JM
168 err = thread_set_state (thread->port, i386_FLOAT_STATE,
169 (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
170 if (err)
c906108c 171 {
da59e081
JM
172 warning ("Couldn't store floating-point state into %s",
173 proc_string (thread));
174 return;
c906108c 175 }
c906108c 176}
c5aa993b 177
da59e081
JM
178/* Store at least register REGNO, or all regs if REGNO == -1. */
179void
180gnu_store_registers (int regno)
c5aa993b 181{
da59e081 182 struct proc *thread;
c906108c 183
da59e081
JM
184 /* Make sure we know about new threads. */
185 inf_update_procs (current_inferior);
c5aa993b 186
39f77062 187 thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
c906108c 188 if (!thread)
da59e081 189 error ("Couldn't store registers into thread %d: No such thread",
39f77062 190 PIDGET (inferior_ptid));
c906108c 191
da59e081 192 if (regno < NUM_GREGS || regno == -1)
c906108c 193 {
da59e081
JM
194 thread_state_t state;
195 thread_state_data_t old_state;
196 int was_aborted = thread->aborted;
197 int was_valid = thread->state_valid;
fb557744 198 int trace;
c906108c 199
da59e081
JM
200 if (!was_aborted && was_valid)
201 memcpy (&old_state, &thread->state, sizeof (old_state));
c906108c 202
da59e081
JM
203 state = proc_get_state (thread, 1);
204 if (!state)
205 {
206 warning ("Couldn't store registers into %s", proc_string (thread));
207 return;
208 }
c906108c 209
fb557744
MK
210 /* Save the T bit. We might try to restore the %eflags register
211 below, but changing the T bit would seriously confuse GDB. */
212 trace = ((struct i386_thread_state *)state)->efl & 0x100;
213
da59e081
JM
214 if (!was_aborted && was_valid)
215 /* See which registers have changed after aborting the thread. */
216 {
217 int check_regno;
218
219 for (check_regno = 0; check_regno < NUM_GREGS; check_regno++)
220 if ((thread->fetched_regs & (1 << check_regno))
221 && memcpy (REG_ADDR (&old_state, check_regno),
222 REG_ADDR (state, check_regno),
223 REGISTER_RAW_SIZE (check_regno)))
224 /* Register CHECK_REGNO has changed! Ack! */
225 {
226 warning ("Register %s changed after the thread was aborted",
227 REGISTER_NAME (check_regno));
228 if (regno >= 0 && regno != check_regno)
383d750b 229 /* Update GDB's copy of the register. */
da59e081
JM
230 supply_register (check_regno, REG_ADDR (state, check_regno));
231 else
232 warning ("... also writing this register! Suspicious...");
233 }
234 }
c906108c 235
da59e081
JM
236#define fill(state, regno) \
237 memcpy (REG_ADDR(state, regno), &registers[REGISTER_BYTE (regno)], \
238 REGISTER_RAW_SIZE (regno))
c906108c 239
da59e081
JM
240 if (regno == -1)
241 {
242 int i;
383d750b 243
da59e081 244 proc_debug (thread, "storing all registers");
c5aa993b 245
da59e081
JM
246 for (i = 0; i < NUM_GREGS; i++)
247 if (register_valid[i])
248 fill (state, i);
249 }
250 else
251 {
252 proc_debug (thread, "storing register %s", REGISTER_NAME (regno));
c906108c 253
780a49fa 254 gdb_assert (register_valid[regno]);
da59e081
JM
255 fill (state, regno);
256 }
fb557744
MK
257
258 /* Restore the T bit. */
259 ((struct i386_thread_state *)state)->efl &= ~0x100;
260 ((struct i386_thread_state *)state)->efl |= trace;
c906108c 261 }
c5aa993b 262
da59e081 263#undef fill
c906108c 264
da59e081
JM
265 if (regno >= NUM_GREGS || regno == -1)
266 {
267 proc_debug (thread, "storing floating-point registers");
383d750b
MK
268
269 store_fpregs (thread, regno);
da59e081 270 }
c906108c 271}
This page took 0.133903 seconds and 4 git commands to generate.