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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [i386v-nat.c] - Diff between revs 105 and 1765

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

Rev 105 Rev 1765
/* Intel 386 native support for SYSV systems (pre-SVR4).
/* Intel 386 native support for SYSV systems (pre-SVR4).
   Copyright (C) 1988, 89, 91, 92, 94, 96, 1998 Free Software Foundation, Inc.
   Copyright (C) 1988, 89, 91, 92, 94, 96, 1998 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 2 of the License, or
   the Free Software Foundation; either version 2 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, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */
   Boston, MA 02111-1307, USA.  */
 
 
#include "defs.h"
#include "defs.h"
 
 
#ifdef HAVE_PTRACE_H
#ifdef HAVE_PTRACE_H
#include <ptrace.h>
#include <ptrace.h>
#else
#else
#ifdef HAVE_SYS_PTRACE_H
#ifdef HAVE_SYS_PTRACE_H
#include <sys/ptrace.h>
#include <sys/ptrace.h>
#endif
#endif
#endif
#endif
 
 
#include "frame.h"
#include "frame.h"
#include "inferior.h"
#include "inferior.h"
#include "language.h"
#include "language.h"
#include "gdbcore.h"
#include "gdbcore.h"
 
 
#ifdef USG
#ifdef USG
#include <sys/types.h>
#include <sys/types.h>
#endif
#endif
 
 
#include <sys/param.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/dir.h>
#include <signal.h>
#include <signal.h>
#include <sys/user.h>
#include <sys/user.h>
#include <sys/ioctl.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <fcntl.h>
 
 
 
 
/* FIXME: The following used to be just "#include <sys/debugreg.h>", but
/* FIXME: The following used to be just "#include <sys/debugreg.h>", but
 * the the Linux 2.1.x kernel and glibc 2.0.x are not in sync; including
 * the the Linux 2.1.x kernel and glibc 2.0.x are not in sync; including
 * <sys/debugreg.h> will result in an error.  With luck, these losers
 * <sys/debugreg.h> will result in an error.  With luck, these losers
 * will get their act together and we can trash this hack in the near future.
 * will get their act together and we can trash this hack in the near future.
 * --jsm 1998-10-21
 * --jsm 1998-10-21
 */
 */
 
 
#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
#ifdef HAVE_ASM_DEBUGREG_H
#ifdef HAVE_ASM_DEBUGREG_H
#include <asm/debugreg.h>
#include <asm/debugreg.h>
#else
#else
#include <sys/debugreg.h>
#include <sys/debugreg.h>
#endif
#endif
#endif
#endif
 
 
#include <sys/file.h>
#include <sys/file.h>
#include "gdb_stat.h"
#include "gdb_stat.h"
 
 
#ifdef HAVE_SYS_REG_H
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
#include <sys/reg.h>
#endif
#endif
 
 
#include "floatformat.h"
#include "floatformat.h"
 
 
#include "target.h"
#include "target.h"


 
 
/* this table must line up with REGISTER_NAMES in tm-i386v.h */
/* this table must line up with REGISTER_NAMES in tm-i386v.h */
/* symbols like 'EAX' come from <sys/reg.h> */
/* symbols like 'EAX' come from <sys/reg.h> */
static int regmap[] =
static int regmap[] =
{
{
  EAX, ECX, EDX, EBX,
  EAX, ECX, EDX, EBX,
  UESP, EBP, ESI, EDI,
  UESP, EBP, ESI, EDI,
  EIP, EFL, CS, SS,
  EIP, EFL, CS, SS,
  DS, ES, FS, GS,
  DS, ES, FS, GS,
};
};
 
 
/* blockend is the value of u.u_ar0, and points to the
/* blockend is the value of u.u_ar0, and points to the
 * place where GS is stored
 * place where GS is stored
 */
 */
 
 
int
int
i386_register_u_addr (blockend, regnum)
i386_register_u_addr (blockend, regnum)
     int blockend;
     int blockend;
     int regnum;
     int regnum;
{
{
  struct user u;
  struct user u;
  int fpstate;
  int fpstate;
  int ubase;
  int ubase;
 
 
  ubase = blockend;
  ubase = blockend;
  /* FIXME:  Should have better way to test floating point range */
  /* FIXME:  Should have better way to test floating point range */
  if (regnum >= FP0_REGNUM && regnum <= (FP0_REGNUM + 7))
  if (regnum >= FP0_REGNUM && regnum <= (FP0_REGNUM + 7))
    {
    {
#ifdef KSTKSZ                   /* SCO, and others? */
#ifdef KSTKSZ                   /* SCO, and others? */
      ubase += 4 * (SS + 1) - KSTKSZ;
      ubase += 4 * (SS + 1) - KSTKSZ;
      fpstate = ubase + ((char *) &u.u_fps.u_fpstate - (char *) &u);
      fpstate = ubase + ((char *) &u.u_fps.u_fpstate - (char *) &u);
      return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
      return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
#else
#else
      fpstate = ubase + ((char *) &u.i387.st_space - (char *) &u);
      fpstate = ubase + ((char *) &u.i387.st_space - (char *) &u);
      return (fpstate + 10 * (regnum - FP0_REGNUM));
      return (fpstate + 10 * (regnum - FP0_REGNUM));
#endif
#endif
    }
    }
  else
  else
    {
    {
      return (ubase + 4 * regmap[regnum]);
      return (ubase + 4 * regmap[regnum]);
    }
    }
 
 
}
}


int
int
kernel_u_size ()
kernel_u_size ()
{
{
  return (sizeof (struct user));
  return (sizeof (struct user));
}
}


#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
 
 
#if !defined (offsetof)
#if !defined (offsetof)
#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
#endif
#endif
 
 
/* Record the value of the debug control register.  */
/* Record the value of the debug control register.  */
static int debug_control_mirror;
static int debug_control_mirror;
 
 
/* Record which address associates with which register.  */
/* Record which address associates with which register.  */
static CORE_ADDR address_lookup[DR_LASTADDR - DR_FIRSTADDR + 1];
static CORE_ADDR address_lookup[DR_LASTADDR - DR_FIRSTADDR + 1];
 
 
static int
static int
i386_insert_aligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
i386_insert_aligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
                                        int));
                                        int));
 
 
static int
static int
i386_insert_nonaligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
i386_insert_nonaligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
                                           int));
                                           int));
 
 
/* Insert a watchpoint.  */
/* Insert a watchpoint.  */
 
 
int
int
i386_insert_watchpoint (pid, addr, len, rw)
i386_insert_watchpoint (pid, addr, len, rw)
     int pid;
     int pid;
     CORE_ADDR addr;
     CORE_ADDR addr;
     int len;
     int len;
     int rw;
     int rw;
{
{
  return i386_insert_aligned_watchpoint (pid, addr, addr, len, rw);
  return i386_insert_aligned_watchpoint (pid, addr, addr, len, rw);
}
}
 
 
static int
static int
i386_insert_aligned_watchpoint (pid, waddr, addr, len, rw)
i386_insert_aligned_watchpoint (pid, waddr, addr, len, rw)
     int pid;
     int pid;
     CORE_ADDR waddr;
     CORE_ADDR waddr;
     CORE_ADDR addr;
     CORE_ADDR addr;
     int len;
     int len;
     int rw;
     int rw;
{
{
  int i;
  int i;
  int read_write_bits, len_bits;
  int read_write_bits, len_bits;
  int free_debug_register;
  int free_debug_register;
  int register_number;
  int register_number;
 
 
  /* Look for a free debug register.  */
  /* Look for a free debug register.  */
  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
    {
    {
      if (address_lookup[i - DR_FIRSTADDR] == 0)
      if (address_lookup[i - DR_FIRSTADDR] == 0)
        break;
        break;
    }
    }
 
 
  /* No more debug registers!  */
  /* No more debug registers!  */
  if (i > DR_LASTADDR)
  if (i > DR_LASTADDR)
    return -1;
    return -1;
 
 
  read_write_bits = (rw & 1) ? DR_RW_READ : DR_RW_WRITE;
  read_write_bits = (rw & 1) ? DR_RW_READ : DR_RW_WRITE;
 
 
  if (len == 1)
  if (len == 1)
    len_bits = DR_LEN_1;
    len_bits = DR_LEN_1;
  else if (len == 2)
  else if (len == 2)
    {
    {
      if (addr % 2)
      if (addr % 2)
        return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
        return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
      len_bits = DR_LEN_2;
      len_bits = DR_LEN_2;
    }
    }
 
 
  else if (len == 4)
  else if (len == 4)
    {
    {
      if (addr % 4)
      if (addr % 4)
        return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
        return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
      len_bits = DR_LEN_4;
      len_bits = DR_LEN_4;
    }
    }
  else
  else
    return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
    return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
 
 
  free_debug_register = i;
  free_debug_register = i;
  register_number = free_debug_register - DR_FIRSTADDR;
  register_number = free_debug_register - DR_FIRSTADDR;
  debug_control_mirror |=
  debug_control_mirror |=
    ((read_write_bits | len_bits)
    ((read_write_bits | len_bits)
     << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * register_number));
     << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * register_number));
  debug_control_mirror |=
  debug_control_mirror |=
    (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
    (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
  debug_control_mirror |= DR_LOCAL_SLOWDOWN;
  debug_control_mirror |= DR_LOCAL_SLOWDOWN;
  debug_control_mirror &= ~DR_CONTROL_RESERVED;
  debug_control_mirror &= ~DR_CONTROL_RESERVED;
 
 
  ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
  ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
          debug_control_mirror);
          debug_control_mirror);
  ptrace (6, pid, offsetof (struct user, u_debugreg[free_debug_register]),
  ptrace (6, pid, offsetof (struct user, u_debugreg[free_debug_register]),
          addr);
          addr);
 
 
  /* Record where we came from.  */
  /* Record where we came from.  */
  address_lookup[register_number] = addr;
  address_lookup[register_number] = addr;
  return 0;
  return 0;
}
}
 
 
static int
static int
i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw)
i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw)
     int pid;
     int pid;
     CORE_ADDR waddr;
     CORE_ADDR waddr;
     CORE_ADDR addr;
     CORE_ADDR addr;
     int len;
     int len;
     int rw;
     int rw;
{
{
  int align;
  int align;
  int size;
  int size;
  int rv;
  int rv;
 
 
  static int size_try_array[16] =
  static int size_try_array[16] =
  {
  {
    1, 1, 1, 1,                 /* trying size one */
    1, 1, 1, 1,                 /* trying size one */
    2, 1, 2, 1,                 /* trying size two */
    2, 1, 2, 1,                 /* trying size two */
    2, 1, 2, 1,                 /* trying size three */
    2, 1, 2, 1,                 /* trying size three */
    4, 1, 2, 1                  /* trying size four */
    4, 1, 2, 1                  /* trying size four */
  };
  };
 
 
  rv = 0;
  rv = 0;
  while (len > 0)
  while (len > 0)
    {
    {
      align = addr % 4;
      align = addr % 4;
      /* Four is the maximum length for 386.  */
      /* Four is the maximum length for 386.  */
      size = (len > 4) ? 3 : len - 1;
      size = (len > 4) ? 3 : len - 1;
      size = size_try_array[size * 4 + align];
      size = size_try_array[size * 4 + align];
 
 
      rv = i386_insert_aligned_watchpoint (pid, waddr, addr, size, rw);
      rv = i386_insert_aligned_watchpoint (pid, waddr, addr, size, rw);
      if (rv)
      if (rv)
        {
        {
          i386_remove_watchpoint (pid, waddr, size);
          i386_remove_watchpoint (pid, waddr, size);
          return rv;
          return rv;
        }
        }
      addr += size;
      addr += size;
      len -= size;
      len -= size;
    }
    }
  return rv;
  return rv;
}
}
 
 
/* Remove a watchpoint.  */
/* Remove a watchpoint.  */
 
 
int
int
i386_remove_watchpoint (pid, addr, len)
i386_remove_watchpoint (pid, addr, len)
     int pid;
     int pid;
     CORE_ADDR addr;
     CORE_ADDR addr;
     int len;
     int len;
{
{
  int i;
  int i;
  int register_number;
  int register_number;
 
 
  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
    {
    {
      register_number = i - DR_FIRSTADDR;
      register_number = i - DR_FIRSTADDR;
      if (address_lookup[register_number] == addr)
      if (address_lookup[register_number] == addr)
        {
        {
          debug_control_mirror &=
          debug_control_mirror &=
            ~(1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
            ~(1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
          address_lookup[register_number] = 0;
          address_lookup[register_number] = 0;
        }
        }
    }
    }
  ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
  ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
          debug_control_mirror);
          debug_control_mirror);
  ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
  ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
 
 
  return 0;
  return 0;
}
}
 
 
/* Check if stopped by a watchpoint.  */
/* Check if stopped by a watchpoint.  */
 
 
CORE_ADDR
CORE_ADDR
i386_stopped_by_watchpoint (pid)
i386_stopped_by_watchpoint (pid)
     int pid;
     int pid;
{
{
  int i;
  int i;
  int status;
  int status;
 
 
  status = ptrace (3, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
  status = ptrace (3, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
  ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
  ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
 
 
  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
    {
    {
      if (status & (1 << (i - DR_FIRSTADDR)))
      if (status & (1 << (i - DR_FIRSTADDR)))
        return address_lookup[i - DR_FIRSTADDR];
        return address_lookup[i - DR_FIRSTADDR];
    }
    }
 
 
  return 0;
  return 0;
}
}
 
 
#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
 
 

powered by: WebSVN 2.1.0

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