mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-12-15 00:00:20 +00:00
ChangeLog:
* s390-nat.c (SUBOFF): Remove. (s390_native_supply, s390_native_collect): New functions. (supply_gregset, supply_fpregset): Use s390_native_supply. (fill_gregset, fill_fpregset): Use s390_native_collect. * s390-tdep.c (s390_pseudo_register_reggroup_p): Update comment. (s390_unwind_pseudo_register): New function. (s390_prologue_frame_unwind_cache): Unwind PSW address and mask registers instead of PC and CC. (s390_backchain_frame_unwind_cache): Likewise. (s390_sigtramp_frame_unwind_cache): Do not unwind PC, CC, or full GPR pseudos. (s390_trad_frame_prev_register): New function. (s390_frame_prev_register): Use it. (s390_sigtramp_frame_prev_register): Likewise. (s390_dwarf2_prev_register): Use s390_unwind_pseudo_register. (s390_dwarf2_frame_init_reg): Unwind PSW address and mask. Use special callback to unwind any pseudo. * features/s390-core32.xml: Add pswm/pswa to save/restore group. * features/s390-core64.xml: Likewise. * features/s390x-core64.xml: Likewise. * features/s390-linux32.c: Regenerate. * features/s390-linux64.c: Likewise. * features/s390x-linux64.c: Likewise. gdbserver/ChangeLog: * linux-s390-low.c (s390_collect_ptrace_register): Fully convert PSW address/mask between 8-byte and 16-byte formats. (s390_supply_ptrace_register): Likewise. (s390_get_pc, s390_set_pc): 4-byte PSW address always includes basic addressing mode bit.
This commit is contained in:
parent
1dd635acb8
commit
d6db1fabcc
@ -1,3 +1,31 @@
|
||||
2011-11-30 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* s390-nat.c (SUBOFF): Remove.
|
||||
(s390_native_supply, s390_native_collect): New functions.
|
||||
(supply_gregset, supply_fpregset): Use s390_native_supply.
|
||||
(fill_gregset, fill_fpregset): Use s390_native_collect.
|
||||
|
||||
* s390-tdep.c (s390_pseudo_register_reggroup_p): Update comment.
|
||||
(s390_unwind_pseudo_register): New function.
|
||||
(s390_prologue_frame_unwind_cache): Unwind PSW address and mask
|
||||
registers instead of PC and CC.
|
||||
(s390_backchain_frame_unwind_cache): Likewise.
|
||||
(s390_sigtramp_frame_unwind_cache): Do not unwind PC, CC, or
|
||||
full GPR pseudos.
|
||||
(s390_trad_frame_prev_register): New function.
|
||||
(s390_frame_prev_register): Use it.
|
||||
(s390_sigtramp_frame_prev_register): Likewise.
|
||||
(s390_dwarf2_prev_register): Use s390_unwind_pseudo_register.
|
||||
(s390_dwarf2_frame_init_reg): Unwind PSW address and mask. Use
|
||||
special callback to unwind any pseudo.
|
||||
|
||||
* features/s390-core32.xml: Add pswm/pswa to save/restore group.
|
||||
* features/s390-core64.xml: Likewise.
|
||||
* features/s390x-core64.xml: Likewise.
|
||||
* features/s390-linux32.c: Regenerate.
|
||||
* features/s390-linux64.c: Likewise.
|
||||
* features/s390x-linux64.c: Likewise.
|
||||
|
||||
2011-11-30 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* s390-tdep.c (s390_gdbarch_init): Call set_gdbarch_get_siginfo_type.
|
||||
|
@ -7,8 +7,8 @@
|
||||
|
||||
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
|
||||
<feature name="org.gnu.gdb.s390.core">
|
||||
<reg name="pswm" bitsize="32" type="uint32" group="psw" save-restore="no"/>
|
||||
<reg name="pswa" bitsize="32" type="uint32" group="psw" save-restore="no"/>
|
||||
<reg name="pswm" bitsize="32" type="uint32" group="psw"/>
|
||||
<reg name="pswa" bitsize="32" type="uint32" group="psw"/>
|
||||
<reg name="r0" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r1" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r2" bitsize="32" type="uint32" group="general"/>
|
||||
|
@ -7,8 +7,8 @@
|
||||
|
||||
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
|
||||
<feature name="org.gnu.gdb.s390.core">
|
||||
<reg name="pswm" bitsize="32" type="uint32" group="psw" save-restore="no"/>
|
||||
<reg name="pswa" bitsize="32" type="uint32" group="psw" save-restore="no"/>
|
||||
<reg name="pswm" bitsize="32" type="uint32" group="psw"/>
|
||||
<reg name="pswa" bitsize="32" type="uint32" group="psw"/>
|
||||
<reg name="r0h" bitsize="32" type="uint32" group="upper"/>
|
||||
<reg name="r0l" bitsize="32" type="uint32" group="lower"/>
|
||||
<reg name="r1h" bitsize="32" type="uint32" group="upper"/>
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* THIS FILE IS GENERATED. Original: s390-linux32.xml */
|
||||
|
||||
#include "defs.h"
|
||||
#include "osabi.h"
|
||||
#include "target-descriptions.h"
|
||||
|
||||
struct target_desc *tdesc_s390_linux32;
|
||||
@ -14,8 +15,8 @@ initialize_tdesc_s390_linux32 (void)
|
||||
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, 0, "psw", 32, "uint32");
|
||||
tdesc_create_reg (feature, "pswa", 1, 0, "psw", 32, "uint32");
|
||||
tdesc_create_reg (feature, "pswm", 0, 1, "psw", 32, "uint32");
|
||||
tdesc_create_reg (feature, "pswa", 1, 1, "psw", 32, "uint32");
|
||||
tdesc_create_reg (feature, "r0", 2, 1, "general", 32, "uint32");
|
||||
tdesc_create_reg (feature, "r1", 3, 1, "general", 32, "uint32");
|
||||
tdesc_create_reg (feature, "r2", 4, 1, "general", 32, "uint32");
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* THIS FILE IS GENERATED. Original: s390-linux64.xml */
|
||||
|
||||
#include "defs.h"
|
||||
#include "osabi.h"
|
||||
#include "target-descriptions.h"
|
||||
|
||||
struct target_desc *tdesc_s390_linux64;
|
||||
@ -14,8 +15,8 @@ initialize_tdesc_s390_linux64 (void)
|
||||
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, 0, "psw", 32, "uint32");
|
||||
tdesc_create_reg (feature, "pswa", 1, 0, "psw", 32, "uint32");
|
||||
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");
|
||||
|
@ -7,8 +7,8 @@
|
||||
|
||||
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
|
||||
<feature name="org.gnu.gdb.s390.core">
|
||||
<reg name="pswm" bitsize="64" type="uint64" group="psw" save-restore="no"/>
|
||||
<reg name="pswa" bitsize="64" type="uint64" group="psw" save-restore="no"/>
|
||||
<reg name="pswm" bitsize="64" type="uint64" group="psw"/>
|
||||
<reg name="pswa" bitsize="64" type="uint64" group="psw"/>
|
||||
<reg name="r0" bitsize="64" type="uint64" group="general"/>
|
||||
<reg name="r1" bitsize="64" type="uint64" group="general"/>
|
||||
<reg name="r2" bitsize="64" type="uint64" group="general"/>
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* THIS FILE IS GENERATED. Original: s390x-linux64.xml */
|
||||
|
||||
#include "defs.h"
|
||||
#include "osabi.h"
|
||||
#include "target-descriptions.h"
|
||||
|
||||
struct target_desc *tdesc_s390x_linux64;
|
||||
@ -14,8 +15,8 @@ initialize_tdesc_s390x_linux64 (void)
|
||||
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, 0, "psw", 64, "uint64");
|
||||
tdesc_create_reg (feature, "pswa", 1, 0, "psw", 64, "uint64");
|
||||
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");
|
||||
|
@ -1,3 +1,11 @@
|
||||
2011-11-30 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* linux-s390-low.c (s390_collect_ptrace_register): Fully convert
|
||||
PSW address/mask between 8-byte and 16-byte formats.
|
||||
(s390_supply_ptrace_register): Likewise.
|
||||
(s390_get_pc, s390_set_pc): 4-byte PSW address always includes
|
||||
basic addressing mode bit.
|
||||
|
||||
2011-11-24 Stan Shebs <stan@codesourcery.com>
|
||||
|
||||
* tracepoint.c (cmd_qtstatus): Use plongest instead of %llx.
|
||||
|
@ -126,16 +126,27 @@ s390_collect_ptrace_register (struct regcache *regcache, int regno, char *buf)
|
||||
collect_register (regcache, (regno & ~1) + 1,
|
||||
buf + sizeof (long) - size);
|
||||
}
|
||||
else if (regaddr == PT_PSWADDR
|
||||
|| (regaddr >= PT_GPR0 && regaddr <= PT_GPR15))
|
||||
else if (regaddr == PT_PSWMASK)
|
||||
{
|
||||
/* Convert 4-byte PSW mask to 8 bytes by clearing bit 12 and copying
|
||||
the basic addressing mode bit from the PSW address. */
|
||||
char *addr = alloca (register_size (regno ^ 1));
|
||||
collect_register (regcache, regno, buf);
|
||||
collect_register (regcache, regno ^ 1, addr);
|
||||
buf[1] &= ~0x8;
|
||||
buf[size] |= (addr[0] & 0x80);
|
||||
}
|
||||
else if (regaddr == PT_PSWADDR)
|
||||
{
|
||||
/* Convert 4-byte PSW address to 8 bytes by clearing the addressing
|
||||
mode bit (which gets copied to the PSW mask instead). */
|
||||
collect_register (regcache, regno, buf + sizeof (long) - size);
|
||||
buf[sizeof (long) - size] &= ~0x80;
|
||||
}
|
||||
else if (regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
|
||||
collect_register (regcache, regno, buf + sizeof (long) - size);
|
||||
else
|
||||
collect_register (regcache, 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 (regaddr == PT_PSWMASK)
|
||||
buf[size] |= 0x80;
|
||||
}
|
||||
else
|
||||
collect_register (regcache, regno, buf);
|
||||
@ -157,8 +168,35 @@ s390_supply_ptrace_register (struct regcache *regcache,
|
||||
supply_register (regcache, (regno & ~1) + 1,
|
||||
buf + sizeof (long) - size);
|
||||
}
|
||||
else if (regaddr == PT_PSWADDR
|
||||
|| (regaddr >= PT_GPR0 && regaddr <= PT_GPR15))
|
||||
else if (regaddr == PT_PSWMASK)
|
||||
{
|
||||
/* Convert 8-byte PSW mask to 4 bytes by setting bit 12 and copying
|
||||
the basic addressing mode into the PSW address. */
|
||||
char *mask = alloca (size);
|
||||
char *addr = alloca (register_size (regno ^ 1));
|
||||
memcpy (mask, buf, size);
|
||||
mask[1] |= 0x8;
|
||||
supply_register (regcache, regno, mask);
|
||||
|
||||
collect_register (regcache, regno ^ 1, addr);
|
||||
addr[0] &= ~0x80;
|
||||
addr[0] |= (buf[size] & 0x80);
|
||||
supply_register (regcache, regno ^ 1, addr);
|
||||
}
|
||||
else if (regaddr == PT_PSWADDR)
|
||||
{
|
||||
/* Convert 8-byte PSW address to 4 bytes by truncating, but
|
||||
keeping the addressing mode bit (which was set from the mask). */
|
||||
char *addr = alloca (size);
|
||||
char amode;
|
||||
collect_register (regcache, regno, addr);
|
||||
amode = addr[0] & 0x80;
|
||||
memcpy (addr, buf + sizeof (long) - size, size);
|
||||
addr[0] &= ~0x80;
|
||||
addr[0] |= amode;
|
||||
supply_register (regcache, regno, addr);
|
||||
}
|
||||
else if (regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
|
||||
supply_register (regcache, regno, buf + sizeof (long) - size);
|
||||
else
|
||||
supply_register (regcache, regno, buf);
|
||||
@ -199,12 +237,9 @@ s390_get_pc (struct regcache *regcache)
|
||||
{
|
||||
if (register_size (0) == 4)
|
||||
{
|
||||
unsigned int pc;
|
||||
collect_register_by_name (regcache, "pswa", &pc);
|
||||
#ifndef __s390x__
|
||||
pc &= 0x7fffffff;
|
||||
#endif
|
||||
return pc;
|
||||
unsigned int pswa;
|
||||
collect_register_by_name (regcache, "pswa", &pswa);
|
||||
return pswa & 0x7fffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -219,11 +254,10 @@ s390_set_pc (struct regcache *regcache, CORE_ADDR newpc)
|
||||
{
|
||||
if (register_size (0) == 4)
|
||||
{
|
||||
unsigned int pc = newpc;
|
||||
#ifndef __s390x__
|
||||
pc |= 0x80000000;
|
||||
#endif
|
||||
supply_register_by_name (regcache, "pswa", &pc);
|
||||
unsigned int pswa;
|
||||
collect_register_by_name (regcache, "pswa", &pswa);
|
||||
pswa = (pswa & 0x80000000) | (newpc & 0x7fffffff);
|
||||
supply_register_by_name (regcache, "pswa", &pswa);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
134
gdb/s390-nat.c
134
gdb/s390-nat.c
@ -55,28 +55,122 @@
|
||||
/* 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, int regno,
|
||||
const gdb_byte *regp, int *regmap)
|
||||
{
|
||||
int offset = regmap[regno];
|
||||
|
||||
#ifdef __s390x__
|
||||
#define SUBOFF(gdbarch, i) \
|
||||
((gdbarch_ptr_bit (gdbarch) == 32 \
|
||||
&& ((i) == S390_PSWA_REGNUM \
|
||||
|| ((i) >= S390_R0_REGNUM && (i) <= S390_R15_REGNUM)))? 4 : 0)
|
||||
#else
|
||||
#define SUBOFF(gdbarch, i) 0
|
||||
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||
if (offset != -1 && gdbarch_ptr_bit (gdbarch) == 32)
|
||||
{
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
||||
|
||||
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)
|
||||
{
|
||||
ULONGEST pswm, pswa;
|
||||
gdb_byte buf[4];
|
||||
|
||||
pswa = extract_unsigned_integer (regp + regmap[S390_PSWA_REGNUM],
|
||||
8, byte_order);
|
||||
pswm = extract_unsigned_integer (regp + regmap[S390_PSWM_REGNUM],
|
||||
8, byte_order);
|
||||
|
||||
store_unsigned_integer (buf, 4, byte_order,
|
||||
(pswa & 0x7fffffff) | (pswm & 0x80000000));
|
||||
regcache_raw_supply (regcache, regno, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM)
|
||||
offset += 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (offset != -1)
|
||||
regcache_raw_supply (regcache, regno, regp + offset);
|
||||
}
|
||||
|
||||
static void
|
||||
s390_native_collect (const struct regcache *regcache, int regno,
|
||||
gdb_byte *regp, int *regmap)
|
||||
{
|
||||
int offset = regmap[regno];
|
||||
|
||||
#ifdef __s390x__
|
||||
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||
if (offset != -1 && gdbarch_ptr_bit (gdbarch) == 32)
|
||||
{
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
||||
|
||||
if (regno == S390_PSWM_REGNUM)
|
||||
{
|
||||
ULONGEST pswm;
|
||||
gdb_byte buf[4];
|
||||
|
||||
regcache_raw_collect (regcache, regno, buf);
|
||||
pswm = extract_unsigned_integer (buf, 4, byte_order);
|
||||
|
||||
/* We don't know the final addressing mode until the PSW address
|
||||
is known, so leave it as-is. When the PSW address is collected
|
||||
(below), the addressing mode will be updated. */
|
||||
store_unsigned_integer (regp + regmap[S390_PSWM_REGNUM],
|
||||
4, byte_order, pswm & 0xfff7ffff);
|
||||
return;
|
||||
}
|
||||
|
||||
if (regno == S390_PSWA_REGNUM)
|
||||
{
|
||||
ULONGEST pswa;
|
||||
gdb_byte buf[4];
|
||||
|
||||
regcache_raw_collect (regcache, regno, 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)
|
||||
{
|
||||
memset (regp + offset, 0, 4);
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
#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)
|
||||
{
|
||||
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||
int i;
|
||||
for (i = 0; i < S390_NUM_REGS; i++)
|
||||
if (regmap_gregset[i] != -1)
|
||||
regcache_raw_supply (regcache, i,
|
||||
(const char *)regp + regmap_gregset[i]
|
||||
+ SUBOFF (gdbarch, i));
|
||||
s390_native_supply (regcache, i, (const gdb_byte *) regp, regmap_gregset);
|
||||
}
|
||||
|
||||
/* Fill register REGNO (if it is a general-purpose register) in
|
||||
@ -85,14 +179,10 @@ supply_gregset (struct regcache *regcache, const gregset_t *regp)
|
||||
void
|
||||
fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
|
||||
{
|
||||
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||
int i;
|
||||
for (i = 0; i < S390_NUM_REGS; i++)
|
||||
if (regmap_gregset[i] != -1)
|
||||
if (regno == -1 || regno == i)
|
||||
regcache_raw_collect (regcache, i,
|
||||
(char *)regp + regmap_gregset[i]
|
||||
+ SUBOFF (gdbarch, i));
|
||||
if (regno == -1 || regno == i)
|
||||
s390_native_collect (regcache, i, (gdb_byte *) regp, regmap_gregset);
|
||||
}
|
||||
|
||||
/* Fill GDB's register array with the floating-point register values
|
||||
@ -102,9 +192,7 @@ supply_fpregset (struct regcache *regcache, const fpregset_t *regp)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < S390_NUM_REGS; i++)
|
||||
if (regmap_fpregset[i] != -1)
|
||||
regcache_raw_supply (regcache, i,
|
||||
(const char *)regp + regmap_fpregset[i]);
|
||||
s390_native_supply (regcache, i, (const gdb_byte *) regp, regmap_fpregset);
|
||||
}
|
||||
|
||||
/* Fill register REGNO (if it is a general-purpose register) in
|
||||
@ -115,10 +203,8 @@ fill_fpregset (const struct regcache *regcache, fpregset_t *regp, int regno)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < S390_NUM_REGS; i++)
|
||||
if (regmap_fpregset[i] != -1)
|
||||
if (regno == -1 || regno == i)
|
||||
regcache_raw_collect (regcache, i,
|
||||
(char *)regp + regmap_fpregset[i]);
|
||||
if (regno == -1 || regno == i)
|
||||
s390_native_collect (regcache, i, (gdb_byte *) regp, regmap_fpregset);
|
||||
}
|
||||
|
||||
/* Find the TID for the current inferior thread to use with ptrace. */
|
||||
|
190
gdb/s390-tdep.c
190
gdb/s390-tdep.c
@ -352,8 +352,14 @@ s390_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
/* PC and CC pseudo registers need to be saved/restored in order to
|
||||
push or pop frames. */
|
||||
/* We usually save/restore the whole PSW, which includes PC and CC.
|
||||
However, some older gdbservers may not support saving/restoring
|
||||
the whole PSW yet, and will return an XML register description
|
||||
excluding those from the save/restore register groups. In those
|
||||
cases, we still need to explicitly save/restore PC and CC in order
|
||||
to push or pop frames. Since this doesn't hurt anything if we
|
||||
already save/restore the whole PSW (it's just redundant), we add
|
||||
PC and CC at this point unconditionally. */
|
||||
if (group == save_reggroup || group == restore_reggroup)
|
||||
return regnum == tdep->pc_regnum || regnum == tdep->cc_regnum;
|
||||
|
||||
@ -1449,6 +1455,79 @@ s390_displaced_step_fixup (struct gdbarch *gdbarch,
|
||||
paddress (gdbarch, regcache_read_pc (regs)));
|
||||
}
|
||||
|
||||
|
||||
/* Helper routine to unwind pseudo registers. */
|
||||
|
||||
static struct value *
|
||||
s390_unwind_pseudo_register (struct frame_info *this_frame, int regnum)
|
||||
{
|
||||
struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
struct type *type = register_type (gdbarch, regnum);
|
||||
|
||||
/* Unwind PC via PSW address. */
|
||||
if (regnum == tdep->pc_regnum)
|
||||
{
|
||||
struct value *val;
|
||||
|
||||
val = frame_unwind_register_value (this_frame, S390_PSWA_REGNUM);
|
||||
if (!value_optimized_out (val))
|
||||
{
|
||||
LONGEST pswa = value_as_long (val);
|
||||
|
||||
if (TYPE_LENGTH (type) == 4)
|
||||
return value_from_pointer (type, pswa & 0x7fffffff);
|
||||
else
|
||||
return value_from_pointer (type, pswa);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unwind CC via PSW mask. */
|
||||
if (regnum == tdep->cc_regnum)
|
||||
{
|
||||
struct value *val;
|
||||
|
||||
val = frame_unwind_register_value (this_frame, S390_PSWM_REGNUM);
|
||||
if (!value_optimized_out (val))
|
||||
{
|
||||
LONGEST pswm = value_as_long (val);
|
||||
|
||||
if (TYPE_LENGTH (type) == 4)
|
||||
return value_from_longest (type, (pswm >> 12) & 3);
|
||||
else
|
||||
return value_from_longest (type, (pswm >> 44) & 3);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
int reg = regnum - tdep->gpr_full_regnum;
|
||||
struct value *val;
|
||||
|
||||
val = frame_unwind_register_value (this_frame, S390_R0_REGNUM + reg);
|
||||
if (!value_optimized_out (val))
|
||||
return value_cast (type, val);
|
||||
}
|
||||
|
||||
return allocate_optimized_out_value (type);
|
||||
}
|
||||
|
||||
static struct value *
|
||||
s390_trad_frame_prev_register (struct frame_info *this_frame,
|
||||
struct trad_frame_saved_reg saved_regs[],
|
||||
int regnum)
|
||||
{
|
||||
if (regnum < S390_NUM_REGS)
|
||||
return trad_frame_get_prev_register (this_frame, saved_regs, regnum);
|
||||
else
|
||||
return s390_unwind_pseudo_register (this_frame, regnum);
|
||||
}
|
||||
|
||||
|
||||
/* Normal stack frames. */
|
||||
|
||||
struct s390_unwind_cache {
|
||||
@ -1465,7 +1544,6 @@ s390_prologue_frame_unwind_cache (struct frame_info *this_frame,
|
||||
struct s390_unwind_cache *info)
|
||||
{
|
||||
struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
int word_size = gdbarch_ptr_bit (gdbarch) / 8;
|
||||
struct s390_prologue_data data;
|
||||
pv_t *fp = &data.gpr[S390_FRAME_REGNUM - S390_R0_REGNUM];
|
||||
@ -1591,7 +1669,7 @@ s390_prologue_frame_unwind_cache (struct frame_info *this_frame,
|
||||
trad_frame_set_unknown (info->saved_regs, i);
|
||||
|
||||
/* CC is always call-clobbered. */
|
||||
trad_frame_set_unknown (info->saved_regs, tdep->cc_regnum);
|
||||
trad_frame_set_unknown (info->saved_regs, S390_PSWM_REGNUM);
|
||||
|
||||
/* Record the addresses of all register spill slots the prologue parser
|
||||
has recognized. Consider only registers defined as call-saved by the
|
||||
@ -1609,16 +1687,16 @@ s390_prologue_frame_unwind_cache (struct frame_info *this_frame,
|
||||
info->saved_regs[S390_F0_REGNUM + i].addr = cfa - data.fpr_slot[i];
|
||||
|
||||
/* Function return will set PC to %r14. */
|
||||
info->saved_regs[tdep->pc_regnum] = info->saved_regs[S390_RETADDR_REGNUM];
|
||||
info->saved_regs[S390_PSWA_REGNUM] = info->saved_regs[S390_RETADDR_REGNUM];
|
||||
|
||||
/* In frameless functions, we unwind simply by moving the return
|
||||
address to the PC. However, if we actually stored to the
|
||||
save area, use that -- we might only think the function frameless
|
||||
because we're in the middle of the prologue ... */
|
||||
if (size == 0
|
||||
&& !trad_frame_addr_p (info->saved_regs, tdep->pc_regnum))
|
||||
&& !trad_frame_addr_p (info->saved_regs, S390_PSWA_REGNUM))
|
||||
{
|
||||
info->saved_regs[tdep->pc_regnum].realreg = S390_RETADDR_REGNUM;
|
||||
info->saved_regs[S390_PSWA_REGNUM].realreg = S390_RETADDR_REGNUM;
|
||||
}
|
||||
|
||||
/* Another sanity check: unless this is a frameless function,
|
||||
@ -1628,7 +1706,7 @@ s390_prologue_frame_unwind_cache (struct frame_info *this_frame,
|
||||
if (size > 0)
|
||||
{
|
||||
if (!trad_frame_addr_p (info->saved_regs, S390_SP_REGNUM)
|
||||
|| !trad_frame_addr_p (info->saved_regs, tdep->pc_regnum))
|
||||
|| !trad_frame_addr_p (info->saved_regs, S390_PSWA_REGNUM))
|
||||
prev_sp = -1;
|
||||
}
|
||||
|
||||
@ -1649,7 +1727,6 @@ s390_backchain_frame_unwind_cache (struct frame_info *this_frame,
|
||||
struct s390_unwind_cache *info)
|
||||
{
|
||||
struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
int word_size = gdbarch_ptr_bit (gdbarch) / 8;
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
||||
CORE_ADDR backchain;
|
||||
@ -1663,7 +1740,7 @@ s390_backchain_frame_unwind_cache (struct frame_info *this_frame,
|
||||
trad_frame_set_unknown (info->saved_regs, i);
|
||||
|
||||
/* CC is always call-clobbered. */
|
||||
trad_frame_set_unknown (info->saved_regs, tdep->cc_regnum);
|
||||
trad_frame_set_unknown (info->saved_regs, S390_PSWM_REGNUM);
|
||||
|
||||
/* Get the backchain. */
|
||||
reg = get_frame_register_unsigned (this_frame, S390_SP_REGNUM);
|
||||
@ -1685,7 +1762,7 @@ s390_backchain_frame_unwind_cache (struct frame_info *this_frame,
|
||||
info->saved_regs[S390_RETADDR_REGNUM].addr = backchain + 14*word_size;
|
||||
|
||||
/* Function return will set PC to %r14. */
|
||||
info->saved_regs[tdep->pc_regnum]
|
||||
info->saved_regs[S390_PSWA_REGNUM]
|
||||
= info->saved_regs[S390_RETADDR_REGNUM];
|
||||
|
||||
/* We use the current value of the frame register as local_base,
|
||||
@ -1739,28 +1816,10 @@ s390_frame_prev_register (struct frame_info *this_frame,
|
||||
void **this_prologue_cache, int regnum)
|
||||
{
|
||||
struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
struct s390_unwind_cache *info
|
||||
= s390_frame_unwind_cache (this_frame, this_prologue_cache);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
int reg = regnum - tdep->gpr_full_regnum + S390_R0_REGNUM;
|
||||
struct value *val, *newval;
|
||||
|
||||
val = trad_frame_get_prev_register (this_frame, info->saved_regs, reg);
|
||||
newval = value_cast (register_type (gdbarch, regnum), val);
|
||||
if (value_optimized_out (val))
|
||||
set_value_optimized_out (newval, 1);
|
||||
|
||||
return newval;
|
||||
}
|
||||
|
||||
return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
|
||||
return s390_trad_frame_prev_register (this_frame, info->saved_regs, regnum);
|
||||
}
|
||||
|
||||
static const struct frame_unwind s390_frame_unwind = {
|
||||
@ -1788,7 +1847,6 @@ s390_stub_frame_unwind_cache (struct frame_info *this_frame,
|
||||
void **this_prologue_cache)
|
||||
{
|
||||
struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
int word_size = gdbarch_ptr_bit (gdbarch) / 8;
|
||||
struct s390_stub_unwind_cache *info;
|
||||
ULONGEST reg;
|
||||
@ -1801,7 +1859,7 @@ s390_stub_frame_unwind_cache (struct frame_info *this_frame,
|
||||
info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
|
||||
|
||||
/* The return address is in register %r14. */
|
||||
info->saved_regs[tdep->pc_regnum].realreg = S390_RETADDR_REGNUM;
|
||||
info->saved_regs[S390_PSWA_REGNUM].realreg = S390_RETADDR_REGNUM;
|
||||
|
||||
/* Retrieve stack pointer and determine our frame base. */
|
||||
reg = get_frame_register_unsigned (this_frame, S390_SP_REGNUM);
|
||||
@ -1826,7 +1884,7 @@ s390_stub_frame_prev_register (struct frame_info *this_frame,
|
||||
{
|
||||
struct s390_stub_unwind_cache *info
|
||||
= s390_stub_frame_unwind_cache (this_frame, this_prologue_cache);
|
||||
return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
|
||||
return s390_trad_frame_prev_register (this_frame, info->saved_regs, regnum);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1875,7 +1933,6 @@ s390_sigtramp_frame_unwind_cache (struct frame_info *this_frame,
|
||||
struct s390_sigtramp_unwind_cache *info;
|
||||
ULONGEST this_sp, prev_sp;
|
||||
CORE_ADDR next_ra, next_cfa, sigreg_ptr, sigreg_high_off;
|
||||
ULONGEST pswm;
|
||||
int i;
|
||||
|
||||
if (*this_prologue_cache)
|
||||
@ -1928,16 +1985,6 @@ s390_sigtramp_frame_unwind_cache (struct frame_info *this_frame,
|
||||
info->saved_regs[S390_PSWA_REGNUM].addr = sigreg_ptr;
|
||||
sigreg_ptr += word_size;
|
||||
|
||||
/* Point PC to PSWA as well. */
|
||||
info->saved_regs[tdep->pc_regnum] = info->saved_regs[S390_PSWA_REGNUM];
|
||||
|
||||
/* Extract CC from PSWM. */
|
||||
pswm = read_memory_unsigned_integer (
|
||||
info->saved_regs[S390_PSWM_REGNUM].addr,
|
||||
word_size, byte_order);
|
||||
trad_frame_set_value (info->saved_regs, tdep->cc_regnum,
|
||||
(pswm >> (8 * word_size - 20)) & 3);
|
||||
|
||||
/* Then the GPRs. */
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
@ -1972,22 +2019,6 @@ s390_sigtramp_frame_unwind_cache (struct frame_info *this_frame,
|
||||
sigreg_ptr += 4;
|
||||
}
|
||||
|
||||
/* Provide read-only copies of the full registers. */
|
||||
if (tdep->gpr_full_regnum != -1)
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
ULONGEST low, high;
|
||||
low = read_memory_unsigned_integer (
|
||||
info->saved_regs[S390_R0_REGNUM + i].addr,
|
||||
4, byte_order);
|
||||
high = read_memory_unsigned_integer (
|
||||
info->saved_regs[S390_R0_UPPER_REGNUM + i].addr,
|
||||
4, byte_order);
|
||||
|
||||
trad_frame_set_value (info->saved_regs, tdep->gpr_full_regnum + i,
|
||||
(high << 32) | low);
|
||||
}
|
||||
|
||||
/* Restore the previous frame's SP. */
|
||||
prev_sp = read_memory_unsigned_integer (
|
||||
info->saved_regs[S390_SP_REGNUM].addr,
|
||||
@ -2015,7 +2046,7 @@ s390_sigtramp_frame_prev_register (struct frame_info *this_frame,
|
||||
{
|
||||
struct s390_sigtramp_unwind_cache *info
|
||||
= s390_sigtramp_frame_unwind_cache (this_frame, this_prologue_cache);
|
||||
return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
|
||||
return s390_trad_frame_prev_register (this_frame, info->saved_regs, regnum);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2098,17 +2129,7 @@ static struct value *
|
||||
s390_dwarf2_prev_register (struct frame_info *this_frame, void **this_cache,
|
||||
int regnum)
|
||||
{
|
||||
struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
int reg = regnum - tdep->gpr_full_regnum;
|
||||
struct value *val, *newval;
|
||||
|
||||
val = frame_unwind_register_value (this_frame, S390_R0_REGNUM + reg);
|
||||
newval = value_cast (register_type (gdbarch, regnum), val);
|
||||
if (value_optimized_out (val))
|
||||
set_value_optimized_out (newval, 1);
|
||||
|
||||
return newval;
|
||||
return s390_unwind_pseudo_register (this_frame, regnum);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2118,9 +2139,17 @@ s390_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
/* The condition code (and thus PSW mask) is call-clobbered. */
|
||||
if (regnum == S390_PSWM_REGNUM)
|
||||
reg->how = DWARF2_FRAME_REG_UNDEFINED;
|
||||
|
||||
/* The PSW address unwinds to the return address. */
|
||||
else if (regnum == S390_PSWA_REGNUM)
|
||||
reg->how = DWARF2_FRAME_REG_RA;
|
||||
|
||||
/* Fixed registers are call-saved or call-clobbered
|
||||
depending on the ABI in use. */
|
||||
if (regnum >= 0 && regnum < S390_NUM_REGS)
|
||||
else if (regnum < S390_NUM_REGS)
|
||||
{
|
||||
if (s390_register_call_saved (gdbarch, regnum))
|
||||
reg->how = DWARF2_FRAME_REG_SAME_VALUE;
|
||||
@ -2128,19 +2157,8 @@ s390_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
|
||||
reg->how = DWARF2_FRAME_REG_UNDEFINED;
|
||||
}
|
||||
|
||||
/* The CC pseudo register is call-clobbered. */
|
||||
else if (regnum == tdep->cc_regnum)
|
||||
reg->how = DWARF2_FRAME_REG_UNDEFINED;
|
||||
|
||||
/* The PC register unwinds to the return address. */
|
||||
else if (regnum == tdep->pc_regnum)
|
||||
reg->how = DWARF2_FRAME_REG_RA;
|
||||
|
||||
/* We install a special function to unwind full GPRs to show at
|
||||
least the lower halves (as the upper halves are undefined). */
|
||||
else if (tdep->gpr_full_regnum != -1
|
||||
&& regnum >= tdep->gpr_full_regnum
|
||||
&& regnum < tdep->gpr_full_regnum + 16)
|
||||
/* We install a special function to unwind pseudos. */
|
||||
else
|
||||
{
|
||||
reg->how = DWARF2_FRAME_REG_FN;
|
||||
reg->loc.fn = s390_dwarf2_prev_register;
|
||||
|
Loading…
Reference in New Issue
Block a user