X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fs390-tdep.c;h=c7b1d7e3947cf7c1e1039992e82cf1480266ca2a;hb=0542c86dbbe17befae1ab88c8a18296d89388bb5;hp=4018ad18de5bb83d755b010f497dcb4fde56ad26;hpb=ee1b3323e66265153132e886875197c10294ff32;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c index 4018ad18de..c7b1d7e394 100644 --- a/gdb/s390-tdep.c +++ b/gdb/s390-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for GDB, the GNU debugger. - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) @@ -10,7 +10,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -19,9 +19,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ #include "defs.h" #include "arch-utils.h" @@ -65,97 +63,54 @@ struct gdbarch_tdep }; -/* Register information. */ - -struct s390_register_info -{ - char *name; - struct type **type; -}; - -static struct s390_register_info s390_register_info[S390_NUM_TOTAL_REGS] = -{ - /* Program Status Word. */ - { "pswm", &builtin_type_long }, - { "pswa", &builtin_type_long }, - - /* General Purpose Registers. */ - { "r0", &builtin_type_long }, - { "r1", &builtin_type_long }, - { "r2", &builtin_type_long }, - { "r3", &builtin_type_long }, - { "r4", &builtin_type_long }, - { "r5", &builtin_type_long }, - { "r6", &builtin_type_long }, - { "r7", &builtin_type_long }, - { "r8", &builtin_type_long }, - { "r9", &builtin_type_long }, - { "r10", &builtin_type_long }, - { "r11", &builtin_type_long }, - { "r12", &builtin_type_long }, - { "r13", &builtin_type_long }, - { "r14", &builtin_type_long }, - { "r15", &builtin_type_long }, - - /* Access Registers. */ - { "acr0", &builtin_type_int }, - { "acr1", &builtin_type_int }, - { "acr2", &builtin_type_int }, - { "acr3", &builtin_type_int }, - { "acr4", &builtin_type_int }, - { "acr5", &builtin_type_int }, - { "acr6", &builtin_type_int }, - { "acr7", &builtin_type_int }, - { "acr8", &builtin_type_int }, - { "acr9", &builtin_type_int }, - { "acr10", &builtin_type_int }, - { "acr11", &builtin_type_int }, - { "acr12", &builtin_type_int }, - { "acr13", &builtin_type_int }, - { "acr14", &builtin_type_int }, - { "acr15", &builtin_type_int }, - - /* Floating Point Control Word. */ - { "fpc", &builtin_type_int }, - - /* Floating Point Registers. */ - { "f0", &builtin_type_double }, - { "f1", &builtin_type_double }, - { "f2", &builtin_type_double }, - { "f3", &builtin_type_double }, - { "f4", &builtin_type_double }, - { "f5", &builtin_type_double }, - { "f6", &builtin_type_double }, - { "f7", &builtin_type_double }, - { "f8", &builtin_type_double }, - { "f9", &builtin_type_double }, - { "f10", &builtin_type_double }, - { "f11", &builtin_type_double }, - { "f12", &builtin_type_double }, - { "f13", &builtin_type_double }, - { "f14", &builtin_type_double }, - { "f15", &builtin_type_double }, - - /* Pseudo registers. */ - { "pc", &builtin_type_void_func_ptr }, - { "cc", &builtin_type_int }, -}; - /* Return the name of register REGNUM. */ static const char * -s390_register_name (int regnum) +s390_register_name (struct gdbarch *gdbarch, int regnum) { + static const char *register_names[S390_NUM_TOTAL_REGS] = + { + /* Program Status Word. */ + "pswm", "pswa", + /* General Purpose Registers. */ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + /* Access Registers. */ + "acr0", "acr1", "acr2", "acr3", "acr4", "acr5", "acr6", "acr7", + "acr8", "acr9", "acr10", "acr11", "acr12", "acr13", "acr14", "acr15", + /* Floating Point Control Word. */ + "fpc", + /* Floating Point Registers. */ + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", + /* Pseudo registers. */ + "pc", "cc", + }; + gdb_assert (regnum >= 0 && regnum < S390_NUM_TOTAL_REGS); - return s390_register_info[regnum].name; + return register_names[regnum]; } /* Return the GDB type object for the "standard" data type of data in - register REGNUM. */ + register REGNUM. */ static struct type * s390_register_type (struct gdbarch *gdbarch, int regnum) { - gdb_assert (regnum >= 0 && regnum < S390_NUM_TOTAL_REGS); - return *s390_register_info[regnum].type; + if (regnum == S390_PSWM_REGNUM || regnum == S390_PSWA_REGNUM) + return builtin_type (gdbarch)->builtin_long; + if (regnum >= S390_R0_REGNUM && regnum <= S390_R15_REGNUM) + return builtin_type (gdbarch)->builtin_long; + if (regnum >= S390_A0_REGNUM && regnum <= S390_A15_REGNUM) + return builtin_type (gdbarch)->builtin_int; + if (regnum == S390_FPC_REGNUM) + return builtin_type (gdbarch)->builtin_int; + if (regnum >= S390_F0_REGNUM && regnum <= S390_F15_REGNUM) + return builtin_type (gdbarch)->builtin_double; + if (regnum == S390_PC_REGNUM) + return builtin_type (gdbarch)->builtin_func_ptr; + if (regnum == S390_CC_REGNUM) + return builtin_type (gdbarch)->builtin_int; + + internal_error (__FILE__, __LINE__, _("invalid regnum")); } /* DWARF Register Mapping. */ @@ -192,7 +147,7 @@ static int s390_dwarf_regmap[] = /* Convert DWARF register number REG to the appropriate register number used by GDB. */ static int -s390_dwarf_reg_to_regnum (int reg) +s390_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) { int regnum = -1; @@ -306,36 +261,17 @@ s390x_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, /* 'float' values are stored in the upper half of floating-point registers, even though we are otherwise a big-endian platform. */ -static int -s390_convert_register_p (int regno, struct type *type) +static struct value * +s390_value_from_register (struct type *type, int regnum, + struct frame_info *frame) { - return (regno >= S390_F0_REGNUM && regno <= S390_F15_REGNUM) - && TYPE_LENGTH (type) < 8; -} - -static void -s390_register_to_value (struct frame_info *frame, int regnum, - struct type *valtype, gdb_byte *out) -{ - gdb_byte in[8]; - int len = TYPE_LENGTH (valtype); - gdb_assert (len < 8); - - get_frame_register (frame, regnum, in); - memcpy (out, in, len); -} + struct value *value = default_value_from_register (type, regnum, frame); + int len = TYPE_LENGTH (type); -static void -s390_value_to_register (struct frame_info *frame, int regnum, - struct type *valtype, const gdb_byte *in) -{ - gdb_byte out[8]; - int len = TYPE_LENGTH (valtype); - gdb_assert (len < 8); + if (regnum >= S390_F0_REGNUM && regnum <= S390_F15_REGNUM && len < 8) + set_value_offset (value, 0); - memset (out, 0, 8); - memcpy (out, in, len); - put_frame_register (frame, regnum, out); + return value; } /* Register groups. */ @@ -444,33 +380,55 @@ s390_supply_regset (const struct regset *regset, struct regcache *regcache, } } +/* Collect register REGNUM from the register cache REGCACHE and store + it in the buffer specified by REGS and LEN as described by the + general-purpose register set REGSET. If REGNUM is -1, do this for + all registers in REGSET. */ +static void +s390_collect_regset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *regs, size_t len) +{ + const int *offset = regset->descr; + int i; + + for (i = 0; i < S390_NUM_REGS; i++) + { + if ((regnum == i || regnum == -1) && offset[i] != -1) + regcache_raw_collect (regcache, i, (char *)regs + offset[i]); + } +} + static const struct regset s390_gregset = { s390_regmap_gregset, - s390_supply_regset + s390_supply_regset, + s390_collect_regset }; static const struct regset s390x_gregset = { s390x_regmap_gregset, - s390_supply_regset + s390_supply_regset, + s390_collect_regset }; static const struct regset s390_fpregset = { s390_regmap_fpregset, - s390_supply_regset + s390_supply_regset, + s390_collect_regset }; /* Return the appropriate register set for the core section identified by SECT_NAME and SECT_SIZE. */ -const struct regset * +static const struct regset * s390_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name, size_t sect_size) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - if (strcmp (sect_name, ".reg") == 0 && sect_size == tdep->sizeof_gregset) + if (strcmp (sect_name, ".reg") == 0 && sect_size >= tdep->sizeof_gregset) return tdep->gregset; - if (strcmp (sect_name, ".reg2") == 0 && sect_size == tdep->sizeof_fpregset) + if (strcmp (sect_name, ".reg2") == 0 && sect_size >= tdep->sizeof_fpregset) return tdep->fpregset; return NULL; @@ -545,12 +503,12 @@ s390_readinstruction (bfd_byte instr[], CORE_ADDR at) static int s390_instrlen[] = { 2, 4, 4, 6 }; int instrlen; - if (deprecated_read_memory_nobpt (at, &instr[0], 2)) + if (target_read_memory (at, &instr[0], 2)) return -1; instrlen = s390_instrlen[instr[0] >> 6]; if (instrlen > 2) { - if (deprecated_read_memory_nobpt (at + 2, &instr[2], instrlen - 2)) + if (target_read_memory (at + 2, &instr[2], instrlen - 2)) return -1; } return instrlen; @@ -814,7 +772,7 @@ s390_load (struct s390_prologue_data *data, we're analyzing the code to unwind past that frame. */ if (pv_is_constant (addr)) { - struct section_table *secp; + struct target_section *secp; secp = target_section_by_addr (¤t_target, addr.k); if (secp != NULL && (bfd_get_section_flags (secp->bfd, secp->the_bfd_section) @@ -1135,11 +1093,11 @@ s390_analyze_prologue (struct gdbarch *gdbarch, /* Advance PC across any function entry prologue instructions to reach some "real" code. */ static CORE_ADDR -s390_skip_prologue (CORE_ADDR pc) +s390_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { struct s390_prologue_data data; CORE_ADDR skip_pc; - skip_pc = s390_analyze_prologue (current_gdbarch, pc, (CORE_ADDR)-1, &data); + skip_pc = s390_analyze_prologue (gdbarch, pc, (CORE_ADDR)-1, &data); return skip_pc ? skip_pc : pc; } @@ -1174,19 +1132,19 @@ s390_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) int d2; if (word_size == 4 - && !deprecated_read_memory_nobpt (pc - 4, insn, 4) + && !target_read_memory (pc - 4, insn, 4) && is_rs (insn, op_lm, &r1, &r3, &d2, &b2) && r3 == S390_SP_REGNUM - S390_R0_REGNUM) return 1; if (word_size == 4 - && !deprecated_read_memory_nobpt (pc - 6, insn, 6) + && !target_read_memory (pc - 6, insn, 6) && is_rsy (insn, op1_lmy, op2_lmy, &r1, &r3, &d2, &b2) && r3 == S390_SP_REGNUM - S390_R0_REGNUM) return 1; if (word_size == 8 - && !deprecated_read_memory_nobpt (pc - 6, insn, 6) + && !target_read_memory (pc - 6, insn, 6) && is_rsy (insn, op1_lmg, op2_lmg, &r1, &r3, &d2, &b2) && r3 == S390_SP_REGNUM - S390_R0_REGNUM) return 1; @@ -1207,10 +1165,10 @@ struct s390_unwind_cache { }; static int -s390_prologue_frame_unwind_cache (struct frame_info *next_frame, +s390_prologue_frame_unwind_cache (struct frame_info *this_frame, struct s390_unwind_cache *info) { - struct gdbarch *gdbarch = get_frame_arch (next_frame); + 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; @@ -1229,13 +1187,13 @@ s390_prologue_frame_unwind_cache (struct frame_info *next_frame, bother searching for it -- with modern compilers this would be mostly pointless anyway. Trust that we'll either have valid DWARF-2 CFI data or else a valid backchain ... */ - func = frame_func_unwind (next_frame); + func = get_frame_func (this_frame); if (!func) return 0; /* Try to analyze the prologue. */ result = s390_analyze_prologue (gdbarch, func, - frame_pc_unwind (next_frame), &data); + get_frame_pc (this_frame), &data); if (!result) return 0; @@ -1257,12 +1215,13 @@ s390_prologue_frame_unwind_cache (struct frame_info *next_frame, /* FIXME: cagney/2004-05-01: This sanity check shouldn't be needed, instead the code should simpliy rely on its analysis. */ - if (get_frame_type (next_frame) == NORMAL_FRAME) + if (get_next_frame (this_frame) + && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME) return 0; /* If we really have a frameless function, %r14 must be valid -- in particular, it must point to a different function. */ - reg = frame_unwind_register_unsigned (next_frame, S390_RETADDR_REGNUM); + reg = get_frame_register_unsigned (this_frame, S390_RETADDR_REGNUM); reg = gdbarch_addr_bits_remove (gdbarch, reg) - 1; if (get_pc_function_start (reg) == func) { @@ -1302,11 +1261,13 @@ s390_prologue_frame_unwind_cache (struct frame_info *next_frame, This can only happen in an innermost frame. */ /* FIXME: cagney/2004-05-01: This sanity check shouldn't be needed, instead the code should simpliy rely on its analysis. */ - if (size > 0 && get_frame_type (next_frame) != NORMAL_FRAME) + if (size > 0 + && (!get_next_frame (this_frame) + || get_frame_type (get_next_frame (this_frame)) != NORMAL_FRAME)) { /* See the comment in s390_in_function_epilogue_p on why this is not completely reliable ... */ - if (s390_in_function_epilogue_p (gdbarch, frame_pc_unwind (next_frame))) + if (s390_in_function_epilogue_p (gdbarch, get_frame_pc (this_frame))) { memset (&data, 0, sizeof (data)); size = 0; @@ -1318,7 +1279,7 @@ s390_prologue_frame_unwind_cache (struct frame_info *next_frame, the current value of the frame register from the next frame, and add back the frame size to arrive that the previous frame's stack pointer value. */ - prev_sp = frame_unwind_register_unsigned (next_frame, frame_pointer) + size; + prev_sp = get_frame_register_unsigned (this_frame, frame_pointer) + size; cfa = prev_sp + 16*word_size + 32; /* Record the addresses of all register spill slots the prologue parser @@ -1383,17 +1344,17 @@ s390_prologue_frame_unwind_cache (struct frame_info *next_frame, } static void -s390_backchain_frame_unwind_cache (struct frame_info *next_frame, +s390_backchain_frame_unwind_cache (struct frame_info *this_frame, struct s390_unwind_cache *info) { - struct gdbarch *gdbarch = get_frame_arch (next_frame); + struct gdbarch *gdbarch = get_frame_arch (this_frame); int word_size = gdbarch_ptr_bit (gdbarch) / 8; CORE_ADDR backchain; ULONGEST reg; LONGEST sp; /* Get the backchain. */ - reg = frame_unwind_register_unsigned (next_frame, S390_SP_REGNUM); + reg = get_frame_register_unsigned (this_frame, S390_SP_REGNUM); backchain = read_memory_unsigned_integer (reg, word_size); /* A zero backchain terminates the frame chain. As additional @@ -1419,11 +1380,11 @@ s390_backchain_frame_unwind_cache (struct frame_info *next_frame, info->local_base = reg; } - info->func = frame_pc_unwind (next_frame); + info->func = get_frame_pc (this_frame); } static struct s390_unwind_cache * -s390_frame_unwind_cache (struct frame_info *next_frame, +s390_frame_unwind_cache (struct frame_info *this_frame, void **this_prologue_cache) { struct s390_unwind_cache *info; @@ -1432,26 +1393,26 @@ s390_frame_unwind_cache (struct frame_info *next_frame, info = FRAME_OBSTACK_ZALLOC (struct s390_unwind_cache); *this_prologue_cache = info; - info->saved_regs = trad_frame_alloc_saved_regs (next_frame); + info->saved_regs = trad_frame_alloc_saved_regs (this_frame); info->func = -1; info->frame_base = -1; info->local_base = -1; /* Try to use prologue analysis to fill the unwind cache. If this fails, fall back to reading the stack backchain. */ - if (!s390_prologue_frame_unwind_cache (next_frame, info)) - s390_backchain_frame_unwind_cache (next_frame, info); + if (!s390_prologue_frame_unwind_cache (this_frame, info)) + s390_backchain_frame_unwind_cache (this_frame, info); return info; } static void -s390_frame_this_id (struct frame_info *next_frame, +s390_frame_this_id (struct frame_info *this_frame, void **this_prologue_cache, struct frame_id *this_id) { struct s390_unwind_cache *info - = s390_frame_unwind_cache (next_frame, this_prologue_cache); + = s390_frame_unwind_cache (this_frame, this_prologue_cache); if (info->frame_base == -1) return; @@ -1459,31 +1420,23 @@ s390_frame_this_id (struct frame_info *next_frame, *this_id = frame_id_build (info->frame_base, info->func); } -static void -s390_frame_prev_register (struct frame_info *next_frame, - void **this_prologue_cache, - int regnum, int *optimizedp, - enum lval_type *lvalp, CORE_ADDR *addrp, - int *realnump, gdb_byte *bufferp) +static struct value * +s390_frame_prev_register (struct frame_info *this_frame, + void **this_prologue_cache, int regnum) { struct s390_unwind_cache *info - = s390_frame_unwind_cache (next_frame, this_prologue_cache); - trad_frame_get_prev_register (next_frame, info->saved_regs, regnum, - optimizedp, lvalp, addrp, realnump, bufferp); + = s390_frame_unwind_cache (this_frame, this_prologue_cache); + return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum); } static const struct frame_unwind s390_frame_unwind = { NORMAL_FRAME, s390_frame_this_id, - s390_frame_prev_register + s390_frame_prev_register, + NULL, + default_frame_sniffer }; -static const struct frame_unwind * -s390_frame_sniffer (struct frame_info *next_frame) -{ - return &s390_frame_unwind; -} - /* Code stubs and their stack frames. For things like PLTs and NULL function calls (where there is no true frame and the return address @@ -1496,10 +1449,10 @@ struct s390_stub_unwind_cache }; static struct s390_stub_unwind_cache * -s390_stub_frame_unwind_cache (struct frame_info *next_frame, +s390_stub_frame_unwind_cache (struct frame_info *this_frame, void **this_prologue_cache) { - struct gdbarch *gdbarch = get_frame_arch (next_frame); + struct gdbarch *gdbarch = get_frame_arch (this_frame); int word_size = gdbarch_ptr_bit (gdbarch) / 8; struct s390_stub_unwind_cache *info; ULONGEST reg; @@ -1509,62 +1462,63 @@ s390_stub_frame_unwind_cache (struct frame_info *next_frame, info = FRAME_OBSTACK_ZALLOC (struct s390_stub_unwind_cache); *this_prologue_cache = info; - info->saved_regs = trad_frame_alloc_saved_regs (next_frame); + info->saved_regs = trad_frame_alloc_saved_regs (this_frame); /* The return address is in register %r14. */ info->saved_regs[S390_PC_REGNUM].realreg = S390_RETADDR_REGNUM; /* Retrieve stack pointer and determine our frame base. */ - reg = frame_unwind_register_unsigned (next_frame, S390_SP_REGNUM); + reg = get_frame_register_unsigned (this_frame, S390_SP_REGNUM); info->frame_base = reg + 16*word_size + 32; return info; } static void -s390_stub_frame_this_id (struct frame_info *next_frame, +s390_stub_frame_this_id (struct frame_info *this_frame, void **this_prologue_cache, struct frame_id *this_id) { struct s390_stub_unwind_cache *info - = s390_stub_frame_unwind_cache (next_frame, this_prologue_cache); - *this_id = frame_id_build (info->frame_base, frame_pc_unwind (next_frame)); + = s390_stub_frame_unwind_cache (this_frame, this_prologue_cache); + *this_id = frame_id_build (info->frame_base, get_frame_pc (this_frame)); } -static void -s390_stub_frame_prev_register (struct frame_info *next_frame, - void **this_prologue_cache, - int regnum, int *optimizedp, - enum lval_type *lvalp, CORE_ADDR *addrp, - int *realnump, gdb_byte *bufferp) +static struct value * +s390_stub_frame_prev_register (struct frame_info *this_frame, + void **this_prologue_cache, int regnum) { struct s390_stub_unwind_cache *info - = s390_stub_frame_unwind_cache (next_frame, this_prologue_cache); - trad_frame_get_prev_register (next_frame, info->saved_regs, regnum, - optimizedp, lvalp, addrp, realnump, bufferp); + = s390_stub_frame_unwind_cache (this_frame, this_prologue_cache); + return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum); } -static const struct frame_unwind s390_stub_frame_unwind = { - NORMAL_FRAME, - s390_stub_frame_this_id, - s390_stub_frame_prev_register -}; - -static const struct frame_unwind * -s390_stub_frame_sniffer (struct frame_info *next_frame) +static int +s390_stub_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_prologue_cache) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR addr_in_block; bfd_byte insn[S390_MAX_INSTR_SIZE]; /* If the current PC points to non-readable memory, we assume we have trapped due to an invalid function pointer call. We handle the non-existing current function like a PLT stub. */ - if (in_plt_section (pc, NULL) - || s390_readinstruction (insn, pc) < 0) - return &s390_stub_frame_unwind; - return NULL; + addr_in_block = get_frame_address_in_block (this_frame); + if (in_plt_section (addr_in_block, NULL) + || s390_readinstruction (insn, get_frame_pc (this_frame)) < 0) + return 1; + return 0; } +static const struct frame_unwind s390_stub_frame_unwind = { + NORMAL_FRAME, + s390_stub_frame_this_id, + s390_stub_frame_prev_register, + NULL, + s390_stub_frame_sniffer +}; + /* Signal trampoline stack frames. */ @@ -1574,10 +1528,10 @@ struct s390_sigtramp_unwind_cache { }; static struct s390_sigtramp_unwind_cache * -s390_sigtramp_frame_unwind_cache (struct frame_info *next_frame, +s390_sigtramp_frame_unwind_cache (struct frame_info *this_frame, void **this_prologue_cache) { - struct gdbarch *gdbarch = get_frame_arch (next_frame); + struct gdbarch *gdbarch = get_frame_arch (this_frame); int word_size = gdbarch_ptr_bit (gdbarch) / 8; struct s390_sigtramp_unwind_cache *info; ULONGEST this_sp, prev_sp; @@ -1589,10 +1543,10 @@ s390_sigtramp_frame_unwind_cache (struct frame_info *next_frame, info = FRAME_OBSTACK_ZALLOC (struct s390_sigtramp_unwind_cache); *this_prologue_cache = info; - info->saved_regs = trad_frame_alloc_saved_regs (next_frame); + info->saved_regs = trad_frame_alloc_saved_regs (this_frame); - this_sp = frame_unwind_register_unsigned (next_frame, S390_SP_REGNUM); - next_ra = frame_pc_unwind (next_frame); + this_sp = get_frame_register_unsigned (this_frame, S390_SP_REGNUM); + next_ra = get_frame_pc (this_frame); next_cfa = this_sp + 16*word_size + 32; /* New-style RT frame: @@ -1665,69 +1619,69 @@ s390_sigtramp_frame_unwind_cache (struct frame_info *next_frame, } static void -s390_sigtramp_frame_this_id (struct frame_info *next_frame, +s390_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_prologue_cache, struct frame_id *this_id) { struct s390_sigtramp_unwind_cache *info - = s390_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache); - *this_id = frame_id_build (info->frame_base, frame_pc_unwind (next_frame)); + = s390_sigtramp_frame_unwind_cache (this_frame, this_prologue_cache); + *this_id = frame_id_build (info->frame_base, get_frame_pc (this_frame)); } -static void -s390_sigtramp_frame_prev_register (struct frame_info *next_frame, - void **this_prologue_cache, - int regnum, int *optimizedp, - enum lval_type *lvalp, CORE_ADDR *addrp, - int *realnump, gdb_byte *bufferp) +static struct value * +s390_sigtramp_frame_prev_register (struct frame_info *this_frame, + void **this_prologue_cache, int regnum) { struct s390_sigtramp_unwind_cache *info - = s390_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache); - trad_frame_get_prev_register (next_frame, info->saved_regs, regnum, - optimizedp, lvalp, addrp, realnump, bufferp); + = s390_sigtramp_frame_unwind_cache (this_frame, this_prologue_cache); + return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum); } -static const struct frame_unwind s390_sigtramp_frame_unwind = { - SIGTRAMP_FRAME, - s390_sigtramp_frame_this_id, - s390_sigtramp_frame_prev_register -}; - -static const struct frame_unwind * -s390_sigtramp_frame_sniffer (struct frame_info *next_frame) +static int +s390_sigtramp_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_prologue_cache) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = get_frame_pc (this_frame); bfd_byte sigreturn[2]; - if (deprecated_read_memory_nobpt (pc, sigreturn, 2)) - return NULL; + if (target_read_memory (pc, sigreturn, 2)) + return 0; if (sigreturn[0] != 0x0a /* svc */) - return NULL; + return 0; if (sigreturn[1] != 119 /* sigreturn */ && sigreturn[1] != 173 /* rt_sigreturn */) - return NULL; + return 0; - return &s390_sigtramp_frame_unwind; + return 1; } +static const struct frame_unwind s390_sigtramp_frame_unwind = { + SIGTRAMP_FRAME, + s390_sigtramp_frame_this_id, + s390_sigtramp_frame_prev_register, + NULL, + s390_sigtramp_frame_sniffer +}; + /* Frame base handling. */ static CORE_ADDR -s390_frame_base_address (struct frame_info *next_frame, void **this_cache) +s390_frame_base_address (struct frame_info *this_frame, void **this_cache) { struct s390_unwind_cache *info - = s390_frame_unwind_cache (next_frame, this_cache); + = s390_frame_unwind_cache (this_frame, this_cache); return info->frame_base; } static CORE_ADDR -s390_local_base_address (struct frame_info *next_frame, void **this_cache) +s390_local_base_address (struct frame_info *this_frame, void **this_cache) { struct s390_unwind_cache *info - = s390_frame_unwind_cache (next_frame, this_cache); + = s390_frame_unwind_cache (this_frame, this_cache); return info->local_base; } @@ -1760,7 +1714,7 @@ s390_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) static void s390_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, struct dwarf2_frame_state_reg *reg, - struct frame_info *next_frame) + struct frame_info *this_frame) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); @@ -1857,6 +1811,7 @@ is_float_singleton (struct type *type) CHECK_TYPEDEF (singleton_type); return (TYPE_CODE (singleton_type) == TYPE_CODE_FLT + || TYPE_CODE (singleton_type) == TYPE_CODE_DECFLOAT || is_float_singleton (singleton_type)); } @@ -1895,6 +1850,7 @@ static int is_float_like (struct type *type) { return (TYPE_CODE (type) == TYPE_CODE_FLT + || TYPE_CODE (type) == TYPE_CODE_DECFLOAT || is_float_singleton (type)); } @@ -1971,7 +1927,8 @@ alignment_of (struct type *type) if (is_integer_like (type) || is_pointer_like (type) - || TYPE_CODE (type) == TYPE_CODE_FLT) + || TYPE_CODE (type) == TYPE_CODE_FLT + || TYPE_CODE (type) == TYPE_CODE_DECFLOAT) alignment = TYPE_LENGTH (type); else if (TYPE_CODE (type) == TYPE_CODE_STRUCT || TYPE_CODE (type) == TYPE_CODE_UNION) @@ -2168,18 +2125,19 @@ s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function, return sp + 16*word_size + 32; } -/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that +/* Assuming THIS_FRAME is a dummy, return the frame ID of that dummy frame. The frame ID's base needs to match the TOS value returned by push_dummy_call, and the PC match the dummy frame's breakpoint. */ static struct frame_id -s390_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) +s390_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) { int word_size = gdbarch_ptr_bit (gdbarch) / 8; - CORE_ADDR sp = s390_unwind_sp (gdbarch, next_frame); + CORE_ADDR sp = get_frame_register_unsigned (this_frame, S390_SP_REGNUM); + sp = gdbarch_addr_bits_remove (gdbarch, sp); return frame_id_build (sp + 16*word_size + 32, - frame_pc_unwind (next_frame)); + get_frame_pc (this_frame)); } static CORE_ADDR @@ -2213,9 +2171,9 @@ s390_return_value_convention (struct gdbarch *gdbarch, struct type *type) } static enum return_value_convention -s390_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *out, - const gdb_byte *in) +s390_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, + gdb_byte *out, const gdb_byte *in) { int word_size = gdbarch_ptr_bit (gdbarch) / 8; int length = TYPE_LENGTH (type); @@ -2226,7 +2184,8 @@ s390_return_value (struct gdbarch *gdbarch, struct type *type, switch (rvc) { case RETURN_VALUE_REGISTER_CONVENTION: - if (TYPE_CODE (type) == TYPE_CODE_FLT) + if (TYPE_CODE (type) == TYPE_CODE_FLT + || TYPE_CODE (type) == TYPE_CODE_DECFLOAT) { /* When we store a single-precision value in an FP register, it occupies the leftmost bits. */ @@ -2262,7 +2221,8 @@ s390_return_value (struct gdbarch *gdbarch, struct type *type, switch (rvc) { case RETURN_VALUE_REGISTER_CONVENTION: - if (TYPE_CODE (type) == TYPE_CODE_FLT) + if (TYPE_CODE (type) == TYPE_CODE_FLT + || TYPE_CODE (type) == TYPE_CODE_DECFLOAT) { /* When we store a single-precision value in an FP register, it occupies the leftmost bits. */ @@ -2297,7 +2257,7 @@ s390_return_value (struct gdbarch *gdbarch, struct type *type, /* Breakpoints. */ static const gdb_byte * -s390_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) +s390_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr) { static const gdb_byte breakpoint[] = { 0x0, 0x1 }; @@ -2309,7 +2269,7 @@ s390_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) /* Address handling. */ static CORE_ADDR -s390_addr_bits_remove (CORE_ADDR addr) +s390_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr) { return addr & 0x7fffffff; } @@ -2318,7 +2278,7 @@ static int s390_address_class_type_flags (int byte_size, int dwarf2_addr_class) { if (byte_size == 4) - return TYPE_FLAG_ADDRESS_CLASS_1; + return TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1; else return 0; } @@ -2326,7 +2286,7 @@ s390_address_class_type_flags (int byte_size, int dwarf2_addr_class) static const char * s390_address_class_type_flags_to_name (struct gdbarch *gdbarch, int type_flags) { - if (type_flags & TYPE_FLAG_ADDRESS_CLASS_1) + if (type_flags & TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1) return "mode32"; else return NULL; @@ -2338,7 +2298,7 @@ s390_address_class_name_to_type_flags (struct gdbarch *gdbarch, const char *name { if (strcmp (name, "mode32") == 0) { - *type_flags_ptr = TYPE_FLAG_ADDRESS_CLASS_1; + *type_flags_ptr = TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1; return 1; } else @@ -2369,8 +2329,14 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_believe_pcc_promotion (gdbarch, 0); set_gdbarch_char_signed (gdbarch, 0); + /* S/390 GNU/Linux uses either 64-bit or 128-bit long doubles. + We can safely let them default to 128-bit, since the debug info + will give the size of type actually used in each case. */ + set_gdbarch_long_double_bit (gdbarch, 128); + set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad); + /* Amount PC must be decremented by after a breakpoint. This is - often the number of bytes returned by BREAKPOINT_FROM_PC but not + often the number of bytes returned by gdbarch_breakpoint_from_pc but not always. */ set_gdbarch_decr_pc_after_break (gdbarch, 2); /* Stack grows downward. */ @@ -2387,28 +2353,25 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_register_name (gdbarch, s390_register_name); set_gdbarch_register_type (gdbarch, s390_register_type); set_gdbarch_stab_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum); - set_gdbarch_dwarf_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum); set_gdbarch_dwarf2_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum); - set_gdbarch_convert_register_p (gdbarch, s390_convert_register_p); - set_gdbarch_register_to_value (gdbarch, s390_register_to_value); - set_gdbarch_value_to_register (gdbarch, s390_value_to_register); + set_gdbarch_value_from_register (gdbarch, s390_value_from_register); set_gdbarch_register_reggroup_p (gdbarch, s390_register_reggroup_p); set_gdbarch_regset_from_core_section (gdbarch, s390_regset_from_core_section); /* Inferior function calls. */ set_gdbarch_push_dummy_call (gdbarch, s390_push_dummy_call); - set_gdbarch_unwind_dummy_id (gdbarch, s390_unwind_dummy_id); + set_gdbarch_dummy_id (gdbarch, s390_dummy_id); set_gdbarch_frame_align (gdbarch, s390_frame_align); set_gdbarch_return_value (gdbarch, s390_return_value); /* Frame handling. */ dwarf2_frame_set_init_reg (gdbarch, s390_dwarf2_frame_init_reg); - frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer); + dwarf2_append_unwinders (gdbarch); frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer); - frame_unwind_append_sniffer (gdbarch, s390_stub_frame_sniffer); - frame_unwind_append_sniffer (gdbarch, s390_sigtramp_frame_sniffer); - frame_unwind_append_sniffer (gdbarch, s390_frame_sniffer); + frame_unwind_append_unwinder (gdbarch, &s390_stub_frame_unwind); + frame_unwind_append_unwinder (gdbarch, &s390_sigtramp_frame_unwind); + frame_unwind_append_unwinder (gdbarch, &s390_frame_unwind); frame_base_set_default (gdbarch, &s390_frame_base); set_gdbarch_unwind_pc (gdbarch, s390_unwind_pc); set_gdbarch_unwind_sp (gdbarch, s390_unwind_sp); @@ -2456,6 +2419,8 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_print_insn (gdbarch, print_insn_s390); + set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); + /* Enable TLS support. */ set_gdbarch_fetch_tls_load_module_address (gdbarch, svr4_fetch_objfile_link_map);