diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2010-01-04 15:03:01 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@de.ibm.com> | 2010-01-04 15:03:01 +0000 |
commit | 7803799a0fb31a9d332cd3bf3547309debea010b (patch) | |
tree | 25069dfa82ff65c3340e823fc26a45de7ab2dd2a /gdb/gdbserver/linux-s390-low.c | |
parent | 1b1818e443eb8f134e0bc2f5ec950c8a16df6883 (diff) | |
download | gdb-7803799a0fb31a9d332cd3bf3547309debea010b.zip gdb-7803799a0fb31a9d332cd3bf3547309debea010b.tar.gz gdb-7803799a0fb31a9d332cd3bf3547309debea010b.tar.bz2 |
* 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.c | 127 |
1 files changed, 108 insertions, 19 deletions
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c index 0407cad..64b1065 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 } |