Home | History | Annotate | Line # | Download | only in gdb
i386-gnu-nat.c revision 1.1.1.4
      1 /* Low level interface to i386 running the GNU Hurd.
      2 
      3    Copyright (C) 1992-2023 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 3 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, see <http://www.gnu.org/licenses/>.  */
     19 
     20 /* Include this first, to pick up the <mach.h> 'thread_info' diversion.  */
     21 #include "gnu-nat.h"
     22 
     23 /* Mach/Hurd headers are not yet ready for C++ compilation.  */
     24 extern "C"
     25 {
     26 #include <mach.h>
     27 #include <mach_error.h>
     28 #include <mach/message.h>
     29 #include <mach/exception.h>
     30 }
     31 
     32 #include "defs.h"
     33 #include "x86-nat.h"
     34 #include "inferior.h"
     35 #include "floatformat.h"
     36 #include "regcache.h"
     37 
     38 #include "i386-tdep.h"
     39 
     40 #include "inf-child.h"
     41 #include "i387-tdep.h"
     42 
     43 /* Offset to the thread_state_t location where REG is stored.  */
     44 #define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
     45 
     46 /* At REG_OFFSET[N] is the offset to the thread_state_t location where
     47    the GDB register N is stored.  */
     48 static int reg_offset[] =
     49 {
     50   REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
     51   REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
     52   REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
     53   REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
     54 };
     55 
     56 #define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
     57 
     58 
     59 
     61 /* The i386 GNU Hurd target.  */
     62 
     63 #ifdef i386_DEBUG_STATE
     64 using gnu_base_target = x86_nat_target<gnu_nat_target>;
     65 #else
     66 using gnu_base_target = gnu_nat_target;
     67 #endif
     68 
     69 struct i386_gnu_nat_target final : public gnu_base_target
     70 {
     71   void fetch_registers (struct regcache *, int) override;
     72   void store_registers (struct regcache *, int) override;
     73 };
     74 
     75 static i386_gnu_nat_target the_i386_gnu_nat_target;
     76 
     77 /* Get the whole floating-point state of THREAD and record the values
     78    of the corresponding (pseudo) registers.  */
     79 
     80 static void
     81 fetch_fpregs (struct regcache *regcache, struct proc *thread)
     82 {
     83   mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
     84   struct i386_float_state state;
     85   kern_return_t err;
     86 
     87   err = thread_get_state (thread->port, i386_FLOAT_STATE,
     88 			  (thread_state_t) &state, &count);
     89   if (err)
     90     {
     91       warning (_("Couldn't fetch floating-point state from %s"),
     92 	       proc_string (thread));
     93       return;
     94     }
     95 
     96   if (!state.initialized)
     97     {
     98       /* The floating-point state isn't initialized.  */
     99       i387_supply_fsave (regcache, -1, NULL);
    100     }
    101   else
    102     {
    103       /* Supply the floating-point registers.  */
    104       i387_supply_fsave (regcache, -1, state.hw_state);
    105     }
    106 }
    107 
    108 /* Fetch register REGNO, or all regs if REGNO is -1.  */
    109 void
    110 i386_gnu_nat_target::fetch_registers (struct regcache *regcache, int regno)
    111 {
    112   struct proc *thread;
    113   ptid_t ptid = regcache->ptid ();
    114 
    115   /* Make sure we know about new threads.  */
    116   inf_update_procs (gnu_current_inf);
    117 
    118   thread = inf_tid_to_thread (gnu_current_inf, ptid.lwp ());
    119   if (!thread)
    120     error (_("Can't fetch registers from thread %s: No such thread"),
    121 	   target_pid_to_str (ptid).c_str ());
    122 
    123   if (regno < I386_NUM_GREGS || regno == -1)
    124     {
    125       thread_state_t state;
    126 
    127       /* This does the dirty work for us.  */
    128       state = proc_get_state (thread, 0);
    129       if (!state)
    130 	{
    131 	  warning (_("Couldn't fetch registers from %s"),
    132 		   proc_string (thread));
    133 	  return;
    134 	}
    135 
    136       if (regno == -1)
    137 	{
    138 	  int i;
    139 
    140 	  proc_debug (thread, "fetching all register");
    141 
    142 	  for (i = 0; i < I386_NUM_GREGS; i++)
    143 	    regcache->raw_supply (i, REG_ADDR (state, i));
    144 	  thread->fetched_regs = ~0;
    145 	}
    146       else
    147 	{
    148 	  proc_debug (thread, "fetching register %s",
    149 		      gdbarch_register_name (regcache->arch (),
    150 					     regno));
    151 
    152 	  regcache->raw_supply (regno, REG_ADDR (state, regno));
    153 	  thread->fetched_regs |= (1 << regno);
    154 	}
    155     }
    156 
    157   if (regno >= I386_NUM_GREGS || regno == -1)
    158     {
    159       proc_debug (thread, "fetching floating-point registers");
    160 
    161       fetch_fpregs (regcache, thread);
    162     }
    163 }
    164 
    165 
    167 /* Store the whole floating-point state into THREAD using information
    168    from the corresponding (pseudo) registers.  */
    169 static void
    170 store_fpregs (const struct regcache *regcache, struct proc *thread, int regno)
    171 {
    172   mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
    173   struct i386_float_state state;
    174   kern_return_t err;
    175 
    176   err = thread_get_state (thread->port, i386_FLOAT_STATE,
    177 			  (thread_state_t) &state, &count);
    178   if (err)
    179     {
    180       warning (_("Couldn't fetch floating-point state from %s"),
    181 	       proc_string (thread));
    182       return;
    183     }
    184 
    185   /* FIXME: kettenis/2001-07-15: Is this right?  Should we somehow
    186      take into account DEPRECATED_REGISTER_VALID like the old code did?  */
    187   i387_collect_fsave (regcache, regno, state.hw_state);
    188 
    189   err = thread_set_state (thread->port, i386_FLOAT_STATE,
    190 			  (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
    191   if (err)
    192     {
    193       warning (_("Couldn't store floating-point state into %s"),
    194 	       proc_string (thread));
    195       return;
    196     }
    197 }
    198 
    199 /* Store at least register REGNO, or all regs if REGNO == -1.  */
    200 void
    201 i386_gnu_nat_target::store_registers (struct regcache *regcache, int regno)
    202 {
    203   struct proc *thread;
    204   struct gdbarch *gdbarch = regcache->arch ();
    205   ptid_t ptid = regcache->ptid ();
    206 
    207   /* Make sure we know about new threads.  */
    208   inf_update_procs (gnu_current_inf);
    209 
    210   thread = inf_tid_to_thread (gnu_current_inf, ptid.lwp ());
    211   if (!thread)
    212     error (_("Couldn't store registers into thread %s: No such thread"),
    213 	   target_pid_to_str (ptid).c_str ());
    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"),
    230 		   proc_string (thread));
    231 	  return;
    232 	}
    233 
    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 
    238       if (!was_aborted && was_valid)
    239 	/* See which registers have changed after aborting the thread.  */
    240 	{
    241 	  int check_regno;
    242 
    243 	  for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++)
    244 	    if ((thread->fetched_regs & (1 << check_regno))
    245 		&& memcpy (REG_ADDR (&old_state, check_regno),
    246 			   REG_ADDR (state, check_regno),
    247 			   register_size (gdbarch, check_regno)))
    248 	      /* Register CHECK_REGNO has changed!  Ack!  */
    249 	      {
    250 		warning (_("Register %s changed after the thread was aborted"),
    251 			 gdbarch_register_name (gdbarch, check_regno));
    252 		if (regno >= 0 && regno != check_regno)
    253 		  /* Update GDB's copy of the register.  */
    254 		  regcache->raw_supply (check_regno,
    255 					REG_ADDR (state, check_regno));
    256 		else
    257 		  warning (_("... also writing this register!  "
    258 			     "Suspicious..."));
    259 	      }
    260 	}
    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 (REG_VALID == regcache->get_register_status (i))
    270 	      regcache->raw_collect (i, REG_ADDR (state, i));
    271 	}
    272       else
    273 	{
    274 	  proc_debug (thread, "storing register %s",
    275 		      gdbarch_register_name (gdbarch, regno));
    276 
    277 	  gdb_assert (REG_VALID == regcache->get_register_status (regno));
    278 	  regcache->raw_collect (regno, REG_ADDR (state, regno));
    279 	}
    280 
    281       /* Restore the T bit.  */
    282       ((struct i386_thread_state *)state)->efl &= ~0x100;
    283       ((struct i386_thread_state *)state)->efl |= trace;
    284     }
    285 
    286   if (regno >= I386_NUM_GREGS || regno == -1)
    287     {
    288       proc_debug (thread, "storing floating-point registers");
    289 
    290       store_fpregs (regcache, thread, regno);
    291     }
    292 }
    293 
    294 
    295 /* Support for debug registers.  */
    297 
    298 #ifdef i386_DEBUG_STATE
    299 /* Get debug registers for thread THREAD.  */
    300 
    301 static void
    302 i386_gnu_dr_get (struct i386_debug_state *regs, struct proc *thread)
    303 {
    304   mach_msg_type_number_t count = i386_DEBUG_STATE_COUNT;
    305   kern_return_t err;
    306 
    307   err = thread_get_state (thread->port, i386_DEBUG_STATE,
    308 			  (thread_state_t) regs, &count);
    309   if (err != 0 || count != i386_DEBUG_STATE_COUNT)
    310     warning (_("Couldn't fetch debug state from %s"),
    311 	     proc_string (thread));
    312 }
    313 
    314 /* Set debug registers for thread THREAD.  */
    315 
    316 static void
    317 i386_gnu_dr_set (const struct i386_debug_state *regs, struct proc *thread)
    318 {
    319   kern_return_t err;
    320 
    321   err = thread_set_state (thread->port, i386_DEBUG_STATE,
    322 			  (thread_state_t) regs, i386_DEBUG_STATE_COUNT);
    323   if (err != 0)
    324     warning (_("Couldn't store debug state into %s"),
    325 	     proc_string (thread));
    326 }
    327 
    328 /* Set DR_CONTROL in THREAD.  */
    329 
    330 static void
    331 i386_gnu_dr_set_control_one (struct proc *thread, void *arg)
    332 {
    333   unsigned long *control = (unsigned long *) arg;
    334   struct i386_debug_state regs;
    335 
    336   i386_gnu_dr_get (&regs, thread);
    337   regs.dr[DR_CONTROL] = *control;
    338   i386_gnu_dr_set (&regs, thread);
    339 }
    340 
    341 /* Set DR_CONTROL to CONTROL in all threads.  */
    342 
    343 static void
    344 i386_gnu_dr_set_control (unsigned long control)
    345 {
    346   inf_update_procs (gnu_current_inf);
    347   inf_threads (gnu_current_inf, i386_gnu_dr_set_control_one, &control);
    348 }
    349 
    350 /* Parameters to set a debugging address.  */
    351 
    352 struct reg_addr
    353 {
    354   int regnum;		/* Register number (zero based).  */
    355   CORE_ADDR addr;	/* Address.  */
    356 };
    357 
    358 /* Set address REGNUM (zero based) to ADDR in THREAD.  */
    359 
    360 static void
    361 i386_gnu_dr_set_addr_one (struct proc *thread, void *arg)
    362 {
    363   struct reg_addr *reg_addr = (struct reg_addr *) arg;
    364   struct i386_debug_state regs;
    365 
    366   i386_gnu_dr_get (&regs, thread);
    367   regs.dr[reg_addr->regnum] = reg_addr->addr;
    368   i386_gnu_dr_set (&regs, thread);
    369 }
    370 
    371 /* Set address REGNUM (zero based) to ADDR in all threads.  */
    372 
    373 static void
    374 i386_gnu_dr_set_addr (int regnum, CORE_ADDR addr)
    375 {
    376   struct reg_addr reg_addr;
    377 
    378   gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
    379 
    380   reg_addr.regnum = regnum;
    381   reg_addr.addr = addr;
    382 
    383   inf_update_procs (gnu_current_inf);
    384   inf_threads (gnu_current_inf, i386_gnu_dr_set_addr_one, &reg_addr);
    385 }
    386 
    387 /* Get debug register REGNUM value from only the one LWP of PTID.  */
    388 
    389 static unsigned long
    390 i386_gnu_dr_get_reg (ptid_t ptid, int regnum)
    391 {
    392   struct i386_debug_state regs;
    393   struct proc *thread;
    394 
    395   /* Make sure we know about new threads.  */
    396   inf_update_procs (gnu_current_inf);
    397 
    398   thread = inf_tid_to_thread (gnu_current_inf, ptid.lwp ());
    399   i386_gnu_dr_get (&regs, thread);
    400 
    401   return regs.dr[regnum];
    402 }
    403 
    404 /* Return the inferior's debug register REGNUM.  */
    405 
    406 static CORE_ADDR
    407 i386_gnu_dr_get_addr (int regnum)
    408 {
    409   gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
    410 
    411   return i386_gnu_dr_get_reg (inferior_ptid, regnum);
    412 }
    413 
    414 /* Get DR_STATUS from only the one thread of INFERIOR_PTID.  */
    415 
    416 static unsigned long
    417 i386_gnu_dr_get_status (void)
    418 {
    419   return i386_gnu_dr_get_reg (inferior_ptid, DR_STATUS);
    420 }
    421 
    422 /* Return the inferior's DR7 debug control register.  */
    423 
    424 static unsigned long
    425 i386_gnu_dr_get_control (void)
    426 {
    427   return i386_gnu_dr_get_reg (inferior_ptid, DR_CONTROL);
    428 }
    429 #endif /* i386_DEBUG_STATE */
    430 
    431 void _initialize_i386gnu_nat ();
    432 void
    433 _initialize_i386gnu_nat ()
    434 {
    435 #ifdef i386_DEBUG_STATE
    436   x86_dr_low.set_control = i386_gnu_dr_set_control;
    437   gdb_assert (DR_FIRSTADDR == 0 && DR_LASTADDR < i386_DEBUG_STATE_COUNT);
    438   x86_dr_low.set_addr = i386_gnu_dr_set_addr;
    439   x86_dr_low.get_addr = i386_gnu_dr_get_addr;
    440   x86_dr_low.get_status = i386_gnu_dr_get_status;
    441   x86_dr_low.get_control = i386_gnu_dr_get_control;
    442   x86_set_debug_register_length (4);
    443 #endif /* i386_DEBUG_STATE */
    444 
    445   gnu_target = &the_i386_gnu_nat_target;
    446 
    447   /* Register the target.  */
    448   add_inf_child_target (&the_i386_gnu_nat_target);
    449 }
    450