X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fs390-linux-tdep.c;h=a0d4cdd7406c83ad5a081989cee57cc3fbb15fee;hb=afa0a4115985939f242bcd54211c98345eefe16b;hp=a6882fbbf4b4a0e7086b6a0ab0528d3f9041305c;hpb=481695ed5f6e0a8a9c9c50bfac1cdd2b3151e6c9;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c index a6882fbbf4..a0d4cdd740 100644 --- a/gdb/s390-linux-tdep.c +++ b/gdb/s390-linux-tdep.c @@ -30,7 +30,6 @@ #include "gdbcore.h" #include "gdbcmd.h" #include "objfiles.h" -#include "floatformat.h" #include "regcache.h" #include "trad-frame.h" #include "frame-base.h" @@ -69,12 +68,14 @@ #include "features/s390-te-linux64.c" #include "features/s390-vx-linux64.c" #include "features/s390-tevx-linux64.c" +#include "features/s390-gs-linux64.c" #include "features/s390x-linux64.c" #include "features/s390x-linux64v1.c" #include "features/s390x-linux64v2.c" #include "features/s390x-te-linux64.c" #include "features/s390x-vx-linux64.c" #include "features/s390x-tevx-linux64.c" +#include "features/s390x-gs-linux64.c" #define XML_SYSCALL_FILENAME_S390 "syscalls/s390-linux.xml" #define XML_SYSCALL_FILENAME_S390X "syscalls/s390x-linux.xml" @@ -113,6 +114,7 @@ struct gdbarch_tdep int have_linux_v1; int have_linux_v2; int have_tdb; + bool have_gs; }; @@ -155,7 +157,7 @@ s390_cannot_store_register (struct gdbarch *gdbarch, int regnum) static void s390_write_pc (struct regcache *regcache, CORE_ADDR pc) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); regcache_cooked_write_unsigned (regcache, tdep->pc_regnum, pc); @@ -728,7 +730,7 @@ s390_is_partial_instruction (struct gdbarch *gdbarch, CORE_ADDR loc, int *len) static std::vector s390_software_single_step (struct regcache *regcache) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); CORE_ADDR loc = regcache_read_pc (regcache); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int len; @@ -834,6 +836,24 @@ static const struct regcache_map_entry s390_regmap_vxrs_high[] = { 0 } }; +static const struct regcache_map_entry s390_regmap_gs[] = + { + { 1, REGCACHE_MAP_SKIP, 8 }, + { 1, S390_GSD_REGNUM, 8 }, + { 1, S390_GSSM_REGNUM, 8 }, + { 1, S390_GSEPLA_REGNUM, 8 }, + { 0 } + }; + +static const struct regcache_map_entry s390_regmap_gsbc[] = + { + { 1, REGCACHE_MAP_SKIP, 8 }, + { 1, S390_BC_GSD_REGNUM, 8 }, + { 1, S390_BC_GSSM_REGNUM, 8 }, + { 1, S390_BC_GSEPLA_REGNUM, 8 }, + { 0 } + }; + /* Supply the TDB regset. Like regcache_supply_regset, but invalidate the TDB registers unless the TDB format field is valid. */ @@ -905,6 +925,18 @@ const struct regset s390_vxrs_high_regset = { regcache_collect_regset }; +const struct regset s390_gs_regset = { + s390_regmap_gs, + regcache_supply_regset, + regcache_collect_regset +}; + +const struct regset s390_gsbc_regset = { + s390_regmap_gsbc, + regcache_supply_regset, + regcache_collect_regset +}; + /* Iterate over supported core file register note sections. */ static void @@ -951,6 +983,23 @@ s390_iterate_over_regset_sections (struct gdbarch *gdbarch, cb (".reg-s390-vxrs-high", 16 * 16, &s390_vxrs_high_regset, "s390 vector registers 16-31", cb_data); } + + /* Iterate over the guarded-storage regsets if in "read" mode, or if + their registers are available. */ + if (tdep->have_gs) + { + if (regcache == NULL + || REG_VALID == regcache_register_status (regcache, + S390_GSD_REGNUM)) + cb (".reg-s390-gs-cb", 4 * 8, &s390_gs_regset, + "s390 guarded-storage registers", cb_data); + + if (regcache == NULL + || REG_VALID == regcache_register_status (regcache, + S390_BC_GSD_REGNUM)) + cb (".reg-s390-gs-bc", 4 * 8, &s390_gsbc_regset, + "s390 guarded-storage broadcast control", cb_data); + } } static const struct target_desc * @@ -959,7 +1008,7 @@ s390_core_read_description (struct gdbarch *gdbarch, { asection *section = bfd_get_section_by_name (abfd, ".reg"); CORE_ADDR hwcap = 0; - int high_gprs, v1, v2, te, vx; + bool high_gprs, v1, v2, te, vx, gs; target_auxv_search (target, AT_HWCAP, &hwcap); if (!section) @@ -971,12 +1020,14 @@ s390_core_read_description (struct gdbarch *gdbarch, v2 = (bfd_get_section_by_name (abfd, ".reg-s390-system-call") != NULL); vx = (hwcap & HWCAP_S390_VX); te = (hwcap & HWCAP_S390_TE); + gs = (hwcap & HWCAP_S390_GS); switch (bfd_section_size (abfd, section)) { case s390_sizeof_gregset: if (high_gprs) - return (te && vx ? tdesc_s390_tevx_linux64 : + return (gs ? tdesc_s390_gs_linux64 : + te && vx ? tdesc_s390_tevx_linux64 : vx ? tdesc_s390_vx_linux64 : te ? tdesc_s390_te_linux64 : v2 ? tdesc_s390_linux64v2 : @@ -986,7 +1037,8 @@ s390_core_read_description (struct gdbarch *gdbarch, v1 ? tdesc_s390_linux32v1 : tdesc_s390_linux32); case s390x_sizeof_gregset: - return (te && vx ? tdesc_s390x_tevx_linux64 : + return (gs ? tdesc_s390x_gs_linux64 : + te && vx ? tdesc_s390x_tevx_linux64 : vx ? tdesc_s390x_vx_linux64 : te ? tdesc_s390x_te_linux64 : v2 ? tdesc_s390x_linux64v2 : @@ -1323,8 +1375,8 @@ s390_store (struct s390_prologue_data *data, /* Check whether we are storing a register into the stack. */ - if (!pv_area_store_would_trash (data->stack, addr)) - pv_area_store (data->stack, addr, size, value); + if (!data->stack->store_would_trash (addr)) + data->stack->store (addr, size, value); /* Note: If this is some store we cannot identify, you might think we @@ -1361,11 +1413,11 @@ s390_load (struct s390_prologue_data *data, } /* Check whether we are accessing one of our save slots. */ - return pv_area_fetch (data->stack, addr, size); + return data->stack->fetch (addr, size); } /* Function for finding saved registers in a 'struct pv_area'; we pass - this to pv_area_scan. + this to pv_area::scan. If VALUE is a saved register, ADDR says it was saved at a constant offset from the frame base, and SIZE indicates that the whole @@ -1434,12 +1486,13 @@ s390_analyze_prologue (struct gdbarch *gdbarch, /* The address of the next instruction after that. */ CORE_ADDR next_pc; + pv_area stack (S390_SP_REGNUM, gdbarch_addr_bit (gdbarch)); + scoped_restore restore_stack = make_scoped_restore (&data->stack, &stack); + /* Set up everything's initial value. */ { int i; - data->stack = make_pv_area (S390_SP_REGNUM, gdbarch_addr_bit (gdbarch)); - /* For the purpose of prologue tracking, we consider the GPR size to be equal to the ABI word size, even if it is actually larger (i.e. when running a 32-bit binary under a 64-bit kernel). */ @@ -1678,10 +1731,7 @@ s390_analyze_prologue (struct gdbarch *gdbarch, } /* Record where all the registers were saved. */ - pv_area_scan (data->stack, s390_check_for_saved, data); - - free_pv_area (data->stack); - data->stack = NULL; + data->stack->scan (s390_check_for_saved, data); return result; } @@ -1811,6 +1861,8 @@ is_non_branch_ril (gdb_byte *insn) return 0; } +typedef buf_displaced_step_closure s390_displaced_step_closure; + /* Implementation of gdbarch_displaced_step_copy_insn. */ static struct displaced_step_closure * @@ -1819,8 +1871,9 @@ s390_displaced_step_copy_insn (struct gdbarch *gdbarch, struct regcache *regs) { size_t len = gdbarch_max_insn_length (gdbarch); - gdb_byte *buf = (gdb_byte *) xmalloc (len); - struct cleanup *old_chain = make_cleanup (xfree, buf); + std::unique_ptr closure + (new s390_displaced_step_closure (len)); + gdb_byte *buf = closure->buf.data (); read_memory (from, buf, len); @@ -1848,7 +1901,7 @@ s390_displaced_step_copy_insn (struct gdbarch *gdbarch, "RIL instruction: offset %s out of range\n", plongest (offset)); } - do_cleanups (old_chain); + return NULL; } @@ -1864,20 +1917,21 @@ s390_displaced_step_copy_insn (struct gdbarch *gdbarch, displaced_step_dump_bytes (gdb_stdlog, buf, len); } - discard_cleanups (old_chain); - return (struct displaced_step_closure *) buf; + return closure.release (); } /* Fix up the state of registers and memory after having single-stepped a displaced instruction. */ static void s390_displaced_step_fixup (struct gdbarch *gdbarch, - struct displaced_step_closure *closure, + struct displaced_step_closure *closure_, CORE_ADDR from, CORE_ADDR to, struct regcache *regs) { /* Our closure is a copy of the instruction. */ - gdb_byte *insn = (gdb_byte *) closure; + s390_displaced_step_closure *closure + = (s390_displaced_step_closure *) closure_; + gdb_byte *insn = closure->buf.data (); static int s390_instrlen[] = { 2, 4, 4, 6 }; int insnlen = s390_instrlen[insn[0] >> 6]; @@ -2643,7 +2697,7 @@ static struct linux_record_tdep s390x_linux_record_tdep; static int s390_all_but_pc_registers_record (struct regcache *regcache) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int i; @@ -2845,7 +2899,7 @@ s390_canonicalize_syscall (int syscall, enum s390_abi_kind abi) static int s390_linux_syscall_record (struct regcache *regcache, LONGEST syscall_native) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int ret; enum gdb_syscall syscall_gdb; @@ -7767,6 +7821,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) int have_linux_v2 = 0; int have_tdb = 0; int have_vx = 0; + int have_gs = 0; int first_pseudo_reg, last_pseudo_reg; static const char *const stap_register_prefixes[] = { "%", NULL }; static const char *const stap_register_indirection_prefixes[] = { "(", @@ -7834,6 +7889,12 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", }; + static const char *const gs_cb[] = { + "gsd", "gssm", "gsepla", + }; + static const char *const gs_bc[] = { + "bc_gsd", "bc_gssm", "bc_gsepla", + }; const struct tdesc_feature *feature; int i, valid_p = 1; @@ -7937,6 +7998,29 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) have_vx = 1; } + /* Guarded-storage registers. */ + feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.gs"); + if (feature) + { + for (i = 0; i < 3; i++) + valid_p &= tdesc_numbered_register (feature, tdesc_data, + S390_GSD_REGNUM + i, + gs_cb[i]); + have_gs = 1; + } + + /* Guarded-storage broadcast control. */ + feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.gsbc"); + if (feature) + { + valid_p &= have_gs; + + for (i = 0; i < 3; i++) + valid_p &= tdesc_numbered_register (feature, tdesc_data, + S390_BC_GSD_REGNUM + i, + gs_bc[i]); + } + if (!valid_p) { tdesc_data_cleanup (tdesc_data); @@ -7970,6 +8054,8 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) continue; if ((tdep->gpr_full_regnum != -1) != have_upper) continue; + if (tdep->have_gs != have_gs) + continue; if (tdesc_data != NULL) tdesc_data_cleanup (tdesc_data); return arches->gdbarch; @@ -7982,6 +8068,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->have_linux_v1 = have_linux_v1; tdep->have_linux_v2 = have_linux_v2; tdep->have_tdb = have_tdb; + tdep->have_gs = have_gs; gdbarch = gdbarch_alloc (&info, tdep); set_gdbarch_believe_pcc_promotion (gdbarch, 0); @@ -8157,10 +8244,12 @@ _initialize_s390_tdep (void) initialize_tdesc_s390_te_linux64 (); initialize_tdesc_s390_vx_linux64 (); initialize_tdesc_s390_tevx_linux64 (); + initialize_tdesc_s390_gs_linux64 (); initialize_tdesc_s390x_linux64 (); initialize_tdesc_s390x_linux64v1 (); initialize_tdesc_s390x_linux64v2 (); initialize_tdesc_s390x_te_linux64 (); initialize_tdesc_s390x_vx_linux64 (); initialize_tdesc_s390x_tevx_linux64 (); + initialize_tdesc_s390x_gs_linux64 (); }