1/* Low level interface to i386 running the GNU Hurd. 2 3 Copyright (C) 1992, 1995, 1996, 1998, 2000, 2001, 2004, 2007 4 Free Software Foundation, Inc. 5 6 This file is part of GDB. 7 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 3 of the License, or 11 (at your option) any later version. 12 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. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21#include "defs.h" 22#include "inferior.h" 23#include "floatformat.h" 24#include "regcache.h" 25 26#include "gdb_assert.h" 27#include <errno.h> 28#include <stdio.h> 29#include "gdb_string.h" 30 31#include <mach.h> 32#include <mach_error.h> 33#include <mach/message.h> 34#include <mach/exception.h> 35 36#include "i386-tdep.h" 37 38#include "gnu-nat.h" 39#include "i387-tdep.h" 40 41#ifdef HAVE_SYS_PROCFS_H 42# include <sys/procfs.h> 43# include "gregset.h" 44#endif 45 46/* Offset to the thread_state_t location where REG is stored. */ 47#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg) 48 49/* At REG_OFFSET[N] is the offset to the thread_state_t location where 50 the GDB register N is stored. */ 51static int reg_offset[] = 52{ 53 REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx), 54 REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi), 55 REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss), 56 REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs) 57}; 58 59#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum]) 60#define CREG_ADDR(state, regnum) ((const char *)(state) + reg_offset[regnum]) 61 62 63/* Get the whole floating-point state of THREAD and record the values 64 of the corresponding (pseudo) registers. */ 65 66static void 67fetch_fpregs (struct regcache *regcache, struct proc *thread) 68{ 69 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT; 70 struct i386_float_state state; 71 error_t err; 72 73 err = thread_get_state (thread->port, i386_FLOAT_STATE, 74 (thread_state_t) &state, &count); 75 if (err) 76 { 77 warning (_("Couldn't fetch floating-point state from %s"), 78 proc_string (thread)); 79 return; 80 } 81 82 if (!state.initialized) 83 { 84 /* The floating-point state isn't initialized. */ 85 i387_supply_fsave (regcache, -1, NULL); 86 } 87 else 88 { 89 /* Supply the floating-point registers. */ 90 i387_supply_fsave (regcache, -1, state.hw_state); 91 } 92} 93 94#ifdef HAVE_SYS_PROCFS_H 95/* These two calls are used by the core-regset.c code for 96 reading ELF core files. */ 97void 98supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregs) 99{ 100 int i; 101 for (i = 0; i < I386_NUM_GREGS; i++) 102 regcache_raw_supply (regcache, i, CREG_ADDR (gregs, i)); 103} 104 105void 106supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregs) 107{ 108 i387_supply_fsave (regcache, -1, fpregs); 109} 110#endif 111 112/* Fetch register REGNO, or all regs if REGNO is -1. */ 113void 114gnu_fetch_registers (struct regcache *regcache, int regno) 115{ 116 struct proc *thread; 117 118 /* Make sure we know about new threads. */ 119 inf_update_procs (current_inferior); 120 121 thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid)); 122 if (!thread) 123 error (_("Can't fetch registers from thread %d: No such thread"), 124 PIDGET (inferior_ptid)); 125 126 if (regno < I386_NUM_GREGS || regno == -1) 127 { 128 thread_state_t state; 129 130 /* This does the dirty work for us. */ 131 state = proc_get_state (thread, 0); 132 if (!state) 133 { 134 warning (_("Couldn't fetch registers from %s"), 135 proc_string (thread)); 136 return; 137 } 138 139 if (regno == -1) 140 { 141 int i; 142 143 proc_debug (thread, "fetching all register"); 144 145 for (i = 0; i < I386_NUM_GREGS; i++) 146 regcache_raw_supply (regcache, i, REG_ADDR (state, i)); 147 thread->fetched_regs = ~0; 148 } 149 else 150 { 151 proc_debug (thread, "fetching register %s", 152 gdbarch_register_name (current_gdbarch, regno)); 153 154 regcache_raw_supply (regcache, regno, 155 REG_ADDR (state, regno)); 156 thread->fetched_regs |= (1 << regno); 157 } 158 } 159 160 if (regno >= I386_NUM_GREGS || regno == -1) 161 { 162 proc_debug (thread, "fetching floating-point registers"); 163 164 fetch_fpregs (regcache, thread); 165 } 166} 167 168 169/* Store the whole floating-point state into THREAD using information 170 from the corresponding (pseudo) registers. */ 171static void 172store_fpregs (const struct regcache *regcache, struct proc *thread, int regno) 173{ 174 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT; 175 struct i386_float_state state; 176 error_t err; 177 178 err = thread_get_state (thread->port, i386_FLOAT_STATE, 179 (thread_state_t) &state, &count); 180 if (err) 181 { 182 warning (_("Couldn't fetch floating-point state from %s"), 183 proc_string (thread)); 184 return; 185 } 186 187 /* FIXME: kettenis/2001-07-15: Is this right? Should we somehow 188 take into account DEPRECATED_REGISTER_VALID like the old code did? */ 189 i387_collect_fsave (regcache, regno, state.hw_state); 190 191 err = thread_set_state (thread->port, i386_FLOAT_STATE, 192 (thread_state_t) &state, i386_FLOAT_STATE_COUNT); 193 if (err) 194 { 195 warning (_("Couldn't store floating-point state into %s"), 196 proc_string (thread)); 197 return; 198 } 199} 200 201/* Store at least register REGNO, or all regs if REGNO == -1. */ 202void 203gnu_store_registers (struct regcache *regcache, int regno) 204{ 205 struct proc *thread; 206 207 /* Make sure we know about new threads. */ 208 inf_update_procs (current_inferior); 209 210 thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid)); 211 if (!thread) 212 error (_("Couldn't store registers into thread %d: No such thread"), 213 PIDGET (inferior_ptid)); 214 215 if (regno < I386_NUM_GREGS || regno == -1) 216 { 217 thread_state_t state; 218 thread_state_data_t old_state; 219 int was_aborted = thread->aborted; 220 int was_valid = thread->state_valid; 221 int trace; 222 223 if (!was_aborted && was_valid) 224 memcpy (&old_state, &thread->state, sizeof (old_state)); 225 226 state = proc_get_state (thread, 1); 227 if (!state) 228 { 229 warning (_("Couldn't store registers into %s"), proc_string (thread)); 230 return; 231 } 232 233 /* Save the T bit. We might try to restore the %eflags register 234 below, but changing the T bit would seriously confuse GDB. */ 235 trace = ((struct i386_thread_state *)state)->efl & 0x100; 236 237 if (!was_aborted && was_valid) 238 /* See which registers have changed after aborting the thread. */ 239 { 240 int check_regno; 241 242 for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++) 243 if ((thread->fetched_regs & (1 << check_regno)) 244 && memcpy (REG_ADDR (&old_state, check_regno), 245 REG_ADDR (state, check_regno), 246 register_size (current_gdbarch, check_regno))) 247 /* Register CHECK_REGNO has changed! Ack! */ 248 { 249 warning (_("Register %s changed after the thread was aborted"), 250 gdbarch_register_name (current_gdbarch, check_regno)); 251 if (regno >= 0 && regno != check_regno) 252 /* Update GDB's copy of the register. */ 253 regcache_raw_supply (regcache, check_regno, 254 REG_ADDR (state, check_regno)); 255 else 256 warning (_("... also writing this register! Suspicious...")); 257 } 258 } 259 260 if (regno == -1) 261 { 262 int i; 263 264 proc_debug (thread, "storing all registers"); 265 266 for (i = 0; i < I386_NUM_GREGS; i++) 267 if (regcache_valid_p (regcache, i)) 268 regcache_raw_collect (regcache, i, REG_ADDR (state, i)); 269 } 270 else 271 { 272 proc_debug (thread, "storing register %s", 273 gdbarch_register_name (current_gdbarch, regno)); 274 275 gdb_assert (regcache_valid_p (regcache, regno)); 276 regcache_raw_collect (regcache, regno, REG_ADDR (state, regno)); 277 } 278 279 /* Restore the T bit. */ 280 ((struct i386_thread_state *)state)->efl &= ~0x100; 281 ((struct i386_thread_state *)state)->efl |= trace; 282 } 283 284 if (regno >= I386_NUM_GREGS || regno == -1) 285 { 286 proc_debug (thread, "storing floating-point registers"); 287 288 store_fpregs (regcache, thread, regno); 289 } 290} 291