/* Target-dependent code for s390.
- Copyright (C) 2001-2019 Free Software Foundation, Inc.
+ Copyright (C) 2001-2021 Free Software Foundation, Inc.
This file is part of GDB.
#include "arch-utils.h"
#include "ax-gdb.h"
-#include "dwarf2-frame.h"
+#include "dwarf2/frame.h"
#include "elf/s390.h"
#include "elf-bfd.h"
#include "frame-base.h"
#include "target-descriptions.h"
#include "trad-frame.h"
#include "value.h"
+#include "inferior.h"
#include "features/s390-linux32.c"
#include "features/s390x-linux64.c"
if (TYPE_LENGTH (t) > 8)
{
- switch (TYPE_CODE (t))
+ switch (t->code ())
{
case TYPE_CODE_INT:
case TYPE_CODE_RANGE:
return 8;
case TYPE_CODE_ARRAY:
- if (TYPE_VECTOR (t))
+ if (t->is_vector ())
return 8;
break;
}
return 0;
}
-typedef buf_displaced_step_closure s390_displaced_step_closure;
+typedef buf_displaced_step_copy_insn_closure
+ s390_displaced_step_copy_insn_closure;
/* Implementation of gdbarch_displaced_step_copy_insn. */
-static struct displaced_step_closure *
+static displaced_step_copy_insn_closure_up
s390_displaced_step_copy_insn (struct gdbarch *gdbarch,
CORE_ADDR from, CORE_ADDR to,
struct regcache *regs)
{
size_t len = gdbarch_max_insn_length (gdbarch);
- std::unique_ptr<s390_displaced_step_closure> closure
- (new s390_displaced_step_closure (len));
+ std::unique_ptr<s390_displaced_step_copy_insn_closure> closure
+ (new s390_displaced_step_copy_insn_closure (len));
gdb_byte *buf = closure->buf.data ();
read_memory (from, buf, len);
{
/* Let the core fall back to stepping over the breakpoint
in-line. */
- if (debug_displaced)
- {
- fprintf_unfiltered (gdb_stdlog,
- "displaced: can't displaced step "
- "RIL instruction: offset %s out of range\n",
- plongest (offset));
- }
+ displaced_debug_printf ("can't displaced step RIL instruction: offset "
+ "%s out of range", plongest (offset));
return NULL;
}
write_memory (to, buf, len);
- if (debug_displaced)
- {
- fprintf_unfiltered (gdb_stdlog, "displaced: copy %s->%s: ",
- paddress (gdbarch, from), paddress (gdbarch, to));
- displaced_step_dump_bytes (gdb_stdlog, buf, len);
- }
+ displaced_debug_printf ("copy %s->%s: %s",
+ paddress (gdbarch, from), paddress (gdbarch, to),
+ displaced_step_dump_bytes (buf, len).c_str ());
- return closure.release ();
+ /* This is a work around for a problem with g++ 4.8. */
+ return displaced_step_copy_insn_closure_up (closure.release ());
}
/* Fix up the state of registers and memory after having single-stepped
static void
s390_displaced_step_fixup (struct gdbarch *gdbarch,
- struct displaced_step_closure *closure_,
+ displaced_step_copy_insn_closure *closure_,
CORE_ADDR from, CORE_ADDR to,
struct regcache *regs)
{
/* Our closure is a copy of the instruction. */
- s390_displaced_step_closure *closure
- = (s390_displaced_step_closure *) closure_;
+ s390_displaced_step_copy_insn_closure *closure
+ = (s390_displaced_step_copy_insn_closure *) closure_;
gdb_byte *insn = closure->buf.data ();
static int s390_instrlen[] = { 2, 4, 4, 6 };
int insnlen = s390_instrlen[insn[0] >> 6];
amode &= 0x80000000;
}
- if (debug_displaced)
- fprintf_unfiltered (gdb_stdlog,
- "displaced: (s390) fixup (%s, %s) pc %s len %d amode 0x%x\n",
- paddress (gdbarch, from), paddress (gdbarch, to),
- paddress (gdbarch, pc), insnlen, (int) amode);
+ displaced_debug_printf ("(s390) fixup (%s, %s) pc %s len %d amode 0x%x",
+ paddress (gdbarch, from), paddress (gdbarch, to),
+ paddress (gdbarch, pc), insnlen, (int) amode);
/* Handle absolute branch and save instructions. */
- if (is_rr (insn, op_basr, &r1, &r2)
+ int op_basr_p = is_rr (insn, op_basr, &r1, &r2);
+ if (op_basr_p
|| is_rx (insn, op_bas, &r1, &d2, &x2, &b2))
{
/* Recompute saved return address in R1. */
regcache_cooked_write_unsigned (regs, S390_R0_REGNUM + r1,
amode | (from + insnlen));
/* Update PC iff the instruction doesn't actually branch. */
- if (insn[0] == op_basr && r2 == 0)
+ if (op_basr_p && r2 == 0)
regcache_write_pc (regs, from + insnlen);
}
else
regcache_write_pc (regs, pc - to + from);
- if (debug_displaced)
- fprintf_unfiltered (gdb_stdlog,
- "displaced: (s390) pc is now %s\n",
- paddress (gdbarch, regcache_read_pc (regs)));
+ displaced_debug_printf ("(s390) pc is now %s",
+ paddress (gdbarch, regcache_read_pc (regs)));
}
/* Implement displaced_step_hw_singlestep gdbarch method. */
-static int
-s390_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
- struct displaced_step_closure *closure)
+static bool
+s390_displaced_step_hw_singlestep (struct gdbarch *gdbarch)
{
- return 1;
+ return true;
}
/* Prologue analysis. */
we're analyzing the code to unwind past that frame. */
if (pv_is_constant (addr))
{
- struct target_section *secp;
- secp = target_section_by_addr (current_top_target (), addr.k);
+ const struct target_section *secp
+ = target_section_by_addr (current_inferior ()->top_target (), addr.k);
if (secp != NULL
&& (bfd_section_flags (secp->the_bfd_section) & SEC_READONLY))
return pv_constant (read_memory_integer (addr.k, size,
/* Implement addr_class_type_flags gdbarch method.
Only used for ABI_LINUX_ZSERIES. */
-static int
+static type_instance_flags
s390_address_class_type_flags (int byte_size, int dwarf2_addr_class)
{
if (byte_size == 4)
Only used for ABI_LINUX_ZSERIES. */
static const char *
-s390_address_class_type_flags_to_name (struct gdbarch *gdbarch, int type_flags)
+s390_address_class_type_flags_to_name (struct gdbarch *gdbarch,
+ type_instance_flags type_flags)
{
if (type_flags & TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1)
return "mode32";
/* Implement addr_class_name_to_type_flags gdbarch method.
Only used for ABI_LINUX_ZSERIES. */
-static int
+static bool
s390_address_class_name_to_type_flags (struct gdbarch *gdbarch,
const char *name,
- int *type_flags_ptr)
+ type_instance_flags *type_flags_ptr)
{
if (strcmp (name, "mode32") == 0)
{
*type_flags_ptr = TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1;
- return 1;
+ return true;
}
else
- return 0;
+ return false;
}
/* Inferior function calls. */
static struct type *
s390_effective_inner_type (struct type *type, unsigned int min_size)
{
- while (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+ while (type->code () == TYPE_CODE_STRUCT)
{
struct type *inner = NULL;
/* Find a non-static field, if any. Unless there's exactly one,
abort the unwrapping. */
- for (int i = 0; i < TYPE_NFIELDS (type); i++)
+ for (int i = 0; i < type->num_fields (); i++)
{
- struct field f = TYPE_FIELD (type, i);
+ struct field f = type->field (i);
if (field_is_static (&f))
continue;
if (inner != NULL)
return type;
- inner = FIELD_TYPE (f);
+ inner = f.type ();
}
if (inner == NULL)
or double. */
type = s390_effective_inner_type (type, 0);
- return (TYPE_CODE (type) == TYPE_CODE_FLT
- || TYPE_CODE (type) == TYPE_CODE_DECFLOAT);
+ return (type->code () == TYPE_CODE_FLT
+ || type->code () == TYPE_CODE_DECFLOAT);
}
/* Return non-zero if TYPE should be passed like a vector. */
/* Structs containing just a vector are passed like a vector. */
type = s390_effective_inner_type (type, TYPE_LENGTH (type));
- return TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type);
+ return type->code () == TYPE_CODE_ARRAY && type->is_vector ();
}
/* Determine whether N is a power of two. */
static int
s390_function_arg_integer (struct type *type)
{
- enum type_code code = TYPE_CODE (type);
+ enum type_code code = type->code ();
if (TYPE_LENGTH (type) > 8)
return 0;
/* Place value in least significant bits of the register or
memory word and sign- or zero-extend to full word size.
This also applies to a struct or union. */
- val = TYPE_UNSIGNED (type)
+ val = type->is_unsigned ()
? extract_unsigned_integer (value_contents (arg),
length, byte_order)
: extract_signed_integer (value_contents (arg),
CORE_ADDR param_area_start, new_sp;
struct type *ftype = check_typedef (value_type (function));
- if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
+ if (ftype->code () == TYPE_CODE_PTR)
ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
arg_prep.copy = sp;
and arg_state.argp with the size of the parameter area. */
for (i = 0; i < nargs; i++)
s390_handle_arg (&arg_state, args[i], tdep, word_size, byte_order,
- TYPE_VARARGS (ftype) && i >= TYPE_NFIELDS (ftype));
+ ftype->has_varargs () && i >= ftype->num_fields ());
param_area_start = align_down (arg_state.copy - arg_state.argp, 8);
/* Write all parameters. */
for (i = 0; i < nargs; i++)
s390_handle_arg (&arg_state, args[i], tdep, word_size, byte_order,
- TYPE_VARARGS (ftype) && i >= TYPE_NFIELDS (ftype));
+ ftype->has_varargs () && i >= ftype->num_fields ());
/* Store return PSWA. In 31-bit mode, keep addressing mode bit. */
if (word_size == 4)
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int word_size = gdbarch_ptr_bit (gdbarch) / 8;
int length = TYPE_LENGTH (type);
- int code = TYPE_CODE (type);
+ int code = type->code ();
if (code == TYPE_CODE_FLT || code == TYPE_CODE_DECFLOAT)
{
if (out != NULL)
regcache->cooked_read_part (S390_R2_REGNUM, word_size - length, length,
out);
- else if (TYPE_UNSIGNED (type))
+ else if (type->is_unsigned ())
regcache_cooked_write_unsigned
(regcache, S390_R2_REGNUM,
extract_unsigned_integer (in, length, byte_order));
type = check_typedef (type);
- switch (TYPE_CODE (type))
+ switch (type->code ())
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
break;
case TYPE_CODE_ARRAY:
rvc = (gdbarch_tdep (gdbarch)->vector_abi == S390_VECTOR_ABI_128
- && TYPE_LENGTH (type) <= 16 && TYPE_VECTOR (type))
+ && TYPE_LENGTH (type) <= 16 && type->is_vector ())
? RETURN_VALUE_REGISTER_CONVENTION
: RETURN_VALUE_STRUCT_CONVENTION;
break;
/* Frame unwinding. */
-/* Implmement the stack_frame_destroyed_p gdbarch method. */
+/* Implement the stack_frame_destroyed_p gdbarch method. */
static int
s390_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
struct value *
s390_trad_frame_prev_register (struct frame_info *this_frame,
- struct trad_frame_saved_reg saved_regs[],
+ trad_frame_saved_reg saved_regs[],
int regnum)
{
if (regnum < S390_NUM_REGS)
CORE_ADDR frame_base;
CORE_ADDR local_base;
- struct trad_frame_saved_reg *saved_regs;
+ trad_frame_saved_reg *saved_regs;
};
/* Unwind THIS_FRAME and write the information into unwind cache INFO using
/* Set up ABI call-saved/call-clobbered registers. */
for (i = 0; i < S390_NUM_REGS; i++)
if (!s390_register_call_saved (gdbarch, i))
- trad_frame_set_unknown (info->saved_regs, i);
+ info->saved_regs[i].set_unknown ();
/* CC is always call-clobbered. */
- trad_frame_set_unknown (info->saved_regs, S390_PSWM_REGNUM);
+ info->saved_regs[S390_PSWM_REGNUM].set_unknown ();
/* Record the addresses of all register spill slots the prologue parser
has recognized. Consider only registers defined as call-saved by the
for (i = 0; i < 16; i++)
if (s390_register_call_saved (gdbarch, S390_R0_REGNUM + i)
&& data.gpr_slot[i] != 0)
- info->saved_regs[S390_R0_REGNUM + i].addr = cfa - data.gpr_slot[i];
+ info->saved_regs[S390_R0_REGNUM + i].set_addr (cfa - data.gpr_slot[i]);
for (i = 0; i < 16; i++)
if (s390_register_call_saved (gdbarch, S390_F0_REGNUM + i)
&& data.fpr_slot[i] != 0)
- info->saved_regs[S390_F0_REGNUM + i].addr = cfa - data.fpr_slot[i];
+ info->saved_regs[S390_F0_REGNUM + i].set_addr (cfa - data.fpr_slot[i]);
/* Function return will set PC to %r14. */
info->saved_regs[S390_PSWA_REGNUM] = info->saved_regs[S390_RETADDR_REGNUM];
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, S390_PSWA_REGNUM))
+ && !info->saved_regs[S390_PSWA_REGNUM].is_addr ())
{
- info->saved_regs[S390_PSWA_REGNUM].realreg = S390_RETADDR_REGNUM;
+ info->saved_regs[S390_PSWA_REGNUM].set_realreg (S390_RETADDR_REGNUM);
}
/* Another sanity check: unless this is a frameless function,
libc's thread_start routine. */
if (size > 0)
{
- if (!trad_frame_addr_p (info->saved_regs, S390_SP_REGNUM)
- || !trad_frame_addr_p (info->saved_regs, S390_PSWA_REGNUM))
+ if (!info->saved_regs[S390_SP_REGNUM].is_addr ()
+ || !info->saved_regs[S390_PSWA_REGNUM].is_addr ())
prev_sp = -1;
}
/* Set up ABI call-saved/call-clobbered registers. */
for (i = 0; i < S390_NUM_REGS; i++)
if (!s390_register_call_saved (gdbarch, i))
- trad_frame_set_unknown (info->saved_regs, i);
+ info->saved_regs[i].set_unknown ();
/* CC is always call-clobbered. */
- trad_frame_set_unknown (info->saved_regs, S390_PSWM_REGNUM);
+ info->saved_regs[S390_PSWM_REGNUM].set_unknown ();
/* Get the backchain. */
reg = get_frame_register_unsigned (this_frame, S390_SP_REGNUM);
/* We don't know which registers were saved, but it will have
to be at least %r14 and %r15. This will allow us to continue
unwinding, but other prev-frame registers may be incorrect ... */
- info->saved_regs[S390_SP_REGNUM].addr = backchain + 15*word_size;
- info->saved_regs[S390_RETADDR_REGNUM].addr = backchain + 14*word_size;
+ info->saved_regs[S390_SP_REGNUM].set_addr (backchain + 15*word_size);
+ info->saved_regs[S390_RETADDR_REGNUM].set_addr (backchain + 14*word_size);
/* Function return will set PC to %r14. */
info->saved_regs[S390_PSWA_REGNUM]
struct s390_stub_unwind_cache
{
CORE_ADDR frame_base;
- struct trad_frame_saved_reg *saved_regs;
+ trad_frame_saved_reg *saved_regs;
};
/* Unwind THIS_FRAME and return the corresponding unwind cache for
info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
/* The return address is in register %r14. */
- info->saved_regs[S390_PSWA_REGNUM].realreg = S390_RETADDR_REGNUM;
+ info->saved_regs[S390_PSWA_REGNUM].set_realreg (S390_RETADDR_REGNUM);
/* Retrieve stack pointer and determine our frame base. */
reg = get_frame_register_unsigned (this_frame, S390_SP_REGNUM);
case 0xe383: /* MSGC - multiply single 64x64mem -> 64 */
case 0xe398: /* ALC - add logical with carry */
case 0xe399: /* SLB - subtract logical with borrow */
- case 0xe727: /* LCBB - load count to block bounduary */
+ case 0xe727: /* LCBB - load count to block boundary */
case 0xeb81: /* ICMY - insert characters under mask */
case 0xebdc: /* SRAK - shift left single */
case 0xebdd: /* SLAK - shift left single */
case 0xe325: /* NTSTG - nontransactional store */
case 0xe326: /* CVDY - convert to decimal */
case 0xe32f: /* STRVG - store reversed */
- case 0xebe3: /* STOCG - store on condition */
case 0xed67: /* STDY - store */
oaddr = s390_record_calc_disp (gdbarch, regcache, inib[3], insn[1], ibyte[4]);
if (record_full_arch_list_add_mem (oaddr, 8))
case 0xe33e: /* STRV - store reversed */
case 0xe350: /* STY - store */
case 0xe3cb: /* STFH - store high */
- case 0xebe1: /* STOCFH - store high on condition */
- case 0xebf3: /* STOC - store on condition */
case 0xed66: /* STEY - store */
oaddr = s390_record_calc_disp (gdbarch, regcache, inib[3], insn[1], ibyte[4]);
if (record_full_arch_list_add_mem (oaddr, 4))
case 0xe704: /* VLLEZ - vector load logical element and zero */
case 0xe705: /* VLREP - vector load and replicate */
case 0xe706: /* VL - vector load */
- case 0xe707: /* VLBB - vector load to block bounduary */
+ case 0xe707: /* VLBB - vector load to block boundary */
case 0xe712: /* VGEG - vector gather element */
case 0xe713: /* VGEF - vector gather element */
case 0xe722: /* VLVG - vector load vr element from gr */
/* 0xeb9c-0xebbf undefined */
/* 0xebc1-0xebdb undefined */
+
+ case 0xebe1: /* STOCFH - store high on condition */
+ case 0xebf3: /* STOC - store on condition */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], ibyte[4]);
+ if (record_full_arch_list_add_mem (oaddr, 4))
+ return -1;
+ break;
+
+ case 0xebe3: /* STOCG - store on condition */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], ibyte[4]);
+ if (record_full_arch_list_add_mem (oaddr, 8))
+ return -1;
+ break;
+
/* 0xebe5 undefined */
/* 0xebe9 undefined */
/* 0xebeb-0xebf1 undefined */
return -1;
break;
- /* 0xed42-0xed47 undefind */
+ /* 0xed42-0xed47 undefined */
case 0xed48: /* SLXT - shift significand left */
case 0xed49: /* SRXT - shift significand right */
return -1;
break;
- /* 0xed4a-0xed4f undefind */
- /* 0xed52-0xed53 undefind */
- /* 0xed56-0xed57 undefind */
- /* 0xed5a-0xed63 undefind */
+ /* 0xed4a-0xed4f undefined */
+ /* 0xed52-0xed53 undefined */
+ /* 0xed56-0xed57 undefined */
+ /* 0xed5a-0xed63 undefined */
/* 0xed68-0xeda7 undefined */
case 0xeda8: /* CZDT - convert to zoned */
struct gdbarch_tdep *tdep = s390_gdbarch_tdep_alloc ();
struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
- struct tdesc_arch_data *tdesc_data = tdesc_data_alloc ();
- info.tdesc_data = tdesc_data;
+ tdesc_arch_data_up tdesc_data = tdesc_data_alloc ();
+ info.tdesc_data = tdesc_data.get ();
set_gdbarch_believe_pcc_promotion (gdbarch, 0);
set_gdbarch_char_signed (gdbarch, 0);
set_gdbarch_displaced_step_copy_insn (gdbarch,
s390_displaced_step_copy_insn);
set_gdbarch_displaced_step_fixup (gdbarch, s390_displaced_step_fixup);
- set_gdbarch_displaced_step_location (gdbarch, linux_displaced_step_location);
+ set_gdbarch_displaced_step_prepare (gdbarch, linux_displaced_step_prepare);
+ set_gdbarch_displaced_step_finish (gdbarch, linux_displaced_step_finish);
+ set_gdbarch_displaced_step_restore_all_in_ptid
+ (gdbarch, linux_displaced_step_restore_all_in_ptid);
set_gdbarch_displaced_step_hw_singlestep (gdbarch, s390_displaced_step_hw_singlestep);
set_gdbarch_software_single_step (gdbarch, s390_software_single_step);
set_gdbarch_max_insn_length (gdbarch, S390_MAX_INSTR_SIZE);
cause GDB to crash with an internal error when the user tries to set
an unsupported OSABI. */
if (!tdesc_has_registers (tdesc))
- {
- if (info.bfd_arch_info->mach == bfd_mach_s390_31)
- tdesc = tdesc_s390_linux32;
- else
- tdesc = tdesc_s390x_linux64;
- }
+ {
+ if (info.bfd_arch_info->mach == bfd_mach_s390_31)
+ tdesc = tdesc_s390_linux32;
+ else
+ tdesc = tdesc_s390x_linux64;
+ }
tdep->tdesc = tdesc;
/* Check any target description for validity. */
- if (!s390_tdesc_valid (tdep, tdesc_data))
+ if (!s390_tdesc_valid (tdep, tdesc_data.get ()))
{
- tdesc_data_cleanup (tdesc_data);
xfree (tdep);
gdbarch_free (gdbarch);
return NULL;
if (tmp->vector_abi != tdep->vector_abi)
continue;
- tdesc_data_cleanup (tdesc_data);
xfree (tdep);
gdbarch_free (gdbarch);
return arches->gdbarch;
}
- tdesc_use_registers (gdbarch, tdep->tdesc, tdesc_data);
+ tdesc_use_registers (gdbarch, tdep->tdesc, std::move (tdesc_data));
set_gdbarch_register_name (gdbarch, s390_register_name);
/* Assign pseudo register numbers. */
return gdbarch;
}
+void _initialize_s390_tdep ();
void
-_initialize_s390_tdep (void)
+_initialize_s390_tdep ()
{
/* Hook us into the gdbarch mechanism. */
register_gdbarch_init (bfd_arch_s390, s390_gdbarch_init);