/* GNU/Linux S/390 specific low level interface, for the remote server
for GDB.
- Copyright (C) 2001-2017 Free Software Foundation, Inc.
+ Copyright (C) 2001-2020 Free Software Foundation, Inc.
This file is part of GDB.
supply_register (regcache, v16 + i, (const char *) buf + 16 * i);
}
-static void
-s390_fill_gs (struct regcache *regcache, void *buf)
-{
- int gsd = find_regno (regcache->tdesc, "gsd");
- int i;
-
- for (i = 0; i < 3; i++)
- collect_register (regcache, gsd + i, (char *) buf + 8 * (i + 1));
-}
-
static void
s390_store_gs (struct regcache *regcache, const void *buf)
{
supply_register (regcache, gsd + i, (const char *) buf + 8 * (i + 1));
}
-static void
-s390_fill_gsbc (struct regcache *regcache, void *buf)
-{
- int bc_gsd = find_regno (regcache->tdesc, "bc_gsd");
- int i;
-
- for (i = 0; i < 3; i++)
- collect_register (regcache, bc_gsd + i, (char *) buf + 8 * (i + 1));
-}
-
static void
s390_store_gsbc (struct regcache *regcache, const void *buf)
{
EXTENDED_REGS, s390_fill_vxrs_low, s390_store_vxrs_low },
{ PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_VXRS_HIGH, 0,
EXTENDED_REGS, s390_fill_vxrs_high, s390_store_vxrs_high },
- { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_GS_CB, 0,
- EXTENDED_REGS, s390_fill_gs, s390_store_gs },
- { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_GS_BC, 0,
- EXTENDED_REGS, s390_fill_gsbc, s390_store_gsbc },
+ /* Guarded storage registers are read-only. */
+ { PTRACE_GETREGSET, -1, NT_S390_GS_CB, 0, EXTENDED_REGS,
+ NULL, s390_store_gs },
+ { PTRACE_GETREGSET, -1, NT_S390_GS_BC, 0, EXTENDED_REGS,
+ NULL, s390_store_gsbc },
NULL_REGSET
};
}
}
-static unsigned long
-s390_get_hwcap (const struct target_desc *tdesc)
-{
- int wordsize = register_size (tdesc, 0);
- gdb_byte *data = (gdb_byte *) alloca (2 * wordsize);
- int offset = 0;
+/* Determine the word size for the given PID, in bytes. */
- while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize)
+#ifdef __s390x__
+static int
+s390_get_wordsize (int pid)
+{
+ errno = 0;
+ PTRACE_XFER_TYPE pswm = ptrace (PTRACE_PEEKUSER, pid,
+ (PTRACE_TYPE_ARG3) 0,
+ (PTRACE_TYPE_ARG4) 0);
+ if (errno != 0)
{
- 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;
+ warning (_("Couldn't determine word size, assuming 64-bit."));
+ return 8;
}
-
- return 0;
+ /* Derive word size from extended addressing mode (PSW bit 31). */
+ return pswm & (1L << 32) ? 8 : 4;
}
+#else
+#define s390_get_wordsize(pid) 4
+#endif
static int
s390_check_regset (int pid, int regset, int regsize)
const struct target_desc *tdesc;
struct regset_info *regset;
- /* Check whether the kernel supports extra register sets. */
+ /* Determine word size and HWCAP. */
int pid = pid_of (current_thread);
+ int wordsize = s390_get_wordsize (pid);
+ unsigned long hwcap = linux_get_hwcap (wordsize);
+
+ /* Check whether the kernel supports extra register sets. */
int have_regset_last_break
= 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);
- int have_regset_vxrs = s390_check_regset (pid, NT_S390_VXRS_LOW, 128)
- && s390_check_regset (pid, NT_S390_VXRS_HIGH, 256);
- int have_regset_gs = s390_check_regset (pid, NT_S390_GS_CB, 32)
- && s390_check_regset (pid, NT_S390_GS_BC, 32);
-
- /* Assume 31-bit inferior process. */
- if (have_regset_system_call)
- tdesc = tdesc_s390_linux32v2;
- else if (have_regset_last_break)
- tdesc = tdesc_s390_linux32v1;
- else
- tdesc = tdesc_s390_linux32;
+ int have_regset_tdb
+ = (s390_check_regset (pid, NT_S390_TDB, 256)
+ && (hwcap & HWCAP_S390_TE) != 0);
+ int have_regset_vxrs
+ = (s390_check_regset (pid, NT_S390_VXRS_LOW, 128)
+ && s390_check_regset (pid, NT_S390_VXRS_HIGH, 256)
+ && (hwcap & HWCAP_S390_VX) != 0);
+ int have_regset_gs
+ = (s390_check_regset (pid, NT_S390_GS_CB, 32)
+ && s390_check_regset (pid, NT_S390_GS_BC, 32)
+ && (hwcap & HWCAP_S390_GS) != 0);
- /* 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. */
{
#ifdef __s390x__
- unsigned int pswm;
- struct regcache *regcache = new_register_cache (tdesc);
-
- fetch_inferior_registers (regcache, find_regno (tdesc, "pswm"));
- collect_register_by_name (regcache, "pswm", &pswm);
- free_register_cache (regcache);
-
- if (pswm & 1)
+ if (wordsize == 8)
{
- if (have_regset_tdb)
- have_regset_tdb =
- (s390_get_hwcap (tdesc_s390x_linux64v2) & HWCAP_S390_TE) != 0;
- if (have_regset_vxrs)
- have_regset_vxrs =
- (s390_get_hwcap (tdesc_s390x_linux64v2) & HWCAP_S390_VX) != 0;
- if (have_regset_gs)
- have_regset_gs =
- (s390_get_hwcap (tdesc_s390x_linux64v2) & HWCAP_S390_GS) != 0;
-
if (have_regset_gs)
tdesc = tdesc_s390x_gs_linux64;
else if (have_regset_vxrs)
using the full 64-bit GPRs. */
else
#endif
- if (s390_get_hwcap (tdesc) & HWCAP_S390_HIGH_GPRS)
+ if (hwcap & HWCAP_S390_HIGH_GPRS)
{
have_hwcap_s390_high_gprs = 1;
- if (have_regset_tdb)
- have_regset_tdb = (s390_get_hwcap (tdesc) & HWCAP_S390_TE) != 0;
- if (have_regset_vxrs)
- have_regset_vxrs = (s390_get_hwcap (tdesc) & HWCAP_S390_VX) != 0;
- if (have_regset_gs)
- have_regset_gs = (s390_get_hwcap (tdesc) & HWCAP_S390_GS) != 0;
-
if (have_regset_gs)
tdesc = tdesc_s390_gs_linux64;
else if (have_regset_vxrs)
else
tdesc = tdesc_s390_linux64;
}
+ else
+ {
+ /* Assume 31-bit inferior process. */
+ if (have_regset_system_call)
+ tdesc = tdesc_s390_linux32v2;
+ else if (have_regset_last_break)
+ tdesc = tdesc_s390_linux32v1;
+ else
+ tdesc = tdesc_s390_linux32;
+ }
have_hwcap_s390_vx = have_regset_vxrs;
}
static void
append_insns (CORE_ADDR *to, size_t len, const unsigned char *buf)
{
- write_inferior_memory (*to, buf, len);
+ target_write_memory (*to, buf, len);
*to += len;
}
return S390_TDESC_VX;
if (tdesc == tdesc_s390x_tevx_linux64)
return S390_TDESC_TEVX;
+ if (tdesc == tdesc_s390x_gs_linux64)
+ return S390_TDESC_GS;
#endif
if (tdesc == tdesc_s390_linux32)
return S390_TDESC_VX;
if (tdesc == tdesc_s390_tevx_linux64)
return S390_TDESC_TEVX;
+ if (tdesc == tdesc_s390_gs_linux64)
+ return S390_TDESC_GS;
return 0;
}
s390_emit_ext (int arg)
{
unsigned char buf[] = {
- 0x8d, 0x20, 0x00, 64 - arg, /* sldl %r2, <64-arg> */
- 0x8e, 0x20, 0x00, 64 - arg, /* srda %r2, <64-arg> */
+ 0x8d, 0x20, 0x00, (unsigned char) (64 - arg), /* sldl %r2, <64-arg> */
+ 0x8e, 0x20, 0x00, (unsigned char) (64 - arg), /* srda %r2, <64-arg> */
};
add_insns (buf, sizeof buf);
}
}
memcpy (buf, &sdiff, sizeof sdiff);
- write_inferior_memory (from, buf, sizeof sdiff);
+ target_write_memory (from, buf, sizeof sdiff);
}
/* Preparation for emitting a literal pool of given size. Loads the address
0x07, 0x07,
};
unsigned char buf[] = {
- 0xa7, 0x15, 0x00, (size + 4) / 2, /* bras %r1, .Lend+size */
+ 0xa7, 0x15, 0x00,
+ (unsigned char) ((size + 4) / 2), /* bras %r1, .Lend+size */
/* .Lend: */
};
if (size == 4)
{
unsigned long long n = num;
unsigned char buf_s[] = {
- 0xa7, 0x38, num >> 8, num, /* lhi %r3, <num> */
- 0x17, 0x22, /* xr %r2, %r2 */
+ /* lhi %r3, <num> */
+ 0xa7, 0x38,
+ (unsigned char) (num >> 8), (unsigned char) num,
+ /* xr %r2, %r2 */
+ 0x17, 0x22,
};
static const unsigned char buf_l[] = {
0x98, 0x23, 0x10, 0x00, /* lm %r2, %r3, 0(%r1) */
s390_emit_reg (int reg)
{
unsigned char bufpre[] = {
- 0x18, 0x29, /* lr %r2, %r9 */
- 0xa7, 0x38, reg >> 8, reg, /* lhi %r3, <reg> */
+ /* lr %r2, %r9 */
+ 0x18, 0x29,
+ /* lhi %r3, <reg> */
+ 0xa7, 0x38, (unsigned char) (reg >> 8), (unsigned char) reg,
};
add_insns (bufpre, sizeof bufpre);
s390_emit_call (get_raw_reg_func_addr ());
s390_emit_zero_ext (int arg)
{
unsigned char buf[] = {
- 0x8d, 0x20, 0x00, 64 - arg, /* sldl %r2, <64-arg> */
- 0x8c, 0x20, 0x00, 64 - arg, /* srdl %r2, <64-arg> */
+ 0x8d, 0x20, 0x00, (unsigned char) (64 - arg), /* sldl %r2, <64-arg> */
+ 0x8c, 0x20, 0x00, (unsigned char) (64 - arg), /* srdl %r2, <64-arg> */
};
add_insns (buf, sizeof buf);
}
s390_emit_stack_adjust (int n)
{
unsigned char buf[] = {
- 0xa7, 0xfa, n * 8 >> 8, n * 8, /* ahi %r15, 8*n */
+ /* ahi %r15, 8*n */
+ 0xa7, 0xfa,
+ (unsigned char ) (n * 8 >> 8), (unsigned char) (n * 8),
};
add_insns (buf, sizeof buf);
}
s390_emit_set_r2 (int arg1)
{
unsigned char buf_s[] = {
- 0xa7, 0x28, arg1 >> 8, arg1, /* lhi %r2, <arg1> */
+ /* lhi %r2, <arg1> */
+ 0xa7, 0x28, (unsigned char) (arg1 >> 8), (unsigned char) arg1,
};
static const unsigned char buf_l[] = {
0x58, 0x20, 0x10, 0x00, /* l %r2, 0(%r1) */
s390x_emit_ext (int arg)
{
unsigned char buf[] = {
- 0xeb, 0x22, 0x00, 64 - arg, 0x00, 0x0d, /* sllg %r2, %r2, <64-arg> */
- 0xeb, 0x22, 0x00, 64 - arg, 0x00, 0x0a, /* srag %r2, %r2, <64-arg> */
+ /* sllg %r2, %r2, <64-arg> */
+ 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0d,
+ /* srag %r2, %r2, <64-arg> */
+ 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0a,
};
add_insns (buf, sizeof buf);
}
{
unsigned long long n = num;
unsigned char buf_s[] = {
- 0xa7, 0x29, num >> 8, num, /* lghi %r2, <num> */
+ /* lghi %r2, <num> */
+ 0xa7, 0x29, (unsigned char) (num >> 8), (unsigned char) num,
};
static const unsigned char buf_l[] = {
0xe3, 0x20, 0x10, 0x00, 0x00, 0x04, /* lg %r2, 0(%r1) */
s390x_emit_reg (int reg)
{
unsigned char buf[] = {
- 0xb9, 0x04, 0x00, 0x29, /* lgr %r2, %r9 */
- 0xa7, 0x39, reg >> 8, reg, /* lghi %r3, <reg> */
+ /* lgr %r2, %r9 */
+ 0xb9, 0x04, 0x00, 0x29,
+ /* lghi %r3, <reg> */
+ 0xa7, 0x39, (unsigned char) (reg >> 8), (unsigned char) reg,
};
add_insns (buf, sizeof buf);
s390x_emit_call (get_raw_reg_func_addr ());
s390x_emit_zero_ext (int arg)
{
unsigned char buf[] = {
- 0xeb, 0x22, 0x00, 64 - arg, 0x00, 0x0d, /* sllg %r2, %r2, <64-arg> */
- 0xeb, 0x22, 0x00, 64 - arg, 0x00, 0x0c, /* srlg %r2, %r2, <64-arg> */
+ /* sllg %r2, %r2, <64-arg> */
+ 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0d,
+ /* srlg %r2, %r2, <64-arg> */
+ 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0c,
};
add_insns (buf, sizeof buf);
}
s390x_emit_stack_adjust (int n)
{
unsigned char buf[] = {
- 0xa7, 0xfb, n * 8 >> 8, n * 8, /* aghi %r15, 8*n */
+ /* aghi %r15, 8*n */
+ 0xa7, 0xfb,
+ (unsigned char) (n * 8 >> 8), (unsigned char) (n * 8),
};
add_insns (buf, sizeof buf);
}
s390_supply_ptrace_register,
NULL, /* siginfo_fixup */
NULL, /* new_process */
+ NULL, /* delete_process */
NULL, /* new_thread */
+ NULL, /* delete_thread */
NULL, /* new_fork */
NULL, /* prepare_to_resume */
NULL, /* process_qsupported */