PowerPC64 ELFv2 ABI: base support
[deliverable/binutils-gdb.git] / gdb / i386gnu-nat.c
CommitLineData
da59e081 1/* Low level interface to i386 running the GNU Hurd.
f6052080 2
ecd75fc8 3 Copyright (C) 1992-2014 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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
c5aa993b 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 17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
19
20#include "defs.h"
21#include "inferior.h"
22#include "floatformat.h"
4e052eda 23#include "regcache.h"
c906108c 24
780a49fa 25#include "gdb_assert.h"
c906108c 26#include <errno.h>
383d750b 27#include <stdio.h>
0e9f083f 28#include <string.h>
c906108c
SS
29
30#include <mach.h>
da59e081 31#include <mach_error.h>
c906108c
SS
32#include <mach/message.h>
33#include <mach/exception.h>
c906108c 34
4604bcad
MK
35#include "i386-tdep.h"
36
c906108c 37#include "gnu-nat.h"
e750d25e 38#include "i387-tdep.h"
c906108c 39
57e76fac
MS
40#ifdef HAVE_SYS_PROCFS_H
41# include <sys/procfs.h>
42# include "gregset.h"
43#endif
c906108c 44
da59e081
JM
45/* Offset to the thread_state_t location where REG is stored. */
46#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
c906108c 47
383d750b
MK
48/* At REG_OFFSET[N] is the offset to the thread_state_t location where
49 the GDB register N is stored. */
c5aa993b 50static int reg_offset[] =
c906108c 51{
c5aa993b
JM
52 REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
53 REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
54 REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
55 REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
c906108c
SS
56};
57
ecccb813
TS
58/* Offset to the greg_t location where REG is stored. */
59#define CREG_OFFSET(reg) (REG_##reg * 4)
60
61/* At CREG_OFFSET[N] is the offset to the greg_t location where
62 the GDB register N is stored. */
63static int creg_offset[] =
64{
65 CREG_OFFSET (EAX), CREG_OFFSET (ECX), CREG_OFFSET (EDX), CREG_OFFSET (EBX),
66 CREG_OFFSET (UESP), CREG_OFFSET (EBP), CREG_OFFSET (ESI), CREG_OFFSET (EDI),
67 CREG_OFFSET (EIP), CREG_OFFSET (EFL), CREG_OFFSET (CS), CREG_OFFSET (SS),
68 CREG_OFFSET (DS), CREG_OFFSET (ES), CREG_OFFSET (FS), CREG_OFFSET (GS)
69};
70
da59e081 71#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
ecccb813 72#define CREG_ADDR(state, regnum) ((const char *)(state) + creg_offset[regnum])
da59e081 73
c906108c 74\f
3303a276
MK
75/* Get the whole floating-point state of THREAD and record the values
76 of the corresponding (pseudo) registers. */
77
da59e081 78static void
56be3814 79fetch_fpregs (struct regcache *regcache, struct proc *thread)
c906108c 80{
da59e081
JM
81 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
82 struct i386_float_state state;
da59e081 83 error_t err;
c906108c 84
da59e081
JM
85 err = thread_get_state (thread->port, i386_FLOAT_STATE,
86 (thread_state_t) &state, &count);
87 if (err)
c906108c 88 {
8a3fe4f8 89 warning (_("Couldn't fetch floating-point state from %s"),
da59e081
JM
90 proc_string (thread));
91 return;
c906108c 92 }
da59e081 93
383d750b 94 if (!state.initialized)
c906108c 95 {
3303a276 96 /* The floating-point state isn't initialized. */
56be3814 97 i387_supply_fsave (regcache, -1, NULL);
3303a276
MK
98 }
99 else
100 {
101 /* Supply the floating-point registers. */
56be3814 102 i387_supply_fsave (regcache, -1, state.hw_state);
c906108c
SS
103 }
104}
da59e081 105
57e76fac
MS
106#ifdef HAVE_SYS_PROCFS_H
107/* These two calls are used by the core-regset.c code for
108 reading ELF core files. */
109void
7f7fe91e 110supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregs)
57e76fac
MS
111{
112 int i;
65e78234 113 for (i = 0; i < I386_NUM_GREGS; i++)
7f7fe91e 114 regcache_raw_supply (regcache, i, CREG_ADDR (gregs, i));
57e76fac
MS
115}
116
117void
7f7fe91e 118supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregs)
57e76fac 119{
7f7fe91e 120 i387_supply_fsave (regcache, -1, fpregs);
57e76fac
MS
121}
122#endif
123
da59e081 124/* Fetch register REGNO, or all regs if REGNO is -1. */
b4d1e8c7 125static void
85a772a5
TS
126gnu_fetch_registers (struct target_ops *ops,
127 struct regcache *regcache, int regno)
c906108c
SS
128{
129 struct proc *thread;
c5aa993b 130
da59e081 131 /* Make sure we know about new threads. */
c289427b 132 inf_update_procs (gnu_current_inf);
c906108c 133
c289427b 134 thread = inf_tid_to_thread (gnu_current_inf,
ca08a94c 135 ptid_get_lwp (inferior_ptid));
c5aa993b 136 if (!thread)
617fd3b5
PA
137 error (_("Can't fetch registers from thread %s: No such thread"),
138 target_pid_to_str (inferior_ptid));
c906108c 139
65e78234 140 if (regno < I386_NUM_GREGS || regno == -1)
c906108c 141 {
da59e081 142 thread_state_t state;
383d750b 143
da59e081
JM
144 /* This does the dirty work for us. */
145 state = proc_get_state (thread, 0);
146 if (!state)
c906108c 147 {
8a3fe4f8 148 warning (_("Couldn't fetch registers from %s"),
da59e081
JM
149 proc_string (thread));
150 return;
c906108c
SS
151 }
152
da59e081 153 if (regno == -1)
c906108c 154 {
da59e081 155 int i;
383d750b 156
da59e081 157 proc_debug (thread, "fetching all register");
383d750b 158
65e78234 159 for (i = 0; i < I386_NUM_GREGS; i++)
56be3814 160 regcache_raw_supply (regcache, i, REG_ADDR (state, i));
da59e081 161 thread->fetched_regs = ~0;
c906108c
SS
162 }
163 else
164 {
c9f4d572 165 proc_debug (thread, "fetching register %s",
875f8d0e
UW
166 gdbarch_register_name (get_regcache_arch (regcache),
167 regno));
383d750b 168
56be3814 169 regcache_raw_supply (regcache, regno,
23a6d369 170 REG_ADDR (state, regno));
da59e081 171 thread->fetched_regs |= (1 << regno);
c906108c
SS
172 }
173 }
da59e081 174
65e78234 175 if (regno >= I386_NUM_GREGS || regno == -1)
da59e081
JM
176 {
177 proc_debug (thread, "fetching floating-point registers");
383d750b 178
56be3814 179 fetch_fpregs (regcache, thread);
da59e081 180 }
c906108c
SS
181}
182\f
da59e081
JM
183
184/* Store the whole floating-point state into THREAD using information
185 from the corresponding (pseudo) registers. */
186static void
56be3814 187store_fpregs (const struct regcache *regcache, struct proc *thread, int regno)
da59e081
JM
188{
189 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
190 struct i386_float_state state;
191 error_t err;
c5aa993b 192
da59e081
JM
193 err = thread_get_state (thread->port, i386_FLOAT_STATE,
194 (thread_state_t) &state, &count);
195 if (err)
c906108c 196 {
8a3fe4f8 197 warning (_("Couldn't fetch floating-point state from %s"),
da59e081
JM
198 proc_string (thread));
199 return;
c906108c 200 }
c5aa993b 201
383d750b 202 /* FIXME: kettenis/2001-07-15: Is this right? Should we somehow
8262ee23 203 take into account DEPRECATED_REGISTER_VALID like the old code did? */
56be3814 204 i387_collect_fsave (regcache, regno, state.hw_state);
383d750b 205
da59e081
JM
206 err = thread_set_state (thread->port, i386_FLOAT_STATE,
207 (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
208 if (err)
c906108c 209 {
8a3fe4f8 210 warning (_("Couldn't store floating-point state into %s"),
da59e081
JM
211 proc_string (thread));
212 return;
c906108c 213 }
c906108c 214}
c5aa993b 215
da59e081 216/* Store at least register REGNO, or all regs if REGNO == -1. */
b4d1e8c7 217static void
85a772a5
TS
218gnu_store_registers (struct target_ops *ops,
219 struct regcache *regcache, int regno)
c5aa993b 220{
da59e081 221 struct proc *thread;
875f8d0e 222 struct gdbarch *gdbarch = get_regcache_arch (regcache);
c906108c 223
da59e081 224 /* Make sure we know about new threads. */
c289427b 225 inf_update_procs (gnu_current_inf);
c5aa993b 226
c289427b 227 thread = inf_tid_to_thread (gnu_current_inf,
ca08a94c 228 ptid_get_lwp (inferior_ptid));
c906108c 229 if (!thread)
617fd3b5
PA
230 error (_("Couldn't store registers into thread %s: No such thread"),
231 target_pid_to_str (inferior_ptid));
c906108c 232
65e78234 233 if (regno < I386_NUM_GREGS || regno == -1)
c906108c 234 {
da59e081
JM
235 thread_state_t state;
236 thread_state_data_t old_state;
237 int was_aborted = thread->aborted;
238 int was_valid = thread->state_valid;
fb557744 239 int trace;
c906108c 240
da59e081
JM
241 if (!was_aborted && was_valid)
242 memcpy (&old_state, &thread->state, sizeof (old_state));
c906108c 243
da59e081
JM
244 state = proc_get_state (thread, 1);
245 if (!state)
246 {
1777feb0
MS
247 warning (_("Couldn't store registers into %s"),
248 proc_string (thread));
da59e081
JM
249 return;
250 }
c906108c 251
fb557744
MK
252 /* Save the T bit. We might try to restore the %eflags register
253 below, but changing the T bit would seriously confuse GDB. */
254 trace = ((struct i386_thread_state *)state)->efl & 0x100;
255
da59e081
JM
256 if (!was_aborted && was_valid)
257 /* See which registers have changed after aborting the thread. */
258 {
259 int check_regno;
260
65e78234 261 for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++)
da59e081
JM
262 if ((thread->fetched_regs & (1 << check_regno))
263 && memcpy (REG_ADDR (&old_state, check_regno),
264 REG_ADDR (state, check_regno),
875f8d0e 265 register_size (gdbarch, check_regno)))
da59e081
JM
266 /* Register CHECK_REGNO has changed! Ack! */
267 {
8a3fe4f8 268 warning (_("Register %s changed after the thread was aborted"),
875f8d0e 269 gdbarch_register_name (gdbarch, check_regno));
da59e081 270 if (regno >= 0 && regno != check_regno)
383d750b 271 /* Update GDB's copy of the register. */
f6052080 272 regcache_raw_supply (regcache, check_regno,
23a6d369 273 REG_ADDR (state, check_regno));
da59e081 274 else
1777feb0
MS
275 warning (_("... also writing this register! "
276 "Suspicious..."));
da59e081
JM
277 }
278 }
c906108c 279
da59e081
JM
280 if (regno == -1)
281 {
282 int i;
383d750b 283
da59e081 284 proc_debug (thread, "storing all registers");
c5aa993b 285
65e78234 286 for (i = 0; i < I386_NUM_GREGS; i++)
672c9795 287 if (REG_VALID == regcache_register_status (regcache, i))
9b8607ce 288 regcache_raw_collect (regcache, i, REG_ADDR (state, i));
da59e081
JM
289 }
290 else
291 {
c9f4d572 292 proc_debug (thread, "storing register %s",
875f8d0e 293 gdbarch_register_name (gdbarch, regno));
c906108c 294
672c9795 295 gdb_assert (REG_VALID == regcache_register_status (regcache, regno));
ecac404d 296 regcache_raw_collect (regcache, regno, REG_ADDR (state, regno));
da59e081 297 }
fb557744
MK
298
299 /* Restore the T bit. */
300 ((struct i386_thread_state *)state)->efl &= ~0x100;
301 ((struct i386_thread_state *)state)->efl |= trace;
c906108c 302 }
c5aa993b 303
65e78234 304 if (regno >= I386_NUM_GREGS || regno == -1)
da59e081
JM
305 {
306 proc_debug (thread, "storing floating-point registers");
383d750b 307
56be3814 308 store_fpregs (regcache, thread, regno);
da59e081 309 }
c906108c 310}
b4d1e8c7
PA
311
312/* Provide a prototype to silence -Wmissing-prototypes. */
313extern initialize_file_ftype _initialize_i386gnu_nat;
314
315void
316_initialize_i386gnu_nat (void)
317{
318 struct target_ops *t;
319
320 /* Fill in the generic GNU/Hurd methods. */
321 t = gnu_target ();
322
323 t->to_fetch_registers = gnu_fetch_registers;
324 t->to_store_registers = gnu_store_registers;
325
326 /* Register the target. */
327 add_target (t);
328}
This page took 1.113344 seconds and 4 git commands to generate.