]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/i386gnu-nat.c
Phase 1 of the ptid_t changes.
[thirdparty/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
SS
28#include <stdio.h>
29#include <errno.h>
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"
37
da59e081
JM
38/* The FPU hardware state. */
39struct env387
40{
41 unsigned short control;
42 unsigned short r0;
43 unsigned short status;
44 unsigned short r1;
45 unsigned short tag;
46 unsigned short r2;
47 unsigned long eip;
48 unsigned short code_seg;
49 unsigned short opcode;
50 unsigned long operand;
51 unsigned short operand_seg;
52 unsigned short r3;
53 unsigned char regs[8][10];
54};
c906108c 55
c906108c 56\f
da59e081
JM
57/* Offset to the thread_state_t location where REG is stored. */
58#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
c906108c 59
da59e081
JM
60/* At reg_offset[i] is the offset to the thread_state_t location where
61 the gdb registers[i] is stored. */
c5aa993b 62static int reg_offset[] =
c906108c 63{
c5aa993b
JM
64 REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
65 REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
66 REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
67 REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
c906108c
SS
68};
69
da59e081
JM
70#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
71
c906108c 72\f
da59e081
JM
73/* Get the whole floating-point state of THREAD and record the
74 values of the corresponding (pseudo) registers. */
75static void
76fetch_fpregs (struct proc *thread)
c906108c 77{
da59e081
JM
78 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
79 struct i386_float_state state;
80 struct env387 *ep = (struct env387 *) state.hw_state;
81 error_t err;
82 int i;
c906108c 83
da59e081
JM
84 err = thread_get_state (thread->port, i386_FLOAT_STATE,
85 (thread_state_t) &state, &count);
86 if (err)
c906108c 87 {
da59e081
JM
88 warning ("Couldn't fetch floating-point state from %s",
89 proc_string (thread));
90 return;
c906108c 91 }
da59e081
JM
92
93 if (! state.initialized)
94 /* The floating-point state isn't initialized. */
c906108c 95 {
da59e081
JM
96 for (i = FP0_REGNUM; i <= FP7_REGNUM; i++)
97 supply_register (i, NULL);
98 for (i = FIRST_FPU_CTRL_REGNUM; i <= LAST_FPU_CTRL_REGNUM; i++)
99 supply_register (i, NULL);
100
101 return;
c906108c 102 }
da59e081
JM
103
104 /* Supply the floating-point registers. */
105 for (i = 0; i < 8; i++)
106 supply_register (FP0_REGNUM + i, ep->regs[i]);
107
108 supply_register (FCTRL_REGNUM, (char *) &ep->control);
109 supply_register (FSTAT_REGNUM, (char *) &ep->status);
110 supply_register (FTAG_REGNUM, (char *) &ep->tag);
111 supply_register (FCOFF_REGNUM, (char *) &ep->eip);
112 supply_register (FDS_REGNUM, (char *) &ep->operand_seg);
113 supply_register (FDOFF_REGNUM, (char *) &ep->operand);
114
115 /* Store the code segment and opcode pseudo registers. */
116 {
117 long l;
118
119 l = ep->code_seg;
120 supply_register (FCS_REGNUM, (char *) &l);
121 l = ep->opcode & ((1 << 11) - 1);
122 supply_register (FOP_REGNUM, (char *) &l);
123 }
c906108c 124}
da59e081
JM
125
126/* Fetch register REGNO, or all regs if REGNO is -1. */
c906108c 127void
da59e081 128gnu_fetch_registers (int regno)
c906108c
SS
129{
130 struct proc *thread;
c5aa993b 131
da59e081
JM
132 /* Make sure we know about new threads. */
133 inf_update_procs (current_inferior);
c906108c 134
39f77062 135 thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
c5aa993b 136 if (!thread)
da59e081 137 error ("Can't fetch registers from thread %d: No such thread",
39f77062 138 PIDGET (inferior_ptid));
c906108c 139
da59e081 140 if (regno < NUM_GREGS || regno == -1)
c906108c 141 {
da59e081
JM
142 thread_state_t state;
143
144 /* This does the dirty work for us. */
145 state = proc_get_state (thread, 0);
146 if (!state)
c906108c 147 {
da59e081
JM
148 warning ("Couldn't fetch registers from %s",
149 proc_string (thread));
150 return;
c906108c
SS
151 }
152
da59e081 153 if (regno == -1)
c906108c 154 {
da59e081
JM
155 int i;
156
157 proc_debug (thread, "fetching all register");
158
159 for (i = 0; i < NUM_GREGS; i++)
160 supply_register (i, REG_ADDR (state, i));
161 thread->fetched_regs = ~0;
c906108c
SS
162 }
163 else
164 {
da59e081
JM
165 proc_debug (thread, "fetching register %s", REGISTER_NAME (regno));
166
167 supply_register (regno, REG_ADDR (state, regno));
168 thread->fetched_regs |= (1 << regno);
c906108c
SS
169 }
170 }
da59e081
JM
171
172 if (regno >= NUM_GREGS || regno == -1)
173 {
174 proc_debug (thread, "fetching floating-point registers");
175
176 fetch_fpregs (thread);
177 }
c906108c 178}
da59e081 179
c906108c 180\f
da59e081
JM
181/* Fill the i387 hardware state EP with selected data from the set of
182 (pseudo) registers specified by REGS and VALID. VALID is an array
183 indicating which registers in REGS are valid. If VALID is zero,
184 all registers are assumed to be valid. */
185static void
186convert_to_env387 (struct env387 *ep, char *regs, signed char *valid)
c906108c
SS
187{
188 int i;
c5aa993b 189
da59e081
JM
190 /* Fill in the floating-point registers. */
191 for (i = 0; i < 8; i++)
192 if (!valid || valid[i])
193 memcpy (ep->regs[i], &regs[REGISTER_BYTE (FP0_REGNUM + i)],
194 REGISTER_RAW_SIZE (FP0_REGNUM + i));
195
196#define fill(member, regno) \
197 if (!valid || valid[(regno)]) \
198 memcpy (&ep->member, &regs[REGISTER_BYTE (regno)], \
199 sizeof (ep->member));
200
201 fill (control, FCTRL_REGNUM);
202 fill (status, FSTAT_REGNUM);
203 fill (tag, FTAG_REGNUM);
204 fill (eip, FCOFF_REGNUM);
205 fill (operand, FDOFF_REGNUM);
206 fill (operand_seg, FDS_REGNUM);
207
208#undef fill
209
210 if (!valid || valid[FCS_REGNUM])
211 ep->code_seg =
212 (* (int *) &registers[REGISTER_BYTE (FCS_REGNUM)] & 0xffff);
213
214 if (!valid || valid[FOP_REGNUM])
215 ep->opcode =
216 ((* (int *) &registers[REGISTER_BYTE (FOP_REGNUM)] & ((1 << 11) - 1)));
217}
218
219/* Store the whole floating-point state into THREAD using information
220 from the corresponding (pseudo) registers. */
221static void
222store_fpregs (struct proc *thread)
223{
224 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
225 struct i386_float_state state;
226 error_t err;
c5aa993b 227
da59e081
JM
228 err = thread_get_state (thread->port, i386_FLOAT_STATE,
229 (thread_state_t) &state, &count);
230 if (err)
c906108c 231 {
da59e081
JM
232 warning ("Couldn't fetch floating-point state from %s",
233 proc_string (thread));
234 return;
c906108c 235 }
c5aa993b 236
da59e081
JM
237 convert_to_env387 ((struct env387 *) state.hw_state,
238 registers, register_valid);
239
240 err = thread_set_state (thread->port, i386_FLOAT_STATE,
241 (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
242 if (err)
c906108c 243 {
da59e081
JM
244 warning ("Couldn't store floating-point state into %s",
245 proc_string (thread));
246 return;
c906108c 247 }
c906108c 248}
c5aa993b 249
da59e081
JM
250/* Store at least register REGNO, or all regs if REGNO == -1. */
251void
252gnu_store_registers (int regno)
c5aa993b 253{
da59e081 254 struct proc *thread;
c906108c 255
da59e081
JM
256 /* Make sure we know about new threads. */
257 inf_update_procs (current_inferior);
c5aa993b 258
39f77062 259 thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
c906108c 260 if (!thread)
da59e081 261 error ("Couldn't store registers into thread %d: No such thread",
39f77062 262 PIDGET (inferior_ptid));
c906108c 263
da59e081 264 if (regno < NUM_GREGS || regno == -1)
c906108c 265 {
da59e081
JM
266 thread_state_t state;
267 thread_state_data_t old_state;
268 int was_aborted = thread->aborted;
269 int was_valid = thread->state_valid;
fb557744 270 int trace;
c906108c 271
da59e081
JM
272 if (!was_aborted && was_valid)
273 memcpy (&old_state, &thread->state, sizeof (old_state));
c906108c 274
da59e081
JM
275 state = proc_get_state (thread, 1);
276 if (!state)
277 {
278 warning ("Couldn't store registers into %s", proc_string (thread));
279 return;
280 }
c906108c 281
fb557744
MK
282 /* Save the T bit. We might try to restore the %eflags register
283 below, but changing the T bit would seriously confuse GDB. */
284 trace = ((struct i386_thread_state *)state)->efl & 0x100;
285
da59e081
JM
286 if (!was_aborted && was_valid)
287 /* See which registers have changed after aborting the thread. */
288 {
289 int check_regno;
290
291 for (check_regno = 0; check_regno < NUM_GREGS; check_regno++)
292 if ((thread->fetched_regs & (1 << check_regno))
293 && memcpy (REG_ADDR (&old_state, check_regno),
294 REG_ADDR (state, check_regno),
295 REGISTER_RAW_SIZE (check_regno)))
296 /* Register CHECK_REGNO has changed! Ack! */
297 {
298 warning ("Register %s changed after the thread was aborted",
299 REGISTER_NAME (check_regno));
300 if (regno >= 0 && regno != check_regno)
301 /* Update gdb's copy of the register. */
302 supply_register (check_regno, REG_ADDR (state, check_regno));
303 else
304 warning ("... also writing this register! Suspicious...");
305 }
306 }
c906108c 307
da59e081
JM
308#define fill(state, regno) \
309 memcpy (REG_ADDR(state, regno), &registers[REGISTER_BYTE (regno)], \
310 REGISTER_RAW_SIZE (regno))
c906108c 311
da59e081
JM
312 if (regno == -1)
313 {
314 int i;
315
316 proc_debug (thread, "storing all registers");
c5aa993b 317
da59e081
JM
318 for (i = 0; i < NUM_GREGS; i++)
319 if (register_valid[i])
320 fill (state, i);
321 }
322 else
323 {
324 proc_debug (thread, "storing register %s", REGISTER_NAME (regno));
c906108c 325
780a49fa 326 gdb_assert (register_valid[regno]);
da59e081
JM
327 fill (state, regno);
328 }
fb557744
MK
329
330 /* Restore the T bit. */
331 ((struct i386_thread_state *)state)->efl &= ~0x100;
332 ((struct i386_thread_state *)state)->efl |= trace;
c906108c 333 }
c5aa993b 334
da59e081 335#undef fill
c906108c 336
da59e081
JM
337 if (regno >= NUM_GREGS || regno == -1)
338 {
339 proc_debug (thread, "storing floating-point registers");
340
341 store_fpregs (thread);
342 }
c906108c 343}