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 |