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