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 <errno.h> 29#include <stdio.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 61 62/* Get the whole floating-point state of THREAD and record the 63 values of the corresponding (pseudo) registers. */ 64static void 65fetch_fpregs (struct proc *thread) 66{ 67 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT; 68 struct i386_float_state state; 69 error_t err; 70 71 err = thread_get_state (thread->port, i386_FLOAT_STATE, 72 (thread_state_t) &state, &count); 73 if (err) 74 { 75 warning ("Couldn't fetch floating-point state from %s", 76 proc_string (thread)); 77 return; 78 } 79 80 if (!state.initialized) 81 /* The floating-point state isn't initialized. */ 82 { 83 int i; 84 85 for (i = FP0_REGNUM; i <= FOP_REGNUM; i++) 86 supply_register (i, NULL); 87 88 return; 89 } 90 91 /* Supply the floating-point registers. */ 92 i387_supply_fsave (current_regcache, -1, state.hw_state); 93} 94 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; 102 for (i = 0; i < I386_NUM_GREGS; i++) 103 supply_register (i, REG_ADDR (gregs, i)); 104} 105 106void 107supply_fpregset (gdb_fpregset_t *fpregs) 108{ 109 i387_supply_fsave (current_regcache, -1, fpregs); 110} 111#endif 112 113/* Fetch register REGNO, or all regs if REGNO is -1. */ 114void 115gnu_fetch_registers (int regno) 116{ 117 struct proc *thread; 118 119 /* Make sure we know about new threads. */ 120 inf_update_procs (current_inferior); 121 122 thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid)); 123 if (!thread) 124 error ("Can't fetch registers from thread %d: No such thread", 125 PIDGET (inferior_ptid)); 126 127 if (regno < I386_NUM_GREGS || regno == -1) 128 { 129 thread_state_t state; 130 131 /* This does the dirty work for us. */ 132 state = proc_get_state (thread, 0); 133 if (!state) 134 { 135 warning ("Couldn't fetch registers from %s", 136 proc_string (thread)); 137 return; 138 } 139 140 if (regno == -1) 141 { 142 int i; 143 144 proc_debug (thread, "fetching all register"); 145 146 for (i = 0; i < I386_NUM_GREGS; i++) 147 supply_register (i, REG_ADDR (state, i)); 148 thread->fetched_regs = ~0; 149 } 150 else 151 { 152 proc_debug (thread, "fetching register %s", REGISTER_NAME (regno)); 153 154 supply_register (regno, REG_ADDR (state, regno)); 155 thread->fetched_regs |= (1 << regno); 156 } 157 } 158 159 if (regno >= I386_NUM_GREGS || regno == -1) 160 { 161 proc_debug (thread, "fetching floating-point registers"); 162 163 fetch_fpregs (thread); 164 } 165} 166 167 168/* Store the whole floating-point state into THREAD using information 169 from the corresponding (pseudo) registers. */ 170static void 171store_fpregs (struct proc *thread, int regno) 172{ 173 mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT; 174 struct i386_float_state state; 175 error_t err; 176 177 err = thread_get_state (thread->port, i386_FLOAT_STATE, 178 (thread_state_t) &state, &count); 179 if (err) 180 { 181 warning ("Couldn't fetch floating-point state from %s", 182 proc_string (thread)); 183 return; 184 } 185 186 /* FIXME: kettenis/2001-07-15: Is this right? Should we somehow 187 take into account DEPRECATED_REGISTER_VALID like the old code did? */ 188 i387_fill_fsave (state.hw_state, regno); 189 190 err = thread_set_state (thread->port, i386_FLOAT_STATE, 191 (thread_state_t) &state, i386_FLOAT_STATE_COUNT); 192 if (err) 193 { 194 warning ("Couldn't store floating-point state into %s", 195 proc_string (thread)); 196 return; 197 } 198} 199 200/* Store at least register REGNO, or all regs if REGNO == -1. */ 201void 202gnu_store_registers (int regno) 203{ 204 struct proc *thread; 205 206 /* Make sure we know about new threads. */ 207 inf_update_procs (current_inferior); 208 209 thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid)); 210 if (!thread) 211 error ("Couldn't store registers into thread %d: No such thread", 212 PIDGET (inferior_ptid)); 213 214 if (regno < I386_NUM_GREGS || regno == -1) 215 { 216 thread_state_t state; 217 thread_state_data_t old_state; 218 int was_aborted = thread->aborted; 219 int was_valid = thread->state_valid; 220 int trace; 221 222 if (!was_aborted && was_valid) 223 memcpy (&old_state, &thread->state, sizeof (old_state)); 224 225 state = proc_get_state (thread, 1); 226 if (!state) 227 { 228 warning ("Couldn't store registers into %s", proc_string (thread)); 229 return; 230 } 231 232 /* Save the T bit. We might try to restore the %eflags register 233 below, but changing the T bit would seriously confuse GDB. */ 234 trace = ((struct i386_thread_state *)state)->efl & 0x100; 235 236 if (!was_aborted && was_valid) 237 /* See which registers have changed after aborting the thread. */ 238 { 239 int check_regno; 240 241 for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++) 242 if ((thread->fetched_regs & (1 << check_regno)) 243 && memcpy (REG_ADDR (&old_state, check_regno), 244 REG_ADDR (state, check_regno), 245 DEPRECATED_REGISTER_RAW_SIZE (check_regno))) 246 /* Register CHECK_REGNO has changed! Ack! */ 247 { 248 warning ("Register %s changed after the thread was aborted", 249 REGISTER_NAME (check_regno)); 250 if (regno >= 0 && regno != check_regno) 251 /* Update GDB's copy of the register. */ 252 supply_register (check_regno, REG_ADDR (state, check_regno)); 253 else 254 warning ("... also writing this register! Suspicious..."); 255 } 256 } 257 258#define fill(state, regno) \ 259 memcpy (REG_ADDR(state, regno), &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)], \ 260 DEPRECATED_REGISTER_RAW_SIZE (regno)) 261 262 if (regno == -1) 263 { 264 int i; 265 266 proc_debug (thread, "storing all registers"); 267 268 for (i = 0; i < I386_NUM_GREGS; i++) 269 if (deprecated_register_valid[i]) 270 fill (state, i); 271 } 272 else 273 { 274 proc_debug (thread, "storing register %s", REGISTER_NAME (regno)); 275 276 gdb_assert (deprecated_register_valid[regno]); 277 fill (state, regno); 278 } 279 280 /* Restore the T bit. */ 281 ((struct i386_thread_state *)state)->efl &= ~0x100; 282 ((struct i386_thread_state *)state)->efl |= trace; 283 } 284 285#undef fill 286 287 if (regno >= I386_NUM_GREGS || regno == -1) 288 { 289 proc_debug (thread, "storing floating-point registers"); 290 291 store_fpregs (thread, regno); 292 } 293} 294