* [PATCH v3 1/3] S/390 regmap rework
2013-06-12 15:12 [RFA PATCH v3 0/3] Add TDB regset support Andreas Arnez
@ 2013-06-12 15:12 ` Andreas Arnez
2013-06-12 15:13 ` [PATCH v3 2/3] Add TDB regset Andreas Arnez
2013-06-12 15:23 ` [PATCH v3 3/3] Dynamic core regset sections support Andreas Arnez
2 siblings, 0 replies; 10+ messages in thread
From: Andreas Arnez @ 2013-06-12 15:12 UTC (permalink / raw)
To: gdb-patches; +Cc: Ulrich.Weigand
S/390 regmap rework: Represent register maps in a less redundant and
more readable way. Also remove some code repetition.
2013-06-12 Andreas Arnez <arnez@linux.vnet.ibm.com>
* s390-tdep.h (S390_IS_GREGSET_REGNUM): New macro.
(S390_IS_FPREGSET_REGNUM): New macro.
* s390-tdep.c (s390_dwarf_regmap): Make const.
(regnum_is_gpr_full): New function for replacing repeated code.
(s390_pseudo_register_name): Use it.
(s390_pseudo_register_type): Likewise.
(s390_pseudo_register_read): Likewise.
(s390_pseudo_register_write): Likewise.
(s390_unwind_pseudo_register): Likewise.
(s390_regmap_gregset): New format for regmap.
(s390x_regmap_gregset): Likewise.
(s390_regmap_fpregset): Likewise.
(s390_regmap_upper): Likewise.
(s390_regmap_last_break): Likewise.
(s390_regmap_system_call): Likewise.
(s390_supply_regset): Adjust to new regmap format.
(s390_collect_regset): Likewise.
* s390-nat.c (s390_native_supply): Adjust to new regmap format.
(s390_native_collect): Likewise.
(supply_gregset): Likewise.
(fill_gregset): Likewise.
(supply_fpregset): Likewise.
(fill_fpregset): Likewise.
(fetch_regset): Likewise.
(store_regset): Likewise.
(s390_linux_fetch_inferior_registers): Likewise.
(s390_linux_fetch_inferior_registers): Likewise.
Index: gdb/gdb/s390-tdep.h
===================================================================
--- gdb.orig/gdb/s390-tdep.h
+++ gdb/gdb/s390-tdep.h
@@ -106,16 +106,24 @@
#define S390_RETADDR_REGNUM S390_R14_REGNUM
#define S390_FRAME_REGNUM S390_R11_REGNUM
+#define S390_IS_GREGSET_REGNUM(i) \
+ (((i) >= S390_PSWM_REGNUM && (i) <= S390_A15_REGNUM) \
+ || ((i) >= S390_R0_UPPER_REGNUM && (i) <= S390_R15_UPPER_REGNUM) \
+ || (i) == S390_ORIG_R2_REGNUM)
+
+#define S390_IS_FPREGSET_REGNUM(i) \
+ ((i) >= S390_FPC_REGNUM && (i) <= S390_F15_REGNUM)
+
/* Core file register sets, defined in s390-tdep.c. */
#define s390_sizeof_gregset 0x90
-extern int s390_regmap_gregset[S390_NUM_REGS];
+extern const short s390_regmap_gregset[];
#define s390x_sizeof_gregset 0xd8
-extern int s390x_regmap_gregset[S390_NUM_REGS];
+extern const short s390x_regmap_gregset[];
#define s390_sizeof_fpregset 0x88
-extern int s390_regmap_fpregset[S390_NUM_REGS];
-extern int s390_regmap_last_break[S390_NUM_REGS];
-extern int s390x_regmap_last_break[S390_NUM_REGS];
-extern int s390_regmap_system_call[S390_NUM_REGS];
+extern const short s390_regmap_fpregset[];
+extern const short s390_regmap_last_break[];
+extern const short s390x_regmap_last_break[];
+extern const short s390_regmap_system_call[];
/* GNU/Linux target descriptions. */
extern struct target_desc *tdesc_s390_linux32;
Index: gdb/gdb/s390-nat.c
===================================================================
--- gdb.orig/gdb/s390-nat.c
+++ gdb/gdb/s390-nat.c
@@ -63,139 +63,129 @@ 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. */
+static void
+s390_native_supply (struct regcache *regcache, const short *map,
+ const gdb_byte *regp)
+{
+ for (; map[0] >= 0; map += 2)
+ regcache_raw_supply (regcache, map[1], regp + map[0]);
+}
static void
-s390_native_supply (struct regcache *regcache, int regno,
- const gdb_byte *regp, int *regmap)
+s390_native_collect (const struct regcache *regcache, const short *map,
+ int regno, gdb_byte *regp)
{
- int offset = regmap[regno];
+ 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];
+ const gdb_byte *p = (const gdb_byte *) regp + map[0];
+ int regno = map[1];
- 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;
+ 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)
+/* 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 offset = regmap[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];
+ gdb_byte *p = (gdb_byte *) regp + map[0];
+ int reg = map[1];
- regcache_raw_collect (regcache, regno, buf);
- pswm = extract_unsigned_integer (buf, 4, byte_order);
+ if (reg >= S390_PSWM_REGNUM && reg <= S390_PSWA_REGNUM)
+ psw_p[reg - S390_PSWM_REGNUM] = p;
- /* 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;
+ 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
@@ -203,9 +193,7 @@ fill_gregset (const struct regcache *reg
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
@@ -214,10 +202,7 @@ supply_fpregset (struct regcache *regcac
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. */
@@ -311,12 +296,10 @@ store_fpregs (const struct regcache *reg
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;
@@ -324,8 +307,7 @@ fetch_regset (struct regcache *regcache,
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);
+ s390_native_supply (regcache, regmap, buf);
}
/* Store all registers in the kernel's register set whose number is REGSET,
@@ -333,12 +315,10 @@ fetch_regset (struct regcache *regcache,
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;
@@ -346,8 +326,7 @@ store_regset (struct regcache *regcache,
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"));
@@ -378,12 +357,10 @@ s390_linux_fetch_inferior_registers (str
{
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)
@@ -406,12 +383,10 @@ s390_linux_store_inferior_registers (str
{
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. */
Index: gdb/gdb/s390-tdep.c
===================================================================
--- gdb.orig/gdb/s390-tdep.c
+++ gdb/gdb/s390-tdep.c
@@ -141,7 +141,7 @@ s390_write_pc (struct regcache *regcache
/* DWARF Register Mapping. */
-static int s390_dwarf_regmap[] =
+static const short s390_dwarf_regmap[] =
{
/* General Purpose Registers. */
S390_R0_REGNUM, S390_R1_REGNUM, S390_R2_REGNUM, S390_R3_REGNUM,
@@ -212,6 +212,14 @@ s390_adjust_frame_regnum (struct gdbarch
/* Pseudo registers. */
+static int
+regnum_is_gpr_full (struct gdbarch_tdep *tdep, int regnum)
+{
+ return (tdep->gpr_full_regnum != -1
+ && regnum >= tdep->gpr_full_regnum
+ && regnum <= tdep->gpr_full_regnum + 15);
+}
+
static const char *
s390_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
{
@@ -223,9 +231,7 @@ s390_pseudo_register_name (struct gdbarc
if (regnum == tdep->cc_regnum)
return "cc";
- if (tdep->gpr_full_regnum != -1
- && regnum >= tdep->gpr_full_regnum
- && regnum < tdep->gpr_full_regnum + 16)
+ if (regnum_is_gpr_full (tdep, regnum))
{
static const char *full_name[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
@@ -248,9 +254,7 @@ s390_pseudo_register_type (struct gdbarc
if (regnum == tdep->cc_regnum)
return builtin_type (gdbarch)->builtin_int;
- if (tdep->gpr_full_regnum != -1
- && regnum >= tdep->gpr_full_regnum
- && regnum < tdep->gpr_full_regnum + 16)
+ if (regnum_is_gpr_full (tdep, regnum))
return builtin_type (gdbarch)->builtin_uint64;
internal_error (__FILE__, __LINE__, _("invalid regnum"));
@@ -295,9 +299,7 @@ s390_pseudo_register_read (struct gdbarc
return status;
}
- if (tdep->gpr_full_regnum != -1
- && regnum >= tdep->gpr_full_regnum
- && regnum < tdep->gpr_full_regnum + 16)
+ if (regnum_is_gpr_full (tdep, regnum))
{
enum register_status status;
ULONGEST val_upper;
@@ -352,9 +354,7 @@ s390_pseudo_register_write (struct gdbar
return;
}
- if (tdep->gpr_full_regnum != -1
- && regnum >= tdep->gpr_full_regnum
- && regnum < tdep->gpr_full_regnum + 16)
+ if (regnum_is_gpr_full (tdep, regnum))
{
regnum -= tdep->gpr_full_regnum;
val = extract_unsigned_integer (buf, regsize, byte_order);
@@ -409,175 +409,166 @@ s390_pseudo_register_reggroup_p (struct
}
-/* Core file register sets. */
+/* Maps for register sets. */
-int s390_regmap_gregset[S390_NUM_REGS] =
-{
- /* Program Status Word. */
- 0x00, 0x04,
- /* General Purpose Registers. */
- 0x08, 0x0c, 0x10, 0x14,
- 0x18, 0x1c, 0x20, 0x24,
- 0x28, 0x2c, 0x30, 0x34,
- 0x38, 0x3c, 0x40, 0x44,
- /* Access Registers. */
- 0x48, 0x4c, 0x50, 0x54,
- 0x58, 0x5c, 0x60, 0x64,
- 0x68, 0x6c, 0x70, 0x74,
- 0x78, 0x7c, 0x80, 0x84,
- /* Floating Point Control Word. */
- -1,
- /* Floating Point Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* GPR Uppper Halves. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* GNU/Linux-specific optional "registers". */
- 0x88, -1, -1,
-};
+const short s390_regmap_gregset[] =
+ {
+ 0x00, S390_PSWM_REGNUM,
+ 0x04, S390_PSWA_REGNUM,
+ 0x08, S390_R0_REGNUM,
+ 0x0c, S390_R1_REGNUM,
+ 0x10, S390_R2_REGNUM,
+ 0x14, S390_R3_REGNUM,
+ 0x18, S390_R4_REGNUM,
+ 0x1c, S390_R5_REGNUM,
+ 0x20, S390_R6_REGNUM,
+ 0x24, S390_R7_REGNUM,
+ 0x28, S390_R8_REGNUM,
+ 0x2c, S390_R9_REGNUM,
+ 0x30, S390_R10_REGNUM,
+ 0x34, S390_R11_REGNUM,
+ 0x38, S390_R12_REGNUM,
+ 0x3c, S390_R13_REGNUM,
+ 0x40, S390_R14_REGNUM,
+ 0x44, S390_R15_REGNUM,
+ 0x48, S390_A0_REGNUM,
+ 0x4c, S390_A1_REGNUM,
+ 0x50, S390_A2_REGNUM,
+ 0x54, S390_A3_REGNUM,
+ 0x58, S390_A4_REGNUM,
+ 0x5c, S390_A5_REGNUM,
+ 0x60, S390_A6_REGNUM,
+ 0x64, S390_A7_REGNUM,
+ 0x68, S390_A8_REGNUM,
+ 0x6c, S390_A9_REGNUM,
+ 0x70, S390_A10_REGNUM,
+ 0x74, S390_A11_REGNUM,
+ 0x78, S390_A12_REGNUM,
+ 0x7c, S390_A13_REGNUM,
+ 0x80, S390_A14_REGNUM,
+ 0x84, S390_A15_REGNUM,
+ 0x88, S390_ORIG_R2_REGNUM,
+ -1, -1
+ };
-int s390x_regmap_gregset[S390_NUM_REGS] =
-{
- /* Program Status Word. */
- 0x00, 0x08,
- /* General Purpose Registers. */
- 0x10, 0x18, 0x20, 0x28,
- 0x30, 0x38, 0x40, 0x48,
- 0x50, 0x58, 0x60, 0x68,
- 0x70, 0x78, 0x80, 0x88,
- /* Access Registers. */
- 0x90, 0x94, 0x98, 0x9c,
- 0xa0, 0xa4, 0xa8, 0xac,
- 0xb0, 0xb4, 0xb8, 0xbc,
- 0xc0, 0xc4, 0xc8, 0xcc,
- /* Floating Point Control Word. */
- -1,
- /* Floating Point Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* GPR Uppper Halves. */
- 0x10, 0x18, 0x20, 0x28,
- 0x30, 0x38, 0x40, 0x48,
- 0x50, 0x58, 0x60, 0x68,
- 0x70, 0x78, 0x80, 0x88,
- /* GNU/Linux-specific optional "registers". */
- 0xd0, -1, -1,
-};
+const short s390x_regmap_gregset[] =
+ {
+ 0x00, S390_PSWM_REGNUM,
+ 0x08, S390_PSWA_REGNUM,
+ 0x10, S390_R0_REGNUM,
+ 0x18, S390_R1_REGNUM,
+ 0x20, S390_R2_REGNUM,
+ 0x28, S390_R3_REGNUM,
+ 0x30, S390_R4_REGNUM,
+ 0x38, S390_R5_REGNUM,
+ 0x40, S390_R6_REGNUM,
+ 0x48, S390_R7_REGNUM,
+ 0x50, S390_R8_REGNUM,
+ 0x58, S390_R9_REGNUM,
+ 0x60, S390_R10_REGNUM,
+ 0x68, S390_R11_REGNUM,
+ 0x70, S390_R12_REGNUM,
+ 0x78, S390_R13_REGNUM,
+ 0x80, S390_R14_REGNUM,
+ 0x88, S390_R15_REGNUM,
+ 0x90, S390_A0_REGNUM,
+ 0x94, S390_A1_REGNUM,
+ 0x98, S390_A2_REGNUM,
+ 0x9c, S390_A3_REGNUM,
+ 0xa0, S390_A4_REGNUM,
+ 0xa4, S390_A5_REGNUM,
+ 0xa8, S390_A6_REGNUM,
+ 0xac, S390_A7_REGNUM,
+ 0xb0, S390_A8_REGNUM,
+ 0xb4, S390_A9_REGNUM,
+ 0xb8, S390_A10_REGNUM,
+ 0xbc, S390_A11_REGNUM,
+ 0xc0, S390_A12_REGNUM,
+ 0xc4, S390_A13_REGNUM,
+ 0xc8, S390_A14_REGNUM,
+ 0xcc, S390_A15_REGNUM,
+ 0x10, S390_R0_UPPER_REGNUM,
+ 0x18, S390_R1_UPPER_REGNUM,
+ 0x20, S390_R2_UPPER_REGNUM,
+ 0x28, S390_R3_UPPER_REGNUM,
+ 0x30, S390_R4_UPPER_REGNUM,
+ 0x38, S390_R5_UPPER_REGNUM,
+ 0x40, S390_R6_UPPER_REGNUM,
+ 0x48, S390_R7_UPPER_REGNUM,
+ 0x50, S390_R8_UPPER_REGNUM,
+ 0x58, S390_R9_UPPER_REGNUM,
+ 0x60, S390_R10_UPPER_REGNUM,
+ 0x68, S390_R11_UPPER_REGNUM,
+ 0x70, S390_R12_UPPER_REGNUM,
+ 0x78, S390_R13_UPPER_REGNUM,
+ 0x80, S390_R14_UPPER_REGNUM,
+ 0x88, S390_R15_UPPER_REGNUM,
+ 0xd0, S390_ORIG_R2_REGNUM,
+ -1, -1
+ };
-int s390_regmap_fpregset[S390_NUM_REGS] =
-{
- /* Program Status Word. */
- -1, -1,
- /* General Purpose Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* Access Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* Floating Point Control Word. */
- 0x00,
- /* Floating Point Registers. */
- 0x08, 0x10, 0x18, 0x20,
- 0x28, 0x30, 0x38, 0x40,
- 0x48, 0x50, 0x58, 0x60,
- 0x68, 0x70, 0x78, 0x80,
- /* GPR Uppper Halves. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* GNU/Linux-specific optional "registers". */
- -1, -1, -1,
-};
+const short s390_regmap_fpregset[] =
+ {
+ 0x00, S390_FPC_REGNUM,
+ 0x08, S390_F0_REGNUM,
+ 0x10, S390_F1_REGNUM,
+ 0x18, S390_F2_REGNUM,
+ 0x20, S390_F3_REGNUM,
+ 0x28, S390_F4_REGNUM,
+ 0x30, S390_F5_REGNUM,
+ 0x38, S390_F6_REGNUM,
+ 0x40, S390_F7_REGNUM,
+ 0x48, S390_F8_REGNUM,
+ 0x50, S390_F9_REGNUM,
+ 0x58, S390_F10_REGNUM,
+ 0x60, S390_F11_REGNUM,
+ 0x68, S390_F12_REGNUM,
+ 0x70, S390_F13_REGNUM,
+ 0x78, S390_F14_REGNUM,
+ 0x80, S390_F15_REGNUM,
+ -1, -1
+ };
-int s390_regmap_upper[S390_NUM_REGS] =
-{
- /* Program Status Word. */
- -1, -1,
- /* General Purpose Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* Access Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* Floating Point Control Word. */
- -1,
- /* Floating Point Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* GPR Uppper Halves. */
- 0x00, 0x04, 0x08, 0x0c,
- 0x10, 0x14, 0x18, 0x1c,
- 0x20, 0x24, 0x28, 0x2c,
- 0x30, 0x34, 0x38, 0x3c,
- /* GNU/Linux-specific optional "registers". */
- -1, -1, -1,
-};
+const short s390_regmap_upper[] =
+ {
+ 0x00, S390_R0_UPPER_REGNUM,
+ 0x04, S390_R1_UPPER_REGNUM,
+ 0x08, S390_R2_UPPER_REGNUM,
+ 0x0c, S390_R3_UPPER_REGNUM,
+ 0x10, S390_R4_UPPER_REGNUM,
+ 0x14, S390_R5_UPPER_REGNUM,
+ 0x18, S390_R6_UPPER_REGNUM,
+ 0x1c, S390_R7_UPPER_REGNUM,
+ 0x20, S390_R8_UPPER_REGNUM,
+ 0x24, S390_R9_UPPER_REGNUM,
+ 0x28, S390_R10_UPPER_REGNUM,
+ 0x2c, S390_R11_UPPER_REGNUM,
+ 0x30, S390_R12_UPPER_REGNUM,
+ 0x34, S390_R13_UPPER_REGNUM,
+ 0x38, S390_R14_UPPER_REGNUM,
+ 0x3c, S390_R15_UPPER_REGNUM,
+ -1, -1
+ };
-int s390_regmap_last_break[S390_NUM_REGS] =
-{
- /* Program Status Word. */
- -1, -1,
- /* General Purpose Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* Access Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* Floating Point Control Word. */
- -1,
- /* Floating Point Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* GPR Uppper Halves. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* GNU/Linux-specific optional "registers". */
- -1, 4, -1,
-};
+const short s390_regmap_last_break[] =
+ {
+ 0x04, S390_LAST_BREAK_REGNUM,
+ -1, -1
+ };
+
+const short s390x_regmap_last_break[] =
+ {
+ 0x00, S390_LAST_BREAK_REGNUM,
+ -1, -1
+ };
+
+const short s390_regmap_system_call[] =
+ {
+ 0x00, S390_SYSTEM_CALL_REGNUM,
+ -1, -1
+ };
-int s390x_regmap_last_break[S390_NUM_REGS] =
-{
- /* Program Status Word. */
- -1, -1,
- /* General Purpose Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* Access Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* Floating Point Control Word. */
- -1,
- /* Floating Point Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* GPR Uppper Halves. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* GNU/Linux-specific optional "registers". */
- -1, 0, -1,
-};
-int s390_regmap_system_call[S390_NUM_REGS] =
-{
- /* Program Status Word. */
- -1, -1,
- /* General Purpose Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* Access Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* Floating Point Control Word. */
- -1,
- /* Floating Point Registers. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* GPR Uppper Halves. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* GNU/Linux-specific optional "registers". */
- -1, -1, 0,
-};
/* Supply register REGNUM from the register set REGSET to register cache
REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
@@ -585,14 +576,10 @@ static void
s390_supply_regset (const struct regset *regset, struct regcache *regcache,
int regnum, const void *regs, size_t len)
{
- const int *offset = regset->descr;
- int i;
-
- for (i = 0; i < S390_NUM_REGS; i++)
- {
- if ((regnum == i || regnum == -1) && offset[i] != -1)
- regcache_raw_supply (regcache, i, (const char *)regs + offset[i]);
- }
+ const short *map;
+ for (map = regset->descr; map[0] >= 0; map += 2)
+ if (regnum == -1 || regnum == map[1])
+ regcache_raw_supply (regcache, map[1], (const char *)regs + map[0]);
}
/* Collect register REGNUM from the register cache REGCACHE and store
@@ -604,14 +591,10 @@ s390_collect_regset (const struct regset
const struct regcache *regcache,
int regnum, void *regs, size_t len)
{
- const int *offset = regset->descr;
- int i;
-
- for (i = 0; i < S390_NUM_REGS; i++)
- {
- if ((regnum == i || regnum == -1) && offset[i] != -1)
- regcache_raw_collect (regcache, i, (char *)regs + offset[i]);
- }
+ const short *map;
+ for (map = regset->descr; map[0] >= 0; map += 2)
+ if (regnum == -1 || regnum == map[1])
+ regcache_raw_collect (regcache, map[1], (char *)regs + map[0]);
}
static const struct regset s390_gregset = {
@@ -1718,9 +1701,7 @@ s390_unwind_pseudo_register (struct fram
/* Unwind full GPRs to show at least the lower halves (as the
upper halves are undefined). */
- if (tdep->gpr_full_regnum != -1
- && regnum >= tdep->gpr_full_regnum
- && regnum < tdep->gpr_full_regnum + 16)
+ if (regnum_is_gpr_full (tdep, regnum))
{
int reg = regnum - tdep->gpr_full_regnum;
struct value *val;
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v3 2/3] Add TDB regset
2013-06-12 15:12 [RFA PATCH v3 0/3] Add TDB regset support Andreas Arnez
2013-06-12 15:12 ` [PATCH v3 1/3] S/390 regmap rework Andreas Arnez
@ 2013-06-12 15:13 ` Andreas Arnez
2013-06-12 15:23 ` [PATCH v3 3/3] Dynamic core regset sections support Andreas Arnez
2 siblings, 0 replies; 10+ messages in thread
From: Andreas Arnez @ 2013-06-12 15:13 UTC (permalink / raw)
To: gdb-patches; +Cc: Ulrich.Weigand
The z/Architecture transactional-execution facility includes support
for a "transaction diagnostic block" (TDB) that is written by the
hardware upon interrupted transactions. From a running inferior the
TDB can be retrieved via PTRACE_GETREGSET, but ENODATA is returned if
the inferior was interrupted outside transactions. Analogously, a
core file conditionally contains the TDB, depending on whether the
process died within a transaction or not.
This patch represents the TDB as a new regset in GDB. A new feature
"org.gnu.gdb.s390.tdb" is defined and new target descriptions are
provided.
gdb/ChangeLog:
2013-06-12 Andreas Arnez <arnez@linux.vnet.ibm.com>
* features/s390-tdb.xml: New file.
* features/s390-te-linux64.xml: New file.
* features/s390x-te-linux64.xml: New file.
* features/Makefile (WHICH): Add new tdescs above.
(s390-te-linux64-expedite): Set.
(s390x-te-linux64-expedite): Set.
* s390-tdep.h (HWCAP_S390_HIGH_GPRS): Define.
(HWCAP_S390_TE): Likewise.
(S390_TDB_DWORD0_REGNUM): Likewise.
(S390_TDB_DWORD0_REGNUM): Likewise.
(S390_TDB_ABORT_CODE_REGNUM): Likewise.
(S390_TDB_CONFLICT_TOKEN_REGNUM): Likewise.
(S390_TDB_ATIA_REGNUM): Likewise.
(S390_TDB_R0_REGNUM): Likewise.
(S390_TDB_R1_REGNUM): Likewise.
(S390_TDB_R2_REGNUM): Likewise.
(S390_TDB_R3_REGNUM): Likewise.
(S390_TDB_R4_REGNUM): Likewise.
(S390_TDB_R5_REGNUM): Likewise.
(S390_TDB_R6_REGNUM): Likewise.
(S390_TDB_R7_REGNUM): Likewise.
(S390_TDB_R8_REGNUM): Likewise.
(S390_TDB_R9_REGNUM): Likewise.
(S390_TDB_R10_REGNUM): Likewise.
(S390_TDB_R11_REGNUM): Likewise.
(S390_TDB_R12_REGNUM): Likewise.
(S390_TDB_R13_REGNUM): Likewise.
(S390_TDB_R14_REGNUM): Likewise.
(S390_TDB_R15_REGNUM): Likewise.
(S390_NUM_REGS): Increase.
(S390_IS_TDBREGSET_REGNUM): New macro.
(s390_regmap_tdb): Declare.
(s390_sizeof_tdbregset): Define.
(tdesc_s390_te_linux64): Declare.
(tdesc_s390x_te_linux64): Likewise.
* s390-tdep.c: Add includes for "auxv.h", <elf.h>,
"features/s390-te-linux64.c", and "features/s390x-te-linux64.c".
(s390_regmap_tdb): New regmap.
(s390_tdb_regset): New regset.
(s390_linux64v2_regset_sections): Add TDB regset to list.
(s390x_linux64v2_regset_sections): Likewise.
(s390_regset_from_core_section): Recognize TDB core note section.
(s390_core_read_description): If HWCAP indicates TE support,
select tdesc_s390_te_linux64 or tdesc_s390_s390x_te_linux64.
(s390_gdbarch_init): Handle TDB regset.
(_initialize_s390_tdep): Initialize new tdescs.
* s390-nat.c (HWCAP_S390_HIGH_GPRS): Remove define.
(have_regset_tdb): New variable.
(s390_native_supply): Support register invalidation.
(fetch_regset): Invalidate registers if ptrace yields ENODATA.
(check_regset): Treat ENODATA as "regset exists".
(s390_linux_fetch_inferior_registers): Add TDB.
(s390_read_description): Check for TDB existence and select
appropriate tdesc.
* gdbserver/configure.srv (srv_regobj): Append new objects
s390-te-linux64.o and s390x-te-linux64.o.
(srv_xmlfiles): Append new files s390-te-linux64.xml,
s390x-te-linux64.xml, and s390-tdb.xml.
* gdbserver/Makefile.in (clean): Add removal of new makefile
targets.
(s390-te-linux64.c): New makefile target.
(s390x-te-linux64.c): Likewise.
* gdbserver/linux-s390-low.c (init_registers_s390_te_linux64): New
declaration.
(tdesc_s390_te_linux64): Likewise.
(init_registers_s390x_te_linux64): Likewise.
(tdesc_s390x_te_linux64): Likewise.
(s390_check_regset): Treat ENODATA as "regset exists".
(s390_arch_setup): Add TDB regset support.
(initialize_low_arch): Initialize registers for new tdescs.
* NEWS: Mention TDB support.
* features/s390-te-linux64.c: New file (generated).
* features/s390x-te-linux64.c: New file (generated).
* regformats/s390-te-linux64.dat: New file (generated).
* regformats/s390x-te-linux64.dat: New file (generated).
gdb/doc/ChangeLog:
2013-06-12 Andreas Arnez <arnez@linux.vnet.ibm.com>
* gdb.texinfo (Decimal Floating Point format): Mention S/390.
(Standard Target Features): Add new node to menu.
(S/390 and System z Features): New node.
gdb/testsuite/ChangeLog:
2013-06-12 Andreas Arnez <arnez@linux.vnet.ibm.com>
* gdb.arch/s390-tdbregs.c: New file.
* gdb.arch/s390-tdbregs.exp: New file.
Index: gdb/gdb/features/s390-tdb.xml
===================================================================
--- /dev/null
+++ gdb/gdb/features/s390-tdb.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010-2013 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.s390.tdb">
+ <reg name="tdb0" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tac" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tct" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="atia" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr0" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr1" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr2" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr3" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr4" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr5" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr6" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr7" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr8" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr9" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr10" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr11" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr12" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr13" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr14" bitsize="64" type="uint64" group="tdb"/>
+ <reg name="tr15" bitsize="64" type="uint64" group="tdb"/>
+</feature>
Index: gdb/gdb/s390-tdep.c
===================================================================
--- gdb.orig/gdb/s390-tdep.c
+++ gdb/gdb/s390-tdep.c
@@ -44,6 +44,7 @@
#include "prologue-value.h"
#include "linux-tdep.h"
#include "s390-tdep.h"
+#include "auxv.h"
#include "stap-probe.h"
#include "ax.h"
@@ -51,6 +52,7 @@
#include "user-regs.h"
#include "cli/cli-utils.h"
#include <ctype.h>
+#include <elf.h>
#include "features/s390-linux32.c"
#include "features/s390-linux32v1.c"
@@ -58,9 +60,11 @@
#include "features/s390-linux64.c"
#include "features/s390-linux64v1.c"
#include "features/s390-linux64v2.c"
+#include "features/s390-te-linux64.c"
#include "features/s390x-linux64.c"
#include "features/s390x-linux64v1.c"
#include "features/s390x-linux64v2.c"
+#include "features/s390x-te-linux64.c"
/* The tdep structure. */
@@ -568,6 +572,30 @@ const short s390_regmap_system_call[] =
-1, -1
};
+const short s390_regmap_tdb[] =
+ {
+ 0x00, S390_TDB_DWORD0_REGNUM,
+ 0x08, S390_TDB_ABORT_CODE_REGNUM,
+ 0x10, S390_TDB_CONFLICT_TOKEN_REGNUM,
+ 0x18, S390_TDB_ATIA_REGNUM,
+ 0x80, S390_TDB_R0_REGNUM,
+ 0x88, S390_TDB_R1_REGNUM,
+ 0x90, S390_TDB_R2_REGNUM,
+ 0x98, S390_TDB_R3_REGNUM,
+ 0xa0, S390_TDB_R4_REGNUM,
+ 0xa8, S390_TDB_R5_REGNUM,
+ 0xb0, S390_TDB_R6_REGNUM,
+ 0xb8, S390_TDB_R7_REGNUM,
+ 0xc0, S390_TDB_R8_REGNUM,
+ 0xc8, S390_TDB_R9_REGNUM,
+ 0xd0, S390_TDB_R10_REGNUM,
+ 0xd8, S390_TDB_R11_REGNUM,
+ 0xe0, S390_TDB_R12_REGNUM,
+ 0xe8, S390_TDB_R13_REGNUM,
+ 0xf0, S390_TDB_R14_REGNUM,
+ 0xf8, S390_TDB_R15_REGNUM,
+ -1, -1
+ };
/* Supply register REGNUM from the register set REGSET to register cache
@@ -639,6 +667,12 @@ static const struct regset s390_system_c
s390_collect_regset
};
+static const struct regset s390_tdb_regset = {
+ s390_regmap_tdb,
+ s390_supply_regset,
+ s390_collect_regset
+};
+
static struct core_regset_section s390_linux32_regset_sections[] =
{
{ ".reg", s390_sizeof_gregset, "general-purpose" },
@@ -687,6 +721,7 @@ static struct core_regset_section s390_l
{ ".reg-s390-high-gprs", 16*4, "s390 GPR upper halves" },
{ ".reg-s390-last-break", 8, "s930 last-break address" },
{ ".reg-s390-system-call", 4, "s390 system-call" },
+ { ".reg-s390-tdb", s390_sizeof_tdbregset, "s390 TDB" },
{ NULL, 0}
};
@@ -711,6 +746,7 @@ static struct core_regset_section s390x_
{ ".reg2", s390_sizeof_fpregset, "floating-point" },
{ ".reg-s390-last-break", 8, "s930 last-break address" },
{ ".reg-s390-system-call", 4, "s390 system-call" },
+ { ".reg-s390-tdb", s390_sizeof_tdbregset, "s390 TDB" },
{ NULL, 0}
};
@@ -739,6 +775,9 @@ s390_regset_from_core_section (struct gd
if (strcmp (sect_name, ".reg-s390-system-call") == 0 && sect_size >= 4)
return &s390_system_call_regset;
+ if (strcmp (sect_name, ".reg-s390-tdb") == 0 && sect_size >= 256)
+ return &s390_tdb_regset;
+
return NULL;
}
@@ -750,6 +789,9 @@ s390_core_read_description (struct gdbar
asection *v1 = bfd_get_section_by_name (abfd, ".reg-s390-last-break");
asection *v2 = bfd_get_section_by_name (abfd, ".reg-s390-system-call");
asection *section = bfd_get_section_by_name (abfd, ".reg");
+ unsigned long hwcap = 0;
+
+ target_auxv_search (target, AT_HWCAP, &hwcap);
if (!section)
return NULL;
@@ -757,14 +799,16 @@ s390_core_read_description (struct gdbar
{
case s390_sizeof_gregset:
if (high_gprs)
- return (v2? tdesc_s390_linux64v2 :
+ return ((hwcap & HWCAP_S390_TE) ? tdesc_s390_te_linux64 :
+ v2? tdesc_s390_linux64v2 :
v1? tdesc_s390_linux64v1 : tdesc_s390_linux64);
else
return (v2? tdesc_s390_linux32v2 :
v1? tdesc_s390_linux32v1 : tdesc_s390_linux32);
case s390x_sizeof_gregset:
- return (v2? tdesc_s390x_linux64v2 :
+ return ((hwcap & HWCAP_S390_TE) ? tdesc_s390x_te_linux64 :
+ v2? tdesc_s390x_linux64v2 :
v1? tdesc_s390x_linux64v1 : tdesc_s390x_linux64);
default:
@@ -3011,6 +3055,11 @@ s390_gdbarch_init (struct gdbarch_info i
"r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h",
"r8h", "r9h", "r10h", "r11h", "r12h", "r13h", "r14h", "r15h"
};
+ static const char *const tdb_regs[] = {
+ "tdb0", "tac", "tct", "atia",
+ "tr0", "tr1", "tr2", "tr3", "tr4", "tr5", "tr6", "tr7",
+ "tr8", "tr9", "tr10", "tr11", "tr12", "tr13", "tr14", "tr15"
+ };
const struct tdesc_feature *feature;
int i, valid_p = 1;
@@ -3088,6 +3137,16 @@ s390_gdbarch_init (struct gdbarch_info i
valid_p = 0;
}
+ /* Transaction diagnostic block. */
+ feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.tdb");
+ if (feature)
+ {
+ for (i = 0; i < ARRAY_SIZE (tdb_regs); i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ S390_TDB_DWORD0_REGNUM + i,
+ tdb_regs[i]);
+ }
+
if (!valid_p)
{
tdesc_data_cleanup (tdesc_data);
@@ -3304,7 +3363,9 @@ _initialize_s390_tdep (void)
initialize_tdesc_s390_linux64 ();
initialize_tdesc_s390_linux64v1 ();
initialize_tdesc_s390_linux64v2 ();
+ initialize_tdesc_s390_te_linux64 ();
initialize_tdesc_s390x_linux64 ();
initialize_tdesc_s390x_linux64v1 ();
initialize_tdesc_s390x_linux64v2 ();
+ initialize_tdesc_s390x_te_linux64 ();
}
Index: gdb/gdb/s390-tdep.h
===================================================================
--- gdb.orig/gdb/s390-tdep.h
+++ gdb/gdb/s390-tdep.h
@@ -19,6 +19,16 @@
#ifndef S390_TDEP_H
#define S390_TDEP_H
+/* Hardware capabilities. */
+
+#ifndef HWCAP_S390_HIGH_GPRS
+#define HWCAP_S390_HIGH_GPRS 512
+#endif
+
+#ifndef HWCAP_S390_TE
+#define HWCAP_S390_TE 1024
+#endif
+
/* Register information. */
/* Program Status Word. */
@@ -98,8 +108,29 @@
#define S390_ORIG_R2_REGNUM 67
#define S390_LAST_BREAK_REGNUM 68
#define S390_SYSTEM_CALL_REGNUM 69
+/* Transaction diagnostic block. */
+#define S390_TDB_DWORD0_REGNUM 70
+#define S390_TDB_ABORT_CODE_REGNUM 71
+#define S390_TDB_CONFLICT_TOKEN_REGNUM 72
+#define S390_TDB_ATIA_REGNUM 73
+#define S390_TDB_R0_REGNUM 74
+#define S390_TDB_R1_REGNUM 75
+#define S390_TDB_R2_REGNUM 76
+#define S390_TDB_R3_REGNUM 77
+#define S390_TDB_R4_REGNUM 78
+#define S390_TDB_R5_REGNUM 79
+#define S390_TDB_R6_REGNUM 80
+#define S390_TDB_R7_REGNUM 81
+#define S390_TDB_R8_REGNUM 82
+#define S390_TDB_R9_REGNUM 83
+#define S390_TDB_R10_REGNUM 84
+#define S390_TDB_R11_REGNUM 85
+#define S390_TDB_R12_REGNUM 86
+#define S390_TDB_R13_REGNUM 87
+#define S390_TDB_R14_REGNUM 88
+#define S390_TDB_R15_REGNUM 89
/* Total. */
-#define S390_NUM_REGS 70
+#define S390_NUM_REGS 90
/* Special register usage. */
#define S390_SP_REGNUM S390_R15_REGNUM
@@ -114,6 +145,9 @@
#define S390_IS_FPREGSET_REGNUM(i) \
((i) >= S390_FPC_REGNUM && (i) <= S390_F15_REGNUM)
+#define S390_IS_TDBREGSET_REGNUM(i) \
+ ((i) >= S390_TDB_DWORD0_REGNUM && (i) <= S390_TDB_R15_REGNUM)
+
/* Core file register sets, defined in s390-tdep.c. */
#define s390_sizeof_gregset 0x90
extern const short s390_regmap_gregset[];
@@ -124,6 +158,8 @@ extern const short s390_regmap_fpregset[
extern const short s390_regmap_last_break[];
extern const short s390x_regmap_last_break[];
extern const short s390_regmap_system_call[];
+extern const short s390_regmap_tdb[];
+#define s390_sizeof_tdbregset 0x100
/* GNU/Linux target descriptions. */
extern struct target_desc *tdesc_s390_linux32;
@@ -132,9 +168,11 @@ extern struct target_desc *tdesc_s390_li
extern struct target_desc *tdesc_s390_linux64;
extern struct target_desc *tdesc_s390_linux64v1;
extern struct target_desc *tdesc_s390_linux64v2;
+extern struct target_desc *tdesc_s390_te_linux64;
extern struct target_desc *tdesc_s390x_linux64;
extern struct target_desc *tdesc_s390x_linux64v1;
extern struct target_desc *tdesc_s390x_linux64v2;
+extern struct target_desc *tdesc_s390x_te_linux64;
#endif
Index: gdb/gdb/s390-nat.c
===================================================================
--- gdb.orig/gdb/s390-nat.c
+++ gdb/gdb/s390-nat.c
@@ -37,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
@@ -51,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. */
@@ -68,7 +65,7 @@ s390_native_supply (struct regcache *reg
const gdb_byte *regp)
{
for (; map[0] >= 0; map += 2)
- regcache_raw_supply (regcache, map[1], regp + map[0]);
+ regcache_raw_supply (regcache, map[1], regp ? regp + map[0] : NULL);
}
static void
@@ -305,9 +302,14 @@ fetch_regset (struct regcache *regcache,
iov.iov_len = regsize;
if (ptrace (PTRACE_GETREGSET, tid, (long) regset, (long) &iov) < 0)
- perror_with_name (_("Couldn't get register set"));
-
- s390_native_supply (regcache, regmap, buf);
+ {
+ 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,
@@ -343,10 +345,10 @@ check_regset (int tid, int regset, int r
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
@@ -373,6 +375,11 @@ s390_linux_fetch_inferior_registers (str
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
@@ -615,6 +622,8 @@ s390_read_description (struct target_ops
= check_regset (tid, NT_S390_LAST_BREAK, 8);
have_regset_system_call
= check_regset (tid, NT_S390_SYSTEM_CALL, 4);
+ have_regset_tdb
+ = check_regset (tid, NT_S390_TDB, s390_sizeof_tdbregset);
#ifdef __s390x__
/* If GDB itself is compiled as 64-bit, we are running on a machine in
@@ -624,12 +633,14 @@ s390_read_description (struct target_ops
that mode, report s390 architecture with 64-bit GPRs. */
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
Index: gdb/gdb/testsuite/gdb.arch/s390-tdbregs.c
===================================================================
--- /dev/null
+++ gdb/gdb/testsuite/gdb.arch/s390-tdbregs.c
@@ -0,0 +1,62 @@
+/* Copyright 2008-2013 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+
+static void
+my_tbegin ()
+{
+ asm volatile ( "1: tbegin 0, 0xff00\n"
+ " jnz 1b"
+ : /* no return value */
+ : /* no inputs */
+ : "cc", "memory" );
+}
+
+static void
+my_tend ()
+{
+ asm volatile ( " tend"
+ : /* no return value */
+ : /* no inputs */
+ : "cc");
+}
+
+void
+try_transaction (void)
+{
+ my_tbegin ();
+ my_tend ();
+}
+
+void
+crash_in_transaction (void)
+{
+ volatile char *p = 0;
+
+ my_tbegin ();
+ *p = 5; /* FAULT */
+ my_tend ();
+}
+
+int
+main (int argc, char *argv[])
+{
+ try_transaction ();
+ crash_in_transaction ();
+ return 0;
+}
Index: gdb/gdb/testsuite/gdb.arch/s390-tdbregs.exp
===================================================================
--- /dev/null
+++ gdb/gdb/testsuite/gdb.arch/s390-tdbregs.exp
@@ -0,0 +1,75 @@
+# Copyright 2004-2013 Free Software Foundation, Inc.
+
+# 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
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@gnu.org
+
+# This file is part of the gdb testsuite.
+
+
+if { ![istarget s390-*-*] && ![istarget s390x-*-* ] } {
+ verbose "Skipping s390 TDB register tests."
+ return
+}
+
+set testfile "s390-tdbregs"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [get_compiler_info] } {
+ return -1
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
+ executable [list debug additional_flags=-march=zEC12]] != "" } {
+ unsupported "No TE support (compile failed)."
+ return
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if { ![runto_main] } then {
+ gdb_suppress_tests
+}
+
+gdb_test_multiple "next" "check for TE support" {
+ -re "Program received signal SIGILL,.*\r\n$gdb_prompt $" {
+ unsupported "No TE support."
+ return
+ }
+ -re "\[0-9\]+.*\r\n$gdb_prompt $" {
+ pass "TE support available"
+ }
+ -re "$gdb_prompt $" {
+ unsupported "No TE support (unknown error)."
+ return
+ }
+}
+
+set crashline [gdb_get_line_number "FAULT"]
+
+gdb_test "print \$tdb0" "\\\$\[0-9\]+ = <unavailable>" "tdb0 unavailable"
+gdb_test "print \$tr0" "\\\$\[0-9\]+ = <unavailable>" "tr0 unavailable"
+gdb_test "next" \
+ "Program received signal SIGSEGV, .*" \
+ "crash in transaction"
+gdb_test "print/x \$tdb0" "\\\$\[0-9\]+ = 0x1.*" "tdb0 available"
+gdb_test "set print symbol-filename" "" "set print symbol-filename"
+gdb_test "print/a \$atia" \
+ "<crash_in_transaction.*:$crashline>" \
+ "ATIA points to crash"
Index: gdb/gdb/gdbserver/linux-s390-low.c
===================================================================
--- gdb.orig/gdb/gdbserver/linux-s390-low.c
+++ gdb/gdb/gdbserver/linux-s390-low.c
@@ -64,6 +64,10 @@ extern const struct target_desc *tdesc_s
void init_registers_s390_linux64v2 (void);
extern const struct target_desc *tdesc_s390_linux64v2;
+/* Defined in auto-generated file s390-te-linux64.c. */
+void init_registers_s390_te_linux64 (void);
+extern const struct target_desc *tdesc_s390_te_linux64;
+
/* Defined in auto-generated file s390x-linux64.c. */
void init_registers_s390x_linux64 (void);
extern const struct target_desc *tdesc_s390x_linux64;
@@ -76,6 +80,10 @@ extern const struct target_desc *tdesc_s
void init_registers_s390x_linux64v2 (void);
extern const struct target_desc *tdesc_s390x_linux64v2;
+/* Defined in auto-generated file s390x-te-linux64.c. */
+void init_registers_s390x_te_linux64 (void);
+extern const struct target_desc *tdesc_s390x_te_linux64;
+
#define s390_num_regs 52
static int s390_regmap[] = {
@@ -391,10 +399,10 @@ s390_check_regset (int pid, int regset,
iov.iov_base = buf;
iov.iov_len = regsize;
- if (ptrace (PTRACE_GETREGSET, pid, (long) regset, (long) &iov) < 0)
- return 0;
- else
+ if (ptrace (PTRACE_GETREGSET, pid, (long) regset, (long) &iov) >= 0
+ || errno == ENODATA)
return 1;
+ return 0;
}
#ifdef __s390x__
@@ -415,6 +423,7 @@ s390_arch_setup (void)
= s390_check_regset (pid, NT_S390_LAST_BREAK, 8);
int have_regset_system_call
= s390_check_regset (pid, NT_S390_SYSTEM_CALL, 4);
+ int have_regset_tdb = s390_check_regset (pid, NT_S390_TDB, 256);
/* Update target_regsets according to available register sets. */
for (regset = s390_regsets; regset->fill_function != NULL; regset++)
@@ -427,6 +436,8 @@ s390_arch_setup (void)
case NT_S390_SYSTEM_CALL:
regset->size = have_regset_system_call? 4 : 0;
break;
+ case NT_S390_TDB:
+ regset->size = have_regset_tdb ? 256 : 0;
default:
break;
}
@@ -451,6 +462,8 @@ s390_arch_setup (void)
if (pswm & 1)
{
+ if (have_regset_tdb)
+ tdesc = tdesc_s390x_te_linux64;
if (have_regset_system_call)
tdesc = tdesc_s390x_linux64v2;
else if (have_regset_last_break)
@@ -465,7 +478,9 @@ s390_arch_setup (void)
{
have_hwcap_s390_high_gprs = 1;
- if (have_regset_system_call)
+ if (have_regset_tdb)
+ tdesc = tdesc_s390_te_linux64;
+ else if (have_regset_system_call)
tdesc = tdesc_s390_linux64v2;
else if (have_regset_last_break)
tdesc = tdesc_s390_linux64v1;
@@ -575,9 +590,11 @@ initialize_low_arch (void)
init_registers_s390_linux64 ();
init_registers_s390_linux64v1 ();
init_registers_s390_linux64v2 ();
+ init_registers_s390_te_linux64 ();
init_registers_s390x_linux64 ();
init_registers_s390x_linux64v1 ();
init_registers_s390x_linux64v2 ();
+ init_registers_s390x_te_linux64 ();
initialize_regsets_info (&s390_regsets_info);
#ifdef __s390x__
Index: gdb/gdb/NEWS
===================================================================
--- gdb.orig/gdb/NEWS
+++ gdb/gdb/NEWS
@@ -87,6 +87,10 @@ show range-stepping
the number of control packets from/to GDB. See "New remote packets"
below.
+* On S/390 targets that provide the transactional-execution feature,
+ the program interruption transaction diagnostic block (TDB) is now
+ represented as a number of additional "registers" in GDB.
+
* New remote packets
vCont;r
Index: gdb/gdb/doc/gdb.texinfo
===================================================================
--- gdb.orig/gdb/doc/gdb.texinfo
+++ gdb/gdb/doc/gdb.texinfo
@@ -13832,8 +13832,8 @@ specified by the extension to support de
There are two encodings in use, depending on the architecture: BID (Binary
Integer Decimal) for x86 and x86-64, and DPD (Densely Packed Decimal) for
-PowerPC. @value{GDBN} will use the appropriate encoding for the configured
-target.
+PowerPC and S/390. @value{GDBN} will use the appropriate encoding for the
+configured target.
Because of a limitation in @file{libdecnumber}, the library used by @value{GDBN}
to manipulate decimal floating point numbers, it is not possible to convert
@@ -42313,6 +42313,7 @@ registers using the capitalization used
* M68K Features::
* Nios II Features::
* PowerPC Features::
+* S/390 and System z Features::
* TIC6x Features::
@end menu
@@ -42502,6 +42503,39 @@ contain registers @samp{ev0h} through @s
these to present registers @samp{ev0} through @samp{ev31} to the
user.
+@node S/390 and System z Features
+@subsection S/390 and System z Features
+@cindex target descriptions, S/390 features
+@cindex target descriptions, System z features
+
+The @samp{org.gnu.gdb.s390.core} feature is required for S/390 and
+System z targets. It should contain the PSW and the 16 general
+registers. In particular, System z targets should provide the 64-bit
+registers @samp{pswm}, @samp{pswa}, and @samp{r0} through @samp{r15}.
+S/390 targets should provide the 32-bit versions of these registers.
+A System z target that runs in 31-bit addressing mode should provide
+32-bit versions of @samp{pswm} and @samp{pswa}, as well as the general
+register's upper halves @samp{r0h} through @samp{r15h}, and their
+lower halves @samp{r0l} through @samp{r15l}.
+
+The @samp{org.gnu.gdb.s390.fpr} feature is required. It should
+contain the 64-bit registers @samp{f0} through @samp{f15}, and
+@samp{fpc}.
+
+The @samp{org.gnu.gdb.s390.acr} feature is required. It should
+contain the 32-bit registers @samp{acr0} through @samp{acr15}.
+
+The @samp{org.gnu.gdb.s390.linux} feature is optional. It should
+contain the register @samp{orig_r2}, which is 64-bit wide on System z
+targets and 32-bit otherwise. In addition, the feature may contain
+the @samp{last_break} register, whose width depends on the addressing
+mode, as well as the @samp{system_call} register, which is always
+32-bit wide.
+
+The @samp{org.gnu.gdb.s390.tdb} feature is optional. It should
+contain the 64-bit registers @samp{tdb0}, @samp{tac}, @samp{tct},
+@samp{atia}, and @samp{tr0} through @samp{tr15}.
+
@node TIC6x Features
@subsection TMS320C6x Features
@cindex target descriptions, TIC6x features
Index: gdb/gdb/features/s390-te-linux64.xml
===================================================================
--- /dev/null
+++ gdb/gdb/features/s390-te-linux64.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010-2013 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!-- S/390 31-bit user-level code on a machine operating
+ in z/Architecture mode. -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>s390:31-bit</architecture>
+ <xi:include href="s390-core64.xml"/>
+ <xi:include href="s390-acr.xml"/>
+ <xi:include href="s390-fpr.xml"/>
+
+ <feature name="org.gnu.gdb.s390.linux">
+ <reg name="orig_r2" bitsize="32" type="uint32" group="system"/>
+ <reg name="last_break" bitsize="32" type="code_ptr" group="system" save-restore="no"/>
+ <reg name="system_call" bitsize="32" type="uint32" group="system"/>
+ </feature>
+
+ <xi:include href="s390-tdb.xml"/>
+</target>
Index: gdb/gdb/features/s390x-te-linux64.xml
===================================================================
--- /dev/null
+++ gdb/gdb/features/s390x-te-linux64.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010-2013 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!-- S/390 64-bit user-level code. -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>s390:64-bit</architecture>
+ <xi:include href="s390x-core64.xml"/>
+ <xi:include href="s390-acr.xml"/>
+ <xi:include href="s390-fpr.xml"/>
+
+ <feature name="org.gnu.gdb.s390.linux">
+ <reg name="orig_r2" bitsize="64" type="uint64" group="system"/>
+ <reg name="last_break" bitsize="64" type="code_ptr" group="system" save-restore="no"/>
+ <reg name="system_call" bitsize="32" type="uint32" group="system"/>
+ </feature>
+
+ <xi:include href="s390-tdb.xml"/>
+</target>
Index: gdb/gdb/features/Makefile
===================================================================
--- gdb.orig/gdb/features/Makefile
+++ gdb/gdb/features/Makefile
@@ -50,6 +50,7 @@ WHICH = aarch64 \
s390-linux32 s390-linux64 s390x-linux64 \
s390-linux32v1 s390-linux64v1 s390x-linux64v1 \
s390-linux32v2 s390-linux64v2 s390x-linux64v2 \
+ s390-te-linux64 s390x-te-linux64 \
tic6x-c64xp tic6x-c64x tic6x-c62x \
tic6x-c64xp-linux tic6x-c64x-linux tic6x-c62x-linux
@@ -84,9 +85,11 @@ s390-linux32v2-expedite = r14,r15,pswa
s390-linux64-expedite = r14l,r15l,pswa
s390-linux64v1-expedite = r14l,r15l,pswa
s390-linux64v2-expedite = r14l,r15l,pswa
+s390-te-linux64-expedite = r14,r15,pswa
s390x-linux64-expedite = r14,r15,pswa
s390x-linux64v1-expedite = r14,r15,pswa
s390x-linux64v2-expedite = r14,r15,pswa
+s390x-te-linux64-expedite = r14,r15,pswa
tic6x-c64xp-expedite = A15,PC
tic6x-c64x-expedite = A15,PC
tic6x-c62x-expedite = A15,PC
Index: gdb/gdb/features/s390-te-linux64.c
===================================================================
--- /dev/null
+++ gdb/gdb/features/s390-te-linux64.c
@@ -0,0 +1,118 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: s390-te-linux64.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_s390_te_linux64;
+static void
+initialize_tdesc_s390_te_linux64 (void)
+{
+ struct target_desc *result = allocate_target_description ();
+ struct tdesc_feature *feature;
+
+ set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit"));
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.s390.core");
+ tdesc_create_reg (feature, "pswm", 0, 1, "psw", 32, "uint32");
+ tdesc_create_reg (feature, "pswa", 1, 1, "psw", 32, "uint32");
+ tdesc_create_reg (feature, "r0h", 2, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r0l", 3, 1, "lower", 32, "uint32");
+ tdesc_create_reg (feature, "r1h", 4, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r1l", 5, 1, "lower", 32, "uint32");
+ tdesc_create_reg (feature, "r2h", 6, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r2l", 7, 1, "lower", 32, "uint32");
+ tdesc_create_reg (feature, "r3h", 8, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r3l", 9, 1, "lower", 32, "uint32");
+ tdesc_create_reg (feature, "r4h", 10, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r4l", 11, 1, "lower", 32, "uint32");
+ tdesc_create_reg (feature, "r5h", 12, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r5l", 13, 1, "lower", 32, "uint32");
+ tdesc_create_reg (feature, "r6h", 14, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r6l", 15, 1, "lower", 32, "uint32");
+ tdesc_create_reg (feature, "r7h", 16, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r7l", 17, 1, "lower", 32, "uint32");
+ tdesc_create_reg (feature, "r8h", 18, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r8l", 19, 1, "lower", 32, "uint32");
+ tdesc_create_reg (feature, "r9h", 20, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r9l", 21, 1, "lower", 32, "uint32");
+ tdesc_create_reg (feature, "r10h", 22, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r10l", 23, 1, "lower", 32, "uint32");
+ tdesc_create_reg (feature, "r11h", 24, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r11l", 25, 1, "lower", 32, "uint32");
+ tdesc_create_reg (feature, "r12h", 26, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r12l", 27, 1, "lower", 32, "uint32");
+ tdesc_create_reg (feature, "r13h", 28, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r13l", 29, 1, "lower", 32, "uint32");
+ tdesc_create_reg (feature, "r14h", 30, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r14l", 31, 1, "lower", 32, "uint32");
+ tdesc_create_reg (feature, "r15h", 32, 1, "upper", 32, "uint32");
+ tdesc_create_reg (feature, "r15l", 33, 1, "lower", 32, "uint32");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.s390.acr");
+ tdesc_create_reg (feature, "acr0", 34, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr1", 35, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr2", 36, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr3", 37, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr4", 38, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr5", 39, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr6", 40, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr7", 41, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr8", 42, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr9", 43, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr10", 44, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr11", 45, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr12", 46, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr13", 47, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr14", 48, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr15", 49, 1, "access", 32, "uint32");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.s390.fpr");
+ tdesc_create_reg (feature, "fpc", 50, 1, "float", 32, "uint32");
+ tdesc_create_reg (feature, "f0", 51, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f1", 52, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f2", 53, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f3", 54, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f4", 55, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f5", 56, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f6", 57, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f7", 58, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f8", 59, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f9", 60, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f10", 61, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f11", 62, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f12", 63, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f13", 64, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f14", 65, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f15", 66, 1, "float", 64, "ieee_double");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.s390.linux");
+ tdesc_create_reg (feature, "orig_r2", 67, 1, "system", 32, "uint32");
+ tdesc_create_reg (feature, "last_break", 68, 0, "system", 32, "code_ptr");
+ tdesc_create_reg (feature, "system_call", 69, 1, "system", 32, "uint32");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.s390.tdb");
+ tdesc_create_reg (feature, "tdb0", 70, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tac", 71, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tct", 72, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "atia", 73, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr0", 74, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr1", 75, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr2", 76, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr3", 77, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr4", 78, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr5", 79, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr6", 80, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr7", 81, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr8", 82, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr9", 83, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr10", 84, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr11", 85, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr12", 86, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr13", 87, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr14", 88, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr15", 89, 1, "tdb", 64, "uint64");
+
+ tdesc_s390_te_linux64 = result;
+}
Index: gdb/gdb/features/s390x-te-linux64.c
===================================================================
--- /dev/null
+++ gdb/gdb/features/s390x-te-linux64.c
@@ -0,0 +1,102 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: s390x-te-linux64.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_s390x_te_linux64;
+static void
+initialize_tdesc_s390x_te_linux64 (void)
+{
+ struct target_desc *result = allocate_target_description ();
+ struct tdesc_feature *feature;
+
+ set_tdesc_architecture (result, bfd_scan_arch ("s390:64-bit"));
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.s390.core");
+ tdesc_create_reg (feature, "pswm", 0, 1, "psw", 64, "uint64");
+ tdesc_create_reg (feature, "pswa", 1, 1, "psw", 64, "uint64");
+ tdesc_create_reg (feature, "r0", 2, 1, "general", 64, "uint64");
+ tdesc_create_reg (feature, "r1", 3, 1, "general", 64, "uint64");
+ tdesc_create_reg (feature, "r2", 4, 1, "general", 64, "uint64");
+ tdesc_create_reg (feature, "r3", 5, 1, "general", 64, "uint64");
+ tdesc_create_reg (feature, "r4", 6, 1, "general", 64, "uint64");
+ tdesc_create_reg (feature, "r5", 7, 1, "general", 64, "uint64");
+ tdesc_create_reg (feature, "r6", 8, 1, "general", 64, "uint64");
+ tdesc_create_reg (feature, "r7", 9, 1, "general", 64, "uint64");
+ tdesc_create_reg (feature, "r8", 10, 1, "general", 64, "uint64");
+ tdesc_create_reg (feature, "r9", 11, 1, "general", 64, "uint64");
+ tdesc_create_reg (feature, "r10", 12, 1, "general", 64, "uint64");
+ tdesc_create_reg (feature, "r11", 13, 1, "general", 64, "uint64");
+ tdesc_create_reg (feature, "r12", 14, 1, "general", 64, "uint64");
+ tdesc_create_reg (feature, "r13", 15, 1, "general", 64, "uint64");
+ tdesc_create_reg (feature, "r14", 16, 1, "general", 64, "uint64");
+ tdesc_create_reg (feature, "r15", 17, 1, "general", 64, "uint64");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.s390.acr");
+ tdesc_create_reg (feature, "acr0", 18, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr1", 19, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr2", 20, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr3", 21, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr4", 22, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr5", 23, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr6", 24, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr7", 25, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr8", 26, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr9", 27, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr10", 28, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr11", 29, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr12", 30, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr13", 31, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr14", 32, 1, "access", 32, "uint32");
+ tdesc_create_reg (feature, "acr15", 33, 1, "access", 32, "uint32");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.s390.fpr");
+ tdesc_create_reg (feature, "fpc", 34, 1, "float", 32, "uint32");
+ tdesc_create_reg (feature, "f0", 35, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f1", 36, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f2", 37, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f3", 38, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f4", 39, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f5", 40, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f6", 41, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f7", 42, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f8", 43, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f9", 44, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f10", 45, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f11", 46, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f12", 47, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f13", 48, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f14", 49, 1, "float", 64, "ieee_double");
+ tdesc_create_reg (feature, "f15", 50, 1, "float", 64, "ieee_double");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.s390.linux");
+ tdesc_create_reg (feature, "orig_r2", 51, 1, "system", 64, "uint64");
+ tdesc_create_reg (feature, "last_break", 52, 0, "system", 64, "code_ptr");
+ tdesc_create_reg (feature, "system_call", 53, 1, "system", 32, "uint32");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.s390.tdb");
+ tdesc_create_reg (feature, "tdb0", 54, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tac", 55, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tct", 56, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "atia", 57, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr0", 58, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr1", 59, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr2", 60, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr3", 61, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr4", 62, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr5", 63, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr6", 64, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr7", 65, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr8", 66, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr9", 67, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr10", 68, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr11", 69, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr12", 70, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr13", 71, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr14", 72, 1, "tdb", 64, "uint64");
+ tdesc_create_reg (feature, "tr15", 73, 1, "tdb", 64, "uint64");
+
+ tdesc_s390x_te_linux64 = result;
+}
Index: gdb/gdb/regformats/s390-te-linux64.dat
===================================================================
--- /dev/null
+++ gdb/gdb/regformats/s390-te-linux64.dat
@@ -0,0 +1,94 @@
+# DO NOT EDIT: generated from s390-te-linux64.xml
+name:s390_te_linux64
+xmltarget:s390-te-linux64.xml
+expedite:r14,r15,pswa
+32:pswm
+32:pswa
+32:r0h
+32:r0l
+32:r1h
+32:r1l
+32:r2h
+32:r2l
+32:r3h
+32:r3l
+32:r4h
+32:r4l
+32:r5h
+32:r5l
+32:r6h
+32:r6l
+32:r7h
+32:r7l
+32:r8h
+32:r8l
+32:r9h
+32:r9l
+32:r10h
+32:r10l
+32:r11h
+32:r11l
+32:r12h
+32:r12l
+32:r13h
+32:r13l
+32:r14h
+32:r14l
+32:r15h
+32:r15l
+32:acr0
+32:acr1
+32:acr2
+32:acr3
+32:acr4
+32:acr5
+32:acr6
+32:acr7
+32:acr8
+32:acr9
+32:acr10
+32:acr11
+32:acr12
+32:acr13
+32:acr14
+32:acr15
+32:fpc
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+32:orig_r2
+32:last_break
+32:system_call
+64:tdb0
+64:tac
+64:tct
+64:atia
+64:tr0
+64:tr1
+64:tr2
+64:tr3
+64:tr4
+64:tr5
+64:tr6
+64:tr7
+64:tr8
+64:tr9
+64:tr10
+64:tr11
+64:tr12
+64:tr13
+64:tr14
+64:tr15
Index: gdb/gdb/regformats/s390x-te-linux64.dat
===================================================================
--- /dev/null
+++ gdb/gdb/regformats/s390x-te-linux64.dat
@@ -0,0 +1,78 @@
+# DO NOT EDIT: generated from s390x-te-linux64.xml
+name:s390x_te_linux64
+xmltarget:s390x-te-linux64.xml
+expedite:r14,r15,pswa
+64:pswm
+64:pswa
+64:r0
+64:r1
+64:r2
+64:r3
+64:r4
+64:r5
+64:r6
+64:r7
+64:r8
+64:r9
+64:r10
+64:r11
+64:r12
+64:r13
+64:r14
+64:r15
+32:acr0
+32:acr1
+32:acr2
+32:acr3
+32:acr4
+32:acr5
+32:acr6
+32:acr7
+32:acr8
+32:acr9
+32:acr10
+32:acr11
+32:acr12
+32:acr13
+32:acr14
+32:acr15
+32:fpc
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+64:orig_r2
+64:last_break
+32:system_call
+64:tdb0
+64:tac
+64:tct
+64:atia
+64:tr0
+64:tr1
+64:tr2
+64:tr3
+64:tr4
+64:tr5
+64:tr6
+64:tr7
+64:tr8
+64:tr9
+64:tr10
+64:tr11
+64:tr12
+64:tr13
+64:tr14
+64:tr15
Index: gdb/gdb/gdbserver/Makefile.in
===================================================================
--- gdb.orig/gdb/gdbserver/Makefile.in
+++ gdb/gdb/gdbserver/Makefile.in
@@ -332,6 +332,9 @@ clean:
rm -f powerpc-isa205-altivec32l.c powerpc-isa205-vsx32l.c powerpc-isa205-altivec64l.c
rm -f powerpc-isa205-vsx64l.c
rm -f s390-linux32.c s390-linux64.c s390x-linux64.c
+ rm -f s390-linux32v1.c s390-linux32v2.c s390-linux64v1.c
+ rm -f s390-linux64v2.c s390x-linux64v1.c s390x-linux64v2.c
+ rm -f s390-te-linux32.c s390-te-linux64.c
rm -f tic6x-c64xp-linux.c tic6x-c64x-linux.c tic6x-c62x-linux.c
rm -f xml-builtin.c stamp-xml
rm -f i386-avx.c i386-avx-linux.c
@@ -662,12 +665,16 @@ s390-linux64v1.c : $(srcdir)/../regforma
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390-linux64v1.dat s390-linux64v1.c
s390-linux64v2.c : $(srcdir)/../regformats/s390-linux64v2.dat $(regdat_sh)
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390-linux64v2.dat s390-linux64v2.c
+s390-te-linux64.c : $(srcdir)/../regformats/s390-te-linux64.dat $(regdat_sh)
+ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390-te-linux64.dat s390-te-linux64.c
s390x-linux64.c : $(srcdir)/../regformats/s390x-linux64.dat $(regdat_sh)
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390x-linux64.dat s390x-linux64.c
s390x-linux64v1.c : $(srcdir)/../regformats/s390x-linux64v1.dat $(regdat_sh)
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390x-linux64v1.dat s390x-linux64v1.c
s390x-linux64v2.c : $(srcdir)/../regformats/s390x-linux64v2.dat $(regdat_sh)
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390x-linux64v2.dat s390x-linux64v2.c
+s390x-te-linux64.c : $(srcdir)/../regformats/s390x-te-linux64.dat $(regdat_sh)
+ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390x-te-linux64.dat s390x-te-linux64.c
tic6x-c64xp-linux.c : $(srcdir)/../regformats/tic6x-c64xp-linux.dat $(regdat_sh)
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/tic6x-c64xp-linux.dat tic6x-c64xp-linux.c
Index: gdb/gdb/gdbserver/configure.srv
===================================================================
--- gdb.orig/gdb/gdbserver/configure.srv
+++ gdb/gdb/gdbserver/configure.srv
@@ -267,9 +267,11 @@ case "${target}" in
srv_regobj="${srv_regobj} s390-linux64.o"
srv_regobj="${srv_regobj} s390-linux64v1.o"
srv_regobj="${srv_regobj} s390-linux64v2.o"
+ srv_regobj="${srv_regobj} s390-te-linux64.o"
srv_regobj="${srv_regobj} s390x-linux64.o"
srv_regobj="${srv_regobj} s390x-linux64v1.o"
srv_regobj="${srv_regobj} s390x-linux64v2.o"
+ srv_regobj="${srv_regobj} s390x-te-linux64.o"
srv_tgtobj="linux-low.o linux-osdata.o linux-s390-low.o linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_xmlfiles="s390-linux32.xml"
@@ -278,14 +280,17 @@ case "${target}" in
srv_xmlfiles="${srv_xmlfiles} s390-linux64.xml"
srv_xmlfiles="${srv_xmlfiles} s390-linux64v1.xml"
srv_xmlfiles="${srv_xmlfiles} s390-linux64v2.xml"
+ srv_xmlfiles="${srv_xmlfiles} s390-te-linux64.xml"
srv_xmlfiles="${srv_xmlfiles} s390x-linux64.xml"
srv_xmlfiles="${srv_xmlfiles} s390x-linux64v1.xml"
srv_xmlfiles="${srv_xmlfiles} s390x-linux64v2.xml"
+ srv_xmlfiles="${srv_xmlfiles} s390x-te-linux64.xml"
srv_xmlfiles="${srv_xmlfiles} s390-core32.xml"
srv_xmlfiles="${srv_xmlfiles} s390-core64.xml"
srv_xmlfiles="${srv_xmlfiles} s390x-core64.xml"
srv_xmlfiles="${srv_xmlfiles} s390-acr.xml"
srv_xmlfiles="${srv_xmlfiles} s390-fpr.xml"
+ srv_xmlfiles="${srv_xmlfiles} s390-tdb.xml"
srv_linux_usrregs=yes
srv_linux_regsets=yes
srv_linux_thread_db=yes
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v3 3/3] Dynamic core regset sections support
2013-06-12 15:12 [RFA PATCH v3 0/3] Add TDB regset support Andreas Arnez
2013-06-12 15:12 ` [PATCH v3 1/3] S/390 regmap rework Andreas Arnez
2013-06-12 15:13 ` [PATCH v3 2/3] Add TDB regset Andreas Arnez
@ 2013-06-12 15:23 ` Andreas Arnez
2013-06-12 16:06 ` Mark Kettenis
2 siblings, 1 reply; 10+ messages in thread
From: Andreas Arnez @ 2013-06-12 15:23 UTC (permalink / raw)
To: gdb-patches; +Cc: Ulrich.Weigand
Rework the handling of core file register note sections. So far the
target-dependent code provided a static list of supported register
note sections via set_gdbarch_core_regset_sections. This patch
replaces the static list by a target-dependent iterator function which
can be set with set_gdbarch_iterate_over_regset_sections. Only those
architectures that have been using set_gdbarch_core_regset_sections
are affected by this change.
The patch is needed on newer z/Architecture systems for correct gcore
handling. With the static approach, gcore always writes the TDB
regset into the core file, even if the TDB registers are currently
invalid. The new iterator omits the TDB in this case.
2013-06-12 Andreas Arnez <arnez@linux.vnet.ibm.com>
* regset.h (struct core_regset_section): Remove structure
declaration.
* gdbarch.sh: Add typedef for iterate_over_regset_sections_cb.
(function_list): Remove core_regset_sections. Add
iterate_over_regset_sections.
* gdbarch.h: Regenerate.
* gdbarch.c: Regenerate.
* linux-tdep.c (linux_collect_regset_section_cb_data): New
structure.
(linux_collect_regset_section_cb): New function.
(linux_collect_thread_registers): Replace loop by iteration
through gdbarch_iterate_over_regset_sections.
(linux_make_corefile_notes_1): Adjust check.
* amd64-linux-tdep.c (amd64_linux_regset_sections): Remove array.
(amd64_linux_iterate_over_regset_sections): New function.
(amd64_linux_init_abi_common): Remove invocation of
set_gdbarch_core_regset_sections; instead, call
set_gdbarch_iterate_over_regset_sections.
* arm-linux-tdep.c (arm_linux_fpa_regset_sections): Remove array.
(arm_linux_vfp_regset_sections): Likewise.
(arm_linux_iterate_over_regset_sections): New function.
(arm_linux_init_abi): Remove invocations of
set_gdbarch_core_regset_sections; instead, call
set_gdbarch_iterate_over_regset_sections.
* i386-linux-tdep.c (i386_linux_regset_sections): Remove array.
(i386_linux_sse_regset_sections): Likewise.
(i386_linux_avx_regset_sections): Likewise.
(i386_linux_iterate_over_regset_sections): New function.
(i386_linux_init_abi): Remove invocations of
set_gdbarch_core_regset_sections; instead, call
set_gdbarch_iterate_over_regset_sections.
* ppc-linux-tdep.c (ppc_linux_vsx_regset_sections): Remove array.
(ppc_linux_vmx_regset_sections): Likewise.
(ppc64_linux_vsx_regset_sections): Likewise.
(ppc64_linux_vmx_regset_sections): Likewise.
(ppc64_linux_fp_regset_sections): Likewise.
(ppc_linux_iterate_over_regset_sections): New function.
(ppc_linux_init_abi): Remove invocations of
set_gdbarch_core_regset_sections; instead, call
set_gdbarch_iterate_over_regset_sections.
* s390-tdep.c (gdbarch_tdep): New fields "have_linux_v1" and
"have_linux_v2".
(s390_linux32_regset_sections): Remove array.
(s390_linux32v1_regset_sections): Likewise.
(s390_linux32v2_regset_sections): Likewise.
(s390_linux64_regset_sections): Likewise.
(s390_linux64v1_regset_sections): Likewise.
(s390_linux64v2_regset_sections): Likewise.
(s390x_linux64_regset_sections): Likewise.
(s390x_linux64v1_regset_sections): Likewise.
(s390x_linux64v2_regset_sections): Likewise.
(s390_iterate_over_regset_sections ): New function.
(s390_gdbarch_init): Initialize new tdep fields "have_linux_v1"
and "have_linux_v2". Remove all invocations of
set_gdbarch_core_regset_sections; instead, call
set_gdbarch_iterate_over_regset_sections.
* corelow.c (get_core_registers_cb): New function.
(get_core_registers): Instead of looping through the list returned
by gdbarch_core_regset_sections, iterate get_core_registers_cb via
gdbarch_iterate_over_regset_sections.
Index: gdb/gdb/gdbarch.sh
===================================================================
--- gdb.orig/gdb/gdbarch.sh
+++ gdb/gdb/gdbarch.sh
@@ -635,8 +635,13 @@ F:CORE_ADDR:fetch_pointer_argument:struc
# name SECT_NAME and size SECT_SIZE.
M:const struct regset *:regset_from_core_section:const char *sect_name, size_t sect_size:sect_name, sect_size
-# Supported register notes in a core file.
-v:struct core_regset_section *:core_regset_sections:const char *name, int len::::::host_address_to_string (gdbarch->core_regset_sections)
+# Iterate over all supported register notes in a core file. For each
+# supported register note section, the iterator must call CB and pass
+# CB_DATA unchanged. If CB returns non-zero, the iterator must stop.
+# If REGCACHE is not NULL, the iterator can limit the supported
+# register note sections based on the current register values.
+# Otherwise it should enumerate all supported register note sections.
+M:void:iterate_over_regset_sections:iterate_over_regset_sections_cb *cb, void *cb_data, const struct regcache *regcache:cb, cb_data, regcache
# Create core file notes
M:char *:make_corefile_notes:bfd *obfd, int *note_size:obfd, note_size
@@ -1120,6 +1125,9 @@ extern struct gdbarch startup_gdbarch;
typedef int (iterate_over_objfiles_in_search_order_cb_ftype)
(struct objfile *objfile, void *cb_data);
+
+typedef int (iterate_over_regset_sections_cb)
+ (const char *sect_name, int size, const char *human_name, void *cb_data);
EOF
# function typedef's
Index: gdb/gdb/linux-tdep.c
===================================================================
--- gdb.orig/gdb/linux-tdep.c
+++ gdb/gdb/linux-tdep.c
@@ -1010,6 +1010,54 @@ linux_make_mappings_corefile_notes (stru
return note_data;
}
+/* Structure for passing information from
+ linux_collect_thread_registers via an iterator to
+ linux_collect_regset_section_cb. */
+
+struct linux_collect_regset_section_cb_data
+{
+ struct gdbarch *gdbarch;
+ const struct regcache *regcache;
+ bfd *obfd;
+ char *note_data;
+ int *note_size;
+ unsigned long lwp;
+ enum gdb_signal stop_signal;
+};
+
+/* Callback for iterate_over_regset_sections that records a single
+ regset in the corefile note section. */
+
+static int
+linux_collect_regset_section_cb (const char *sect_name, int size,
+ const char *human_name, void *cb_data)
+{
+ const struct regset *regset;
+ char *buf;
+ struct linux_collect_regset_section_cb_data *data = cb_data;
+
+ regset = gdbarch_regset_from_core_section (data->gdbarch, sect_name, size);
+ gdb_assert (regset && regset->collect_regset);
+
+ buf = xmalloc (size);
+ regset->collect_regset (regset, data->regcache, -1, buf, size);
+
+ /* PRSTATUS still needs to be treated specially. */
+ if (strcmp (sect_name, ".reg") == 0)
+ data->note_data = (char *) elfcore_write_prstatus
+ (data->obfd, data->note_data, data->note_size, data->lwp,
+ gdb_signal_to_host (data->stop_signal), buf);
+ else
+ data->note_data = (char *) elfcore_write_register_note
+ (data->obfd, data->note_data, data->note_size,
+ sect_name, buf, size);
+ xfree (buf);
+
+ if (!data->note_data)
+ return 1; /* Abort iteration. */
+ return 0;
+}
+
/* Records the thread's register state for the corefile note
section. */
@@ -1020,47 +1068,24 @@ linux_collect_thread_registers (const st
enum gdb_signal stop_signal)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
- struct core_regset_section *sect_list;
- unsigned long lwp;
+ struct linux_collect_regset_section_cb_data data;
- sect_list = gdbarch_core_regset_sections (gdbarch);
- gdb_assert (sect_list);
+ data.gdbarch = gdbarch;
+ data.regcache = regcache;
+ data.obfd = obfd;
+ data.note_data = note_data;
+ data.note_size = note_size;
+ data.stop_signal = stop_signal;
/* For remote targets the LWP may not be available, so use the TID. */
- lwp = ptid_get_lwp (ptid);
- if (!lwp)
- lwp = ptid_get_tid (ptid);
-
- while (sect_list->sect_name != NULL)
- {
- const struct regset *regset;
- char *buf;
-
- regset = gdbarch_regset_from_core_section (gdbarch,
- sect_list->sect_name,
- sect_list->size);
- gdb_assert (regset && regset->collect_regset);
-
- buf = xmalloc (sect_list->size);
- regset->collect_regset (regset, regcache, -1, buf, sect_list->size);
-
- /* PRSTATUS still needs to be treated specially. */
- if (strcmp (sect_list->sect_name, ".reg") == 0)
- note_data = (char *) elfcore_write_prstatus
- (obfd, note_data, note_size, lwp,
- gdb_signal_to_host (stop_signal), buf);
- else
- note_data = (char *) elfcore_write_register_note
- (obfd, note_data, note_size,
- sect_list->sect_name, buf, sect_list->size);
- xfree (buf);
- sect_list++;
-
- if (!note_data)
- return NULL;
- }
-
- return note_data;
+ data.lwp = ptid_get_lwp (ptid);
+ if (!data.lwp)
+ data.lwp = ptid_get_tid (ptid);
+
+ gdbarch_iterate_over_regset_sections (gdbarch,
+ linux_collect_regset_section_cb,
+ &data, regcache);
+ return data.note_data;
}
/* Fetch the siginfo data for the current thread, if it exists. If
@@ -1440,7 +1465,7 @@ linux_make_corefile_notes_1 (struct gdba
converted to gdbarch_core_regset_sections, we no longer need to fall back
to the target method at this point. */
- if (!gdbarch_core_regset_sections (gdbarch))
+ if (!gdbarch_iterate_over_regset_sections_p (gdbarch))
return target_make_corefile_notes (obfd, note_size);
else
return linux_make_corefile_notes (gdbarch, obfd, note_size,
Index: gdb/gdb/s390-tdep.c
===================================================================
--- gdb.orig/gdb/s390-tdep.c
+++ gdb/gdb/s390-tdep.c
@@ -84,6 +84,9 @@ struct gdbarch_tdep
const struct regset *fpregset;
int sizeof_fpregset;
+
+ int have_linux_v1;
+ int have_linux_v2;
};
@@ -673,83 +676,37 @@ static const struct regset s390_tdb_regs
s390_collect_regset
};
-static struct core_regset_section s390_linux32_regset_sections[] =
-{
- { ".reg", s390_sizeof_gregset, "general-purpose" },
- { ".reg2", s390_sizeof_fpregset, "floating-point" },
- { NULL, 0}
-};
-
-static struct core_regset_section s390_linux32v1_regset_sections[] =
-{
- { ".reg", s390_sizeof_gregset, "general-purpose" },
- { ".reg2", s390_sizeof_fpregset, "floating-point" },
- { ".reg-s390-last-break", 8, "s390 last-break address" },
- { NULL, 0}
-};
-
-static struct core_regset_section s390_linux32v2_regset_sections[] =
-{
- { ".reg", s390_sizeof_gregset, "general-purpose" },
- { ".reg2", s390_sizeof_fpregset, "floating-point" },
- { ".reg-s390-last-break", 8, "s390 last-break address" },
- { ".reg-s390-system-call", 4, "s390 system-call" },
- { NULL, 0}
-};
-
-static struct core_regset_section s390_linux64_regset_sections[] =
-{
- { ".reg", s390_sizeof_gregset, "general-purpose" },
- { ".reg2", s390_sizeof_fpregset, "floating-point" },
- { ".reg-s390-high-gprs", 16*4, "s390 GPR upper halves" },
- { NULL, 0}
-};
-
-static struct core_regset_section s390_linux64v1_regset_sections[] =
-{
- { ".reg", s390_sizeof_gregset, "general-purpose" },
- { ".reg2", s390_sizeof_fpregset, "floating-point" },
- { ".reg-s390-high-gprs", 16*4, "s390 GPR upper halves" },
- { ".reg-s390-last-break", 8, "s930 last-break address" },
- { NULL, 0}
-};
-
-static struct core_regset_section s390_linux64v2_regset_sections[] =
-{
- { ".reg", s390_sizeof_gregset, "general-purpose" },
- { ".reg2", s390_sizeof_fpregset, "floating-point" },
- { ".reg-s390-high-gprs", 16*4, "s390 GPR upper halves" },
- { ".reg-s390-last-break", 8, "s930 last-break address" },
- { ".reg-s390-system-call", 4, "s390 system-call" },
- { ".reg-s390-tdb", s390_sizeof_tdbregset, "s390 TDB" },
- { NULL, 0}
-};
-
-static struct core_regset_section s390x_linux64_regset_sections[] =
-{
- { ".reg", s390x_sizeof_gregset, "general-purpose" },
- { ".reg2", s390_sizeof_fpregset, "floating-point" },
- { NULL, 0}
-};
-
-static struct core_regset_section s390x_linux64v1_regset_sections[] =
-{
- { ".reg", s390x_sizeof_gregset, "general-purpose" },
- { ".reg2", s390_sizeof_fpregset, "floating-point" },
- { ".reg-s390-last-break", 8, "s930 last-break address" },
- { NULL, 0}
-};
-
-static struct core_regset_section s390x_linux64v2_regset_sections[] =
+/* Iterate over supported core file register note sections. */
+static void
+s390_iterate_over_regset_sections (struct gdbarch *gdbarch,
+ iterate_over_regset_sections_cb *cb,
+ void *cb_data,
+ const struct regcache *regcache)
{
- { ".reg", s390x_sizeof_gregset, "general-purpose" },
- { ".reg2", s390_sizeof_fpregset, "floating-point" },
- { ".reg-s390-last-break", 8, "s930 last-break address" },
- { ".reg-s390-system-call", 4, "s390 system-call" },
- { ".reg-s390-tdb", s390_sizeof_tdbregset, "s390 TDB" },
- { NULL, 0}
-};
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int is_32_bit = tdep->abi == ABI_LINUX_S390 && tdep->gpr_full_regnum == -1;
+ if ((*cb) (".reg", is_32_bit ? s390_sizeof_gregset : s390x_sizeof_gregset,
+ "general-purpose", cb_data))
+ return;
+ if ((*cb) (".reg2", s390_sizeof_fpregset, "floating-point", cb_data))
+ return;
+ if (tdep->abi == ABI_LINUX_S390 && tdep->gpr_full_regnum != -1)
+ if ((*cb) (".reg-s390-high-gprs", 16*4, "s390 GPR upper halves", cb_data))
+ return;
+ if (tdep->have_linux_v1)
+ if ((*cb) (".reg-s390-last-break", 8, "s930 last-break address", cb_data))
+ return;
+ if (tdep->have_linux_v2)
+ {
+ if ((*cb) (".reg-s390-system-call", 4, "s390 system-call", cb_data))
+ return;
+ if (regcache == NULL
+ || REG_VALID == regcache_register_status (regcache,
+ S390_TDB_DWORD0_REGNUM))
+ (*cb) (".reg-s390-tdb", s390_sizeof_tdbregset, "s390 TDB", cb_data);
+ }
+}
/* Return the appropriate register set for the core section identified
by SECT_NAME and SECT_SIZE. */
@@ -3160,20 +3117,23 @@ s390_gdbarch_init (struct gdbarch_info i
arches = gdbarch_list_lookup_by_info (arches->next, &info))
{
tdep = gdbarch_tdep (arches->gdbarch);
- if (!tdep)
- continue;
- if (tdep->abi != tdep_abi)
- continue;
- if ((tdep->gpr_full_regnum != -1) != have_upper)
- continue;
- if (tdesc_data != NULL)
- tdesc_data_cleanup (tdesc_data);
- return arches->gdbarch;
+ if (tdep
+ && tdep->abi == tdep_abi
+ && (tdep->gpr_full_regnum != -1) == have_upper
+ && tdep->have_linux_v1 == have_linux_v1
+ && tdep->have_linux_v2 == have_linux_v2)
+ {
+ if (tdesc_data != NULL)
+ tdesc_data_cleanup (tdesc_data);
+ return arches->gdbarch;
+ }
}
/* Otherwise create a new gdbarch for the specified machine type. */
tdep = XCALLOC (1, struct gdbarch_tdep);
tdep->abi = tdep_abi;
+ tdep->have_linux_v1 = have_linux_v1;
+ tdep->have_linux_v2 = have_linux_v2;
gdbarch = gdbarch_alloc (&info, tdep);
set_gdbarch_believe_pcc_promotion (gdbarch, 0);
@@ -3204,6 +3164,8 @@ s390_gdbarch_init (struct gdbarch_info i
set_gdbarch_regset_from_core_section (gdbarch,
s390_regset_from_core_section);
set_gdbarch_core_read_description (gdbarch, s390_core_read_description);
+ set_gdbarch_iterate_over_regset_sections (gdbarch,
+ s390_iterate_over_regset_sections);
set_gdbarch_cannot_store_register (gdbarch, s390_cannot_store_register);
set_gdbarch_write_pc (gdbarch, s390_write_pc);
set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read);
@@ -3271,31 +3233,6 @@ s390_gdbarch_init (struct gdbarch_info i
set_gdbarch_addr_bits_remove (gdbarch, s390_addr_bits_remove);
set_solib_svr4_fetch_link_map_offsets
(gdbarch, svr4_ilp32_fetch_link_map_offsets);
-
- if (have_upper)
- {
- if (have_linux_v2)
- set_gdbarch_core_regset_sections (gdbarch,
- s390_linux64v2_regset_sections);
- else if (have_linux_v1)
- set_gdbarch_core_regset_sections (gdbarch,
- s390_linux64v1_regset_sections);
- else
- set_gdbarch_core_regset_sections (gdbarch,
- s390_linux64_regset_sections);
- }
- else
- {
- if (have_linux_v2)
- set_gdbarch_core_regset_sections (gdbarch,
- s390_linux32v2_regset_sections);
- else if (have_linux_v1)
- set_gdbarch_core_regset_sections (gdbarch,
- s390_linux32v1_regset_sections);
- else
- set_gdbarch_core_regset_sections (gdbarch,
- s390_linux32_regset_sections);
- }
break;
case ABI_LINUX_ZSERIES:
@@ -3315,16 +3252,6 @@ s390_gdbarch_init (struct gdbarch_info i
s390_address_class_type_flags_to_name);
set_gdbarch_address_class_name_to_type_flags (gdbarch,
s390_address_class_name_to_type_flags);
-
- if (have_linux_v2)
- set_gdbarch_core_regset_sections (gdbarch,
- s390x_linux64v2_regset_sections);
- else if (have_linux_v1)
- set_gdbarch_core_regset_sections (gdbarch,
- s390x_linux64v1_regset_sections);
- else
- set_gdbarch_core_regset_sections (gdbarch,
- s390x_linux64_regset_sections);
break;
}
Index: gdb/gdb/gdbarch.c
===================================================================
--- gdb.orig/gdb/gdbarch.c
+++ gdb/gdb/gdbarch.c
@@ -236,7 +236,7 @@ struct gdbarch
gdbarch_register_reggroup_p_ftype *register_reggroup_p;
gdbarch_fetch_pointer_argument_ftype *fetch_pointer_argument;
gdbarch_regset_from_core_section_ftype *regset_from_core_section;
- struct core_regset_section * core_regset_sections;
+ gdbarch_iterate_over_regset_sections_ftype *iterate_over_regset_sections;
gdbarch_make_corefile_notes_ftype *make_corefile_notes;
gdbarch_elfcore_write_linux_prpsinfo_ftype *elfcore_write_linux_prpsinfo;
gdbarch_find_memory_regions_ftype *find_memory_regions;
@@ -408,7 +408,7 @@ struct gdbarch startup_gdbarch =
default_register_reggroup_p, /* register_reggroup_p */
0, /* fetch_pointer_argument */
0, /* regset_from_core_section */
- 0, /* core_regset_sections */
+ 0, /* iterate_over_regset_sections */
0, /* make_corefile_notes */
0, /* elfcore_write_linux_prpsinfo */
0, /* find_memory_regions */
@@ -712,6 +712,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of register_reggroup_p, invalid_p == 0 */
/* Skip verify of fetch_pointer_argument, has predicate. */
/* Skip verify of regset_from_core_section, has predicate. */
+ /* Skip verify of iterate_over_regset_sections, has predicate. */
/* Skip verify of make_corefile_notes, has predicate. */
/* Skip verify of elfcore_write_linux_prpsinfo, has predicate. */
/* Skip verify of find_memory_regions, has predicate. */
@@ -898,9 +899,6 @@ gdbarch_dump (struct gdbarch *gdbarch, s
"gdbarch_dump: core_read_description = <%s>\n",
host_address_to_string (gdbarch->core_read_description));
fprintf_unfiltered (file,
- "gdbarch_dump: core_regset_sections = %s\n",
- host_address_to_string (gdbarch->core_regset_sections));
- fprintf_unfiltered (file,
"gdbarch_dump: gdbarch_core_xfer_shared_libraries_p() = %d\n",
gdbarch_core_xfer_shared_libraries_p (gdbarch));
fprintf_unfiltered (file,
@@ -1102,6 +1100,12 @@ gdbarch_dump (struct gdbarch *gdbarch, s
"gdbarch_dump: iterate_over_objfiles_in_search_order = <%s>\n",
host_address_to_string (gdbarch->iterate_over_objfiles_in_search_order));
fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_iterate_over_regset_sections_p() = %d\n",
+ gdbarch_iterate_over_regset_sections_p (gdbarch));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: iterate_over_regset_sections = <%s>\n",
+ host_address_to_string (gdbarch->iterate_over_regset_sections));
+ fprintf_unfiltered (file,
"gdbarch_dump: long_bit = %s\n",
plongest (gdbarch->long_bit));
fprintf_unfiltered (file,
@@ -3345,20 +3349,28 @@ set_gdbarch_regset_from_core_section (st
gdbarch->regset_from_core_section = regset_from_core_section;
}
-struct core_regset_section *
-gdbarch_core_regset_sections (struct gdbarch *gdbarch)
+int
+gdbarch_iterate_over_regset_sections_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->iterate_over_regset_sections != NULL;
+}
+
+void
+gdbarch_iterate_over_regset_sections (struct gdbarch *gdbarch, iterate_over_regset_sections_cb *cb, void *cb_data, const struct regcache *regcache)
{
gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->iterate_over_regset_sections != NULL);
if (gdbarch_debug >= 2)
- fprintf_unfiltered (gdb_stdlog, "gdbarch_core_regset_sections called\n");
- return gdbarch->core_regset_sections;
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_iterate_over_regset_sections called\n");
+ gdbarch->iterate_over_regset_sections (gdbarch, cb, cb_data, regcache);
}
void
-set_gdbarch_core_regset_sections (struct gdbarch *gdbarch,
- struct core_regset_section * core_regset_sections)
+set_gdbarch_iterate_over_regset_sections (struct gdbarch *gdbarch,
+ gdbarch_iterate_over_regset_sections_ftype iterate_over_regset_sections)
{
- gdbarch->core_regset_sections = core_regset_sections;
+ gdbarch->iterate_over_regset_sections = iterate_over_regset_sections;
}
int
Index: gdb/gdb/gdbarch.h
===================================================================
--- gdb.orig/gdb/gdbarch.h
+++ gdb/gdb/gdbarch.h
@@ -85,6 +85,9 @@ extern struct gdbarch startup_gdbarch;
typedef int (iterate_over_objfiles_in_search_order_cb_ftype)
(struct objfile *objfile, void *cb_data);
+typedef int (iterate_over_regset_sections_cb)
+ (const char *sect_name, int size, const char *human_name, void *cb_data);
+
/* The following are pre-initialized by GDBARCH. */
@@ -724,10 +727,18 @@ typedef const struct regset * (gdbarch_r
extern const struct regset * gdbarch_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name, size_t sect_size);
extern void set_gdbarch_regset_from_core_section (struct gdbarch *gdbarch, gdbarch_regset_from_core_section_ftype *regset_from_core_section);
-/* Supported register notes in a core file. */
-
-extern struct core_regset_section * gdbarch_core_regset_sections (struct gdbarch *gdbarch);
-extern void set_gdbarch_core_regset_sections (struct gdbarch *gdbarch, struct core_regset_section * core_regset_sections);
+/* Iterate over all supported register notes in a core file. For each
+ supported register note section, the iterator must call CB and pass
+ CB_DATA unchanged. If CB returns non-zero, the iterator must stop.
+ If REGCACHE is not NULL, the iterator can limit the supported
+ register note sections based on the current register values.
+ Otherwise it should enumerate all supported register note sections. */
+
+extern int gdbarch_iterate_over_regset_sections_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_iterate_over_regset_sections_ftype) (struct gdbarch *gdbarch, iterate_over_regset_sections_cb *cb, void *cb_data, const struct regcache *regcache);
+extern void gdbarch_iterate_over_regset_sections (struct gdbarch *gdbarch, iterate_over_regset_sections_cb *cb, void *cb_data, const struct regcache *regcache);
+extern void set_gdbarch_iterate_over_regset_sections (struct gdbarch *gdbarch, gdbarch_iterate_over_regset_sections_ftype *iterate_over_regset_sections);
/* Create core file notes */
Index: gdb/gdb/arm-linux-tdep.c
===================================================================
--- gdb.orig/gdb/arm-linux-tdep.c
+++ gdb/gdb/arm-linux-tdep.c
@@ -724,21 +724,25 @@ arm_linux_regset_from_core_section (stru
return NULL;
}
-/* Core file register set sections. */
+/* Iterate over core file register note sections. */
-static struct core_regset_section arm_linux_fpa_regset_sections[] =
+static void
+arm_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
+ iterate_over_regset_sections_cb *cb,
+ void *cb_data,
+ const struct regcache *regcache)
{
- { ".reg", ARM_LINUX_SIZEOF_GREGSET, "general-purpose" },
- { ".reg2", ARM_LINUX_SIZEOF_NWFPE, "FPA floating-point" },
- { NULL, 0}
-};
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-static struct core_regset_section arm_linux_vfp_regset_sections[] =
-{
- { ".reg", ARM_LINUX_SIZEOF_GREGSET, "general-purpose" },
- { ".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, "VFP floating-point" },
- { NULL, 0}
-};
+ if ((*cb) (".reg", ARM_LINUX_SIZEOF_GREGSET, "general-purpose", cb_data))
+ return;
+
+ if (tdep->have_vfp_registers)
+ (*cb) (".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, "VFP floating-point",
+ cb_data);
+ else if (tdep->have_fpa_registers)
+ (*cb) (".reg2", ARM_LINUX_SIZEOF_NWFPE, "FPA floating-point", cb_data);
+}
/* Determine target description from core file. */
@@ -1262,13 +1266,10 @@ arm_linux_init_abi (struct gdbarch_info
/* Core file support. */
set_gdbarch_regset_from_core_section (gdbarch,
arm_linux_regset_from_core_section);
+ set_gdbarch_iterate_over_regset_sections
+ (gdbarch, arm_linux_iterate_over_regset_sections);
set_gdbarch_core_read_description (gdbarch, arm_linux_core_read_description);
- if (tdep->have_vfp_registers)
- set_gdbarch_core_regset_sections (gdbarch, arm_linux_vfp_regset_sections);
- else if (tdep->have_fpa_registers)
- set_gdbarch_core_regset_sections (gdbarch, arm_linux_fpa_regset_sections);
-
set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
/* Displaced stepping. */
Index: gdb/gdb/regset.h
===================================================================
--- gdb.orig/gdb/regset.h
+++ gdb/gdb/regset.h
@@ -23,14 +23,6 @@
struct gdbarch;
struct regcache;
-/* Data structure for the supported register notes in a core file. */
-struct core_regset_section
-{
- const char *sect_name;
- int size;
- const char *human_name;
-};
-
/* Data structure describing a register set. */
typedef void (supply_regset_ftype) (const struct regset *, struct regcache *,
Index: gdb/gdb/i386-linux-tdep.c
===================================================================
--- gdb.orig/gdb/i386-linux-tdep.c
+++ gdb/gdb/i386-linux-tdep.c
@@ -52,27 +52,27 @@
#include "features/i386/i386-mmx-linux.c"
#include "features/i386/i386-avx-linux.c"
-/* Supported register note sections. */
-static struct core_regset_section i386_linux_regset_sections[] =
-{
- { ".reg", 68, "general-purpose" },
- { ".reg2", 108, "floating-point" },
- { NULL, 0 }
-};
+/* Iterate over core file register note sections. */
-static struct core_regset_section i386_linux_sse_regset_sections[] =
+static void
+i386_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
+ iterate_over_regset_sections_cb *cb,
+ void *cb_data,
+ const struct regcache *regcache)
{
- { ".reg", 68, "general-purpose" },
- { ".reg-xfp", 512, "extended floating-point" },
- { NULL, 0 }
-};
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-static struct core_regset_section i386_linux_avx_regset_sections[] =
-{
- { ".reg", 68, "general-purpose" },
- { ".reg-xstate", I386_XSTATE_MAX_SIZE, "XSAVE extended state" },
- { NULL, 0 }
-};
+ if ((*cb) (".reg", 68, "general-purpose", cb_data))
+ return;
+
+ if (tdep->xstateregset)
+ (*cb) (".reg-xstate", I386_XSTATE_MAX_SIZE, "XSAVE extended state",
+ cb_data);
+ else if (I387_NUM_XMM_REGS (tdep))
+ (*cb) (".reg-xfp", 512, "extended floating-point", cb_data);
+ else
+ (*cb) (".reg2", 108, "floating-point", cb_data);
+}
/* Return non-zero, when the register is in the corresponding register
group. Put the LINUX_ORIG_EAX register in the system group. */
@@ -939,14 +939,9 @@ i386_linux_init_abi (struct gdbarch_info
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
- /* Install supported register note sections. */
- if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx"))
- set_gdbarch_core_regset_sections (gdbarch, i386_linux_avx_regset_sections);
- else if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.sse"))
- set_gdbarch_core_regset_sections (gdbarch, i386_linux_sse_regset_sections);
- else
- set_gdbarch_core_regset_sections (gdbarch, i386_linux_regset_sections);
-
+ /* Core file support. */
+ set_gdbarch_iterate_over_regset_sections
+ (gdbarch, i386_linux_iterate_over_regset_sections);
set_gdbarch_core_read_description (gdbarch,
i386_linux_core_read_description);
Index: gdb/gdb/ppc-linux-tdep.c
===================================================================
--- gdb.orig/gdb/ppc-linux-tdep.c
+++ gdb/gdb/ppc-linux-tdep.c
@@ -256,53 +256,26 @@ ppc_linux_return_value (struct gdbarch *
readbuf, writebuf);
}
-static struct core_regset_section ppc_linux_vsx_regset_sections[] =
-{
- { ".reg", 48 * 4, "general-purpose" },
- { ".reg2", 264, "floating-point" },
- { ".reg-ppc-vmx", 544, "ppc Altivec" },
- { ".reg-ppc-vsx", 256, "POWER7 VSX" },
- { NULL, 0}
-};
-
-static struct core_regset_section ppc_linux_vmx_regset_sections[] =
-{
- { ".reg", 48 * 4, "general-purpose" },
- { ".reg2", 264, "floating-point" },
- { ".reg-ppc-vmx", 544, "ppc Altivec" },
- { NULL, 0}
-};
-
-static struct core_regset_section ppc_linux_fp_regset_sections[] =
-{
- { ".reg", 48 * 4, "general-purpose" },
- { ".reg2", 264, "floating-point" },
- { NULL, 0}
-};
-
-static struct core_regset_section ppc64_linux_vsx_regset_sections[] =
-{
- { ".reg", 48 * 8, "general-purpose" },
- { ".reg2", 264, "floating-point" },
- { ".reg-ppc-vmx", 544, "ppc Altivec" },
- { ".reg-ppc-vsx", 256, "POWER7 VSX" },
- { NULL, 0}
-};
-
-static struct core_regset_section ppc64_linux_vmx_regset_sections[] =
+static void
+ppc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
+ iterate_over_regset_sections_cb *cb,
+ void *cb_data,
+ const struct regcache *regcache)
{
- { ".reg", 48 * 8, "general-purpose" },
- { ".reg2", 264, "floating-point" },
- { ".reg-ppc-vmx", 544, "ppc Altivec" },
- { NULL, 0}
-};
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int have_vsx = tdep->ppc_vr0_regnum != -1;
+ int have_altivec = tdep->ppc_vsr0_upper_regnum != -1;
-static struct core_regset_section ppc64_linux_fp_regset_sections[] =
-{
- { ".reg", 48 * 8, "general-purpose" },
- { ".reg2", 264, "floating-point" },
- { NULL, 0}
-};
+ if ((*cb) (".reg", 48 * tdep->wordsize, "general-purpose", cb_data))
+ return;
+ if ((*cb) (".reg2", 264, "floating-point", cb_data))
+ return;
+ if (have_altivec)
+ if ((*cb) (".reg-ppc-vmx", 544, "ppc Altivec", cb_data))
+ return;
+ if (have_vsx)
+ (*cb) (".reg-ppc-vsx", 256, "POWER7 VSX", cb_data);
+}
/* PLT stub in executable. */
static struct ppc_insn_pattern powerpc32_plt_stub[] =
@@ -1305,18 +1278,9 @@ ppc_linux_init_abi (struct gdbarch_info
else
set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc");
- /* Supported register sections. */
- if (tdesc_find_feature (info.target_desc,
- "org.gnu.gdb.power.vsx"))
- set_gdbarch_core_regset_sections (gdbarch,
- ppc_linux_vsx_regset_sections);
- else if (tdesc_find_feature (info.target_desc,
- "org.gnu.gdb.power.altivec"))
- set_gdbarch_core_regset_sections (gdbarch,
- ppc_linux_vmx_regset_sections);
- else
- set_gdbarch_core_regset_sections (gdbarch,
- ppc_linux_fp_regset_sections);
+ /* Iterator for supported register sections. */
+ set_gdbarch_iterate_over_regset_sections
+ (gdbarch, ppc_linux_iterate_over_regset_sections);
if (powerpc_so_ops.in_dynsym_resolve_code == NULL)
{
@@ -1360,18 +1324,9 @@ ppc_linux_init_abi (struct gdbarch_info
else
set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpc");
- /* Supported register sections. */
- if (tdesc_find_feature (info.target_desc,
- "org.gnu.gdb.power.vsx"))
- set_gdbarch_core_regset_sections (gdbarch,
- ppc64_linux_vsx_regset_sections);
- else if (tdesc_find_feature (info.target_desc,
- "org.gnu.gdb.power.altivec"))
- set_gdbarch_core_regset_sections (gdbarch,
- ppc64_linux_vmx_regset_sections);
- else
- set_gdbarch_core_regset_sections (gdbarch,
- ppc64_linux_fp_regset_sections);
+ /* Iterator for supported register sections. */
+ set_gdbarch_iterate_over_regset_sections
+ (gdbarch, ppc_linux_iterate_over_regset_sections);
}
/* PPC32 uses a different prpsinfo32 compared to most other Linux
Index: gdb/gdb/amd64-linux-tdep.c
===================================================================
--- gdb.orig/gdb/amd64-linux-tdep.c
+++ gdb/gdb/amd64-linux-tdep.c
@@ -51,15 +51,6 @@
#include "record-full.h"
#include "linux-record.h"
-/* Supported register note sections. */
-static struct core_regset_section amd64_linux_regset_sections[] =
-{
- { ".reg", 27 * 8, "general-purpose" },
- { ".reg2", 512, "floating-point" },
- { ".reg-xstate", I386_XSTATE_MAX_SIZE, "XSAVE extended state" },
- { NULL, 0 }
-};
-
/* Mapping between the general-purpose registers in `struct user'
format and GDB's register cache layout. */
@@ -1278,6 +1269,23 @@ amd64_linux_record_signal (struct gdbarc
return 0;
}
+/* Iterate over supported core file register note sections. */
+
+static void
+amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
+ iterate_over_regset_sections_cb *cb,
+ void *cb_data,
+ const struct regcache *regcache)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if ((*cb) (".reg", 27 * 8, "general-purpose", cb_data))
+ return;
+ if ((*cb) (".reg2", 512, "floating-point", cb_data))
+ return;
+ (*cb) (".reg-xstate", I386_XSTATE_MAX_SIZE, "XSAVE extended state", cb_data);
+}
+
/* Get Linux/x86 target description from core dump. */
static const struct target_desc *
@@ -1336,9 +1344,9 @@ amd64_linux_init_abi_common(struct gdbar
/* GNU/Linux uses the dynamic linker included in the GNU C Library. */
set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
- /* Install supported register note sections. */
- set_gdbarch_core_regset_sections (gdbarch, amd64_linux_regset_sections);
-
+ /* Core file support. */
+ set_gdbarch_iterate_over_regset_sections
+ (gdbarch, amd64_linux_iterate_over_regset_sections);
set_gdbarch_core_read_description (gdbarch,
amd64_linux_core_read_description);
Index: gdb/gdb/corelow.c
===================================================================
--- gdb.orig/gdb/corelow.c
+++ gdb/gdb/corelow.c
@@ -547,6 +547,24 @@ get_core_register_section (struct regcac
bfd_section_vma (core_bfd, section)));
}
+/* Callback for get_core_registers that handles a single core file
+ register note section. */
+
+static int
+get_core_registers_cb (const char *sect_name, int size,
+ const char *human_name, void *cb_data)
+{
+ struct regcache *regcache = (struct regcache *) cb_data;
+
+ if (strcmp (sect_name, ".reg") == 0)
+ get_core_register_section (regcache, sect_name, 0, human_name, 1);
+ else if (strcmp (sect_name, ".reg2") == 0)
+ get_core_register_section (regcache, sect_name, 2, human_name, 0);
+ else
+ get_core_register_section (regcache, sect_name, 3, human_name, 0);
+
+ return 0;
+}
/* Get the registers out of a core file. This is the machine-
independent part. Fetch_core_registers is the machine-dependent
@@ -559,8 +577,8 @@ static void
get_core_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
{
- struct core_regset_section *sect_list;
int i;
+ struct gdbarch *gdbarch;
if (!(core_gdbarch && gdbarch_regset_from_core_section_p (core_gdbarch))
&& (core_vec == NULL || core_vec->core_read_registers == NULL))
@@ -570,23 +588,11 @@ get_core_registers (struct target_ops *o
return;
}
- sect_list = gdbarch_core_regset_sections (get_regcache_arch (regcache));
- if (sect_list)
- while (sect_list->sect_name != NULL)
- {
- if (strcmp (sect_list->sect_name, ".reg") == 0)
- get_core_register_section (regcache, sect_list->sect_name,
- 0, sect_list->human_name, 1);
- else if (strcmp (sect_list->sect_name, ".reg2") == 0)
- get_core_register_section (regcache, sect_list->sect_name,
- 2, sect_list->human_name, 0);
- else
- get_core_register_section (regcache, sect_list->sect_name,
- 3, sect_list->human_name, 0);
-
- sect_list++;
- }
-
+ gdbarch = get_regcache_arch (regcache);
+ if (gdbarch_iterate_over_regset_sections_p (gdbarch))
+ gdbarch_iterate_over_regset_sections (gdbarch,
+ get_core_registers_cb,
+ (void *) regcache, NULL);
else
{
get_core_register_section (regcache,
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v3 3/3] Dynamic core regset sections support
2013-06-12 15:23 ` [PATCH v3 3/3] Dynamic core regset sections support Andreas Arnez
@ 2013-06-12 16:06 ` Mark Kettenis
2013-06-13 9:32 ` Andreas Arnez
0 siblings, 1 reply; 10+ messages in thread
From: Mark Kettenis @ 2013-06-12 16:06 UTC (permalink / raw)
To: arnez; +Cc: gdb-patches, Ulrich.Weigand
> From: Andreas Arnez <arnez@linux.vnet.ibm.com>
> Date: Wed, 12 Jun 2013 17:13:33 +0200
>
> Rework the handling of core file register note sections. So far the
> target-dependent code provided a static list of supported register
> note sections via set_gdbarch_core_regset_sections. This patch
> replaces the static list by a target-dependent iterator function which
> can be set with set_gdbarch_iterate_over_regset_sections. Only those
> architectures that have been using set_gdbarch_core_regset_sections
> are affected by this change.
>
> The patch is needed on newer z/Architecture systems for correct gcore
> handling. With the static approach, gcore always writes the TDB
> regset into the core file, even if the TDB registers are currently
> invalid. The new iterator omits the TDB in this case.
Sorry, but I really don't like the obfuscation that this diff brings
to the amd64 & i186 Linux targets. Is there really no other way to
this? Is it really that bad to write out the invalid TDB registers?
If GDB recognizes them as invalid, this shouldn't be a big issue
should it?
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 3/3] Dynamic core regset sections support
2013-06-12 16:06 ` Mark Kettenis
@ 2013-06-13 9:32 ` Andreas Arnez
2013-06-13 11:02 ` Pedro Alves
0 siblings, 1 reply; 10+ messages in thread
From: Andreas Arnez @ 2013-06-13 9:32 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches, Ulrich.Weigand
Mark Kettenis <mark.kettenis@xs4all.nl> writes:
> Sorry, but I really don't like the obfuscation that this diff brings
> to the amd64 & i186 Linux targets.
If you can point me specifically to the spot where the obfuscation
occurs, I'll do my best to clean it up. A side-intention with the patch
actually was to *improve* readability, mainly by avoiding copy- & pasted
array initializers and distributed code logic. And indeed, while
offering improved flexibility, the patch overall saves 60 lines of code:
11 files changed, 266 insertions(+), 326 deletions(-)
amd64 is the only architecture that suffers from a slight code increase
(8 lines).
> Is there really no other way to this?
There are always other ways ;-) I already implemented some of them, and
the proposed patch seemed like the best approach to me.
> Is it really that bad to write out the invalid TDB registers? If GDB
> recognizes them as invalid, this shouldn't be a big issue should it?
Do you mean to always write the TDB regset into the core dump, like
without the patch? And then add some logic such that GDB recognizes
zero values in the register note section as invalid and clears the
regset? Or do I misinterpret your suggestion?
BTW, I wonder how transaction diagnostics works on x86. E.g., when an
illegal instruction occurs within a hardware transaction, will the core
dump contain the address of the violating instruction?
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 3/3] Dynamic core regset sections support
2013-06-13 9:32 ` Andreas Arnez
@ 2013-06-13 11:02 ` Pedro Alves
2013-06-13 12:23 ` Andreas Arnez
0 siblings, 1 reply; 10+ messages in thread
From: Pedro Alves @ 2013-06-13 11:02 UTC (permalink / raw)
To: Andreas Arnez; +Cc: Mark Kettenis, gdb-patches, Ulrich.Weigand
On 06/13/2013 10:16 AM, Andreas Arnez wrote:
> Mark Kettenis <mark.kettenis@xs4all.nl> writes:
>
>> Sorry, but I really don't like the obfuscation that this diff brings
>> to the amd64 & i186 Linux targets.
>
> If you can point me specifically to the spot where the obfuscation
> occurs, I'll do my best to clean it up. A side-intention with the patch
> actually was to *improve* readability, mainly by avoiding copy- & pasted
> array initializers and distributed code logic. And indeed, while
> offering improved flexibility, the patch overall saves 60 lines of code:
>
> 11 files changed, 266 insertions(+), 326 deletions(-)
>
> amd64 is the only architecture that suffers from a slight code increase
> (8 lines).
>
>> Is there really no other way to this?
>
> There are always other ways ;-) I already implemented some of them, and
> the proposed patch seemed like the best approach to me.
>
>> Is it really that bad to write out the invalid TDB registers? If GDB
>> recognizes them as invalid, this shouldn't be a big issue should it?
>
> Do you mean to always write the TDB regset into the core dump, like
> without the patch? And then add some logic such that GDB recognizes
> zero values in the register note section as invalid and clears the
> regset? Or do I misinterpret your suggestion?
Not zero, but present them as unavailable/invalid. I tend to agree with
Mark. Isn't there a control register GDB can read to check whether
a transaction is in progress (useful for both core and live debugging) ?
> BTW, I wonder how transaction diagnostics works on x86. E.g., when an
> illegal instruction occurs within a hardware transaction, will the core
> dump contain the address of the violating instruction?
I haven't personally tried debugging anything with transaction support yet.
--
Pedro Alves
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 3/3] Dynamic core regset sections support
2013-06-13 11:02 ` Pedro Alves
@ 2013-06-13 12:23 ` Andreas Arnez
2013-06-13 14:44 ` Pedro Alves
0 siblings, 1 reply; 10+ messages in thread
From: Andreas Arnez @ 2013-06-13 12:23 UTC (permalink / raw)
To: Pedro Alves; +Cc: Mark Kettenis, gdb-patches, Ulrich.Weigand
Pedro Alves <palves@redhat.com> writes:
>> Do you mean to always write the TDB regset into the core dump, like
>> without the patch? And then add some logic such that GDB recognizes
>> zero values in the register note section as invalid and clears the
>> regset? Or do I misinterpret your suggestion?
>
> Not zero, but present them as unavailable/invalid.
Not sure I understand your point here. *Presenting them* as unavailable
is exactly what the patch does.
> Isn't there a control register GDB can read to check whether a
> transaction is in progress (useful for both core and live debugging) ?
No, the kernel indicates an interrupted transaction with the presence of
the TDB regset. This applies to ptrace as well as to a core dump. My
goal for gcore was to behave the same.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 3/3] Dynamic core regset sections support
2013-06-13 12:23 ` Andreas Arnez
@ 2013-06-13 14:44 ` Pedro Alves
2013-06-13 17:36 ` Andreas Arnez
0 siblings, 1 reply; 10+ messages in thread
From: Pedro Alves @ 2013-06-13 14:44 UTC (permalink / raw)
To: Andreas Arnez; +Cc: Mark Kettenis, gdb-patches, Ulrich.Weigand
On 06/13/2013 12:02 PM, Andreas Arnez wrote:
> Pedro Alves <palves@redhat.com> writes:
>
>>> Do you mean to always write the TDB regset into the core dump, like
>>> without the patch? And then add some logic such that GDB recognizes
>>> zero values in the register note section as invalid and clears the
>>> regset? Or do I misinterpret your suggestion?
>>
>> Not zero, but present them as unavailable/invalid.
>
> Not sure I understand your point here. *Presenting them* as unavailable
> is exactly what the patch does.
Well, you were the one who brought zeros up. ;-)
Mark didn't seem to imply any connection between zeros and the registers'
validity, and I was reinforcing the idea. I'm not sure what you meant
by clearing, but that seemed to imply zeroing too. If you had a control
register to check, there would be no need to zero out registers.
>> Isn't there a control register GDB can read to check whether a
>> transaction is in progress (useful for both core and live debugging) ?
>
> No, the kernel indicates an interrupted transaction with the presence of
> the TDB regset. This applies to ptrace as well as to a core dump. My
> goal for gcore was to behave the same.
I see...
I tried to do a little investigation on s390 transactions. It's now my
understanding that these "registers" are really a memory block whose
address passed in by the user to the hardware when a transaction is
started with TBEGIN. There's a tbegin variant ("simple tbegin" ?) that
doesn't take such a tcb address, and I guess there's some way the kernel
coordinates with the hardware to know/specify where the tcb is written to.
I couldn't find the definite manual/document that explains what exactly
the TDB contains though (tdb0, atia, etc?), only references like
"If the transaction fails, the TDB is populated with lots of information.".
Cool, what is lots, though? :-) Do you have a pointer, for my own
education, and for the archives?
I was mildly wondering whether it wouldn't be a little better to expose
this through a new target object (and target_read/qXfer:read) instead,
and add a $_tdb convenience variable (similar to $_siginfo --
p $_tdb; p $_tdb.atia, etc.). That'd mean no read of the TDB block unless
the user requested it, possibility to error out when outside a transaction,
and a way for the user to put the whole TDB in GDB's value
history.
--
Pedro Alves
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v3 3/3] Dynamic core regset sections support
2013-06-13 14:44 ` Pedro Alves
@ 2013-06-13 17:36 ` Andreas Arnez
0 siblings, 0 replies; 10+ messages in thread
From: Andreas Arnez @ 2013-06-13 17:36 UTC (permalink / raw)
To: Pedro Alves; +Cc: Mark Kettenis, gdb-patches, Ulrich.Weigand
Pedro Alves <palves@redhat.com> writes:
> On 06/13/2013 12:02 PM, Andreas Arnez wrote:
>> Pedro Alves <palves@redhat.com> writes:
>>
>>>> Do you mean to always write the TDB regset into the core dump, like
>>>> without the patch? And then add some logic such that GDB recognizes
>>>> zero values in the register note section as invalid and clears the
>>>> regset? Or do I misinterpret your suggestion?
>>>
>>> Not zero, but present them as unavailable/invalid.
>>
>> Not sure I understand your point here. *Presenting them* as unavailable
>> is exactly what the patch does.
>
> Well, you were the one who brought zeros up. ;-)
Zeros are written by gcore without the patch, because this is what a
register note section happens to be filled with when the registers are
actually unavailable. The patch avoids that and doesn't write the
section at all.
> Mark didn't seem to imply any connection between zeros and the
> registers' validity, and I was reinforcing the idea. I'm not sure
> what you meant by clearing, but that seemed to imply zeroing too.
No, I meant marking unavailable.
>>> Isn't there a control register GDB can read to check whether a
>>> transaction is in progress (useful for both core and live debugging) ?
>>
>> No, the kernel indicates an interrupted transaction with the presence of
>> the TDB regset. This applies to ptrace as well as to a core dump. My
>> goal for gcore was to behave the same.
>
> I see...
>
> I tried to do a little investigation on s390 transactions. It's now
> my understanding that these "registers" are really a memory block
> whose address passed in by the user to the hardware when a transaction
> is started with TBEGIN. There's a tbegin variant ("simple tbegin" ?)
> that doesn't take such a tcb address, and I guess there's some way the
> kernel coordinates with the hardware to know/specify where the tcb is
> written to.
Almost. There are two ways the TDB can get written. The way you
describe is for a "normal" transaction abort. The other way is for an
abort due to a program interruption, like an illegal instruction, or a
breakpoint or watchpoint hit. In that case the hardware writes the
"program-interruption TDB" to a fixed address, independently from any
user-specified address.
> I couldn't find the definite manual/document that explains what
> exactly the TDB contains though (tdb0, atia, etc?), only references
> like "If the transaction fails, the TDB is populated with lots of
> information.". Cool, what is lots, though? :-) Do you have a pointer,
> for my own education, and for the archives?
See the z/Architecture Principles of Operation:
http://publibfp.boulder.ibm.com/epubs/pdf/dz9zr009.pdf
Specifically, refer to the section "Transactional-Execution Facility" in
chapter 5, "Program Execution".
> I was mildly wondering whether it wouldn't be a little better to
> expose this through a new target object (and target_read/qXfer:read)
> instead, and add a $_tdb convenience variable (similar to $_siginfo --
> p $_tdb; p $_tdb.atia, etc.). That'd mean no read of the TDB block
> unless the user requested it, possibility to error out when outside a
> transaction, and a way for the user to put the whole TDB in GDB's
> value history.
Interesting thought. There are probably pros and cons either way. The
regset approach seemed most straightforward, because the kernel presents
the program interruption TDB as a regset. Retrieving the TDB only on
user request won't work in the long run, because it contains vital
information for transaction debugging. I'm currently working on a GDB
patch to exploit that.
^ permalink raw reply [flat|nested] 10+ messages in thread