OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [gdb/] [i386gnu-nat.c] - Diff between revs 827 and 840

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 827 Rev 840
/* Low level interface to i386 running the GNU Hurd.
/* Low level interface to i386 running the GNU Hurd.
 
 
   Copyright (C) 1992, 1995, 1996, 1998, 2000, 2001, 2004, 2007, 2008
   Copyright (C) 1992, 1995, 1996, 1998, 2000, 2001, 2004, 2007, 2008
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
#include "defs.h"
#include "defs.h"
#include "inferior.h"
#include "inferior.h"
#include "floatformat.h"
#include "floatformat.h"
#include "regcache.h"
#include "regcache.h"
 
 
#include "gdb_assert.h"
#include "gdb_assert.h"
#include <errno.h>
#include <errno.h>
#include <stdio.h>
#include <stdio.h>
#include "gdb_string.h"
#include "gdb_string.h"
 
 
#include <mach.h>
#include <mach.h>
#include <mach_error.h>
#include <mach_error.h>
#include <mach/message.h>
#include <mach/message.h>
#include <mach/exception.h>
#include <mach/exception.h>
 
 
#include "i386-tdep.h"
#include "i386-tdep.h"
 
 
#include "gnu-nat.h"
#include "gnu-nat.h"
#include "i387-tdep.h"
#include "i387-tdep.h"
 
 
#ifdef HAVE_SYS_PROCFS_H
#ifdef HAVE_SYS_PROCFS_H
# include <sys/procfs.h>
# include <sys/procfs.h>
# include "gregset.h"
# include "gregset.h"
#endif
#endif
 
 
/* Offset to the thread_state_t location where REG is stored.  */
/* Offset to the thread_state_t location where REG is stored.  */
#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
 
 
/* At REG_OFFSET[N] is the offset to the thread_state_t location where
/* At REG_OFFSET[N] is the offset to the thread_state_t location where
   the GDB register N is stored.  */
   the GDB register N is stored.  */
static int reg_offset[] =
static int reg_offset[] =
{
{
  REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
  REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
  REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
  REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
  REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
  REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
  REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
  REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
};
};
 
 
#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
#define CREG_ADDR(state, regnum) ((const char *)(state) + reg_offset[regnum])
#define CREG_ADDR(state, regnum) ((const char *)(state) + reg_offset[regnum])
 
 


/* Get the whole floating-point state of THREAD and record the values
/* Get the whole floating-point state of THREAD and record the values
   of the corresponding (pseudo) registers.  */
   of the corresponding (pseudo) registers.  */
 
 
static void
static void
fetch_fpregs (struct regcache *regcache, struct proc *thread)
fetch_fpregs (struct regcache *regcache, struct proc *thread)
{
{
  mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
  mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
  struct i386_float_state state;
  struct i386_float_state state;
  error_t err;
  error_t err;
 
 
  err = thread_get_state (thread->port, i386_FLOAT_STATE,
  err = thread_get_state (thread->port, i386_FLOAT_STATE,
                          (thread_state_t) &state, &count);
                          (thread_state_t) &state, &count);
  if (err)
  if (err)
    {
    {
      warning (_("Couldn't fetch floating-point state from %s"),
      warning (_("Couldn't fetch floating-point state from %s"),
               proc_string (thread));
               proc_string (thread));
      return;
      return;
    }
    }
 
 
  if (!state.initialized)
  if (!state.initialized)
    {
    {
      /* The floating-point state isn't initialized.  */
      /* The floating-point state isn't initialized.  */
      i387_supply_fsave (regcache, -1, NULL);
      i387_supply_fsave (regcache, -1, NULL);
    }
    }
  else
  else
    {
    {
      /* Supply the floating-point registers.  */
      /* Supply the floating-point registers.  */
      i387_supply_fsave (regcache, -1, state.hw_state);
      i387_supply_fsave (regcache, -1, state.hw_state);
    }
    }
}
}
 
 
#ifdef HAVE_SYS_PROCFS_H
#ifdef HAVE_SYS_PROCFS_H
/* These two calls are used by the core-regset.c code for
/* These two calls are used by the core-regset.c code for
   reading ELF core files.  */
   reading ELF core files.  */
void
void
supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregs)
supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregs)
{
{
  int i;
  int i;
  for (i = 0; i < I386_NUM_GREGS; i++)
  for (i = 0; i < I386_NUM_GREGS; i++)
    regcache_raw_supply (regcache, i, CREG_ADDR (gregs, i));
    regcache_raw_supply (regcache, i, CREG_ADDR (gregs, i));
}
}
 
 
void
void
supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregs)
supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregs)
{
{
  i387_supply_fsave (regcache, -1, fpregs);
  i387_supply_fsave (regcache, -1, fpregs);
}
}
#endif
#endif
 
 
/* Fetch register REGNO, or all regs if REGNO is -1.  */
/* Fetch register REGNO, or all regs if REGNO is -1.  */
void
void
gnu_fetch_registers (struct regcache *regcache, int regno)
gnu_fetch_registers (struct regcache *regcache, int regno)
{
{
  struct proc *thread;
  struct proc *thread;
 
 
  /* Make sure we know about new threads.  */
  /* Make sure we know about new threads.  */
  inf_update_procs (current_inferior);
  inf_update_procs (current_inferior);
 
 
  thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
  thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
  if (!thread)
  if (!thread)
    error (_("Can't fetch registers from thread %d: No such thread"),
    error (_("Can't fetch registers from thread %d: No such thread"),
           PIDGET (inferior_ptid));
           PIDGET (inferior_ptid));
 
 
  if (regno < I386_NUM_GREGS || regno == -1)
  if (regno < I386_NUM_GREGS || regno == -1)
    {
    {
      thread_state_t state;
      thread_state_t state;
 
 
      /* This does the dirty work for us.  */
      /* This does the dirty work for us.  */
      state = proc_get_state (thread, 0);
      state = proc_get_state (thread, 0);
      if (!state)
      if (!state)
        {
        {
          warning (_("Couldn't fetch registers from %s"),
          warning (_("Couldn't fetch registers from %s"),
                   proc_string (thread));
                   proc_string (thread));
          return;
          return;
        }
        }
 
 
      if (regno == -1)
      if (regno == -1)
        {
        {
          int i;
          int i;
 
 
          proc_debug (thread, "fetching all register");
          proc_debug (thread, "fetching all register");
 
 
          for (i = 0; i < I386_NUM_GREGS; i++)
          for (i = 0; i < I386_NUM_GREGS; i++)
            regcache_raw_supply (regcache, i, REG_ADDR (state, i));
            regcache_raw_supply (regcache, i, REG_ADDR (state, i));
          thread->fetched_regs = ~0;
          thread->fetched_regs = ~0;
        }
        }
      else
      else
        {
        {
          proc_debug (thread, "fetching register %s",
          proc_debug (thread, "fetching register %s",
                      gdbarch_register_name (get_regcache_arch (regcache),
                      gdbarch_register_name (get_regcache_arch (regcache),
                                             regno));
                                             regno));
 
 
          regcache_raw_supply (regcache, regno,
          regcache_raw_supply (regcache, regno,
                               REG_ADDR (state, regno));
                               REG_ADDR (state, regno));
          thread->fetched_regs |= (1 << regno);
          thread->fetched_regs |= (1 << regno);
        }
        }
    }
    }
 
 
  if (regno >= I386_NUM_GREGS || regno == -1)
  if (regno >= I386_NUM_GREGS || regno == -1)
    {
    {
      proc_debug (thread, "fetching floating-point registers");
      proc_debug (thread, "fetching floating-point registers");
 
 
      fetch_fpregs (regcache, thread);
      fetch_fpregs (regcache, thread);
    }
    }
}
}


 
 
/* Store the whole floating-point state into THREAD using information
/* Store the whole floating-point state into THREAD using information
   from the corresponding (pseudo) registers.  */
   from the corresponding (pseudo) registers.  */
static void
static void
store_fpregs (const struct regcache *regcache, struct proc *thread, int regno)
store_fpregs (const struct regcache *regcache, struct proc *thread, int regno)
{
{
  mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
  mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
  struct i386_float_state state;
  struct i386_float_state state;
  error_t err;
  error_t err;
 
 
  err = thread_get_state (thread->port, i386_FLOAT_STATE,
  err = thread_get_state (thread->port, i386_FLOAT_STATE,
                          (thread_state_t) &state, &count);
                          (thread_state_t) &state, &count);
  if (err)
  if (err)
    {
    {
      warning (_("Couldn't fetch floating-point state from %s"),
      warning (_("Couldn't fetch floating-point state from %s"),
               proc_string (thread));
               proc_string (thread));
      return;
      return;
    }
    }
 
 
  /* FIXME: kettenis/2001-07-15: Is this right?  Should we somehow
  /* FIXME: kettenis/2001-07-15: Is this right?  Should we somehow
     take into account DEPRECATED_REGISTER_VALID like the old code did?  */
     take into account DEPRECATED_REGISTER_VALID like the old code did?  */
  i387_collect_fsave (regcache, regno, state.hw_state);
  i387_collect_fsave (regcache, regno, state.hw_state);
 
 
  err = thread_set_state (thread->port, i386_FLOAT_STATE,
  err = thread_set_state (thread->port, i386_FLOAT_STATE,
                          (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
                          (thread_state_t) &state, i386_FLOAT_STATE_COUNT);
  if (err)
  if (err)
    {
    {
      warning (_("Couldn't store floating-point state into %s"),
      warning (_("Couldn't store floating-point state into %s"),
               proc_string (thread));
               proc_string (thread));
      return;
      return;
    }
    }
}
}
 
 
/* Store at least register REGNO, or all regs if REGNO == -1.  */
/* Store at least register REGNO, or all regs if REGNO == -1.  */
void
void
gnu_store_registers (struct regcache *regcache, int regno)
gnu_store_registers (struct regcache *regcache, int regno)
{
{
  struct proc *thread;
  struct proc *thread;
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
 
 
  /* Make sure we know about new threads.  */
  /* Make sure we know about new threads.  */
  inf_update_procs (current_inferior);
  inf_update_procs (current_inferior);
 
 
  thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
  thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
  if (!thread)
  if (!thread)
    error (_("Couldn't store registers into thread %d: No such thread"),
    error (_("Couldn't store registers into thread %d: No such thread"),
           PIDGET (inferior_ptid));
           PIDGET (inferior_ptid));
 
 
  if (regno < I386_NUM_GREGS || regno == -1)
  if (regno < I386_NUM_GREGS || regno == -1)
    {
    {
      thread_state_t state;
      thread_state_t state;
      thread_state_data_t old_state;
      thread_state_data_t old_state;
      int was_aborted = thread->aborted;
      int was_aborted = thread->aborted;
      int was_valid = thread->state_valid;
      int was_valid = thread->state_valid;
      int trace;
      int trace;
 
 
      if (!was_aborted && was_valid)
      if (!was_aborted && was_valid)
        memcpy (&old_state, &thread->state, sizeof (old_state));
        memcpy (&old_state, &thread->state, sizeof (old_state));
 
 
      state = proc_get_state (thread, 1);
      state = proc_get_state (thread, 1);
      if (!state)
      if (!state)
        {
        {
          warning (_("Couldn't store registers into %s"), proc_string (thread));
          warning (_("Couldn't store registers into %s"), proc_string (thread));
          return;
          return;
        }
        }
 
 
      /* Save the T bit.  We might try to restore the %eflags register
      /* Save the T bit.  We might try to restore the %eflags register
         below, but changing the T bit would seriously confuse GDB.  */
         below, but changing the T bit would seriously confuse GDB.  */
      trace = ((struct i386_thread_state *)state)->efl & 0x100;
      trace = ((struct i386_thread_state *)state)->efl & 0x100;
 
 
      if (!was_aborted && was_valid)
      if (!was_aborted && was_valid)
        /* See which registers have changed after aborting the thread.  */
        /* See which registers have changed after aborting the thread.  */
        {
        {
          int check_regno;
          int check_regno;
 
 
          for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++)
          for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++)
            if ((thread->fetched_regs & (1 << check_regno))
            if ((thread->fetched_regs & (1 << check_regno))
                && memcpy (REG_ADDR (&old_state, check_regno),
                && memcpy (REG_ADDR (&old_state, check_regno),
                           REG_ADDR (state, check_regno),
                           REG_ADDR (state, check_regno),
                           register_size (gdbarch, check_regno)))
                           register_size (gdbarch, check_regno)))
              /* Register CHECK_REGNO has changed!  Ack!  */
              /* Register CHECK_REGNO has changed!  Ack!  */
              {
              {
                warning (_("Register %s changed after the thread was aborted"),
                warning (_("Register %s changed after the thread was aborted"),
                         gdbarch_register_name (gdbarch, check_regno));
                         gdbarch_register_name (gdbarch, check_regno));
                if (regno >= 0 && regno != check_regno)
                if (regno >= 0 && regno != check_regno)
                  /* Update GDB's copy of the register.  */
                  /* Update GDB's copy of the register.  */
                  regcache_raw_supply (regcache, check_regno,
                  regcache_raw_supply (regcache, check_regno,
                                       REG_ADDR (state, check_regno));
                                       REG_ADDR (state, check_regno));
                else
                else
                  warning (_("... also writing this register!  Suspicious..."));
                  warning (_("... also writing this register!  Suspicious..."));
              }
              }
        }
        }
 
 
      if (regno == -1)
      if (regno == -1)
        {
        {
          int i;
          int i;
 
 
          proc_debug (thread, "storing all registers");
          proc_debug (thread, "storing all registers");
 
 
          for (i = 0; i < I386_NUM_GREGS; i++)
          for (i = 0; i < I386_NUM_GREGS; i++)
            if (regcache_valid_p (regcache, i))
            if (regcache_valid_p (regcache, i))
              regcache_raw_collect (regcache, i, REG_ADDR (state, i));
              regcache_raw_collect (regcache, i, REG_ADDR (state, i));
        }
        }
      else
      else
        {
        {
          proc_debug (thread, "storing register %s",
          proc_debug (thread, "storing register %s",
                      gdbarch_register_name (gdbarch, regno));
                      gdbarch_register_name (gdbarch, regno));
 
 
          gdb_assert (regcache_valid_p (regcache, regno));
          gdb_assert (regcache_valid_p (regcache, regno));
          regcache_raw_collect (regcache, regno, REG_ADDR (state, regno));
          regcache_raw_collect (regcache, regno, REG_ADDR (state, regno));
        }
        }
 
 
      /* Restore the T bit.  */
      /* Restore the T bit.  */
      ((struct i386_thread_state *)state)->efl &= ~0x100;
      ((struct i386_thread_state *)state)->efl &= ~0x100;
      ((struct i386_thread_state *)state)->efl |= trace;
      ((struct i386_thread_state *)state)->efl |= trace;
    }
    }
 
 
  if (regno >= I386_NUM_GREGS || regno == -1)
  if (regno >= I386_NUM_GREGS || regno == -1)
    {
    {
      proc_debug (thread, "storing floating-point registers");
      proc_debug (thread, "storing floating-point registers");
 
 
      store_fpregs (regcache, thread, regno);
      store_fpregs (regcache, thread, regno);
    }
    }
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.