diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2011-12-06 14:14:50 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@de.ibm.com> | 2011-12-06 14:14:50 +0000 |
commit | c642a4345689554fbb6308c27ce59c1e86d87a7c (patch) | |
tree | 3dc2e596ea83f78b02ca132e94e24a2d3da4cace /gdb/s390-nat.c | |
parent | 355b81d94960ef44b9773b9fe2b6646af2ddd5a2 (diff) | |
download | gdb-c642a4345689554fbb6308c27ce59c1e86d87a7c.zip gdb-c642a4345689554fbb6308c27ce59c1e86d87a7c.tar.gz gdb-c642a4345689554fbb6308c27ce59c1e86d87a7c.tar.bz2 |
ChangeLog:
* s390-tdep.h (S390_ORIG_R2_REGNUM): Define.
(S390_LAST_BREAK_REGNUM): Likewise.
(S390_SYSTEM_CALL_REGNUM): Likewise.
(S390_NUM_REGS): Update.
(s390_regmap_last_break): Add declaration.
(s390x_regmap_last_break): Likewise.
(s390_regmap_system_call): Likewise.
(tdesc_s390_linux32v1): Add declaration.
(tdesc_s390_linux32v2): Likewise.
(tdesc_s390_linux64v1): Likewise.
(tdesc_s390_linux64v2): Likewise.
(tdesc_s390x_linux64v1): Likewise.
(tdesc_s390x_linux64v2): Likewise.
* s390-tdep.c: Include new target description files
"features/s390-linux32v1.c", "features/s390-linux32v2.c",
"features/s390-linux64v1.c", "features/s390-linux64v2.c",
"features/s390x-linux64v1.c", and "features/s390x-linux64v2.c".
(s390_cannot_store_register): New function.
(s390_write_pc): Likewise.
(s390_dwarf_regmap): Add fields for new registers.
(s390_regmap_gregset): Likewise.
(s390x_regmap_gregset): Likewise.
(s390_regmap_fpregset): Likewise.
(s390_regmap_upper): Likewise.
(s390_regmap_last_break): New variable.
(s390x_regmap_last_break): Likewise.
(s390_regmap_system_call): Likewise.
(s390_last_break_regset): Likewise.
(s390x_last_break_regset): Likewise.
(s390_system_call_regset): Likewise.
(s390_upper_regset_sections): Rename to ...
(s390_linux64_regset_sections): ... this.
(s390_linux32_regset_sections): New variable.
(s390x_linux64_regset_sections): Likewise.
(s390_linux32v1_regset_sections): Likewise.
(s390_linux32v2_regset_sections): Likewise.
(s390_linux64v1_regset_sections): Likewise.
(s390_linux64v2_regset_sections): Likewise.
(s390x_linux64v1_regset_sections): Likewise.
(s390x_linux64v2_regset_sections): Likewise.
(s390_regset_from_core_section): Handle .reg-s390-last-break and
.reg-s390-system-call core file sections.
(s390_core_read_description): Check for presence of
.reg-s390-last-break and .reg-s390-system-call core file
sections and return appropriate target description.
(s390_gdbarch_init): Detect Linux-specific registers "orig_r2",
"last_break" and "system_call" in target description. Install
appropriate gdbarch_core_regset_sections array.
Call set_gdbarch_cannot_store_register and set_gdbarch_write_pc.
(_initialize_s390_tdep): Initialize additional target descriptions.
* s390-nat.c: Include "elf/common.h".
(PTRACE_GETREGSET, PTRACE_SETREGSET): Define if undefined.
(have_regset_last_break): New static variable.
(have_regset_system_call): Likewise.
(s390_native_supply): Handle S390_ORIG_R2_REGNUM.
(s390_native_collect): Likewise.
(fetch_regset, store_regset, check_regset): New functions.
(s390_linux_fetch_inferior_registers): Handle S390_LAST_BREAK_REGNUM
and S390_SYSTEM_CALL_REGNUM.
(s390_linux_store_inferior_registers): Likewise.
(s390_read_description): Check for presence of NT_S390_LAST_BREAK
and NT_S390_SYSTEM_CALL regsets and use appropriate description.
* features/Makefile (WHICH): Add s390-linux32v1, s390-linux64v1,
s390x-linux64v1, s390-linux32v2, s390-linux64v2, and s390x-linux64v2.
(s390-linux32v1-expedite): Define.
(s390-linux32v2-expedite): Likewise.
(s390-linux64v1-expedite): Likewise.
(s390-linux64v2-expedite): Likewise.
(s390x-linux64v1-expedite): Likewise.
(s390x-linux64v2-expedite): Likewise.
* features/s390-linux32.xml: Add orig_r2 register.
* features/s390-linux64.xml: Likewise.
* features/s390x-linux64.xml: Likewise.
* features/s390-linux32v1.xml: New file.
* features/s390-linux32v2.xml: Likewise.
* features/s390-linux64v1.xml: Likewise.
* features/s390-linux64v2.xml: Likewise.
* features/s390x-linux64v1.xml: Likewise.
* features/s390x-linux64v2.xml: Likewise.
* features/s390-linux32.c: Regenerate.
* features/s390-linux64.c: Likewise.
* features/s390x-linux64.c: Likewise.
* features/s390-linux32v1.c: New generated file.
* features/s390-linux32v2.c: Likewise.
* features/s390-linux64v1.c: Likewise.
* features/s390-linux64v2.c: Likewise.
* features/s390x-linux64v1.c: Likewise.
* features/s390x-linux64v2.c: Likewise.
* regformats/s390-linux32.dat: Regenerate.
* regformats/s390-linux64.dat: Regenerate.
* regformats/s390x-linux64.dat: Regenerate.
* regformats/s390-linux32v1.dat: New generated file.
* regformats/s390-linux32v2.dat: Likewise.
* regformats/s390-linux64v1.dat: Likewise.
* regformats/s390-linux64v2.dat: Likewise.
* regformats/s390x-linux64v1.dat: Likewise.
* regformats/s390x-linux64v2.dat: Likewise.
gdbserver/ChangeLog:
* Makefile.in (s390-linux32v1.o, s390-linux32v1.c): New rules.
(s390-linux32v2.o, s390-linux32v2.c): Likewise.
(s390-linux64v1.o, s390-linux64v1.c): Likewise.
(s390-linux64v2.o, s390-linux64v2.c): Likewise.
(s390x-linux64v1.o, s390x-linux64v1.c): Likewise.
(s390x-linux64v2.o, s390x-linux64v2.c): Likewise.
* configure.srv [s390*-*-linux*] (srv_regobj): Add new objects.
(srv_xmlfiles): Add new XML files.
* linux-s390-low.c: Include "elf/common.h", <sys/ptrace.h>,
and <sys/uio.h>.
(PTRACE_GETREGSET, PTRACE_SETREGSET): Define if undefined.
(init_registers_s390_linux32v1): Add prototype.
(init_registers_s390_linux32v2): Likewise.
(init_registers_s390_linux64v1): Likewise.
(init_registers_s390_linux64v2): Likewise.
(init_registers_s390x_linux64v1): Likewise.
(init_registers_s390x_linux64v2): Likewise.
(s390_num_regs): Increment to 52.
(s390_regmap): Add orig_r2 register.
(s390_num_regs_3264): Increment to 68.
(s390_regmap_3264): Add orig_r2 register.
(s390_collect_ptrace_register): Handle orig_r2 register.
(s390_supply_ptrace_register): Likewise.
(s390_fill_last_break): New function.
(s390_store_last_break): Likewise.
(s390_fill_system_call): New function.
(s390_store_system_call): Likewise.
(target_regsets): Handle NT_S390_LAST_BREAK and NT_S390_SYSTEM_CALL
register sets.
(s390_check_regset): New function.
(s390_arch_setup): Check for presence of NT_S390_LAST_BREAK and
NT_S390_SYSTEM_CALL regsets and use appropriate description.
Update target_regsets for available register sets.
testsuite/ChangeLog:
* gdb.base/callfuncs.exp (fetch_all_registers): Filter out read-only
last_break register on s390*-*-* targets.
Diffstat (limited to 'gdb/s390-nat.c')
-rw-r--r-- | gdb/s390-nat.c | 118 |
1 files changed, 113 insertions, 5 deletions
diff --git a/gdb/s390-nat.c b/gdb/s390-nat.c index c1eec1c..ae3c868 100644 --- a/gdb/s390-nat.c +++ b/gdb/s390-nat.c @@ -28,6 +28,7 @@ #include "auxv.h" #include "s390-tdep.h" +#include "elf/common.h" #include <asm/ptrace.h> #include <sys/ptrace.h> @@ -40,6 +41,16 @@ #define HWCAP_S390_HIGH_GPRS 512 #endif +#ifndef PTRACE_GETREGSET +#define PTRACE_GETREGSET 0x4204 +#endif + +#ifndef PTRACE_SETREGSET +#define PTRACE_SETREGSET 0x4205 +#endif + +static int have_regset_last_break = 0; +static int have_regset_system_call = 0; /* Map registers to gregset/ptrace offsets. These arrays are defined in s390-tdep.c. */ @@ -97,7 +108,8 @@ s390_native_supply (struct regcache *regcache, int regno, return; } - if (regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM) + if ((regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM) + || regno == S390_ORIG_R2_REGNUM) offset += 4; } #endif @@ -151,7 +163,8 @@ s390_native_collect (const struct regcache *regcache, int regno, return; } - if (regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM) + if ((regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM) + || regno == S390_ORIG_R2_REGNUM) { memset (regp + offset, 0, 4); offset += 4; @@ -293,6 +306,70 @@ store_fpregs (const struct regcache *regcache, int tid, int regnum) perror_with_name (_("Couldn't write floating point status")); } +/* Fetch all registers in the kernel's register set whose number is REGSET, + whose size is REGSIZE, and whose layout is described by REGMAP, from + 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) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + gdb_byte *buf = alloca (regsize); + struct iovec iov; + int i; + + iov.iov_base = buf; + iov.iov_len = regsize; + + if (ptrace (PTRACE_GETREGSET, tid, (long) regset, (long) &iov) < 0) + perror_with_name (_("Couldn't get register set")); + + for (i = 0; i < S390_NUM_REGS; i++) + s390_native_supply (regcache, i, buf, regmap); +} + +/* Store all registers in the kernel's register set whose number is REGSET, + whose size is REGSIZE, and whose layout is described by REGMAP, from + GDB's register cache back to process/thread TID. */ +static void +store_regset (struct regcache *regcache, int tid, + int regset, int regsize, int *regmap) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + gdb_byte *buf = alloca (regsize); + struct iovec iov; + int i; + + iov.iov_base = buf; + iov.iov_len = regsize; + + if (ptrace (PTRACE_GETREGSET, tid, (long) regset, (long) &iov) < 0) + perror_with_name (_("Couldn't get register set")); + + for (i = 0; i < S390_NUM_REGS; i++) + s390_native_collect (regcache, i, buf, regmap); + + if (ptrace (PTRACE_SETREGSET, tid, (long) regset, (long) &iov) < 0) + perror_with_name (_("Couldn't set register set")); +} + +/* Check whether the kernel provides a register set with number REGSET + of size REGSIZE for process/thread TID. */ +static int +check_regset (int tid, int regset, int regsize) +{ + gdb_byte *buf = alloca (regsize); + struct iovec iov; + + iov.iov_base = buf; + iov.iov_len = regsize; + + if (ptrace (PTRACE_GETREGSET, tid, (long) regset, (long) &iov) < 0) + return 0; + else + return 1; +} + /* Fetch register REGNUM from the child process. If REGNUM is -1, do this for all registers. */ static void @@ -308,6 +385,17 @@ s390_linux_fetch_inferior_registers (struct target_ops *ops, if (regnum == -1 || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1)) fetch_fpregs (regcache, tid); + + if (have_regset_last_break) + if (regnum == -1 || regnum == S390_LAST_BREAK_REGNUM) + fetch_regset (regcache, tid, NT_S390_LAST_BREAK, 8, + (gdbarch_ptr_bit (get_regcache_arch (regcache)) == 32 + ? s390_regmap_last_break : s390x_regmap_last_break)); + + if (have_regset_system_call) + if (regnum == -1 || regnum == S390_SYSTEM_CALL_REGNUM) + fetch_regset (regcache, tid, NT_S390_SYSTEM_CALL, 4, + s390_regmap_system_call); } /* Store register REGNUM back into the child process. If REGNUM is @@ -325,6 +413,13 @@ s390_linux_store_inferior_registers (struct target_ops *ops, if (regnum == -1 || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1)) store_fpregs (regcache, tid, regnum); + + /* S390_LAST_BREAK_REGNUM is read-only. */ + + if (have_regset_system_call) + if (regnum == -1 || regnum == S390_SYSTEM_CALL_REGNUM) + store_regset (regcache, tid, NT_S390_SYSTEM_CALL, 4, + s390_regmap_system_call); } @@ -539,6 +634,13 @@ s390_get_hwcap (void) static const struct target_desc * s390_read_description (struct target_ops *ops) { + int tid = s390_inferior_tid (); + + have_regset_last_break + = check_regset (tid, NT_S390_LAST_BREAK, 8); + have_regset_system_call + = check_regset (tid, NT_S390_SYSTEM_CALL, 4); + #ifdef __s390x__ /* If GDB itself is compiled as 64-bit, we are running on a machine in z/Architecture mode. If the target is running in 64-bit addressing @@ -547,16 +649,22 @@ s390_read_description (struct target_ops *ops) that mode, report s390 architecture with 64-bit GPRs. */ if (s390_target_wordsize () == 8) - return tdesc_s390x_linux64; + return (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 tdesc_s390_linux64; + return (have_regset_system_call? tdesc_s390_linux64v2 : + have_regset_last_break? tdesc_s390_linux64v1 : + tdesc_s390_linux64); #endif /* If GDB itself is compiled as 31-bit, or if we're running a 31-bit inferior on a 64-bit kernel that does not support using 64-bit registers in 31-bit mode, report s390 architecture with 32-bit GPRs. */ - return tdesc_s390_linux32; + return (have_regset_system_call? tdesc_s390_linux32v2 : + have_regset_last_break? tdesc_s390_linux32v1 : + tdesc_s390_linux32); } void _initialize_s390_nat (void); |