summaryrefslogtreecommitdiff
path: root/gdb/gdbserver/linux-s390-low.c
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2010-01-04 15:02:55 +0000
committerUlrich Weigand <uweigand@de.ibm.com>2010-01-04 15:02:55 +0000
commit458c3aedcb159b3389fb171221719c8b05e9ef43 (patch)
tree7501cb8581652d5a5b0ef51ca4fcf3e918f04f84 /gdb/gdbserver/linux-s390-low.c
parente3677eede2324b389b8a94b298a7e69ac737b731 (diff)
downloadgdb-458c3aedcb159b3389fb171221719c8b05e9ef43.tar.gz
* features/Makefile (WHICH): Add s390-linux32, s390-linux64,
and s390x-linux64. (s390-linux32-expedite): Define. (s390-linux64-expedite): Define. (s390x-linux64-expedite): Define. * features/s390-acr.xml: New file. * features/s390-fpr.xml: New file. * features/s390-core32.xml: New file. * features/s390-core64.xml: New file. * features/s390x-core64.xml: New file. * features/s390-linux32.xml: New file. * features/s390-linux64.xml: New file. * features/s390x-linux64.xml: New file. * features/s390-linux32.c: New generated file. * features/s390-linux64.c: New generated file. * features/s390x-linux64.c: New generated file. * regformats/s390-linux32.dat: New generated file. * regformats/s390-linux64.dat: New generated file. * regformats/s390x-linux64.dat: New generated file. * regformats/reg-s390.dat: Remove. * regformats/reg-s390x.dat: Remove. * s390-nat.c: Include "auxv.h" and <elf.h>. (HWCAP_S390_HIGH_GPRS): Define if undefined. (s390_target_wordsize): New function. (s390_auxv_parse): Likewise. (s390_get_hwcap): Likewise. (s390_read_description): Likewise. (_initialize_s390_nat): Install s390_auxv_parse and s390_read_description. * s390-tdep.c: Include "features/s390-linux32.c", "features/s390-linux64.c", and "features/s390x-linux64.c". (struct gdbarch_tdep): Add gpr_full_regnum, pc_regnum, and cc_regnum. (s390_register_call_saved): New function. (s390_register_name): Remove. (s390_register_type): Remove. (s390_dwarf_regmap): Add lower half GPR pseudo DWARF CFI regnums. (s390_dwarf_reg_to_regnum): Remap GPR regnums to full GPRs. (s390_adjust_frame_regnum): Remap GPR regnums to lower halves for CFI. (s390_pseudo_register_name): New function. (s390_pseudo_register_type): New function. (s390_pseudo_register_read): Handle both 32-bit and 64-bit cases. Handle full GPR pesudos and varying pseudo register numbers. (s390_pseudo_register_write): Likewise (s390x_pseudo_register_read): Remove. (s390x_pseudo_register_write): Likewise. (s390_register_group): Remove. (s390_pseudo_register_group): New function. (s390_regmap_gregset): Add GPR upper halves. (s390x_regmap_gregset): Likewise. (s390_regmap_fpregset): Likewise. (s390_regmap_upper): New global variable. (s390_upper_regset): New global variable. (s390_upper_regset_sections): New global variable. (s390_regset_from_core_section): Handle GPR upper halves. (s390_core_read_description): New function. (s390_prologue_frame_unwind_cache): Set up ABI call-saved/clobbered register information. Handle varying pseudo register numbers. (s390_backchain_frame_unwind_cache): Likewise. (s390_frame_prev_register): Unwind full GPRs to show lower halves. (s390_stub_frame_unwind_cache): Handle varying pseudo register numbers. (s390_sigtramp_frame_unwind_cache): Unwind PSWM and PSWA as well as PC and CC pseudos. Unwind upper halves and full GPRs as appropriate. Handle varying pseudo register numbers. (s390_unwind_pc): Handle varying pseudo register numbers. (s390_dwarf2_prev_register): New function. (s390_dwarf2_frame_init_reg): Set up ABI call-saved/clobbered register information. Handle varying pseudo register numbers. Install s390_dwarf2_prev_register to unwind full GPRs. (s390_gdbarch_init): Handle target descriptions. Assign varying pseudo register numbers. Install s390_adjust_frame_regnum. (_initialize_s390_tdep): Initialize target descriptions. * s390-tdep.h (S390_R0_UPPER_REGNUM .. S390_R15_UPPER_REGNUM): Define. (S390_NUM_REGS): Redefine to include upper half registers. (S390_PC_REGNUM, S390_CC_REGNUM): Remove. (S390_NUM_PSEUDO_REGS, S390_NUM_TOTAL_REGS): Likewise. (tdesc_s390_linux32): Add declaration. (tdesc_s390_linux64): Likewise. (tdesc_s390x_linux64): Likewise. gdb/testsuite/ * gdb.xml/tdesc-regs.exp: Support s390*-*-* targets. gdbserver/ * Makefile.in (clean): Remove new generated files. (reg-s390.o, reg-s390.c): Remove rules. (reg-s390x.o, reg-s390x.c): Likewise. (s390-linux32.o, s390-linux32.c): Add rules. (s390-linux64.o, s390-linux64.c): Likewise. (s390x-linux64.o, s390x-linux64.c): Likewise. * configure.srv (s390*-*-linux*): Update srv_regobj and srv_xmlfiles. * linux-s390-low.c: Include <elf.h>. (HWCAP_S390_HIGH_GPRS): Define if undefined. (init_registers_s390): Remove prototype. (init_registers_s390x): Likewise. (init_registers_s390_linux32): Add prototype. (init_registers_s390_linux64): Likewise. (init_registers_s390x_linux64): Likewise. (s390_num_regs_3264): New define. (s390_regmap_3264): New global variable. (s390_cannot_fetch_register): Remove obsolete check. (s390_cannot_store_register): Likewise. (s390_collect_ptrace_register): Handle upper/lower register halves. (s390_supply_ptrace_register): Likewise. (s390_fill_gregset): Update to register number changes. (s390_get_hwcap): New routine. (s390_arch_setup): Detect 32-bit process running on 64-bit system. Install appropriate regmap and register set.
Diffstat (limited to 'gdb/gdbserver/linux-s390-low.c')
-rw-r--r--gdb/gdbserver/linux-s390-low.c127
1 files changed, 108 insertions, 19 deletions
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index 0407cadb933..64b1065dc01 100644
--- a/gdb/gdbserver/linux-s390-low.c
+++ b/gdb/gdbserver/linux-s390-low.c
@@ -24,12 +24,18 @@
#include "linux-low.h"
#include <asm/ptrace.h>
+#include <elf.h>
-/* Defined in auto-generated file reg-s390.c. */
-void init_registers_s390 (void);
-/* Defined in auto-generated file reg-s390x.c. */
-void init_registers_s390x (void);
+#ifndef HWCAP_S390_HIGH_GPRS
+#define HWCAP_S390_HIGH_GPRS 512
+#endif
+/* Defined in auto-generated file s390-linux32.c. */
+void init_registers_s390_linux32 (void);
+/* Defined in auto-generated file s390-linux64.c. */
+void init_registers_s390_linux64 (void);
+/* Defined in auto-generated file s390x-linux64.c. */
+void init_registers_s390x_linux64 (void);
#define s390_num_regs 51
@@ -61,21 +67,41 @@ static int s390_regmap[] = {
#endif
};
+#ifdef __s390x__
+#define s390_num_regs_3264 67
+
+static int s390_regmap_3264[] = {
+ PT_PSWMASK, PT_PSWADDR,
+
+ PT_GPR0, PT_GPR0, PT_GPR1, PT_GPR1, PT_GPR2, PT_GPR2, PT_GPR3, PT_GPR3,
+ PT_GPR4, PT_GPR4, PT_GPR5, PT_GPR5, PT_GPR6, PT_GPR6, PT_GPR7, PT_GPR7,
+ PT_GPR8, PT_GPR8, PT_GPR9, PT_GPR9, PT_GPR10, PT_GPR10, PT_GPR11, PT_GPR11,
+ PT_GPR12, PT_GPR12, PT_GPR13, PT_GPR13, PT_GPR14, PT_GPR14, PT_GPR15, PT_GPR15,
+
+ PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
+ PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
+ PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
+ PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
+
+ PT_FPC,
+
+ PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
+ PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
+ PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
+ PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
+};
+#endif
+
+
static int
s390_cannot_fetch_register (int regno)
{
- if (s390_regmap[regno] == -1)
- return 1;
-
return 0;
}
static int
s390_cannot_store_register (int regno)
{
- if (s390_regmap[regno] == -1)
- return 1;
-
return 0;
}
@@ -85,17 +111,25 @@ s390_collect_ptrace_register (int regno, char *buf)
int size = register_size (regno);
if (size < sizeof (long))
{
+ int regaddr = the_low_target.regmap[regno];
+
memset (buf, 0, sizeof (long));
- if (regno == find_regno ("pswa")
- || (regno >= find_regno ("r0") && regno <= find_regno ("r15")))
+ if ((regno ^ 1) < the_low_target.num_regs
+ && the_low_target.regmap[regno ^ 1] == regaddr)
+ {
+ collect_register (regno & ~1, buf);
+ collect_register ((regno & ~1) + 1, buf + sizeof (long) - size);
+ }
+ else if (regaddr == PT_PSWADDR
+ || (regaddr >= PT_GPR0 && regaddr <= PT_GPR15))
collect_register (regno, buf + sizeof (long) - size);
else
collect_register (regno, buf);
/* When debugging a 32-bit inferior on a 64-bit host, make sure
the 31-bit addressing mode bit is set in the PSW mask. */
- if (regno == find_regno ("pswm"))
+ if (regaddr == PT_PSWMASK)
buf[size] |= 0x80;
}
else
@@ -108,8 +142,16 @@ s390_supply_ptrace_register (int regno, const char *buf)
int size = register_size (regno);
if (size < sizeof (long))
{
- if (regno == find_regno ("pswa")
- || (regno >= find_regno ("r0") && regno <= find_regno ("r15")))
+ int regaddr = the_low_target.regmap[regno];
+
+ if ((regno ^ 1) < the_low_target.num_regs
+ && the_low_target.regmap[regno ^ 1] == regaddr)
+ {
+ supply_register (regno & ~1, buf);
+ supply_register ((regno & ~1) + 1, buf + sizeof (long) - size);
+ }
+ else if (regaddr == PT_PSWADDR
+ || (regaddr >= PT_GPR0 && regaddr <= PT_GPR15))
supply_register (regno, buf + sizeof (long) - size);
else
supply_register (regno, buf);
@@ -125,8 +167,15 @@ static void s390_fill_gregset (void *buf)
{
int i;
- for (i = 0; i < 34; i++)
- s390_collect_ptrace_register (i, (char *) buf + s390_regmap[i]);
+ for (i = 0; i < the_low_target.num_regs; i++)
+ {
+ if (the_low_target.regmap[i] < PT_PSWMASK
+ || the_low_target.regmap[i] > PT_ACR15)
+ continue;
+
+ s390_collect_ptrace_register (i, (char *) buf
+ + the_low_target.regmap[i]);
+ }
}
struct regset_info target_regsets[] = {
@@ -176,12 +225,43 @@ s390_set_pc (CORE_ADDR newpc)
}
}
+#ifdef __s390x__
+static unsigned long
+s390_get_hwcap (void)
+{
+ int wordsize = register_size (0);
+ unsigned char *data = alloca (2 * wordsize);
+ int offset = 0;
+
+ while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize)
+ {
+ if (wordsize == 4)
+ {
+ unsigned int *data_p = (unsigned int *)data;
+ if (data_p[0] == AT_HWCAP)
+ return data_p[1];
+ }
+ else
+ {
+ unsigned long *data_p = (unsigned long *)data;
+ if (data_p[0] == AT_HWCAP)
+ return data_p[1];
+ }
+
+ offset += 2 * wordsize;
+ }
+
+ return 0;
+}
+#endif
static void
s390_arch_setup (void)
{
/* Assume 31-bit inferior process. */
- init_registers_s390 ();
+ init_registers_s390_linux32 ();
+ the_low_target.num_regs = s390_num_regs;
+ the_low_target.regmap = s390_regmap;
/* On a 64-bit host, check the low bit of the (31-bit) PSWM
-- if this is one, we actually have a 64-bit inferior. */
@@ -190,7 +270,16 @@ s390_arch_setup (void)
unsigned int pswm;
collect_register_by_name ("pswm", &pswm);
if (pswm & 1)
- init_registers_s390x ();
+ init_registers_s390x_linux64 ();
+
+ /* For a 31-bit inferior, check whether the kernel supports
+ using the full 64-bit GPRs. */
+ else if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS)
+ {
+ init_registers_s390_linux64 ();
+ the_low_target.num_regs = s390_num_regs_3264;
+ the_low_target.regmap = s390_regmap_3264;
+ }
}
#endif
}