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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [s390-nat.c] - Diff between revs 834 and 842

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

Rev 834 Rev 842
/* S390 native-dependent code for GDB, the GNU debugger.
/* S390 native-dependent code for GDB, the GNU debugger.
   Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, 2009
   Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, 2009
   Free Software Foundation, Inc
   Free Software Foundation, Inc
 
 
   Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
   Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
   for IBM Deutschland Entwicklung GmbH, IBM Corporation.
   for IBM Deutschland Entwicklung GmbH, IBM Corporation.
 
 
   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 "regcache.h"
#include "regcache.h"
#include "inferior.h"
#include "inferior.h"
#include "target.h"
#include "target.h"
#include "linux-nat.h"
#include "linux-nat.h"
#include "auxv.h"
#include "auxv.h"
 
 
#include "s390-tdep.h"
#include "s390-tdep.h"
 
 
#include <asm/ptrace.h>
#include <asm/ptrace.h>
#include <sys/ptrace.h>
#include <sys/ptrace.h>
#include <asm/types.h>
#include <asm/types.h>
#include <sys/procfs.h>
#include <sys/procfs.h>
#include <sys/ucontext.h>
#include <sys/ucontext.h>
#include <elf.h>
#include <elf.h>
 
 
#ifndef HWCAP_S390_HIGH_GPRS
#ifndef HWCAP_S390_HIGH_GPRS
#define HWCAP_S390_HIGH_GPRS 512
#define HWCAP_S390_HIGH_GPRS 512
#endif
#endif
 
 
 
 
/* Map registers to gregset/ptrace offsets.
/* Map registers to gregset/ptrace offsets.
   These arrays are defined in s390-tdep.c.  */
   These arrays are defined in s390-tdep.c.  */
 
 
#ifdef __s390x__
#ifdef __s390x__
#define regmap_gregset s390x_regmap_gregset
#define regmap_gregset s390x_regmap_gregset
#else
#else
#define regmap_gregset s390_regmap_gregset
#define regmap_gregset s390_regmap_gregset
#endif
#endif
 
 
#define regmap_fpregset s390_regmap_fpregset
#define regmap_fpregset s390_regmap_fpregset
 
 
/* When debugging a 32-bit executable running under a 64-bit kernel,
/* When debugging a 32-bit executable running under a 64-bit kernel,
   we have to fix up the 64-bit registers we get from the kernel
   we have to fix up the 64-bit registers we get from the kernel
   to make them look like 32-bit registers.  */
   to make them look like 32-bit registers.  */
#ifdef __s390x__
#ifdef __s390x__
#define SUBOFF(gdbarch, i) \
#define SUBOFF(gdbarch, i) \
        ((gdbarch_ptr_bit (gdbarch) == 32 \
        ((gdbarch_ptr_bit (gdbarch) == 32 \
          && ((i) == S390_PSWA_REGNUM \
          && ((i) == S390_PSWA_REGNUM \
              || ((i) >= S390_R0_REGNUM && (i) <= S390_R15_REGNUM)))? 4 : 0)
              || ((i) >= S390_R0_REGNUM && (i) <= S390_R15_REGNUM)))? 4 : 0)
#else
#else
#define SUBOFF(gdbarch, i) 0
#define SUBOFF(gdbarch, i) 0
#endif
#endif
 
 
 
 
/* Fill GDB's register array with the general-purpose register values
/* Fill GDB's register array with the general-purpose register values
   in *REGP.  */
   in *REGP.  */
void
void
supply_gregset (struct regcache *regcache, const gregset_t *regp)
supply_gregset (struct regcache *regcache, const gregset_t *regp)
{
{
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  int i;
  int i;
  for (i = 0; i < S390_NUM_REGS; i++)
  for (i = 0; i < S390_NUM_REGS; i++)
    if (regmap_gregset[i] != -1)
    if (regmap_gregset[i] != -1)
      regcache_raw_supply (regcache, i,
      regcache_raw_supply (regcache, i,
                           (const char *)regp + regmap_gregset[i]
                           (const char *)regp + regmap_gregset[i]
                             + SUBOFF (gdbarch, i));
                             + SUBOFF (gdbarch, i));
}
}
 
 
/* Fill register REGNO (if it is a general-purpose register) in
/* Fill register REGNO (if it is a general-purpose register) in
   *REGP with the value in GDB's register array.  If REGNO is -1,
   *REGP with the value in GDB's register array.  If REGNO is -1,
   do this for all registers.  */
   do this for all registers.  */
void
void
fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
{
{
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  int i;
  int i;
  for (i = 0; i < S390_NUM_REGS; i++)
  for (i = 0; i < S390_NUM_REGS; i++)
    if (regmap_gregset[i] != -1)
    if (regmap_gregset[i] != -1)
      if (regno == -1 || regno == i)
      if (regno == -1 || regno == i)
        regcache_raw_collect (regcache, i,
        regcache_raw_collect (regcache, i,
                              (char *)regp + regmap_gregset[i]
                              (char *)regp + regmap_gregset[i]
                                + SUBOFF (gdbarch, i));
                                + SUBOFF (gdbarch, i));
}
}
 
 
/* Fill GDB's register array with the floating-point register values
/* Fill GDB's register array with the floating-point register values
   in *REGP.  */
   in *REGP.  */
void
void
supply_fpregset (struct regcache *regcache, const fpregset_t *regp)
supply_fpregset (struct regcache *regcache, const fpregset_t *regp)
{
{
  int i;
  int i;
  for (i = 0; i < S390_NUM_REGS; i++)
  for (i = 0; i < S390_NUM_REGS; i++)
    if (regmap_fpregset[i] != -1)
    if (regmap_fpregset[i] != -1)
      regcache_raw_supply (regcache, i,
      regcache_raw_supply (regcache, i,
                           (const char *)regp + regmap_fpregset[i]);
                           (const char *)regp + regmap_fpregset[i]);
}
}
 
 
/* Fill register REGNO (if it is a general-purpose register) in
/* Fill register REGNO (if it is a general-purpose register) in
   *REGP with the value in GDB's register array.  If REGNO is -1,
   *REGP with the value in GDB's register array.  If REGNO is -1,
   do this for all registers.  */
   do this for all registers.  */
void
void
fill_fpregset (const struct regcache *regcache, fpregset_t *regp, int regno)
fill_fpregset (const struct regcache *regcache, fpregset_t *regp, int regno)
{
{
  int i;
  int i;
  for (i = 0; i < S390_NUM_REGS; i++)
  for (i = 0; i < S390_NUM_REGS; i++)
    if (regmap_fpregset[i] != -1)
    if (regmap_fpregset[i] != -1)
      if (regno == -1 || regno == i)
      if (regno == -1 || regno == i)
        regcache_raw_collect (regcache, i,
        regcache_raw_collect (regcache, i,
                              (char *)regp + regmap_fpregset[i]);
                              (char *)regp + regmap_fpregset[i]);
}
}
 
 
/* Find the TID for the current inferior thread to use with ptrace.  */
/* Find the TID for the current inferior thread to use with ptrace.  */
static int
static int
s390_inferior_tid (void)
s390_inferior_tid (void)
{
{
  /* GNU/Linux LWP ID's are process ID's.  */
  /* GNU/Linux LWP ID's are process ID's.  */
  int tid = TIDGET (inferior_ptid);
  int tid = TIDGET (inferior_ptid);
  if (tid == 0)
  if (tid == 0)
    tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
    tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
 
 
  return tid;
  return tid;
}
}
 
 
/* Fetch all general-purpose registers from process/thread TID and
/* Fetch all general-purpose registers from process/thread TID and
   store their values in GDB's register cache.  */
   store their values in GDB's register cache.  */
static void
static void
fetch_regs (struct regcache *regcache, int tid)
fetch_regs (struct regcache *regcache, int tid)
{
{
  gregset_t regs;
  gregset_t regs;
  ptrace_area parea;
  ptrace_area parea;
 
 
  parea.len = sizeof (regs);
  parea.len = sizeof (regs);
  parea.process_addr = (addr_t) &regs;
  parea.process_addr = (addr_t) &regs;
  parea.kernel_addr = offsetof (struct user_regs_struct, psw);
  parea.kernel_addr = offsetof (struct user_regs_struct, psw);
  if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
  if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
    perror_with_name (_("Couldn't get registers"));
    perror_with_name (_("Couldn't get registers"));
 
 
  supply_gregset (regcache, (const gregset_t *) &regs);
  supply_gregset (regcache, (const gregset_t *) &regs);
}
}
 
 
/* Store all valid general-purpose registers in GDB's register cache
/* Store all valid general-purpose registers in GDB's register cache
   into the process/thread specified by TID.  */
   into the process/thread specified by TID.  */
static void
static void
store_regs (const struct regcache *regcache, int tid, int regnum)
store_regs (const struct regcache *regcache, int tid, int regnum)
{
{
  gregset_t regs;
  gregset_t regs;
  ptrace_area parea;
  ptrace_area parea;
 
 
  parea.len = sizeof (regs);
  parea.len = sizeof (regs);
  parea.process_addr = (addr_t) &regs;
  parea.process_addr = (addr_t) &regs;
  parea.kernel_addr = offsetof (struct user_regs_struct, psw);
  parea.kernel_addr = offsetof (struct user_regs_struct, psw);
  if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
  if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
    perror_with_name (_("Couldn't get registers"));
    perror_with_name (_("Couldn't get registers"));
 
 
  fill_gregset (regcache, &regs, regnum);
  fill_gregset (regcache, &regs, regnum);
 
 
  if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
  if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
    perror_with_name (_("Couldn't write registers"));
    perror_with_name (_("Couldn't write registers"));
}
}
 
 
/* Fetch all floating-point registers from process/thread TID and store
/* Fetch all floating-point registers from process/thread TID and store
   their values in GDB's register cache.  */
   their values in GDB's register cache.  */
static void
static void
fetch_fpregs (struct regcache *regcache, int tid)
fetch_fpregs (struct regcache *regcache, int tid)
{
{
  fpregset_t fpregs;
  fpregset_t fpregs;
  ptrace_area parea;
  ptrace_area parea;
 
 
  parea.len = sizeof (fpregs);
  parea.len = sizeof (fpregs);
  parea.process_addr = (addr_t) &fpregs;
  parea.process_addr = (addr_t) &fpregs;
  parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs);
  parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs);
  if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
  if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
    perror_with_name (_("Couldn't get floating point status"));
    perror_with_name (_("Couldn't get floating point status"));
 
 
  supply_fpregset (regcache, (const fpregset_t *) &fpregs);
  supply_fpregset (regcache, (const fpregset_t *) &fpregs);
}
}
 
 
/* Store all valid floating-point registers in GDB's register cache
/* Store all valid floating-point registers in GDB's register cache
   into the process/thread specified by TID.  */
   into the process/thread specified by TID.  */
static void
static void
store_fpregs (const struct regcache *regcache, int tid, int regnum)
store_fpregs (const struct regcache *regcache, int tid, int regnum)
{
{
  fpregset_t fpregs;
  fpregset_t fpregs;
  ptrace_area parea;
  ptrace_area parea;
 
 
  parea.len = sizeof (fpregs);
  parea.len = sizeof (fpregs);
  parea.process_addr = (addr_t) &fpregs;
  parea.process_addr = (addr_t) &fpregs;
  parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs);
  parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs);
  if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
  if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0)
    perror_with_name (_("Couldn't get floating point status"));
    perror_with_name (_("Couldn't get floating point status"));
 
 
  fill_fpregset (regcache, &fpregs, regnum);
  fill_fpregset (regcache, &fpregs, regnum);
 
 
  if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
  if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0)
    perror_with_name (_("Couldn't write floating point status"));
    perror_with_name (_("Couldn't write floating point status"));
}
}
 
 
/* Fetch register REGNUM from the child process.  If REGNUM is -1, do
/* Fetch register REGNUM from the child process.  If REGNUM is -1, do
   this for all registers.  */
   this for all registers.  */
static void
static void
s390_linux_fetch_inferior_registers (struct target_ops *ops,
s390_linux_fetch_inferior_registers (struct target_ops *ops,
                                     struct regcache *regcache, int regnum)
                                     struct regcache *regcache, int regnum)
{
{
  int tid = s390_inferior_tid ();
  int tid = s390_inferior_tid ();
 
 
  if (regnum == -1
  if (regnum == -1
      || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
      || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
    fetch_regs (regcache, tid);
    fetch_regs (regcache, tid);
 
 
  if (regnum == -1
  if (regnum == -1
      || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
      || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
    fetch_fpregs (regcache, tid);
    fetch_fpregs (regcache, tid);
}
}
 
 
/* Store register REGNUM back into the child process.  If REGNUM is
/* Store register REGNUM back into the child process.  If REGNUM is
   -1, do this for all registers.  */
   -1, do this for all registers.  */
static void
static void
s390_linux_store_inferior_registers (struct target_ops *ops,
s390_linux_store_inferior_registers (struct target_ops *ops,
                                     struct regcache *regcache, int regnum)
                                     struct regcache *regcache, int regnum)
{
{
  int tid = s390_inferior_tid ();
  int tid = s390_inferior_tid ();
 
 
  if (regnum == -1
  if (regnum == -1
      || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
      || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
    store_regs (regcache, tid, regnum);
    store_regs (regcache, tid, regnum);
 
 
  if (regnum == -1
  if (regnum == -1
      || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
      || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
    store_fpregs (regcache, tid, regnum);
    store_fpregs (regcache, tid, regnum);
}
}
 
 
 
 
/* Hardware-assisted watchpoint handling.  */
/* Hardware-assisted watchpoint handling.  */
 
 
/* We maintain a list of all currently active watchpoints in order
/* We maintain a list of all currently active watchpoints in order
   to properly handle watchpoint removal.
   to properly handle watchpoint removal.
 
 
   The only thing we actually need is the total address space area
   The only thing we actually need is the total address space area
   spanned by the watchpoints.  */
   spanned by the watchpoints.  */
 
 
struct watch_area
struct watch_area
{
{
  struct watch_area *next;
  struct watch_area *next;
  CORE_ADDR lo_addr;
  CORE_ADDR lo_addr;
  CORE_ADDR hi_addr;
  CORE_ADDR hi_addr;
};
};
 
 
static struct watch_area *watch_base = NULL;
static struct watch_area *watch_base = NULL;
 
 
static int
static int
s390_stopped_by_watchpoint (void)
s390_stopped_by_watchpoint (void)
{
{
  per_lowcore_bits per_lowcore;
  per_lowcore_bits per_lowcore;
  ptrace_area parea;
  ptrace_area parea;
  int result;
  int result;
 
 
  /* Speed up common case.  */
  /* Speed up common case.  */
  if (!watch_base)
  if (!watch_base)
    return 0;
    return 0;
 
 
  parea.len = sizeof (per_lowcore);
  parea.len = sizeof (per_lowcore);
  parea.process_addr = (addr_t) & per_lowcore;
  parea.process_addr = (addr_t) & per_lowcore;
  parea.kernel_addr = offsetof (struct user_regs_struct, per_info.lowcore);
  parea.kernel_addr = offsetof (struct user_regs_struct, per_info.lowcore);
  if (ptrace (PTRACE_PEEKUSR_AREA, s390_inferior_tid (), &parea) < 0)
  if (ptrace (PTRACE_PEEKUSR_AREA, s390_inferior_tid (), &parea) < 0)
    perror_with_name (_("Couldn't retrieve watchpoint status"));
    perror_with_name (_("Couldn't retrieve watchpoint status"));
 
 
  result = (per_lowcore.perc_storage_alteration == 1
  result = (per_lowcore.perc_storage_alteration == 1
            && per_lowcore.perc_store_real_address == 0);
            && per_lowcore.perc_store_real_address == 0);
 
 
  if (result)
  if (result)
    {
    {
      /* Do not report this watchpoint again.  */
      /* Do not report this watchpoint again.  */
      memset (&per_lowcore, 0, sizeof (per_lowcore));
      memset (&per_lowcore, 0, sizeof (per_lowcore));
      if (ptrace (PTRACE_POKEUSR_AREA, s390_inferior_tid (), &parea) < 0)
      if (ptrace (PTRACE_POKEUSR_AREA, s390_inferior_tid (), &parea) < 0)
        perror_with_name (_("Couldn't clear watchpoint status"));
        perror_with_name (_("Couldn't clear watchpoint status"));
    }
    }
 
 
  return result;
  return result;
}
}
 
 
static void
static void
s390_fix_watch_points (ptid_t ptid)
s390_fix_watch_points (ptid_t ptid)
{
{
  int tid;
  int tid;
 
 
  per_struct per_info;
  per_struct per_info;
  ptrace_area parea;
  ptrace_area parea;
 
 
  CORE_ADDR watch_lo_addr = (CORE_ADDR)-1, watch_hi_addr = 0;
  CORE_ADDR watch_lo_addr = (CORE_ADDR)-1, watch_hi_addr = 0;
  struct watch_area *area;
  struct watch_area *area;
 
 
  tid = TIDGET (ptid);
  tid = TIDGET (ptid);
  if (tid == 0)
  if (tid == 0)
    tid = PIDGET (ptid);
    tid = PIDGET (ptid);
 
 
  for (area = watch_base; area; area = area->next)
  for (area = watch_base; area; area = area->next)
    {
    {
      watch_lo_addr = min (watch_lo_addr, area->lo_addr);
      watch_lo_addr = min (watch_lo_addr, area->lo_addr);
      watch_hi_addr = max (watch_hi_addr, area->hi_addr);
      watch_hi_addr = max (watch_hi_addr, area->hi_addr);
    }
    }
 
 
  parea.len = sizeof (per_info);
  parea.len = sizeof (per_info);
  parea.process_addr = (addr_t) & per_info;
  parea.process_addr = (addr_t) & per_info;
  parea.kernel_addr = offsetof (struct user_regs_struct, per_info);
  parea.kernel_addr = offsetof (struct user_regs_struct, per_info);
  if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea) < 0)
  if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea) < 0)
    perror_with_name (_("Couldn't retrieve watchpoint status"));
    perror_with_name (_("Couldn't retrieve watchpoint status"));
 
 
  if (watch_base)
  if (watch_base)
    {
    {
      per_info.control_regs.bits.em_storage_alteration = 1;
      per_info.control_regs.bits.em_storage_alteration = 1;
      per_info.control_regs.bits.storage_alt_space_ctl = 1;
      per_info.control_regs.bits.storage_alt_space_ctl = 1;
    }
    }
  else
  else
    {
    {
      per_info.control_regs.bits.em_storage_alteration = 0;
      per_info.control_regs.bits.em_storage_alteration = 0;
      per_info.control_regs.bits.storage_alt_space_ctl = 0;
      per_info.control_regs.bits.storage_alt_space_ctl = 0;
    }
    }
  per_info.starting_addr = watch_lo_addr;
  per_info.starting_addr = watch_lo_addr;
  per_info.ending_addr = watch_hi_addr;
  per_info.ending_addr = watch_hi_addr;
 
 
  if (ptrace (PTRACE_POKEUSR_AREA, tid, &parea) < 0)
  if (ptrace (PTRACE_POKEUSR_AREA, tid, &parea) < 0)
    perror_with_name (_("Couldn't modify watchpoint status"));
    perror_with_name (_("Couldn't modify watchpoint status"));
}
}
 
 
static int
static int
s390_insert_watchpoint (CORE_ADDR addr, int len, int type)
s390_insert_watchpoint (CORE_ADDR addr, int len, int type)
{
{
  struct lwp_info *lp;
  struct lwp_info *lp;
  ptid_t ptid;
  ptid_t ptid;
  struct watch_area *area = xmalloc (sizeof (struct watch_area));
  struct watch_area *area = xmalloc (sizeof (struct watch_area));
 
 
  if (!area)
  if (!area)
    return -1;
    return -1;
 
 
  area->lo_addr = addr;
  area->lo_addr = addr;
  area->hi_addr = addr + len - 1;
  area->hi_addr = addr + len - 1;
 
 
  area->next = watch_base;
  area->next = watch_base;
  watch_base = area;
  watch_base = area;
 
 
  ALL_LWPS (lp, ptid)
  ALL_LWPS (lp, ptid)
    s390_fix_watch_points (ptid);
    s390_fix_watch_points (ptid);
  return 0;
  return 0;
}
}
 
 
static int
static int
s390_remove_watchpoint (CORE_ADDR addr, int len, int type)
s390_remove_watchpoint (CORE_ADDR addr, int len, int type)
{
{
  struct lwp_info *lp;
  struct lwp_info *lp;
  ptid_t ptid;
  ptid_t ptid;
  struct watch_area *area, **parea;
  struct watch_area *area, **parea;
 
 
  for (parea = &watch_base; *parea; parea = &(*parea)->next)
  for (parea = &watch_base; *parea; parea = &(*parea)->next)
    if ((*parea)->lo_addr == addr
    if ((*parea)->lo_addr == addr
        && (*parea)->hi_addr == addr + len - 1)
        && (*parea)->hi_addr == addr + len - 1)
      break;
      break;
 
 
  if (!*parea)
  if (!*parea)
    {
    {
      fprintf_unfiltered (gdb_stderr,
      fprintf_unfiltered (gdb_stderr,
                          "Attempt to remove nonexistent watchpoint.\n");
                          "Attempt to remove nonexistent watchpoint.\n");
      return -1;
      return -1;
    }
    }
 
 
  area = *parea;
  area = *parea;
  *parea = area->next;
  *parea = area->next;
  xfree (area);
  xfree (area);
 
 
  ALL_LWPS (lp, ptid)
  ALL_LWPS (lp, ptid)
    s390_fix_watch_points (ptid);
    s390_fix_watch_points (ptid);
  return 0;
  return 0;
}
}
 
 
static int
static int
s390_can_use_hw_breakpoint (int type, int cnt, int othertype)
s390_can_use_hw_breakpoint (int type, int cnt, int othertype)
{
{
  return type == bp_hardware_watchpoint;
  return type == bp_hardware_watchpoint;
}
}
 
 
static int
static int
s390_region_ok_for_hw_watchpoint (CORE_ADDR addr, int cnt)
s390_region_ok_for_hw_watchpoint (CORE_ADDR addr, int cnt)
{
{
  return 1;
  return 1;
}
}
 
 
static int
static int
s390_target_wordsize (void)
s390_target_wordsize (void)
{
{
  int wordsize = 4;
  int wordsize = 4;
 
 
  /* Check for 64-bit inferior process.  This is the case when the host is
  /* Check for 64-bit inferior process.  This is the case when the host is
     64-bit, and in addition bit 32 of the PSW mask is set.  */
     64-bit, and in addition bit 32 of the PSW mask is set.  */
#ifdef __s390x__
#ifdef __s390x__
  long pswm;
  long pswm;
 
 
  errno = 0;
  errno = 0;
  pswm = (long) ptrace (PTRACE_PEEKUSER, s390_inferior_tid (), PT_PSWMASK, 0);
  pswm = (long) ptrace (PTRACE_PEEKUSER, s390_inferior_tid (), PT_PSWMASK, 0);
  if (errno == 0 && (pswm & 0x100000000ul) != 0)
  if (errno == 0 && (pswm & 0x100000000ul) != 0)
    wordsize = 8;
    wordsize = 8;
#endif
#endif
 
 
  return wordsize;
  return wordsize;
}
}
 
 
static int
static int
s390_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
s390_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
                 gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
                 gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
{
{
  int sizeof_auxv_field = s390_target_wordsize ();
  int sizeof_auxv_field = s390_target_wordsize ();
  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
  gdb_byte *ptr = *readptr;
  gdb_byte *ptr = *readptr;
 
 
  if (endptr == ptr)
  if (endptr == ptr)
    return 0;
    return 0;
 
 
  if (endptr - ptr < sizeof_auxv_field * 2)
  if (endptr - ptr < sizeof_auxv_field * 2)
    return -1;
    return -1;
 
 
  *typep = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
  *typep = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
  ptr += sizeof_auxv_field;
  ptr += sizeof_auxv_field;
  *valp = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
  *valp = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
  ptr += sizeof_auxv_field;
  ptr += sizeof_auxv_field;
 
 
  *readptr = ptr;
  *readptr = ptr;
  return 1;
  return 1;
}
}
 
 
#ifdef __s390x__
#ifdef __s390x__
static unsigned long
static unsigned long
s390_get_hwcap (void)
s390_get_hwcap (void)
{
{
  CORE_ADDR field;
  CORE_ADDR field;
 
 
  if (target_auxv_search (&current_target, AT_HWCAP, &field))
  if (target_auxv_search (&current_target, AT_HWCAP, &field))
    return (unsigned long) field;
    return (unsigned long) field;
 
 
  return 0;
  return 0;
}
}
#endif
#endif
 
 
static const struct target_desc *
static const struct target_desc *
s390_read_description (struct target_ops *ops)
s390_read_description (struct target_ops *ops)
{
{
#ifdef __s390x__
#ifdef __s390x__
  /* If GDB itself is compiled as 64-bit, we are running on a machine in
  /* If GDB itself is compiled as 64-bit, we are running on a machine in
     z/Architecture mode.  If the target is running in 64-bit addressing
     z/Architecture mode.  If the target is running in 64-bit addressing
     mode, report s390x architecture.  If the target is running in 31-bit
     mode, report s390x architecture.  If the target is running in 31-bit
     addressing mode, but the kernel supports using 64-bit registers in
     addressing mode, but the kernel supports using 64-bit registers in
     that mode, report s390 architecture with 64-bit GPRs.  */
     that mode, report s390 architecture with 64-bit GPRs.  */
 
 
  if (s390_target_wordsize () == 8)
  if (s390_target_wordsize () == 8)
    return tdesc_s390x_linux64;
    return tdesc_s390x_linux64;
 
 
  if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS)
  if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS)
    return tdesc_s390_linux64;
    return tdesc_s390_linux64;
#endif
#endif
 
 
  /* If GDB itself is compiled as 31-bit, or if we're running a 31-bit inferior
  /* If GDB itself is compiled as 31-bit, or if we're running a 31-bit inferior
     on a 64-bit kernel that does not support using 64-bit registers in 31-bit
     on a 64-bit kernel that does not support using 64-bit registers in 31-bit
     mode, report s390 architecture with 32-bit GPRs.  */
     mode, report s390 architecture with 32-bit GPRs.  */
  return tdesc_s390_linux32;
  return tdesc_s390_linux32;
}
}
 
 
void _initialize_s390_nat (void);
void _initialize_s390_nat (void);
 
 
void
void
_initialize_s390_nat (void)
_initialize_s390_nat (void)
{
{
  struct target_ops *t;
  struct target_ops *t;
 
 
  /* Fill in the generic GNU/Linux methods.  */
  /* Fill in the generic GNU/Linux methods.  */
  t = linux_target ();
  t = linux_target ();
 
 
  /* Add our register access methods.  */
  /* Add our register access methods.  */
  t->to_fetch_registers = s390_linux_fetch_inferior_registers;
  t->to_fetch_registers = s390_linux_fetch_inferior_registers;
  t->to_store_registers = s390_linux_store_inferior_registers;
  t->to_store_registers = s390_linux_store_inferior_registers;
 
 
  /* Add our watchpoint methods.  */
  /* Add our watchpoint methods.  */
  t->to_can_use_hw_breakpoint = s390_can_use_hw_breakpoint;
  t->to_can_use_hw_breakpoint = s390_can_use_hw_breakpoint;
  t->to_region_ok_for_hw_watchpoint = s390_region_ok_for_hw_watchpoint;
  t->to_region_ok_for_hw_watchpoint = s390_region_ok_for_hw_watchpoint;
  t->to_have_continuable_watchpoint = 1;
  t->to_have_continuable_watchpoint = 1;
  t->to_stopped_by_watchpoint = s390_stopped_by_watchpoint;
  t->to_stopped_by_watchpoint = s390_stopped_by_watchpoint;
  t->to_insert_watchpoint = s390_insert_watchpoint;
  t->to_insert_watchpoint = s390_insert_watchpoint;
  t->to_remove_watchpoint = s390_remove_watchpoint;
  t->to_remove_watchpoint = s390_remove_watchpoint;
 
 
  /* Detect target architecture.  */
  /* Detect target architecture.  */
  t->to_read_description = s390_read_description;
  t->to_read_description = s390_read_description;
  t->to_auxv_parse = s390_auxv_parse;
  t->to_auxv_parse = s390_auxv_parse;
 
 
  /* Register the target.  */
  /* Register the target.  */
  linux_nat_add_target (t);
  linux_nat_add_target (t);
  linux_nat_set_new_thread (t, s390_fix_watch_points);
  linux_nat_set_new_thread (t, s390_fix_watch_points);
}
}
 
 

powered by: WebSVN 2.1.0

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