| Index: gdb/s390-linux-nat.c
|
| diff --git a/gdb/s390-nat.c b/gdb/s390-linux-nat.c
|
| similarity index 76%
|
| rename from gdb/s390-nat.c
|
| rename to gdb/s390-linux-nat.c
|
| index bad1b437f88ba93306f42e91d47476a4cd902a27..cf3f7d7c8288d795ec9e666857f8f79bf4a94513 100644
|
| --- a/gdb/s390-nat.c
|
| +++ b/gdb/s390-linux-nat.c
|
| @@ -1,6 +1,5 @@
|
| /* S390 native-dependent code for GDB, the GNU debugger.
|
| - Copyright (C) 2001, 2003-2007, 2009, 2012 Free Software Foundation,
|
| - Inc.
|
| + Copyright (C) 2001-2013 Free Software Foundation, Inc.
|
|
|
| Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
|
| for IBM Deutschland Entwicklung GmbH, IBM Corporation.
|
| @@ -28,7 +27,7 @@
|
| #include "auxv.h"
|
| #include "gregset.h"
|
|
|
| -#include "s390-tdep.h"
|
| +#include "s390-linux-tdep.h"
|
| #include "elf/common.h"
|
|
|
| #include <asm/ptrace.h>
|
| @@ -38,10 +37,6 @@
|
| #include <sys/ucontext.h>
|
| #include <elf.h>
|
|
|
| -#ifndef HWCAP_S390_HIGH_GPRS
|
| -#define HWCAP_S390_HIGH_GPRS 512
|
| -#endif
|
| -
|
| #ifndef PTRACE_GETREGSET
|
| #define PTRACE_GETREGSET 0x4204
|
| #endif
|
| @@ -52,6 +47,7 @@
|
|
|
| static int have_regset_last_break = 0;
|
| static int have_regset_system_call = 0;
|
| +static int have_regset_tdb = 0;
|
|
|
| /* Map registers to gregset/ptrace offsets.
|
| These arrays are defined in s390-tdep.c. */
|
| @@ -64,139 +60,139 @@ static int have_regset_system_call = 0;
|
|
|
| #define regmap_fpregset s390_regmap_fpregset
|
|
|
| -/* 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
|
| - to make them look like 32-bit registers. */
|
| +/* Fill the regset described by MAP into REGCACHE, using the values
|
| + from REGP. The MAP array represents each register as a pair
|
| + (offset, regno) of short integers and is terminated with -1. */
|
|
|
| static void
|
| -s390_native_supply (struct regcache *regcache, int regno,
|
| - const gdb_byte *regp, int *regmap)
|
| +s390_native_supply (struct regcache *regcache, const short *map,
|
| + const gdb_byte *regp)
|
| {
|
| - int offset = regmap[regno];
|
| + for (; map[0] >= 0; map += 2)
|
| + regcache_raw_supply (regcache, map[1], regp ? regp + map[0] : NULL);
|
| +}
|
| +
|
| +/* Collect the register REGNO out of the regset described by MAP from
|
| + REGCACHE into REGP. If REGNO == -1, do this for all registers in
|
| + this regset. */
|
| +
|
| +static void
|
| +s390_native_collect (const struct regcache *regcache, const short *map,
|
| + int regno, gdb_byte *regp)
|
| +{
|
| + for (; map[0] >= 0; map += 2)
|
| + if (regno == -1 || regno == map[1])
|
| + regcache_raw_collect (regcache, map[1], regp + map[0]);
|
| +}
|
| +
|
| +/* Fill GDB's register array with the general-purpose register values
|
| + in *REGP.
|
| +
|
| + 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 to
|
| + make them look like 32-bit registers. */
|
|
|
| +void
|
| +supply_gregset (struct regcache *regcache, const gregset_t *regp)
|
| +{
|
| #ifdef __s390x__
|
| struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
| - if (offset != -1 && gdbarch_ptr_bit (gdbarch) == 32)
|
| + if (gdbarch_ptr_bit (gdbarch) == 32)
|
| {
|
| enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
| + ULONGEST pswm = 0, pswa = 0;
|
| + gdb_byte buf[4];
|
| + const short *map;
|
|
|
| - if (regno == S390_PSWM_REGNUM)
|
| - {
|
| - ULONGEST pswm;
|
| - gdb_byte buf[4];
|
| -
|
| - pswm = extract_unsigned_integer (regp + regmap[S390_PSWM_REGNUM],
|
| - 8, byte_order);
|
| -
|
| - store_unsigned_integer (buf, 4, byte_order, (pswm >> 32) | 0x80000);
|
| - regcache_raw_supply (regcache, regno, buf);
|
| - return;
|
| - }
|
| -
|
| - if (regno == S390_PSWA_REGNUM)
|
| + for (map = regmap_gregset; map[0] >= 0; map += 2)
|
| {
|
| - ULONGEST pswm, pswa;
|
| - gdb_byte buf[4];
|
| -
|
| - pswa = extract_unsigned_integer (regp + regmap[S390_PSWA_REGNUM],
|
| - 8, byte_order);
|
| - pswm = extract_unsigned_integer (regp + regmap[S390_PSWM_REGNUM],
|
| - 8, byte_order);
|
| -
|
| - store_unsigned_integer (buf, 4, byte_order,
|
| - (pswa & 0x7fffffff) | (pswm & 0x80000000));
|
| - regcache_raw_supply (regcache, regno, buf);
|
| - return;
|
| + const gdb_byte *p = (const gdb_byte *) regp + map[0];
|
| + int regno = map[1];
|
| +
|
| + if (regno == S390_PSWM_REGNUM)
|
| + pswm = extract_unsigned_integer (p, 8, byte_order);
|
| + else if (regno == S390_PSWA_REGNUM)
|
| + pswa = extract_unsigned_integer (p, 8, byte_order);
|
| + else
|
| + {
|
| + if ((regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM)
|
| + || regno == S390_ORIG_R2_REGNUM)
|
| + p += 4;
|
| + regcache_raw_supply (regcache, regno, p);
|
| + }
|
| }
|
|
|
| - if ((regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM)
|
| - || regno == S390_ORIG_R2_REGNUM)
|
| - offset += 4;
|
| + store_unsigned_integer (buf, 4, byte_order, (pswm >> 32) | 0x80000);
|
| + regcache_raw_supply (regcache, S390_PSWM_REGNUM, buf);
|
| + store_unsigned_integer (buf, 4, byte_order,
|
| + (pswa & 0x7fffffff) | (pswm & 0x80000000));
|
| + regcache_raw_supply (regcache, S390_PSWA_REGNUM, buf);
|
| + return;
|
| }
|
| #endif
|
|
|
| - if (offset != -1)
|
| - regcache_raw_supply (regcache, regno, regp + offset);
|
| + s390_native_supply (regcache, regmap_gregset, (const gdb_byte *) regp);
|
| }
|
|
|
| -static void
|
| -s390_native_collect (const struct regcache *regcache, int regno,
|
| - gdb_byte *regp, int *regmap)
|
| -{
|
| - int offset = regmap[regno];
|
| +/* Fill register REGNO (if it is a general-purpose register) in
|
| + *REGP with the value in GDB's register array. If REGNO is -1,
|
| + do this for all registers. */
|
|
|
| +void
|
| +fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
|
| +{
|
| #ifdef __s390x__
|
| struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
| - if (offset != -1 && gdbarch_ptr_bit (gdbarch) == 32)
|
| + if (gdbarch_ptr_bit (gdbarch) == 32)
|
| {
|
| - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
| + gdb_byte *psw_p[2];
|
| + const short *map;
|
|
|
| - if (regno == S390_PSWM_REGNUM)
|
| + for (map = regmap_gregset; map[0] >= 0; map += 2)
|
| {
|
| - ULONGEST pswm;
|
| - gdb_byte buf[4];
|
| -
|
| - regcache_raw_collect (regcache, regno, buf);
|
| - pswm = extract_unsigned_integer (buf, 4, byte_order);
|
| -
|
| - /* We don't know the final addressing mode until the PSW address
|
| - is known, so leave it as-is. When the PSW address is collected
|
| - (below), the addressing mode will be updated. */
|
| - store_unsigned_integer (regp + regmap[S390_PSWM_REGNUM],
|
| - 4, byte_order, pswm & 0xfff7ffff);
|
| - return;
|
| + gdb_byte *p = (gdb_byte *) regp + map[0];
|
| + int reg = map[1];
|
| +
|
| + if (reg >= S390_PSWM_REGNUM && reg <= S390_PSWA_REGNUM)
|
| + psw_p[reg - S390_PSWM_REGNUM] = p;
|
| +
|
| + else if (regno == -1 || regno == reg)
|
| + {
|
| + if ((reg >= S390_R0_REGNUM && reg <= S390_R15_REGNUM)
|
| + || reg == S390_ORIG_R2_REGNUM)
|
| + {
|
| + memset (p, 0, 4);
|
| + p += 4;
|
| + }
|
| + regcache_raw_collect (regcache, reg, p + 4);
|
| + }
|
| }
|
|
|
| - if (regno == S390_PSWA_REGNUM)
|
| + if (regno == -1
|
| + || regno == S390_PSWM_REGNUM || regno == S390_PSWA_REGNUM)
|
| {
|
| - ULONGEST pswa;
|
| + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
| + ULONGEST pswa, pswm;
|
| gdb_byte buf[4];
|
|
|
| - regcache_raw_collect (regcache, regno, buf);
|
| + regcache_raw_collect (regcache, S390_PSWM_REGNUM, buf);
|
| + pswm = extract_unsigned_integer (buf, 4, byte_order);
|
| + regcache_raw_collect (regcache, S390_PSWA_REGNUM, buf);
|
| pswa = extract_unsigned_integer (buf, 4, byte_order);
|
|
|
| - store_unsigned_integer (regp + regmap[S390_PSWA_REGNUM],
|
| - 8, byte_order, pswa & 0x7fffffff);
|
| -
|
| - /* Update basic addressing mode bit in PSW mask, see above. */
|
| - store_unsigned_integer (regp + regmap[S390_PSWM_REGNUM] + 4,
|
| - 4, byte_order, pswa & 0x80000000);
|
| - return;
|
| - }
|
| -
|
| - if ((regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM)
|
| - || regno == S390_ORIG_R2_REGNUM)
|
| - {
|
| - memset (regp + offset, 0, 4);
|
| - offset += 4;
|
| + if (regno == -1 || regno == S390_PSWM_REGNUM)
|
| + store_unsigned_integer (psw_p[0], 8, byte_order,
|
| + ((pswm & 0xfff7ffff) << 32) |
|
| + (pswa & 0x80000000));
|
| + if (regno == -1 || regno == S390_PSWA_REGNUM)
|
| + store_unsigned_integer (psw_p[1], 8, byte_order,
|
| + pswa & 0x7fffffff);
|
| }
|
| + return;
|
| }
|
| #endif
|
|
|
| - if (offset != -1)
|
| - regcache_raw_collect (regcache, regno, regp + offset);
|
| -}
|
| -
|
| -/* Fill GDB's register array with the general-purpose register values
|
| - in *REGP. */
|
| -void
|
| -supply_gregset (struct regcache *regcache, const gregset_t *regp)
|
| -{
|
| - int i;
|
| - for (i = 0; i < S390_NUM_REGS; i++)
|
| - s390_native_supply (regcache, i, (const gdb_byte *) regp, regmap_gregset);
|
| -}
|
| -
|
| -/* Fill register REGNO (if it is a general-purpose register) in
|
| - *REGP with the value in GDB's register array. If REGNO is -1,
|
| - do this for all registers. */
|
| -void
|
| -fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
|
| -{
|
| - int i;
|
| - for (i = 0; i < S390_NUM_REGS; i++)
|
| - if (regno == -1 || regno == i)
|
| - s390_native_collect (regcache, i, (gdb_byte *) regp, regmap_gregset);
|
| + s390_native_collect (regcache, regmap_gregset, regno, (gdb_byte *) regp);
|
| }
|
|
|
| /* Fill GDB's register array with the floating-point register values
|
| @@ -204,9 +200,7 @@ fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
|
| void
|
| supply_fpregset (struct regcache *regcache, const fpregset_t *regp)
|
| {
|
| - int i;
|
| - for (i = 0; i < S390_NUM_REGS; i++)
|
| - s390_native_supply (regcache, i, (const gdb_byte *) regp, regmap_fpregset);
|
| + s390_native_supply (regcache, regmap_fpregset, (const gdb_byte *) regp);
|
| }
|
|
|
| /* Fill register REGNO (if it is a general-purpose register) in
|
| @@ -215,10 +209,7 @@ supply_fpregset (struct regcache *regcache, const fpregset_t *regp)
|
| void
|
| fill_fpregset (const struct regcache *regcache, fpregset_t *regp, int regno)
|
| {
|
| - int i;
|
| - for (i = 0; i < S390_NUM_REGS; i++)
|
| - if (regno == -1 || regno == i)
|
| - s390_native_collect (regcache, i, (gdb_byte *) regp, regmap_fpregset);
|
| + s390_native_collect (regcache, regmap_fpregset, regno, (gdb_byte *) regp);
|
| }
|
|
|
| /* Find the TID for the current inferior thread to use with ptrace. */
|
| @@ -226,9 +217,9 @@ static int
|
| s390_inferior_tid (void)
|
| {
|
| /* GNU/Linux LWP ID's are process ID's. */
|
| - int tid = TIDGET (inferior_ptid);
|
| + int tid = ptid_get_lwp (inferior_ptid);
|
| if (tid == 0)
|
| - tid = PIDGET (inferior_ptid); /* Not a threaded program. */
|
| + tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */
|
|
|
| return tid;
|
| }
|
| @@ -312,21 +303,23 @@ store_fpregs (const struct regcache *regcache, int tid, int regnum)
|
| process/thread TID and store their values in GDB's register cache. */
|
| static void
|
| fetch_regset (struct regcache *regcache, int tid,
|
| - int regset, int regsize, int *regmap)
|
| + int regset, int regsize, const short *regmap)
|
| {
|
| - struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
| gdb_byte *buf = alloca (regsize);
|
| struct iovec iov;
|
| - int i;
|
|
|
| iov.iov_base = buf;
|
| iov.iov_len = regsize;
|
|
|
| if (ptrace (PTRACE_GETREGSET, tid, (long) regset, (long) &iov) < 0)
|
| - perror_with_name (_("Couldn't get register set"));
|
| -
|
| - for (i = 0; i < S390_NUM_REGS; i++)
|
| - s390_native_supply (regcache, i, buf, regmap);
|
| + {
|
| + if (errno == ENODATA)
|
| + s390_native_supply (regcache, regmap, NULL);
|
| + else
|
| + perror_with_name (_("Couldn't get register set"));
|
| + }
|
| + else
|
| + s390_native_supply (regcache, regmap, buf);
|
| }
|
|
|
| /* Store all registers in the kernel's register set whose number is REGSET,
|
| @@ -334,12 +327,10 @@ fetch_regset (struct regcache *regcache, int tid,
|
| GDB's register cache back to process/thread TID. */
|
| static void
|
| store_regset (struct regcache *regcache, int tid,
|
| - int regset, int regsize, int *regmap)
|
| + int regset, int regsize, const short *regmap)
|
| {
|
| - struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
| gdb_byte *buf = alloca (regsize);
|
| struct iovec iov;
|
| - int i;
|
|
|
| iov.iov_base = buf;
|
| iov.iov_len = regsize;
|
| @@ -347,8 +338,7 @@ store_regset (struct regcache *regcache, int tid,
|
| if (ptrace (PTRACE_GETREGSET, tid, (long) regset, (long) &iov) < 0)
|
| perror_with_name (_("Couldn't get register set"));
|
|
|
| - for (i = 0; i < S390_NUM_REGS; i++)
|
| - s390_native_collect (regcache, i, buf, regmap);
|
| + s390_native_collect (regcache, regmap, -1, buf);
|
|
|
| if (ptrace (PTRACE_SETREGSET, tid, (long) regset, (long) &iov) < 0)
|
| perror_with_name (_("Couldn't set register set"));
|
| @@ -365,10 +355,10 @@ check_regset (int tid, int regset, int regsize)
|
| iov.iov_base = buf;
|
| iov.iov_len = regsize;
|
|
|
| - if (ptrace (PTRACE_GETREGSET, tid, (long) regset, (long) &iov) < 0)
|
| - return 0;
|
| - else
|
| + if (ptrace (PTRACE_GETREGSET, tid, (long) regset, (long) &iov) >= 0
|
| + || errno == ENODATA)
|
| return 1;
|
| + return 0;
|
| }
|
|
|
| /* Fetch register REGNUM from the child process. If REGNUM is -1, do
|
| @@ -379,12 +369,10 @@ s390_linux_fetch_inferior_registers (struct target_ops *ops,
|
| {
|
| int tid = s390_inferior_tid ();
|
|
|
| - if (regnum == -1
|
| - || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
|
| + if (regnum == -1 || S390_IS_GREGSET_REGNUM (regnum))
|
| fetch_regs (regcache, tid);
|
|
|
| - if (regnum == -1
|
| - || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
|
| + if (regnum == -1 || S390_IS_FPREGSET_REGNUM (regnum))
|
| fetch_fpregs (regcache, tid);
|
|
|
| if (have_regset_last_break)
|
| @@ -397,6 +385,11 @@ s390_linux_fetch_inferior_registers (struct target_ops *ops,
|
| if (regnum == -1 || regnum == S390_SYSTEM_CALL_REGNUM)
|
| fetch_regset (regcache, tid, NT_S390_SYSTEM_CALL, 4,
|
| s390_regmap_system_call);
|
| +
|
| + if (have_regset_tdb)
|
| + if (regnum == -1 || S390_IS_TDBREGSET_REGNUM (regnum))
|
| + fetch_regset (regcache, tid, NT_S390_TDB, s390_sizeof_tdbregset,
|
| + s390_regmap_tdb);
|
| }
|
|
|
| /* Store register REGNUM back into the child process. If REGNUM is
|
| @@ -407,12 +400,10 @@ s390_linux_store_inferior_registers (struct target_ops *ops,
|
| {
|
| int tid = s390_inferior_tid ();
|
|
|
| - if (regnum == -1
|
| - || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
|
| + if (regnum == -1 || S390_IS_GREGSET_REGNUM (regnum))
|
| store_regs (regcache, tid, regnum);
|
|
|
| - if (regnum == -1
|
| - || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
|
| + if (regnum == -1 || S390_IS_FPREGSET_REGNUM (regnum))
|
| store_fpregs (regcache, tid, regnum);
|
|
|
| /* S390_LAST_BREAK_REGNUM is read-only. */
|
| @@ -483,9 +474,9 @@ s390_fix_watch_points (struct lwp_info *lp)
|
| CORE_ADDR watch_lo_addr = (CORE_ADDR)-1, watch_hi_addr = 0;
|
| struct watch_area *area;
|
|
|
| - tid = TIDGET (lp->ptid);
|
| + tid = ptid_get_lwp (lp->ptid);
|
| if (tid == 0)
|
| - tid = PIDGET (lp->ptid);
|
| + tid = ptid_get_pid (lp->ptid);
|
|
|
| for (area = watch_base; area; area = area->next)
|
| {
|
| @@ -524,11 +515,11 @@ s390_insert_watchpoint (CORE_ADDR addr, int len, int type,
|
| struct watch_area *area = xmalloc (sizeof (struct watch_area));
|
|
|
| if (!area)
|
| - return -1;
|
| + return -1;
|
|
|
| area->lo_addr = addr;
|
| area->hi_addr = addr + len - 1;
|
| -
|
| +
|
| area->next = watch_base;
|
| watch_base = area;
|
|
|
| @@ -601,7 +592,7 @@ s390_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
|
| gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
|
| {
|
| 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;
|
|
|
| if (endptr == ptr)
|
| @@ -649,13 +640,18 @@ s390_read_description (struct target_ops *ops)
|
| addressing mode, but the kernel supports using 64-bit registers in
|
| that mode, report s390 architecture with 64-bit GPRs. */
|
|
|
| + have_regset_tdb = (s390_get_hwcap () & HWCAP_S390_TE) ?
|
| + check_regset (tid, NT_S390_TDB, s390_sizeof_tdbregset) : 0;
|
| +
|
| if (s390_target_wordsize () == 8)
|
| - return (have_regset_system_call? tdesc_s390x_linux64v2 :
|
| + return (have_regset_tdb ? tdesc_s390x_te_linux64 :
|
| + have_regset_system_call? tdesc_s390x_linux64v2 :
|
| have_regset_last_break? tdesc_s390x_linux64v1 :
|
| tdesc_s390x_linux64);
|
|
|
| if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS)
|
| - return (have_regset_system_call? tdesc_s390_linux64v2 :
|
| + return (have_regset_tdb ? tdesc_s390_te_linux64 :
|
| + have_regset_system_call? tdesc_s390_linux64v2 :
|
| have_regset_last_break? tdesc_s390_linux64v1 :
|
| tdesc_s390_linux64);
|
| #endif
|
|
|