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