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