Phase 1 of the ptid_t changes.
[deliverable/binutils-gdb.git] / gdb / i386gnu-nat.c
1 /* Low level interface to i386 running the GNU Hurd.
2 Copyright 1992, 1995, 1996, 1998, 2000, 2001
3 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
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.
11
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.
16
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. */
21
22 #include "defs.h"
23 #include "inferior.h"
24 #include "floatformat.h"
25 #include "regcache.h"
26
27 #include "gdb_assert.h"
28 #include <stdio.h>
29 #include <errno.h>
30
31 #include <mach.h>
32 #include <mach_error.h>
33 #include <mach/message.h>
34 #include <mach/exception.h>
35
36 #include "gnu-nat.h"
37
38 /* The FPU hardware state. */
39 struct 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 };
55
56 \f
57 /* Offset to the thread_state_t location where REG is stored. */
58 #define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
59
60 /* At reg_offset[i] is the offset to the thread_state_t location where
61 the gdb registers[i] is stored. */
62 static int reg_offset[] =
63 {
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)
68 };
69
70 #define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
71
72 \f
73 /* Get the whole floating-point state of THREAD and record the
74 values of the corresponding (pseudo) registers. */
75 static void
76 fetch_fpregs (struct proc *thread)
77 {
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;
83
84 err = thread_get_state (thread->port, i386_FLOAT_STATE,
85 (thread_state_t) &state, &count);
86 if (err)
87 {
88 warning ("Couldn't fetch floating-point state from %s",
89 proc_string (thread));
90 return;
91 }
92
93 if (! state.initialized)
94 /* The floating-point state isn't initialized. */
95 {
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;
102 }
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 }
124 }
125
126 /* Fetch register REGNO, or all regs if REGNO is -1. */
127 void
128 gnu_fetch_registers (int regno)
129 {
130 struct proc *thread;
131
132 /* Make sure we know about new threads. */
133 inf_update_procs (current_inferior);
134
135 thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
136 if (!thread)
137 error ("Can't fetch registers from thread %d: No such thread",
138 PIDGET (inferior_ptid));
139
140 if (regno < NUM_GREGS || regno == -1)
141 {
142 thread_state_t state;
143
144 /* This does the dirty work for us. */
145 state = proc_get_state (thread, 0);
146 if (!state)
147 {
148 warning ("Couldn't fetch registers from %s",
149 proc_string (thread));
150 return;
151 }
152
153 if (regno == -1)
154 {
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;
162 }
163 else
164 {
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);
169 }
170 }
171
172 if (regno >= NUM_GREGS || regno == -1)
173 {
174 proc_debug (thread, "fetching floating-point registers");
175
176 fetch_fpregs (thread);
177 }
178 }
179
180 \f
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. */
185 static void
186 convert_to_env387 (struct env387 *ep, char *regs, signed char *valid)
187 {
188 int i;
189
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. */
221 static void
222 store_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;
227
228 err = thread_get_state (thread->port, i386_FLOAT_STATE,
229 (thread_state_t) &state, &count);
230 if (err)
231 {
232 warning ("Couldn't fetch floating-point state from %s",
233 proc_string (thread));
234 return;
235 }
236
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)
243 {
244 warning ("Couldn't store floating-point state into %s",
245 proc_string (thread));
246 return;
247 }
248 }
249
250 /* Store at least register REGNO, or all regs if REGNO == -1. */
251 void
252 gnu_store_registers (int regno)
253 {
254 struct proc *thread;
255
256 /* Make sure we know about new threads. */
257 inf_update_procs (current_inferior);
258
259 thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
260 if (!thread)
261 error ("Couldn't store registers into thread %d: No such thread",
262 PIDGET (inferior_ptid));
263
264 if (regno < NUM_GREGS || regno == -1)
265 {
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;
270 int trace;
271
272 if (!was_aborted && was_valid)
273 memcpy (&old_state, &thread->state, sizeof (old_state));
274
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 }
281
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
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 }
307
308 #define fill(state, regno) \
309 memcpy (REG_ADDR(state, regno), &registers[REGISTER_BYTE (regno)], \
310 REGISTER_RAW_SIZE (regno))
311
312 if (regno == -1)
313 {
314 int i;
315
316 proc_debug (thread, "storing all registers");
317
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));
325
326 gdb_assert (register_valid[regno]);
327 fill (state, regno);
328 }
329
330 /* Restore the T bit. */
331 ((struct i386_thread_state *)state)->efl &= ~0x100;
332 ((struct i386_thread_state *)state)->efl |= trace;
333 }
334
335 #undef fill
336
337 if (regno >= NUM_GREGS || regno == -1)
338 {
339 proc_debug (thread, "storing floating-point registers");
340
341 store_fpregs (thread);
342 }
343 }
This page took 0.036463 seconds and 4 git commands to generate.