From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30113 invoked by alias); 19 Jan 2004 19:31:14 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 30073 invoked from network); 19 Jan 2004 19:31:03 -0000 Received: from unknown (HELO faui10.informatik.uni-erlangen.de) (131.188.31.10) by sources.redhat.com with SMTP; 19 Jan 2004 19:31:03 -0000 Received: from faui1d.informatik.uni-erlangen.de (faui1d [131.188.31.34]) by faui10.informatik.uni-erlangen.de (8.9.3p3/8.1.9-FAU) with ESMTP id UAA08291; Mon, 19 Jan 2004 20:31:01 +0100 (CET) From: Ulrich Weigand Received: (from weigand@localhost) by faui1d.informatik.uni-erlangen.de (8.9.3p3/8.1.6-FAU) id UAA02622; Mon, 19 Jan 2004 20:31:01 +0100 (CET) Message-Id: <200401191931.UAA02622@faui1d.informatik.uni-erlangen.de> Subject: [PATCH] S/390 port modernization - revised 4/4 To: gdb-patches@sources.redhat.com Date: Mon, 19 Jan 2004 19:31:00 -0000 Cc: uweigand@de.ibm.com MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-SW-Source: 2004-01/txt/msg00523.txt.bz2 Hello, this is a revised version of patch 4/4 to update the s390 backend, updated to remove problems detected by the ARI. Retested on s390-ibm-linux and s390x-ibm-linux with no new regressions. Bye, Ulrich ChangeLog: * s390-tdep.c: Include "trad-frame.h", "frame-base.h", and "frame-unwind.h". (s390_readinstruction): Reformat. Use read_memory_nobpt. (GDB_TARGET_IS_ESAME, S390_GPR_SIZE, S390_FPR_SIZE): Remove. (S390_SYSCALL_OPCODE, S390_SYSCALL_SIZE): Remove. (S390_SIGCONTEXT_SREGS_OFFSET, S390X_SIGCONTEXT_SREGS_OFFSET, S390_SIGREGS_FP0_OFFSET, S390X_SIGREGS_FP0_OFFSET, S390_UC_MCONTEXT_OFFSET, S390X_UC_MCONTEXT_OFFSET, S390_SIGNAL_FRAMESIZE, s390_NR_sigreturn, s390_NR_rt_sigreturn): Remove. (struct frame_extra_info): Remove. (s390_memset_extra_info): Remove. (op_*, op1_*, op2_* enums): Add several new opcodes. (is_rse): Renamed to ... (is_rsy): ... this. Support long displacements. (is_rxe): Renamed to ... (is_rxy): ... this. Support long displacements. (compute_x_addr): Support long displacements. (struct s390_prologue_data): New data type. (s390_on_stack): Change API to use struct s390_prologue_data. (s390_store): Reimplement. (s390_load): New function. (s390_get_signal_frame_info): Remove. (s390_get_frame_info): Remove, replace by ... (s390_analyze_prolog): ... this new function. (s390_check_function_end): Remove. (s390_function_start): Remove. (s390_frameless_function_invokation): Remove. (s390_is_sigreturn): Remove. (s390_init_frame_pc_first): Remove. (s390_init_frame_extra_info): Remove. (s390_frame_init_saved_regs): Remove. (s390_frame_saved_pc_nofix): Remove. (s390_frame_saved_pc): Remove. (s390_frame_chain): Remove. (s390_fp_regnum, s390_read_fp): Remove. (s390_pop_frame_regular, s390_pop_frame): Remove. (s390_saved_pc_after_call): Remove. (s390_skip_prologue): Reimplement. (s390_in_function_epilogue_p): Support long displacements. (struct s390_unwind_cache): New data structure. (s390_frame_unwind_cache): New function. (s390_prologue_frame_unwind_cache): Likewise. (s390_backchain_frame_unwind_cache): Likewise. (s390_frame_this_id, s390_frame_prev_register): Likewise. (s390_frame_unwind): Define. (s390_frame_sniffer): New function. (struct s390_pltstub_unwind_cache): New data structure. (s390_pltstub_frame_unwind_cache): New function. (s390_pltstub_frame_this_id): Likewise. (s390_pltstub_frame_prev_register): Likewise. (s390_pltstub_frame_unwind): Define. (s390_pltstub_frame_sniffer): New function. (struct s390_sigtramp_unwind_cache): New data structure. (s390_sigtramp_frame_unwind_cache): New function. (s390_sigtramp_frame_this_id): Likewise. (s390_sigtramp_frame_prev_register): Likewise. (s390_sigtramp_frame_unwind): Define. (s390_sigtramp_frame_sniffer): New function. (s390_frame_base_address, s390_local_base_address): New functions. (s390_frame_base): Define. (s390_unwind_pc, s390_unwind_sp): New function. (s390_push_dummy_call): Use new frame base location. (s390_unwind_dummy_id): Likewise. (s390_gdbarch_init): Remove calls to: set_gdbarch_frameless_function_invocation, set_gdbarch_deprecated_init_frame_pc, set_gdbarch_deprecated_frame_chain, set_gdbarch_deprecated_frame_init_saved_regs, set_gdbarch_deprecated_pop_frame, set_gdbarch_deprecated_init_extra_frame_info, set_gdbarch_deprecated_init_frame_pc_first, set_gdbarch_deprecated_target_read_fp, set_gdbarch_deprecated_frame_saved_pc, set_gdbarch_deprecated_saved_pc_after_call, set_gdbarch_deprecated_fp_regnum. Add calls to: set_gdbarch_in_solib_call_trampoline, frame_unwind_append_sniffer, frame_base_set_default, set_gdbarch_unwind_pc, set_gdbarch_unwind_sp. * Makefile.in (s390-tdep.o): Update dependencies. diff -c -p -r gdb-head/gdb/Makefile.in gdb-head-new/gdb/Makefile.in *** gdb-head/gdb/Makefile.in Sun Jan 18 17:27:53 2004 --- gdb-head-new/gdb/Makefile.in Sun Jan 18 18:11:51 2004 *************** s390-nat.o: s390-nat.c $(defs_h) $(tm_h) *** 2252,2257 **** --- 2252,2258 ---- s390-tdep.o: s390-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) $(inferior_h) \ $(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(symfile_h) \ $(objfiles_h) $(tm_h) $(__bfd_bfd_h) $(floatformat_h) $(regcache_h) \ + $(trad_frame_h) $(frame_base_h) $(frame_unwind_h) \ $(reggroups_h) $(regset_h) $(value_h) $(gdb_assert_h) $(dis_asm_h) \ $(s390_tdep_h) scm-exp.o: scm-exp.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \ diff -c -p -r gdb-head/gdb/s390-tdep.c gdb-head-new/gdb/s390-tdep.c *** gdb-head/gdb/s390-tdep.c Sun Jan 18 18:03:57 2004 --- gdb-head-new/gdb/s390-tdep.c Sun Jan 18 18:11:51 2004 *************** *** 36,41 **** --- 36,44 ---- #include "../bfd/bfd.h" #include "floatformat.h" #include "regcache.h" + #include "trad-frame.h" + #include "frame-base.h" + #include "frame-unwind.h" #include "reggroups.h" #include "regset.h" #include "value.h" *************** s390_regset_from_core_section (struct gd *** 473,544 **** } - #define GDB_TARGET_IS_ESAME (TARGET_ARCHITECTURE->mach == bfd_mach_s390_64) - #define S390_GPR_SIZE (GDB_TARGET_IS_ESAME ? 8 : 4) - #define S390_FPR_SIZE (8) - #define S390_MAX_INSTR_SIZE (6) - #define S390_SYSCALL_OPCODE (0x0a) - #define S390_SYSCALL_SIZE (2) - #define S390_SIGCONTEXT_SREGS_OFFSET (8) - #define S390X_SIGCONTEXT_SREGS_OFFSET (8) - #define S390_SIGREGS_FP0_OFFSET (144) - #define S390X_SIGREGS_FP0_OFFSET (216) - #define S390_UC_MCONTEXT_OFFSET (256) - #define S390X_UC_MCONTEXT_OFFSET (344) - #define S390_SIGNAL_FRAMESIZE (GDB_TARGET_IS_ESAME ? 160:96) - #define s390_NR_sigreturn 119 - #define s390_NR_rt_sigreturn 173 - - - - struct frame_extra_info - { - int initialised; - int good_prologue; - CORE_ADDR function_start; - CORE_ADDR skip_prologue_function_start; - CORE_ADDR saved_pc_valid; - CORE_ADDR saved_pc; - CORE_ADDR sig_fixed_saved_pc_valid; - CORE_ADDR sig_fixed_saved_pc; - CORE_ADDR frame_pointer_saved_pc; /* frame pointer needed for alloca */ - CORE_ADDR stack_bought_valid; - CORE_ADDR stack_bought; /* amount we decrement the stack pointer by */ - CORE_ADDR sigcontext; - }; - - - static CORE_ADDR s390_frame_saved_pc_nofix (struct frame_info *fi); - - static int - s390_readinstruction (bfd_byte instr[], CORE_ADDR at) - { - int instrlen; - - static int s390_instrlen[] = { - 2, - 4, - 4, - 6 - }; - if (target_read_memory (at, &instr[0], 2)) - return -1; - instrlen = s390_instrlen[instr[0] >> 6]; - if (instrlen > 2) - { - if (target_read_memory (at + 2, &instr[2], instrlen - 2)) - return -1; - } - return instrlen; - } - - static void - s390_memset_extra_info (struct frame_extra_info *fextra_info) - { - memset (fextra_info, 0, sizeof (struct frame_extra_info)); - } - - /* Prologue analysis. */ /* When we analyze a prologue, we're really doing 'abstract --- 476,481 ---- *************** pv_is_array_ref (struct prologue_value * *** 930,961 **** op1_* and op2_* enums. */ enum { ! op1_aghi = 0xa7, op2_aghi = 0xb, ! op1_ahi = 0xa7, op2_ahi = 0xa, ! op_ar = 0x1a, ! op_basr = 0x0d, ! op1_bras = 0xa7, op2_bras = 0x5, ! op_l = 0x58, ! op_la = 0x41, ! op1_larl = 0xc0, op2_larl = 0x0, ! op_lgr = 0xb904, ! op1_lghi = 0xa7, op2_lghi = 0x9, ! op1_lhi = 0xa7, op2_lhi = 0x8, op_lr = 0x18, ! op_nr = 0x14, ! op_ngr = 0xb980, ! op_s = 0x5b, op_st = 0x50, ! op_std = 0x60, op1_stg = 0xe3, op2_stg = 0x24, op_stm = 0x90, op1_stmg = 0xeb, op2_stmg = 0x24, ! op_lm = 0x98, ! op1_lmg = 0xeb, op2_lmg = 0x04, ! op_svc = 0x0a, }; /* The functions below are for recognizing and decoding S/390 instructions of various formats. Each of them checks whether INSN is an instruction of the given format, with the specified opcodes. --- 867,938 ---- op1_* and op2_* enums. */ enum { ! op1_lhi = 0xa7, op2_lhi = 0x08, ! op1_lghi = 0xa7, op2_lghi = 0x09, op_lr = 0x18, ! op_lgr = 0xb904, ! op_l = 0x58, ! op1_ly = 0xe3, op2_ly = 0x58, ! op1_lg = 0xe3, op2_lg = 0x04, ! op_lm = 0x98, ! op1_lmy = 0xeb, op2_lmy = 0x98, ! op1_lmg = 0xeb, op2_lmg = 0x04, op_st = 0x50, ! op1_sty = 0xe3, op2_sty = 0x50, op1_stg = 0xe3, op2_stg = 0x24, + op_std = 0x60, op_stm = 0x90, + op1_stmy = 0xeb, op2_stmy = 0x90, op1_stmg = 0xeb, op2_stmg = 0x24, ! op1_aghi = 0xa7, op2_aghi = 0x0b, ! op1_ahi = 0xa7, op2_ahi = 0x0a, ! op_ar = 0x1a, ! op_agr = 0xb908, ! op_a = 0x5a, ! op1_ay = 0xe3, op2_ay = 0x5a, ! op1_ag = 0xe3, op2_ag = 0x08, ! op_sr = 0x1b, ! op_sgr = 0xb909, ! op_s = 0x5b, ! op1_sy = 0xe3, op2_sy = 0x5b, ! op1_sg = 0xe3, op2_sg = 0x09, ! op_nr = 0x14, ! op_ngr = 0xb980, ! op_la = 0x41, ! op1_lay = 0xe3, op2_lay = 0x71, ! op1_larl = 0xc0, op2_larl = 0x00, ! op_basr = 0x0d, ! op_bas = 0x4d, ! op_bcr = 0x07, ! op_bc = 0x0d, ! op1_bras = 0xa7, op2_bras = 0x05, ! op1_brasl= 0xc0, op2_brasl= 0x05, ! op1_brc = 0xa7, op2_brc = 0x04, ! op1_brcl = 0xc0, op2_brcl = 0x04, }; + /* Read a single instruction from address AT. */ + + #define S390_MAX_INSTR_SIZE 6 + static int + s390_readinstruction (bfd_byte instr[], CORE_ADDR at) + { + static int s390_instrlen[] = { 2, 4, 4, 6 }; + int instrlen; + + if (read_memory_nobpt (at, &instr[0], 2)) + return -1; + instrlen = s390_instrlen[instr[0] >> 6]; + if (instrlen > 2) + { + if (read_memory_nobpt (at + 2, &instr[2], instrlen - 2)) + return -1; + } + return instrlen; + } + + /* The functions below are for recognizing and decoding S/390 instructions of various formats. Each of them checks whether INSN is an instruction of the given format, with the specified opcodes. *************** is_rs (bfd_byte *insn, int op, *** 1052,1068 **** static int ! is_rse (bfd_byte *insn, int op1, int op2, unsigned int *r1, unsigned int *r3, unsigned int *d2, unsigned int *b2) { if (insn[0] == op1 - /* Yes, insn[5]. insn[4] is unused. */ && insn[5] == op2) { *r1 = (insn[1] >> 4) & 0xf; *r3 = insn[1] & 0xf; *b2 = (insn[2] >> 4) & 0xf; ! *d2 = ((insn[2] & 0xf) << 8) | insn[3]; return 1; } else --- 1029,1046 ---- static int ! is_rsy (bfd_byte *insn, int op1, int op2, unsigned int *r1, unsigned int *r3, unsigned int *d2, unsigned int *b2) { if (insn[0] == op1 && insn[5] == op2) { *r1 = (insn[1] >> 4) & 0xf; *r3 = insn[1] & 0xf; *b2 = (insn[2] >> 4) & 0xf; ! /* The 'long displacement' is a 20-bit signed integer. */ ! *d2 = ((((insn[2] & 0xf) << 8) | insn[3] | (insn[4] << 12)) ! ^ 0x80000) - 0x80000; return 1; } else *************** is_rx (bfd_byte *insn, int op, *** 1088,1104 **** static int ! is_rxe (bfd_byte *insn, int op1, int op2, unsigned int *r1, unsigned int *d2, unsigned int *x2, unsigned int *b2) { if (insn[0] == op1 - /* Yes, insn[5]. insn[4] is unused. */ && insn[5] == op2) { *r1 = (insn[1] >> 4) & 0xf; *x2 = insn[1] & 0xf; *b2 = (insn[2] >> 4) & 0xf; ! *d2 = ((insn[2] & 0xf) << 8) | insn[3]; return 1; } else --- 1066,1083 ---- static int ! is_rxy (bfd_byte *insn, int op1, int op2, unsigned int *r1, unsigned int *d2, unsigned int *x2, unsigned int *b2) { if (insn[0] == op1 && insn[5] == op2) { *r1 = (insn[1] >> 4) & 0xf; *x2 = insn[1] & 0xf; *b2 = (insn[2] >> 4) & 0xf; ! /* The 'long displacement' is a 20-bit signed integer. */ ! *d2 = ((((insn[2] & 0xf) << 8) | insn[3] | (insn[4] << 12)) ! ^ 0x80000) - 0x80000; return 1; } else *************** is_rxe (bfd_byte *insn, int op1, int op2 *** 1110,1116 **** L R1, D2(X2, B2) ! Here, X2 and B2 are registers, and D2 is an unsigned 12-bit constant; the effective address is the sum of all three. If either X2 or B2 are zero, then it doesn't contribute to the sum --- this means that r0 can't be used as either X2 or B2. --- 1089,1095 ---- L R1, D2(X2, B2) ! Here, X2 and B2 are registers, and D2 is a signed 20-bit constant; the effective address is the sum of all three. If either X2 or B2 are zero, then it doesn't contribute to the sum --- this means that r0 can't be used as either X2 or B2. *************** is_rxe (bfd_byte *insn, int op1, int op2 *** 1120,1126 **** static void compute_x_addr (struct prologue_value *addr, struct prologue_value *gpr, ! unsigned int d2, unsigned int x2, unsigned int b2) { /* We can't just add stuff directly in addr; it might alias some of the registers we need to read. */ --- 1099,1105 ---- static void compute_x_addr (struct prologue_value *addr, struct prologue_value *gpr, ! int d2, unsigned int x2, unsigned int b2) { /* We can't just add stuff directly in addr; it might alias some of the registers we need to read. */ *************** compute_x_addr (struct prologue_value *a *** 1143,1169 **** #define S390_NUM_GPRS 16 #define S390_NUM_FPRS 16 /* If the SIZE bytes at ADDR are a stack slot we're actually tracking, return pv_definite_yes and set *STACK to point to the slot. If we're sure that they are not any of our stack slots, then return pv_definite_no. Otherwise, return pv_maybe. ! - GPR is an array indexed by GPR number giving the current values ! of the general-purpose registers. ! - SPILL is an array tracking the spill area of the caller's frame; ! SPILL[i] is the i'th spill slot. The spill slots are designated ! for r2 -- r15, and then f0, f2, f4, and f6. ! - BACK_CHAIN is the value of the back chain slot; it's only valid ! when the current frame actually has some space for a back chain ! slot --- that is, when the current value of the stack pointer ! (according to GPR) is at least S390_STACK_FRAME_OVERHEAD bytes ! less than its original value. */ static enum pv_boolean s390_on_stack (struct prologue_value *addr, CORE_ADDR size, ! struct prologue_value *gpr, ! struct prologue_value *spill, ! struct prologue_value *back_chain, struct prologue_value **stack) { struct prologue_value gpr_spill_addr; --- 1122,1162 ---- #define S390_NUM_GPRS 16 #define S390_NUM_FPRS 16 + struct s390_prologue_data { + + /* The size of a GPR or FPR. */ + int gpr_size; + int fpr_size; + + /* The general-purpose registers. */ + struct prologue_value gpr[S390_NUM_GPRS]; + + /* The floating-point registers. */ + struct prologue_value fpr[S390_NUM_FPRS]; + + /* The register spill stack slots in the caller's frame --- + general-purpose registers r2 through r15, and floating-point + registers. spill[i] is where gpr i+2 gets spilled; + spill[(14, 15, 16, 17)] is where (f0, f2, f4, f6) get spilled. */ + struct prologue_value spill[S390_NUM_SPILL_SLOTS]; + + /* The value of the back chain slot. This is only valid if the stack + pointer is known to be less than its original value --- that is, + if we have indeed allocated space on the stack. */ + struct prologue_value back_chain; + }; + /* If the SIZE bytes at ADDR are a stack slot we're actually tracking, return pv_definite_yes and set *STACK to point to the slot. If we're sure that they are not any of our stack slots, then return pv_definite_no. Otherwise, return pv_maybe. ! ! DATA describes our current state (registers and stack slots). */ static enum pv_boolean s390_on_stack (struct prologue_value *addr, CORE_ADDR size, ! struct s390_prologue_data *data, struct prologue_value **stack) { struct prologue_value gpr_spill_addr; *************** s390_on_stack (struct prologue_value *ad *** 1173,1181 **** enum pv_boolean b; /* Construct the addresses of the spill arrays and the back chain. */ ! pv_set_to_register (&gpr_spill_addr, S390_SP_REGNUM, 2 * S390_GPR_SIZE); ! pv_set_to_register (&fpr_spill_addr, S390_SP_REGNUM, 16 * S390_GPR_SIZE); ! back_chain_addr = gpr[S390_SP_REGNUM - S390_R0_REGNUM]; /* We have to check for GPR and FPR references using two separate calls to pv_is_array_ref, since the GPR and FPR spill slots are --- 1166,1174 ---- enum pv_boolean b; /* Construct the addresses of the spill arrays and the back chain. */ ! pv_set_to_register (&gpr_spill_addr, S390_SP_REGNUM, 2 * data->gpr_size); ! pv_set_to_register (&fpr_spill_addr, S390_SP_REGNUM, 16 * data->gpr_size); ! back_chain_addr = data->gpr[S390_SP_REGNUM - S390_R0_REGNUM]; /* We have to check for GPR and FPR references using two separate calls to pv_is_array_ref, since the GPR and FPR spill slots are *************** s390_on_stack (struct prologue_value *ad *** 1183,1202 **** isn't really an array.) */ /* Was it a reference to the GPR spill array? */ ! b = pv_is_array_ref (addr, size, &gpr_spill_addr, 14, S390_GPR_SIZE, &i); if (b == pv_definite_yes) { ! *stack = &spill[i]; return pv_definite_yes; } if (b == pv_maybe) return pv_maybe; /* Was it a reference to the FPR spill array? */ ! b = pv_is_array_ref (addr, size, &fpr_spill_addr, 4, S390_FPR_SIZE, &i); if (b == pv_definite_yes) { ! *stack = &spill[14 + i]; return pv_definite_yes; } if (b == pv_maybe) --- 1176,1195 ---- isn't really an array.) */ /* Was it a reference to the GPR spill array? */ ! b = pv_is_array_ref (addr, size, &gpr_spill_addr, 14, data->gpr_size, &i); if (b == pv_definite_yes) { ! *stack = &data->spill[i]; return pv_definite_yes; } if (b == pv_maybe) return pv_maybe; /* Was it a reference to the FPR spill array? */ ! b = pv_is_array_ref (addr, size, &fpr_spill_addr, 4, data->fpr_size, &i); if (b == pv_definite_yes) { ! *stack = &data->spill[14 + i]; return pv_definite_yes; } if (b == pv_maybe) *************** s390_on_stack (struct prologue_value *ad *** 1205,1214 **** /* Was it a reference to the back chain? This isn't quite right. We ought to check whether we have actually allocated any new frame at all. */ ! b = pv_is_array_ref (addr, size, &back_chain_addr, 1, S390_GPR_SIZE, &i); if (b == pv_definite_yes) { ! *stack = back_chain; return pv_definite_yes; } if (b == pv_maybe) --- 1198,1207 ---- /* Was it a reference to the back chain? This isn't quite right. We ought to check whether we have actually allocated any new frame at all. */ ! b = pv_is_array_ref (addr, size, &back_chain_addr, 1, data->gpr_size, &i); if (b == pv_definite_yes) { ! *stack = &data->back_chain; return pv_definite_yes; } if (b == pv_maybe) *************** s390_on_stack (struct prologue_value *ad *** 1219,1294 **** } ! /* Do a SIZE-byte store of VALUE to ADDR. GPR, SPILL, and BACK_CHAIN, ! and the return value are as described for s390_on_stack, above. ! Note that, when this returns pv_maybe, we have to assume that all ! of our memory now contains unknown values. */ ! static enum pv_boolean s390_store (struct prologue_value *addr, CORE_ADDR size, struct prologue_value *value, ! struct prologue_value *gpr, ! struct prologue_value *spill, ! struct prologue_value *back_chain) { struct prologue_value *stack; - enum pv_boolean on_stack - = s390_on_stack (addr, size, gpr, spill, back_chain, &stack); ! if (on_stack == pv_definite_yes) ! *stack = *value; ! return on_stack; } - ! /* The current frame looks like a signal delivery frame: the first ! instruction is an 'svc' opcode. If the next frame is a signal ! handler's frame, set FI's saved register map to point into the ! signal context structure. */ ! static void ! s390_get_signal_frame_info (struct frame_info *fi) ! { ! struct frame_info *next_frame = get_next_frame (fi); ! ! if (next_frame ! && get_frame_extra_info (next_frame) ! && get_frame_extra_info (next_frame)->sigcontext) ! { ! /* We're definitely backtracing from a signal handler. */ ! CORE_ADDR *saved_regs = deprecated_get_frame_saved_regs (fi); ! CORE_ADDR save_reg_addr = (get_frame_extra_info (next_frame)->sigcontext ! + DEPRECATED_REGISTER_BYTE (S390_R0_REGNUM)); ! int reg; ! for (reg = 0; reg < S390_NUM_GPRS; reg++) ! { ! saved_regs[S390_R0_REGNUM + reg] = save_reg_addr; ! save_reg_addr += S390_GPR_SIZE; ! } ! save_reg_addr = (get_frame_extra_info (next_frame)->sigcontext ! + (GDB_TARGET_IS_ESAME ? S390X_SIGREGS_FP0_OFFSET : ! S390_SIGREGS_FP0_OFFSET)); ! for (reg = 0; reg < S390_NUM_FPRS; reg++) ! { ! saved_regs[S390_F0_REGNUM + reg] = save_reg_addr; ! save_reg_addr += S390_FPR_SIZE; ! } } - } ! static int ! s390_get_frame_info (CORE_ADDR start_pc, ! struct frame_extra_info *fextra_info, ! struct frame_info *fi, ! int init_extra_info) { /* Our return value: ! zero if we were able to read all the instructions we wanted, or ! -1 if we got an error trying to read memory. */ ! int result = 0; /* The current PC for our abstract interpretation. */ CORE_ADDR pc; --- 1212,1301 ---- } ! /* Do a SIZE-byte store of VALUE to ADDR. */ ! static void s390_store (struct prologue_value *addr, CORE_ADDR size, struct prologue_value *value, ! struct s390_prologue_data *data) { struct prologue_value *stack; ! /* We can do it if it's definitely a reference to something on the stack. */ ! if (s390_on_stack (addr, size, data, &stack) == pv_definite_yes) ! { ! *stack = *value; ! return; ! } ! ! /* Note: If s390_on_stack returns pv_maybe, you might think we should ! forget our cached values, as any of those might have been hit. ! However, we make the assumption that --since the fields we track ! are save areas private to compiler, and never directly exposed to ! the user-- every access to our data is explicit. Hence, every ! memory access we cannot follow can't hit our data. */ } ! /* Do a SIZE-byte load from ADDR into VALUE. */ ! static void ! s390_load (struct prologue_value *addr, ! CORE_ADDR size, ! struct prologue_value *value, ! struct s390_prologue_data *data) ! { ! struct prologue_value *stack; ! /* If it's a load from an in-line constant pool, then we can ! simulate that, under the assumption that the code isn't ! going to change between the time the processor actually ! executed it creating the current frame, and the time when ! we're analyzing the code to unwind past that frame. */ ! if (addr->kind == pv_constant) ! { ! struct section_table *secp; ! secp = target_section_by_addr (¤t_target, addr->k); ! if (secp != NULL ! && (bfd_get_section_flags (secp->bfd, secp->the_bfd_section) ! & SEC_READONLY)) ! { ! pv_set_to_constant (value, read_memory_integer (addr->k, size)); ! return; ! } ! } ! /* If it's definitely a reference to something on the stack, ! we can do that. */ ! if (s390_on_stack (addr, size, data, &stack) == pv_definite_yes) ! { ! *value = *stack; ! return; } + /* Otherwise, we don't know the value. */ + pv_set_to_unknown (value); + } + ! /* Analyze the prologue of the function starting at START_PC, ! continuing at most until CURRENT_PC. Initialize DATA to ! hold all information we find out about the state of the registers ! and stack slots. Return the address of the instruction after ! the last one that changed the SP, FP, or back chain; or zero ! on error. */ ! static CORE_ADDR ! s390_analyze_prologue (struct gdbarch *gdbarch, ! CORE_ADDR start_pc, ! CORE_ADDR current_pc, ! struct s390_prologue_data *data) { + int word_size = gdbarch_ptr_bit (gdbarch) / 8; + /* Our return value: ! The address of the instruction after the last one that changed ! the SP, FP, or back chain; zero if we got an error trying to ! read memory. */ ! CORE_ADDR result = start_pc; /* The current PC for our abstract interpretation. */ CORE_ADDR pc; *************** s390_get_frame_info (CORE_ADDR start_pc, *** 1296,1350 **** /* The address of the next instruction after that. */ CORE_ADDR next_pc; - /* The general-purpose registers. */ - struct prologue_value gpr[S390_NUM_GPRS]; - - /* The floating-point registers. */ - struct prologue_value fpr[S390_NUM_FPRS]; - - /* The register spill stack slots in the caller's frame --- - general-purpose registers r2 through r15, and floating-point - registers. spill[i] is where gpr i+2 gets spilled; - spill[(14, 15, 16, 17)] is where (f0, f2, f4, f6) get spilled. */ - struct prologue_value spill[S390_NUM_SPILL_SLOTS]; - - /* The value of the back chain slot. This is only valid if the stack - pointer is known to be less than its original value --- that is, - if we have indeed allocated space on the stack. */ - struct prologue_value back_chain; - - /* The address of the instruction after the last one that changed - the SP, FP, or back chain. */ - CORE_ADDR after_last_frame_setup_insn = start_pc; - /* Set up everything's initial value. */ { int i; for (i = 0; i < S390_NUM_GPRS; i++) ! pv_set_to_register (&gpr[i], S390_R0_REGNUM + i, 0); for (i = 0; i < S390_NUM_FPRS; i++) ! pv_set_to_register (&fpr[i], S390_F0_REGNUM + i, 0); for (i = 0; i < S390_NUM_SPILL_SLOTS; i++) ! pv_set_to_unknown (&spill[i]); ! pv_set_to_unknown (&back_chain); } ! /* Start interpreting instructions, until we hit something we don't ! know how to interpret. (Ideally, we should stop at the frame's ! real current PC, but at the moment, our callers don't give us ! that info.) */ ! for (pc = start_pc; ; pc = next_pc) { bfd_byte insn[S390_MAX_INSTR_SIZE]; int insn_len = s390_readinstruction (insn, pc); /* Fields for various kinds of instructions. */ ! unsigned int b2, r1, r2, d2, x2, r3; ! int i2; /* The values of SP, FP, and back chain before this instruction, for detecting instructions that change them. */ --- 1303,1340 ---- /* The address of the next instruction after that. */ CORE_ADDR next_pc; /* Set up everything's initial value. */ { int i; + /* 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). */ + data->gpr_size = word_size; + data->fpr_size = 8; + for (i = 0; i < S390_NUM_GPRS; i++) ! pv_set_to_register (&data->gpr[i], S390_R0_REGNUM + i, 0); for (i = 0; i < S390_NUM_FPRS; i++) ! pv_set_to_register (&data->fpr[i], S390_F0_REGNUM + i, 0); for (i = 0; i < S390_NUM_SPILL_SLOTS; i++) ! pv_set_to_unknown (&data->spill[i]); ! pv_set_to_unknown (&data->back_chain); } ! /* Start interpreting instructions, until we hit the frame's ! current PC or the first branch instruction. */ ! for (pc = start_pc; pc > 0 && pc < current_pc; pc = next_pc) { bfd_byte insn[S390_MAX_INSTR_SIZE]; int insn_len = s390_readinstruction (insn, pc); /* Fields for various kinds of instructions. */ ! unsigned int b2, r1, r2, x2, r3; ! int i2, d2; /* The values of SP, FP, and back chain before this instruction, for detecting instructions that change them. */ *************** s390_get_frame_info (CORE_ADDR start_pc, *** 1353,1534 **** /* If we got an error trying to read the instruction, report it. */ if (insn_len < 0) { ! result = -1; break; } next_pc = pc + insn_len; ! pre_insn_sp = gpr[S390_SP_REGNUM - S390_R0_REGNUM]; ! pre_insn_fp = gpr[S390_FRAME_REGNUM - S390_R0_REGNUM]; ! pre_insn_back_chain = back_chain; ! ! /* A special case, first --- only recognized as the very first ! instruction of the function, for signal delivery frames: ! SVC i --- system call */ ! if (pc == start_pc ! && is_rr (insn, op_svc, &r1, &r2)) ! { ! if (fi) ! s390_get_signal_frame_info (fi); ! break; ! } ! ! /* AHI r1, i2 --- add halfword immediate */ ! else if (is_ri (insn, op1_ahi, op2_ahi, &r1, &i2)) ! pv_add_constant (&gpr[r1], i2); ! ! /* AGHI r1, i2 --- add halfword immediate (64-bit version) */ ! else if (GDB_TARGET_IS_ESAME ! && is_ri (insn, op1_aghi, op2_aghi, &r1, &i2)) ! pv_add_constant (&gpr[r1], i2); ! /* AR r1, r2 -- add register */ ! else if (is_rr (insn, op_ar, &r1, &r2)) ! pv_add (&gpr[r1], &gpr[r1], &gpr[r2]); ! /* BASR r1, 0 --- branch and save ! Since r2 is zero, this saves the PC in r1, but doesn't branch. */ ! else if (is_rr (insn, op_basr, &r1, &r2) ! && r2 == 0) ! pv_set_to_constant (&gpr[r1], next_pc); ! /* BRAS r1, i2 --- branch relative and save */ ! else if (is_ri (insn, op1_bras, op2_bras, &r1, &i2)) { ! pv_set_to_constant (&gpr[r1], next_pc); ! next_pc = pc + i2 * 2; ! /* We'd better not interpret any backward branches. We'll ! never terminate. */ ! if (next_pc <= pc) ! break; } ! /* L r1, d2(x2, b2) --- load */ ! else if (is_rx (insn, op_l, &r1, &d2, &x2, &b2)) { struct prologue_value addr; - struct prologue_value *stack; - - compute_x_addr (&addr, gpr, d2, x2, b2); ! /* If it's a load from an in-line constant pool, then we can ! simulate that, under the assumption that the code isn't ! going to change between the time the processor actually ! executed it creating the current frame, and the time when ! we're analyzing the code to unwind past that frame. */ ! if (addr.kind == pv_constant ! && start_pc <= addr.k ! && addr.k < next_pc) ! pv_set_to_constant (&gpr[r1], ! read_memory_integer (addr.k, 4)); ! ! /* If it's definitely a reference to something on the stack, ! we can do that. */ ! else if (s390_on_stack (&addr, 4, gpr, spill, &back_chain, &stack) ! == pv_definite_yes) ! gpr[r1] = *stack; ! ! /* Otherwise, we don't know the value. */ ! else ! pv_set_to_unknown (&gpr[r1]); } ! /* LA r1, d2(x2, b2) --- load address */ ! else if (is_rx (insn, op_la, &r1, &d2, &x2, &b2)) ! compute_x_addr (&gpr[r1], gpr, d2, x2, b2); ! ! /* LARL r1, i2 --- load address relative long */ ! else if (GDB_TARGET_IS_ESAME ! && is_ril (insn, op1_larl, op2_larl, &r1, &i2)) ! pv_set_to_constant (&gpr[r1], pc + i2 * 2); ! ! /* LGR r1, r2 --- load from register */ ! else if (GDB_TARGET_IS_ESAME ! && is_rre (insn, op_lgr, &r1, &r2)) ! gpr[r1] = gpr[r2]; ! ! /* LHI r1, i2 --- load halfword immediate */ ! else if (is_ri (insn, op1_lhi, op2_lhi, &r1, &i2)) ! pv_set_to_constant (&gpr[r1], i2); ! ! /* LGHI r1, i2 --- load halfword immediate --- 64-bit version */ ! else if (is_ri (insn, op1_lghi, op2_lghi, &r1, &i2)) ! pv_set_to_constant (&gpr[r1], i2); ! ! /* LR r1, r2 --- load from register */ ! else if (is_rr (insn, op_lr, &r1, &r2)) ! gpr[r1] = gpr[r2]; ! ! /* NGR r1, r2 --- logical and --- 64-bit version */ ! else if (GDB_TARGET_IS_ESAME ! && is_rre (insn, op_ngr, &r1, &r2)) ! pv_logical_and (&gpr[r1], &gpr[r1], &gpr[r2]); ! ! /* NR r1, r2 --- logical and */ ! else if (is_rr (insn, op_nr, &r1, &r2)) ! pv_logical_and (&gpr[r1], &gpr[r1], &gpr[r2]); ! ! /* NGR r1, r2 --- logical and --- 64-bit version */ ! else if (GDB_TARGET_IS_ESAME ! && is_rre (insn, op_ngr, &r1, &r2)) ! pv_logical_and (&gpr[r1], &gpr[r1], &gpr[r2]); ! /* NR r1, r2 --- logical and */ ! else if (is_rr (insn, op_nr, &r1, &r2)) ! pv_logical_and (&gpr[r1], &gpr[r1], &gpr[r2]); ! /* S r1, d2(x2, b2) --- subtract from memory */ ! else if (is_rx (insn, op_s, &r1, &d2, &x2, &b2)) { struct prologue_value addr; - struct prologue_value value; - struct prologue_value *stack; ! compute_x_addr (&addr, gpr, d2, x2, b2); ! /* If it's a load from an in-line constant pool, then we can ! simulate that, under the assumption that the code isn't ! going to change between the time the processor actually ! executed it and the time when we're analyzing it. */ ! if (addr.kind == pv_constant ! && start_pc <= addr.k ! && addr.k < pc) ! pv_set_to_constant (&value, read_memory_integer (addr.k, 4)); ! ! /* If it's definitely a reference to something on the stack, ! we could do that. */ ! else if (s390_on_stack (&addr, 4, gpr, spill, &back_chain, &stack) ! == pv_definite_yes) ! value = *stack; ! ! /* Otherwise, we don't know the value. */ ! else ! pv_set_to_unknown (&value); ! pv_subtract (&gpr[r1], &gpr[r1], &value); } ! /* ST r1, d2(x2, b2) --- store */ ! else if (is_rx (insn, op_st, &r1, &d2, &x2, &b2)) { struct prologue_value addr; ! compute_x_addr (&addr, gpr, d2, x2, b2); ! ! /* The below really should be '4', not 'S390_GPR_SIZE'; this ! instruction always stores 32 bits, regardless of the full ! size of the GPR. */ ! if (s390_store (&addr, 4, &gpr[r1], gpr, spill, &back_chain) ! == pv_maybe) ! /* If we can't be sure that it's *not* a store to ! something we're tracing, then we would have to mark all ! our memory as unknown --- after all, it *could* be a ! store to any of them --- so we might as well just stop ! interpreting. */ ! break; } /* STD r1, d2(x2,b2) --- store floating-point register */ --- 1343,1436 ---- /* If we got an error trying to read the instruction, report it. */ if (insn_len < 0) { ! result = 0; break; } next_pc = pc + insn_len; ! pre_insn_sp = data->gpr[S390_SP_REGNUM - S390_R0_REGNUM]; ! pre_insn_fp = data->gpr[S390_FRAME_REGNUM - S390_R0_REGNUM]; ! pre_insn_back_chain = data->back_chain; ! /* LHI r1, i2 --- load halfword immediate */ ! if (word_size == 4 ! && is_ri (insn, op1_lhi, op2_lhi, &r1, &i2)) ! pv_set_to_constant (&data->gpr[r1], i2); ! ! /* LGHI r1, i2 --- load halfword immediate (64-bit version) */ ! else if (word_size == 8 ! && is_ri (insn, op1_lghi, op2_lghi, &r1, &i2)) ! pv_set_to_constant (&data->gpr[r1], i2); ! /* LR r1, r2 --- load from register */ ! else if (word_size == 4 ! && is_rr (insn, op_lr, &r1, &r2)) ! data->gpr[r1] = data->gpr[r2]; ! /* LGR r1, r2 --- load from register (64-bit version) */ ! else if (word_size == 8 ! && is_rre (insn, op_lgr, &r1, &r2)) ! data->gpr[r1] = data->gpr[r2]; ! /* L r1, d2(x2, b2) --- load */ ! else if (word_size == 4 ! && is_rx (insn, op_l, &r1, &d2, &x2, &b2)) { ! struct prologue_value addr; ! compute_x_addr (&addr, data->gpr, d2, x2, b2); ! s390_load (&addr, 4, &data->gpr[r1], data); } ! /* LY r1, d2(x2, b2) --- load (long-displacement version) */ ! else if (word_size == 4 ! && is_rxy (insn, op1_ly, op2_ly, &r1, &d2, &x2, &b2)) { struct prologue_value addr; ! compute_x_addr (&addr, data->gpr, d2, x2, b2); ! s390_load (&addr, 4, &data->gpr[r1], data); } ! /* LG r1, d2(x2, b2) --- load (64-bit version) */ ! else if (word_size == 8 ! && is_rxy (insn, op1_lg, op2_lg, &r1, &d2, &x2, &b2)) ! { ! struct prologue_value addr; ! compute_x_addr (&addr, data->gpr, d2, x2, b2); ! s390_load (&addr, 8, &data->gpr[r1], data); ! } ! /* ST r1, d2(x2, b2) --- store */ ! else if (word_size == 4 ! && is_rx (insn, op_st, &r1, &d2, &x2, &b2)) { struct prologue_value addr; ! compute_x_addr (&addr, data->gpr, d2, x2, b2); ! s390_store (&addr, 4, &data->gpr[r1], data); ! } ! /* STY r1, d2(x2, b2) --- store (long-displacement version) */ ! else if (word_size == 4 ! && is_rxy (insn, op1_sty, op2_sty, &r1, &d2, &x2, &b2)) ! { ! struct prologue_value addr; ! compute_x_addr (&addr, data->gpr, d2, x2, b2); ! s390_store (&addr, 4, &data->gpr[r1], data); } ! /* STG r1, d2(x2, b2) --- store (64-bit version) */ ! else if (word_size == 8 ! && is_rxy (insn, op1_stg, op2_stg, &r1, &d2, &x2, &b2)) { struct prologue_value addr; ! compute_x_addr (&addr, data->gpr, d2, x2, b2); ! s390_store (&addr, 8, &data->gpr[r1], data); } /* STD r1, d2(x2,b2) --- store floating-point register */ *************** s390_get_frame_info (CORE_ADDR start_pc, *** 1536,1576 **** { struct prologue_value addr; ! compute_x_addr (&addr, gpr, d2, x2, b2); ! ! if (s390_store (&addr, 8, &fpr[r1], gpr, spill, &back_chain) ! == pv_maybe) ! /* If we can't be sure that it's *not* a store to ! something we're tracing, then we would have to mark all ! our memory as unknown --- after all, it *could* be a ! store to any of them --- so we might as well just stop ! interpreting. */ ! break; } ! /* STG r1, d2(x2, b2) --- 64-bit store */ ! else if (GDB_TARGET_IS_ESAME ! && is_rxe (insn, op1_stg, op2_stg, &r1, &d2, &x2, &b2)) { struct prologue_value addr; ! compute_x_addr (&addr, gpr, d2, x2, b2); ! ! /* The below really should be '8', not 'S390_GPR_SIZE'; this ! instruction always stores 64 bits, regardless of the full ! size of the GPR. */ ! if (s390_store (&addr, 8, &gpr[r1], gpr, spill, &back_chain) ! == pv_maybe) ! /* If we can't be sure that it's *not* a store to ! something we're tracing, then we would have to mark all ! our memory as unknown --- after all, it *could* be a ! store to any of them --- so we might as well just stop ! interpreting. */ ! break; } ! /* STM r1, r3, d2(b2) --- store multiple */ ! else if (is_rs (insn, op_stm, &r1, &r3, &d2, &b2)) { int regnum; int offset; --- 1438,1467 ---- { struct prologue_value addr; ! compute_x_addr (&addr, data->gpr, d2, x2, b2); ! s390_store (&addr, 8, &data->fpr[r1], data); } ! /* STM r1, r3, d2(b2) --- store multiple */ ! else if (word_size == 4 ! && is_rs (insn, op_stm, &r1, &r3, &d2, &b2)) { + int regnum; + int offset; struct prologue_value addr; ! for (regnum = r1, offset = 0; ! regnum <= r3; ! regnum++, offset += 4) ! { ! compute_x_addr (&addr, data->gpr, d2 + offset, 0, b2); ! s390_store (&addr, 4, &data->gpr[regnum], data); ! } } ! /* STMY r1, r3, d2(b2) --- store multiple (long-displacement version) */ ! else if (word_size == 4 ! && is_rsy (insn, op1_stmy, op2_stmy, &r1, &r3, &d2, &b2)) { int regnum; int offset; *************** s390_get_frame_info (CORE_ADDR start_pc, *** 1580,1606 **** regnum <= r3; regnum++, offset += 4) { ! compute_x_addr (&addr, gpr, d2 + offset, 0, b2); ! ! if (s390_store (&addr, 4, &gpr[regnum], gpr, spill, &back_chain) ! == pv_maybe) ! /* If we can't be sure that it's *not* a store to ! something we're tracing, then we would have to mark all ! our memory as unknown --- after all, it *could* be a ! store to any of them --- so we might as well just stop ! interpreting. */ ! break; } - - /* If we left the loop early, we should stop interpreting - altogether. */ - if (regnum <= r3) - break; } ! /* STMG r1, r3, d2(b2) --- store multiple, 64-bit */ ! else if (GDB_TARGET_IS_ESAME ! && is_rse (insn, op1_stmg, op2_stmg, &r1, &r3, &d2, &b2)) { int regnum; int offset; --- 1471,1484 ---- regnum <= r3; regnum++, offset += 4) { ! compute_x_addr (&addr, data->gpr, d2 + offset, 0, b2); ! s390_store (&addr, 4, &data->gpr[regnum], data); } } ! /* STMG r1, r3, d2(b2) --- store multiple (64-bit version) */ ! else if (word_size == 8 ! && is_rsy (insn, op1_stmg, op2_stmg, &r1, &r3, &d2, &b2)) { int regnum; int offset; *************** s390_get_frame_info (CORE_ADDR start_pc, *** 1610,1640 **** regnum <= r3; regnum++, offset += 8) { ! compute_x_addr (&addr, gpr, d2 + offset, 0, b2); ! ! if (s390_store (&addr, 8, &gpr[regnum], gpr, spill, &back_chain) ! == pv_maybe) ! /* If we can't be sure that it's *not* a store to ! something we're tracing, then we would have to mark all ! our memory as unknown --- after all, it *could* be a ! store to any of them --- so we might as well just stop ! interpreting. */ ! break; } ! /* If we left the loop early, we should stop interpreting ! altogether. */ ! if (regnum <= r3) break; } else /* An instruction we don't know how to simulate. The only safe thing to do would be to set every value we're tracking ! to 'unknown'. Instead, we'll be optimistic: we just stop ! interpreting, and assume that the machine state we've got ! now is good enough for unwinding the stack. */ ! break; /* Record the address after the last instruction that changed the FP, SP, or backlink. Ignore instructions that changed --- 1488,1664 ---- regnum <= r3; regnum++, offset += 8) { ! compute_x_addr (&addr, data->gpr, d2 + offset, 0, b2); ! s390_store (&addr, 8, &data->gpr[regnum], data); } + } + + /* AHI r1, i2 --- add halfword immediate */ + else if (word_size == 4 + && is_ri (insn, op1_ahi, op2_ahi, &r1, &i2)) + pv_add_constant (&data->gpr[r1], i2); + + /* AGHI r1, i2 --- add halfword immediate (64-bit version) */ + else if (word_size == 8 + && is_ri (insn, op1_aghi, op2_aghi, &r1, &i2)) + pv_add_constant (&data->gpr[r1], i2); + + /* AR r1, r2 -- add register */ + else if (word_size == 4 + && is_rr (insn, op_ar, &r1, &r2)) + pv_add (&data->gpr[r1], &data->gpr[r1], &data->gpr[r2]); + + /* AGR r1, r2 -- add register (64-bit version) */ + else if (word_size == 8 + && is_rre (insn, op_agr, &r1, &r2)) + pv_add (&data->gpr[r1], &data->gpr[r1], &data->gpr[r2]); + + /* A r1, d2(x2, b2) -- add */ + else if (word_size == 4 + && is_rx (insn, op_a, &r1, &d2, &x2, &b2)) + { + struct prologue_value addr; + struct prologue_value value; + + compute_x_addr (&addr, data->gpr, d2, x2, b2); + s390_load (&addr, 4, &value, data); + + pv_add (&data->gpr[r1], &data->gpr[r1], &value); + } + + /* AY r1, d2(x2, b2) -- add (long-displacement version) */ + else if (word_size == 4 + && is_rxy (insn, op1_ay, op2_ay, &r1, &d2, &x2, &b2)) + { + struct prologue_value addr; + struct prologue_value value; + + compute_x_addr (&addr, data->gpr, d2, x2, b2); + s390_load (&addr, 4, &value, data); + + pv_add (&data->gpr[r1], &data->gpr[r1], &value); + } + + /* AG r1, d2(x2, b2) -- add (64-bit version) */ + else if (word_size == 8 + && is_rxy (insn, op1_ag, op2_ag, &r1, &d2, &x2, &b2)) + { + struct prologue_value addr; + struct prologue_value value; + + compute_x_addr (&addr, data->gpr, d2, x2, b2); + s390_load (&addr, 8, &value, data); + + pv_add (&data->gpr[r1], &data->gpr[r1], &value); + } + + /* SR r1, r2 -- subtract register */ + else if (word_size == 4 + && is_rr (insn, op_sr, &r1, &r2)) + pv_subtract (&data->gpr[r1], &data->gpr[r1], &data->gpr[r2]); + + /* SGR r1, r2 -- subtract register (64-bit version) */ + else if (word_size == 8 + && is_rre (insn, op_sgr, &r1, &r2)) + pv_subtract (&data->gpr[r1], &data->gpr[r1], &data->gpr[r2]); + + /* S r1, d2(x2, b2) -- subtract */ + else if (word_size == 4 + && is_rx (insn, op_s, &r1, &d2, &x2, &b2)) + { + struct prologue_value addr; + struct prologue_value value; + + compute_x_addr (&addr, data->gpr, d2, x2, b2); + s390_load (&addr, 4, &value, data); + + pv_subtract (&data->gpr[r1], &data->gpr[r1], &value); + } + + /* SY r1, d2(x2, b2) -- subtract (long-displacement version) */ + else if (word_size == 4 + && is_rxy (insn, op1_sy, op2_sy, &r1, &d2, &x2, &b2)) + { + struct prologue_value addr; + struct prologue_value value; + + compute_x_addr (&addr, data->gpr, d2, x2, b2); + s390_load (&addr, 4, &value, data); + + pv_subtract (&data->gpr[r1], &data->gpr[r1], &value); + } + + /* SG r1, d2(x2, b2) -- subtract (64-bit version) */ + else if (word_size == 8 + && is_rxy (insn, op1_sg, op2_sg, &r1, &d2, &x2, &b2)) + { + struct prologue_value addr; + struct prologue_value value; + + compute_x_addr (&addr, data->gpr, d2, x2, b2); + s390_load (&addr, 8, &value, data); + + pv_subtract (&data->gpr[r1], &data->gpr[r1], &value); + } + + /* NR r1, r2 --- logical and */ + else if (word_size == 4 + && is_rr (insn, op_nr, &r1, &r2)) + pv_logical_and (&data->gpr[r1], &data->gpr[r1], &data->gpr[r2]); + + /* NGR r1, r2 >--- logical and (64-bit version) */ + else if (word_size == 8 + && is_rre (insn, op_ngr, &r1, &r2)) + pv_logical_and (&data->gpr[r1], &data->gpr[r1], &data->gpr[r2]); + + /* LA r1, d2(x2, b2) --- load address */ + else if (is_rx (insn, op_la, &r1, &d2, &x2, &b2)) + compute_x_addr (&data->gpr[r1], data->gpr, d2, x2, b2); + + /* LAY r1, d2(x2, b2) --- load address (long-displacement version) */ + else if (is_rxy (insn, op1_lay, op2_lay, &r1, &d2, &x2, &b2)) + compute_x_addr (&data->gpr[r1], data->gpr, d2, x2, b2); ! /* LARL r1, i2 --- load address relative long */ ! else if (is_ril (insn, op1_larl, op2_larl, &r1, &i2)) ! pv_set_to_constant (&data->gpr[r1], pc + i2 * 2); ! ! /* BASR r1, 0 --- branch and save ! Since r2 is zero, this saves the PC in r1, but doesn't branch. */ ! else if (is_rr (insn, op_basr, &r1, &r2) ! && r2 == 0) ! pv_set_to_constant (&data->gpr[r1], next_pc); ! ! /* BRAS r1, i2 --- branch relative and save */ ! else if (is_ri (insn, op1_bras, op2_bras, &r1, &i2)) ! { ! pv_set_to_constant (&data->gpr[r1], next_pc); ! next_pc = pc + i2 * 2; ! ! /* We'd better not interpret any backward branches. We'll ! never terminate. */ ! if (next_pc <= pc) break; } + /* Terminate search when hitting any other branch instruction. */ + else if (is_rr (insn, op_basr, &r1, &r2) + || is_rx (insn, op_bas, &r1, &d2, &x2, &b2) + || is_rr (insn, op_bcr, &r1, &r2) + || is_rx (insn, op_bc, &r1, &d2, &x2, &b2) + || is_ri (insn, op1_brc, op2_brc, &r1, &i2) + || is_ril (insn, op1_brcl, op2_brcl, &r1, &i2) + || is_ril (insn, op1_brasl, op2_brasl, &r2, &i2)) + break; + else /* An instruction we don't know how to simulate. The only safe thing to do would be to set every value we're tracking ! to 'unknown'. Instead, we'll be optimistic: we assume that ! we *can* interpret every instruction that the compiler uses ! to manipulate any of the data we're interested in here -- ! then we can just ignore anything else. */ ! ; /* Record the address after the last instruction that changed the FP, SP, or backlink. Ignore instructions that changed *************** s390_get_frame_info (CORE_ADDR start_pc, *** 1642,1836 **** restore instructions. (The back chain is never restored, just popped.) */ { ! struct prologue_value *sp = &gpr[S390_SP_REGNUM - S390_R0_REGNUM]; ! struct prologue_value *fp = &gpr[S390_FRAME_REGNUM - S390_R0_REGNUM]; if ((! pv_is_identical (&pre_insn_sp, sp) && ! pv_is_register (sp, S390_SP_REGNUM, 0)) || (! pv_is_identical (&pre_insn_fp, fp) && ! pv_is_register (fp, S390_FRAME_REGNUM, 0)) ! || ! pv_is_identical (&pre_insn_back_chain, &back_chain)) ! after_last_frame_setup_insn = next_pc; } } - /* Okay, now gpr[], fpr[], spill[], and back_chain reflect the state - of the machine as of the first instruction we couldn't interpret - (hopefully the first non-prologue instruction). */ - { - /* The size of the frame, or (CORE_ADDR) -1 if we couldn't figure - that out. */ - CORE_ADDR frame_size = -1; - - /* The value the SP had upon entry to the function, or - (CORE_ADDR) -1 if we can't figure that out. */ - CORE_ADDR original_sp = -1; - - /* Are we using S390_FRAME_REGNUM as a frame pointer register? */ - int using_frame_pointer = 0; - - /* If S390_FRAME_REGNUM is some constant offset from the SP, then - that strongly suggests that we're going to use that as our - frame pointer register, not the SP. */ - { - struct prologue_value *fp = &gpr[S390_FRAME_REGNUM - S390_R0_REGNUM]; - - if (fp->kind == pv_register - && fp->reg == S390_SP_REGNUM) - using_frame_pointer = 1; - } - - /* If we were given a frame_info structure, we may be able to use - the frame's base address to figure out the actual value of the - original SP. */ - if (fi && get_frame_base (fi)) - { - int frame_base_regno; - struct prologue_value *frame_base; - - /* The meaning of the frame base depends on whether the - function uses a frame pointer register other than the SP or - not (see s390_read_fp): - - If the function does use a frame pointer register other - than the SP, then the frame base is that register's - value. - - If the function doesn't use a frame pointer, then the - frame base is the SP itself. - We're duplicating some of the logic of s390_fp_regnum here, - but we don't want to call that, because it would just do - exactly the same analysis we've already done above. */ - if (using_frame_pointer) - frame_base_regno = S390_FRAME_REGNUM; - else - frame_base_regno = S390_SP_REGNUM; - - frame_base = &gpr[frame_base_regno - S390_R0_REGNUM]; - - /* We know the frame base address; if the value of whatever - register it came from is a constant offset from the - original SP, then we can reconstruct the original SP just - by subtracting off that constant. */ - if (frame_base->kind == pv_register - && frame_base->reg == S390_SP_REGNUM) - original_sp = get_frame_base (fi) - frame_base->k; - } - - /* If the analysis said that the current SP value is the original - value less some constant, then that constant is the frame size. */ - { - struct prologue_value *sp = &gpr[S390_SP_REGNUM - S390_R0_REGNUM]; - - if (sp->kind == pv_register - && sp->reg == S390_SP_REGNUM) - frame_size = -sp->k; - } - - /* If we knew other registers' current values, we could check if - the analysis said any of those were related to the original SP - value, too. But for now, we'll just punt. */ - - /* If the caller passed in an 'extra info' structure, fill in the - parts we can. */ - if (fextra_info) - { - if (init_extra_info || ! fextra_info->initialised) - { - s390_memset_extra_info (fextra_info); - fextra_info->function_start = start_pc; - fextra_info->initialised = 1; - } - - if (frame_size != -1) - { - fextra_info->stack_bought_valid = 1; - fextra_info->stack_bought = frame_size; - } - - /* Assume everything was okay, and indicate otherwise when we - find something amiss. */ - fextra_info->good_prologue = 1; - - if (using_frame_pointer) - /* Actually, nobody cares about the exact PC, so any - non-zero value will do here. */ - fextra_info->frame_pointer_saved_pc = 1; - - /* If we weren't able to find the size of the frame, or find - the original sp based on actual current register values, - then we're not going to be able to unwind this frame. - - (If we're just doing prologue analysis to set a breakpoint, - then frame_size might be known, but original_sp unknown; if - we're analyzing a real frame which uses alloca, then - original_sp might be known (from the frame pointer - register), but the frame size might be unknown.) */ - if (original_sp == -1 && frame_size == -1) - fextra_info->good_prologue = 0; - - if (fextra_info->good_prologue) - fextra_info->skip_prologue_function_start - = after_last_frame_setup_insn; - else - /* If the prologue was too complex for us to make sense of, - then perhaps it's better to just not skip anything at - all. */ - fextra_info->skip_prologue_function_start = start_pc; - } - - /* Indicate where registers were saved on the stack, if: - - the caller seems to want to know, - - the caller provided an actual SP, and - - the analysis gave us enough information to actually figure it - out. */ - if (fi - && deprecated_get_frame_saved_regs (fi) - && original_sp != -1) - { - int slot_num; - CORE_ADDR slot_addr; - CORE_ADDR *saved_regs = deprecated_get_frame_saved_regs (fi); - - /* Scan the spill array; if a spill slot says it holds the - original value of some register, then record that slot's - address as the place that register was saved. - - Just for kicks, note that, even if registers aren't saved - in their officially-sanctioned slots, this will still work - --- we know what really got put where. */ - - /* First, the slots for r2 -- r15. */ - for (slot_num = 0, slot_addr = original_sp + 2 * S390_GPR_SIZE; - slot_num < 14; - slot_num++, slot_addr += S390_GPR_SIZE) - { - struct prologue_value *slot = &spill[slot_num]; - - if (slot->kind == pv_register - && slot->k == 0) - saved_regs[slot->reg] = slot_addr; - } - - /* Then, the slots for f0, f2, f4, and f6. They're a - different size. */ - for (slot_num = 14, slot_addr = original_sp + 16 * S390_GPR_SIZE; - slot_num < S390_NUM_SPILL_SLOTS; - slot_num++, slot_addr += S390_FPR_SIZE) - { - struct prologue_value *slot = &spill[slot_num]; - - if (slot->kind == pv_register - && slot->k == 0) - saved_regs[slot->reg] = slot_addr; - } - - /* The stack pointer's element of saved_regs[] is special. */ - saved_regs[S390_SP_REGNUM] = original_sp; - } - } - return result; } /* Return true if we are in the functin's epilogue, i.e. after the instruction that destroyed the function's stack frame. */ static int --- 1666,1697 ---- restore instructions. (The back chain is never restored, just popped.) */ { ! struct prologue_value *sp = &data->gpr[S390_SP_REGNUM - S390_R0_REGNUM]; ! struct prologue_value *fp = &data->gpr[S390_FRAME_REGNUM - S390_R0_REGNUM]; if ((! pv_is_identical (&pre_insn_sp, sp) && ! pv_is_register (sp, S390_SP_REGNUM, 0)) || (! pv_is_identical (&pre_insn_fp, fp) && ! pv_is_register (fp, S390_FRAME_REGNUM, 0)) ! || ! pv_is_identical (&pre_insn_back_chain, &data->back_chain)) ! result = next_pc; } } return result; } + /* Advance PC across any function entry prologue instructions to reach + some "real" code. */ + static CORE_ADDR + s390_skip_prologue (CORE_ADDR pc) + { + struct s390_prologue_data data; + CORE_ADDR skip_pc; + skip_pc = s390_analyze_prologue (current_gdbarch, pc, (CORE_ADDR)-1, &data); + return skip_pc ? skip_pc : pc; + } + /* Return true if we are in the functin's epilogue, i.e. after the instruction that destroyed the function's stack frame. */ static int *************** s390_in_function_epilogue_p (struct gdba *** 1867,2340 **** && r3 == S390_SP_REGNUM - S390_R0_REGNUM) return 1; if (word_size == 8 && !read_memory_nobpt (pc - 6, insn, 6) ! && is_rse (insn, op1_lmg, op2_lmg, &r1, &r3, &d2, &b2) && r3 == S390_SP_REGNUM - S390_R0_REGNUM) return 1; return 0; } static int ! s390_check_function_end (CORE_ADDR pc) { ! bfd_byte instr[S390_MAX_INSTR_SIZE]; ! int regidx, instrlen; ! instrlen = s390_readinstruction (instr, pc); ! if (instrlen < 0) ! return -1; ! /* check for BR */ ! if (instrlen != 2 || instr[0] != 07 || (instr[1] >> 4) != 0xf) return 0; - regidx = instr[1] & 0xf; - /* Check for LMG or LG */ - instrlen = - s390_readinstruction (instr, pc - (GDB_TARGET_IS_ESAME ? 6 : 4)); - if (instrlen < 0) - return -1; - if (GDB_TARGET_IS_ESAME) - { ! if (instrlen != 6 || instr[0] != 0xeb || instr[5] != 0x4) return 0; } ! else if (instrlen != 4 || instr[0] != 0x98) { ! return 0; } ! if ((instr[2] >> 4) != 0xf) ! return 0; ! if (regidx == 14) ! return 1; ! instrlen = s390_readinstruction (instr, pc - (GDB_TARGET_IS_ESAME ? 12 : 8)); ! if (instrlen < 0) ! return -1; ! if (GDB_TARGET_IS_ESAME) { ! /* Check for LG */ ! if (instrlen != 6 || instr[0] != 0xe3 || instr[5] != 0x4) ! return 0; } ! else { ! /* Check for L */ ! if (instrlen != 4 || instr[0] != 0x58) ! return 0; } ! if (instr[2] >> 4 != 0xf) ! return 0; ! if (instr[1] >> 4 != regidx) ! return 0; return 1; } ! static CORE_ADDR ! s390_sniff_pc_function_start (CORE_ADDR pc, struct frame_info *fi) { ! CORE_ADDR function_start, test_function_start; ! int loop_cnt, err, function_end; ! struct frame_extra_info fextra_info; ! function_start = get_pc_function_start (pc); ! ! if (function_start == 0) ! { ! test_function_start = pc; ! if (test_function_start & 1) ! return 0; /* This has to be bogus */ ! loop_cnt = 0; ! do ! { ! err = ! s390_get_frame_info (test_function_start, &fextra_info, fi, 1); ! loop_cnt++; ! test_function_start -= 2; ! function_end = s390_check_function_end (test_function_start); ! } ! while (!(function_end == 1 || err || loop_cnt >= 4096 || ! (fextra_info.good_prologue))); ! if (fextra_info.good_prologue) ! function_start = fextra_info.function_start; ! else if (function_end == 1) ! function_start = test_function_start; } ! return function_start; } ! static CORE_ADDR ! s390_function_start (struct frame_info *fi) ! { ! CORE_ADDR function_start = 0; ! if (get_frame_extra_info (fi) && get_frame_extra_info (fi)->initialised) ! function_start = get_frame_extra_info (fi)->function_start; ! else if (get_frame_pc (fi)) ! function_start = get_frame_func (fi); ! return function_start; } ! static int ! s390_frameless_function_invocation (struct frame_info *fi) { ! struct frame_extra_info fextra_info, *fextra_info_ptr; ! int frameless = 0; ! if (get_next_frame (fi) == NULL) /* no may be frameless */ ! { ! if (get_frame_extra_info (fi)) ! fextra_info_ptr = get_frame_extra_info (fi); ! else ! { ! fextra_info_ptr = &fextra_info; ! s390_get_frame_info (s390_sniff_pc_function_start (get_frame_pc (fi), fi), ! fextra_info_ptr, fi, 1); ! } ! frameless = (fextra_info_ptr->stack_bought_valid ! && fextra_info_ptr->stack_bought == 0); ! } ! return frameless; } ! static int ! s390_is_sigreturn (CORE_ADDR pc, struct frame_info *sighandler_fi, ! CORE_ADDR *sregs, CORE_ADDR *sigcaller_pc) { ! bfd_byte instr[S390_MAX_INSTR_SIZE]; ! int instrlen; ! CORE_ADDR scontext; ! int retval = 0; ! CORE_ADDR orig_sp; ! CORE_ADDR temp_sregs; ! ! scontext = temp_sregs = 0; ! ! instrlen = s390_readinstruction (instr, pc); ! if (sigcaller_pc) ! *sigcaller_pc = 0; ! if (((instrlen == S390_SYSCALL_SIZE) && ! (instr[0] == S390_SYSCALL_OPCODE)) && ! ((instr[1] == s390_NR_sigreturn) || (instr[1] == s390_NR_rt_sigreturn))) ! { ! if (sighandler_fi) ! { ! if (s390_frameless_function_invocation (sighandler_fi)) ! orig_sp = get_frame_base (sighandler_fi); ! else ! orig_sp = ADDR_BITS_REMOVE ((CORE_ADDR) ! read_memory_integer (get_frame_base (sighandler_fi), ! S390_GPR_SIZE)); ! if (orig_sp && sigcaller_pc) ! { ! scontext = orig_sp + S390_SIGNAL_FRAMESIZE; ! if (pc == scontext && instr[1] == s390_NR_rt_sigreturn) ! { ! /* We got a new style rt_signal */ ! /* get address of read ucontext->uc_mcontext */ ! temp_sregs = orig_sp + (GDB_TARGET_IS_ESAME ? ! S390X_UC_MCONTEXT_OFFSET : ! S390_UC_MCONTEXT_OFFSET); ! } ! else ! { ! /* read sigcontext->sregs */ ! temp_sregs = ADDR_BITS_REMOVE ((CORE_ADDR) ! read_memory_integer (scontext ! + ! (GDB_TARGET_IS_ESAME ! ? ! S390X_SIGCONTEXT_SREGS_OFFSET ! : ! S390_SIGCONTEXT_SREGS_OFFSET), ! S390_GPR_SIZE)); ! ! } ! /* read sigregs->psw.addr */ ! *sigcaller_pc = ! ADDR_BITS_REMOVE ((CORE_ADDR) ! read_memory_integer (temp_sregs + ! DEPRECATED_REGISTER_BYTE (S390_PSWA_REGNUM), ! S390_GPR_SIZE)); ! } ! } ! retval = 1; ! } ! if (sregs) ! *sregs = temp_sregs; ! return retval; } ! /* ! We need to do something better here but this will keep us out of trouble ! for the moment. ! For some reason the blockframe.c calls us with fi->next->fromleaf ! so this seems of little use to us. */ ! static CORE_ADDR ! s390_init_frame_pc_first (int next_fromleaf, struct frame_info *fi) { ! CORE_ADDR sigcaller_pc; ! CORE_ADDR pc = 0; ! if (next_fromleaf) ! { ! pc = ADDR_BITS_REMOVE (read_register (S390_RETADDR_REGNUM)); ! /* fix signal handlers */ ! } ! else if (get_next_frame (fi) && get_frame_pc (get_next_frame (fi))) ! pc = s390_frame_saved_pc_nofix (get_next_frame (fi)); ! if (pc && get_next_frame (fi) && get_frame_base (get_next_frame (fi)) ! && s390_is_sigreturn (pc, get_next_frame (fi), NULL, &sigcaller_pc)) ! { ! pc = sigcaller_pc; ! } ! return pc; } static void ! s390_init_extra_frame_info (int fromleaf, struct frame_info *fi) { ! frame_extra_info_zalloc (fi, sizeof (struct frame_extra_info)); ! if (get_frame_pc (fi)) ! s390_get_frame_info (s390_sniff_pc_function_start (get_frame_pc (fi), fi), ! get_frame_extra_info (fi), fi, 1); ! else ! s390_memset_extra_info (get_frame_extra_info (fi)); } ! /* If saved registers of frame FI are not known yet, read and cache them. ! &FEXTRA_INFOP contains struct frame_extra_info; TDATAP can be NULL, ! in which case the framedata are read. */ ! static void ! s390_frame_init_saved_regs (struct frame_info *fi) { ! int quick; ! ! if (deprecated_get_frame_saved_regs (fi) == NULL) ! { ! /* zalloc memsets the saved regs */ ! frame_saved_regs_zalloc (fi); ! if (get_frame_pc (fi)) ! { ! quick = (get_frame_extra_info (fi) ! && get_frame_extra_info (fi)->initialised ! && get_frame_extra_info (fi)->good_prologue); ! s390_get_frame_info (quick ! ? get_frame_extra_info (fi)->function_start ! : s390_sniff_pc_function_start (get_frame_pc (fi), fi), ! get_frame_extra_info (fi), fi, !quick); ! } ! } } ! static CORE_ADDR ! s390_frame_saved_pc_nofix (struct frame_info *fi) { ! if (get_frame_extra_info (fi) && get_frame_extra_info (fi)->saved_pc_valid) ! return get_frame_extra_info (fi)->saved_pc; ! if (deprecated_generic_find_dummy_frame (get_frame_pc (fi), ! get_frame_base (fi))) ! return deprecated_read_register_dummy (get_frame_pc (fi), ! get_frame_base (fi), S390_PC_REGNUM); ! ! s390_frame_init_saved_regs (fi); ! if (get_frame_extra_info (fi)) ! { ! get_frame_extra_info (fi)->saved_pc_valid = 1; ! if (get_frame_extra_info (fi)->good_prologue ! && deprecated_get_frame_saved_regs (fi)[S390_RETADDR_REGNUM]) ! get_frame_extra_info (fi)->saved_pc ! = ADDR_BITS_REMOVE (read_memory_integer ! (deprecated_get_frame_saved_regs (fi)[S390_RETADDR_REGNUM], ! S390_GPR_SIZE)); ! else ! get_frame_extra_info (fi)->saved_pc ! = ADDR_BITS_REMOVE (read_register (S390_RETADDR_REGNUM)); ! return get_frame_extra_info (fi)->saved_pc; ! } ! return 0; ! } ! static CORE_ADDR ! s390_frame_saved_pc (struct frame_info *fi) ! { ! CORE_ADDR saved_pc = 0, sig_pc; ! if (get_frame_extra_info (fi) ! && get_frame_extra_info (fi)->sig_fixed_saved_pc_valid) ! return get_frame_extra_info (fi)->sig_fixed_saved_pc; ! saved_pc = s390_frame_saved_pc_nofix (fi); ! if (get_frame_extra_info (fi)) { ! get_frame_extra_info (fi)->sig_fixed_saved_pc_valid = 1; ! if (saved_pc) ! { ! if (s390_is_sigreturn (saved_pc, fi, NULL, &sig_pc)) ! saved_pc = sig_pc; ! } ! get_frame_extra_info (fi)->sig_fixed_saved_pc = saved_pc; } - return saved_pc; - } ! /* We want backtraces out of signal handlers so we don't set ! (get_frame_type (thisframe) == SIGTRAMP_FRAME) to 1 */ ! static CORE_ADDR ! s390_frame_chain (struct frame_info *thisframe) ! { ! CORE_ADDR prev_fp = 0; ! if (deprecated_generic_find_dummy_frame (get_frame_pc (thisframe), ! get_frame_base (thisframe))) ! return deprecated_read_register_dummy (get_frame_pc (thisframe), ! get_frame_base (thisframe), ! S390_SP_REGNUM); ! else { ! int sigreturn = 0; ! CORE_ADDR sregs = 0; ! struct frame_extra_info prev_fextra_info; ! memset (&prev_fextra_info, 0, sizeof (prev_fextra_info)); ! if (get_frame_pc (thisframe)) ! { ! CORE_ADDR saved_pc, sig_pc; ! saved_pc = s390_frame_saved_pc_nofix (thisframe); ! if (saved_pc) ! { ! if ((sigreturn = ! s390_is_sigreturn (saved_pc, thisframe, &sregs, &sig_pc))) ! saved_pc = sig_pc; ! s390_get_frame_info (s390_sniff_pc_function_start ! (saved_pc, NULL), &prev_fextra_info, NULL, ! 1); ! } ! } ! if (sigreturn) ! { ! /* read sigregs,regs.gprs[11 or 15] */ ! prev_fp = read_memory_integer (sregs + ! DEPRECATED_REGISTER_BYTE (S390_R0_REGNUM + ! (prev_fextra_info. ! frame_pointer_saved_pc ! ? 11 : 15)), ! S390_GPR_SIZE); ! get_frame_extra_info (thisframe)->sigcontext = sregs; ! } ! else ! { ! if (deprecated_get_frame_saved_regs (thisframe)) ! { ! int regno; ! ! if (prev_fextra_info.frame_pointer_saved_pc ! && deprecated_get_frame_saved_regs (thisframe)[S390_FRAME_REGNUM]) ! regno = S390_FRAME_REGNUM; ! else ! regno = S390_SP_REGNUM; ! ! if (deprecated_get_frame_saved_regs (thisframe)[regno]) ! { ! /* The SP's entry of `saved_regs' is special. */ ! if (regno == S390_SP_REGNUM) ! prev_fp = deprecated_get_frame_saved_regs (thisframe)[regno]; ! else ! prev_fp = ! read_memory_integer (deprecated_get_frame_saved_regs (thisframe)[regno], ! S390_GPR_SIZE); ! } ! } ! } } - return ADDR_BITS_REMOVE (prev_fp); - } ! /* ! Whether struct frame_extra_info is actually needed I'll have to figure ! out as our frames are similar to rs6000 there is a possibility ! i386 dosen't need it. */ ! /* Not the most efficent code in the world */ ! static int ! s390_fp_regnum (void) ! { ! int regno = S390_SP_REGNUM; ! struct frame_extra_info fextra_info; ! CORE_ADDR pc = ADDR_BITS_REMOVE (read_register (S390_PC_REGNUM)); ! s390_get_frame_info (s390_sniff_pc_function_start (pc, NULL), &fextra_info, ! NULL, 1); ! if (fextra_info.frame_pointer_saved_pc) ! regno = S390_FRAME_REGNUM; ! return regno; } ! static CORE_ADDR ! s390_read_fp (void) { ! return read_register (s390_fp_regnum ()); } ! static void ! s390_pop_frame_regular (struct frame_info *frame) { ! int regnum; ! write_register (S390_PC_REGNUM, DEPRECATED_FRAME_SAVED_PC (frame)); ! /* Restore any saved registers. */ ! if (deprecated_get_frame_saved_regs (frame)) ! { ! for (regnum = 0; regnum < NUM_REGS; regnum++) ! if (deprecated_get_frame_saved_regs (frame)[regnum] != 0) ! { ! ULONGEST value; ! ! value = read_memory_unsigned_integer (deprecated_get_frame_saved_regs (frame)[regnum], ! DEPRECATED_REGISTER_RAW_SIZE (regnum)); ! write_register (regnum, value); ! } ! /* Actually cut back the stack. Remember that the SP's element of ! saved_regs is the old SP itself, not the address at which it is ! saved. */ ! write_register (S390_SP_REGNUM, deprecated_get_frame_saved_regs (frame)[S390_SP_REGNUM]); ! } ! /* Throw away any cached frame information. */ ! flush_cached_frames (); } ! /* Destroy the innermost (Top-Of-Stack) stack frame, restoring the ! machine state that was in effect before the frame was created. ! Used in the contexts of the "return" command, and of ! target function calls from the debugger. */ ! static void ! s390_pop_frame (void) { ! /* This function checks for and handles generic dummy frames, and ! calls back to our function for ordinary frames. */ ! generic_pop_current_frame (s390_pop_frame_regular); } --- 1728,2300 ---- && r3 == S390_SP_REGNUM - S390_R0_REGNUM) return 1; + if (word_size == 4 + && !read_memory_nobpt (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 && !read_memory_nobpt (pc - 6, insn, 6) ! && is_rsy (insn, op1_lmg, op2_lmg, &r1, &r3, &d2, &b2) && r3 == S390_SP_REGNUM - S390_R0_REGNUM) return 1; return 0; } + + /* Normal stack frames. */ + + struct s390_unwind_cache { + + CORE_ADDR func; + CORE_ADDR frame_base; + CORE_ADDR local_base; + + struct trad_frame_saved_reg *saved_regs; + }; + static int ! s390_prologue_frame_unwind_cache (struct frame_info *next_frame, ! struct s390_unwind_cache *info) { ! struct gdbarch *gdbarch = get_frame_arch (next_frame); ! int word_size = gdbarch_ptr_bit (gdbarch) / 8; ! struct s390_prologue_data data; ! struct prologue_value *fp = &data.gpr[S390_FRAME_REGNUM - S390_R0_REGNUM]; ! struct prologue_value *sp = &data.gpr[S390_SP_REGNUM - S390_R0_REGNUM]; ! int slot_num; ! CORE_ADDR slot_addr; ! CORE_ADDR func; ! CORE_ADDR result; ! ULONGEST reg; ! CORE_ADDR prev_sp; ! int frame_pointer; ! int size; ! ! /* Try to find the function start address. If we can't find it, we don't ! 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); ! if (!func) ! return 0; ! /* Try to analyze the prologue. */ ! result = s390_analyze_prologue (gdbarch, func, ! frame_pc_unwind (next_frame), &data); ! if (!result) ! return 0; ! ! /* If this was successful, we should have found the instruction that ! sets the stack pointer register to the previous value of the stack ! pointer minus the frame size. */ ! if (sp->kind != pv_register || sp->reg != S390_SP_REGNUM) return 0; ! /* A frame size of zero at this point can mean either a real ! frameless function, or else a failure to find the prologue. ! Perform some sanity checks to verify we really have a ! frameless function. */ ! if (sp->k == 0) ! { ! /* If the next frame is a NORMAL_FRAME, this frame *cannot* have frame ! size zero. This is only possible if the next frame is a sentinel ! frame, a dummy frame, or a signal trampoline frame. */ ! if (get_frame_type (next_frame) == NORMAL_FRAME ! /* For some reason, sentinel frames are NORMAL_FRAMEs ! -- but they have negative frame level. */ ! && frame_relative_level (next_frame) >= 0) 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 = gdbarch_addr_bits_remove (gdbarch, reg) - 1; + if (get_pc_function_start (reg) == func) + { + /* However, there is one case where it *is* valid for %r14 + to point to the same function -- if this is a recursive + call, and we have stopped in the prologue *before* the + stack frame was allocated. + + Recognize this case by looking ahead a bit ... */ + + struct s390_prologue_data data2; + struct prologue_value *sp = &data2.gpr[S390_SP_REGNUM - S390_R0_REGNUM]; + + if (!(s390_analyze_prologue (gdbarch, func, (CORE_ADDR)-1, &data2) + && sp->kind == pv_register + && sp->reg == S390_SP_REGNUM + && sp->k != 0)) + return 0; + } + } + + + /* OK, we've found valid prologue data. */ + size = -sp->k; + + /* If the frame pointer originally also holds the same value + as the stack pointer, we're probably using it. If it holds + some other value -- even a constant offset -- it is most + likely used as temp register. */ + if (pv_is_identical (sp, fp)) + frame_pointer = S390_FRAME_REGNUM; + else + frame_pointer = S390_SP_REGNUM; + + /* If we've detected a function with stack frame, we'll still have to + treat it as frameless if we're currently within the function epilog + code at a point where the frame pointer has already been restored. + This can only happen in an innermost frame. */ + if (size > 0 + && (get_frame_type (next_frame) != NORMAL_FRAME + || frame_relative_level (next_frame) < 0)) + { + /* 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))) + { + memset (&data, 0, sizeof (data)); + size = 0; + frame_pointer = S390_SP_REGNUM; + } } ! ! /* Once we know the frame register and the frame size, we can unwind ! 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; ! ! /* Scan the spill array; if a spill slot says it holds the ! original value of some register, then record that slot's ! address as the place that register was saved. */ ! ! /* Slots for %r2 .. %r15. */ ! for (slot_num = 0, slot_addr = prev_sp + 2 * data.gpr_size; ! slot_num < 14; ! slot_num++, slot_addr += data.gpr_size) { ! struct prologue_value *slot = &data.spill[slot_num]; ! ! if (slot->kind == pv_register ! && slot->k == 0) ! info->saved_regs[slot->reg].addr = slot_addr; } ! ! /* Slots for %f0 .. %f6. */ ! for (slot_num = 14, slot_addr = prev_sp + 16 * data.gpr_size; ! slot_num < S390_NUM_SPILL_SLOTS; ! slot_num++, slot_addr += data.fpr_size) { ! struct prologue_value *slot = &data.spill[slot_num]; ! ! if (slot->kind == pv_register ! && slot->k == 0) ! info->saved_regs[slot->reg].addr = slot_addr; } ! ! /* Function return will set PC to %r14. */ ! info->saved_regs[S390_PC_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, S390_PC_REGNUM)) { ! info->saved_regs[S390_PC_REGNUM].realreg = S390_RETADDR_REGNUM; } ! ! /* Another sanity check: unless this is a frameless function, ! we should have found spill slots for SP and PC. ! If not, we cannot unwind further -- this happens e.g. in ! 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_PC_REGNUM)) ! prev_sp = -1; ! } ! ! /* We use the current value of the frame register as local_base, ! and the top of the register save area as frame_base. */ ! if (prev_sp != -1) ! { ! info->frame_base = prev_sp + 16*word_size + 32; ! info->local_base = prev_sp - size; ! } ! ! info->func = func; return 1; } ! static void ! s390_backchain_frame_unwind_cache (struct frame_info *next_frame, ! struct s390_unwind_cache *info) { ! struct gdbarch *gdbarch = get_frame_arch (next_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); ! backchain = read_memory_unsigned_integer (reg, word_size); ! ! /* A zero backchain terminates the frame chain. As additional ! sanity check, let's verify that the spill slot for SP in the ! save area pointed to by the backchain in fact links back to ! the save area. */ ! if (backchain != 0 ! && safe_read_memory_integer (backchain + 15*word_size, word_size, &sp) ! && (CORE_ADDR)sp == backchain) ! { ! /* 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; ! ! /* Function return will set PC to %r14. */ ! info->saved_regs[S390_PC_REGNUM] = info->saved_regs[S390_RETADDR_REGNUM]; ! ! /* We use the current value of the frame register as local_base, ! and the top of the register save area as frame_base. */ ! info->frame_base = backchain + 16*word_size + 32; ! info->local_base = reg; } ! ! info->func = frame_pc_unwind (next_frame); } + static struct s390_unwind_cache * + s390_frame_unwind_cache (struct frame_info *next_frame, + void **this_prologue_cache) + { + struct s390_unwind_cache *info; + if (*this_prologue_cache) + return *this_prologue_cache; + info = FRAME_OBSTACK_ZALLOC (struct s390_unwind_cache); + *this_prologue_cache = info; + info->saved_regs = trad_frame_alloc_saved_regs (next_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); ! return info; } + static void + s390_frame_this_id (struct frame_info *next_frame, + void **this_prologue_cache, + struct frame_id *this_id) + { + struct s390_unwind_cache *info + = s390_frame_unwind_cache (next_frame, this_prologue_cache); + if (info->frame_base == -1) + return; + *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, void *bufferp) { ! struct s390_unwind_cache *info ! = s390_frame_unwind_cache (next_frame, this_prologue_cache); ! trad_frame_prev_register (next_frame, info->saved_regs, regnum, ! optimizedp, lvalp, addrp, realnump, bufferp); ! } ! static const struct frame_unwind s390_frame_unwind = { ! NORMAL_FRAME, ! s390_frame_this_id, ! s390_frame_prev_register ! }; + static const struct frame_unwind * + s390_frame_sniffer (struct frame_info *next_frame) + { + return &s390_frame_unwind; } ! /* PLT stub stack frames. */ ! ! struct s390_pltstub_unwind_cache { ! ! CORE_ADDR frame_base; ! struct trad_frame_saved_reg *saved_regs; ! }; ! ! static struct s390_pltstub_unwind_cache * ! s390_pltstub_frame_unwind_cache (struct frame_info *next_frame, ! void **this_prologue_cache) { ! struct gdbarch *gdbarch = get_frame_arch (next_frame); ! int word_size = gdbarch_ptr_bit (gdbarch) / 8; ! struct s390_pltstub_unwind_cache *info; ! ULONGEST reg; ! ! if (*this_prologue_cache) ! return *this_prologue_cache; ! ! info = FRAME_OBSTACK_ZALLOC (struct s390_pltstub_unwind_cache); ! *this_prologue_cache = info; ! info->saved_regs = trad_frame_alloc_saved_regs (next_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); ! info->frame_base = reg + 16*word_size + 32; ! ! return info; } ! static void ! s390_pltstub_frame_this_id (struct frame_info *next_frame, ! void **this_prologue_cache, ! struct frame_id *this_id) { ! struct s390_pltstub_unwind_cache *info ! = s390_pltstub_frame_unwind_cache (next_frame, this_prologue_cache); ! *this_id = frame_id_build (info->frame_base, frame_pc_unwind (next_frame)); } static void ! s390_pltstub_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, void *bufferp) { ! struct s390_pltstub_unwind_cache *info ! = s390_pltstub_frame_unwind_cache (next_frame, this_prologue_cache); ! trad_frame_prev_register (next_frame, info->saved_regs, regnum, ! optimizedp, lvalp, addrp, realnump, bufferp); } ! static const struct frame_unwind s390_pltstub_frame_unwind = { ! NORMAL_FRAME, ! s390_pltstub_frame_this_id, ! s390_pltstub_frame_prev_register ! }; ! static const struct frame_unwind * ! s390_pltstub_frame_sniffer (struct frame_info *next_frame) { + if (!in_plt_section (frame_pc_unwind (next_frame), NULL)) + return NULL; ! return &s390_pltstub_frame_unwind; } + /* Signal trampoline stack frames. */ ! struct s390_sigtramp_unwind_cache { ! CORE_ADDR frame_base; ! struct trad_frame_saved_reg *saved_regs; ! }; ! ! static struct s390_sigtramp_unwind_cache * ! s390_sigtramp_frame_unwind_cache (struct frame_info *next_frame, ! void **this_prologue_cache) { ! struct gdbarch *gdbarch = get_frame_arch (next_frame); ! int word_size = gdbarch_ptr_bit (gdbarch) / 8; ! struct s390_sigtramp_unwind_cache *info; ! ULONGEST this_sp, prev_sp; ! CORE_ADDR next_ra, next_cfa, sigreg_ptr; ! int i; ! if (*this_prologue_cache) ! return *this_prologue_cache; ! info = FRAME_OBSTACK_ZALLOC (struct s390_sigtramp_unwind_cache); ! *this_prologue_cache = info; ! info->saved_regs = trad_frame_alloc_saved_regs (next_frame); ! this_sp = frame_unwind_register_unsigned (next_frame, S390_SP_REGNUM); ! next_ra = frame_pc_unwind (next_frame); ! next_cfa = this_sp + 16*word_size + 32; ! /* New-style RT frame: ! retcode + alignment (8 bytes) ! siginfo (128 bytes) ! ucontext (contains sigregs at offset 5 words) */ ! if (next_ra == next_cfa) { ! sigreg_ptr = next_cfa + 8 + 128 + 5*word_size; } + /* Old-style RT frame and all non-RT frames: + old signal mask (8 bytes) + pointer to sigregs */ + else + { + sigreg_ptr = read_memory_unsigned_integer (next_cfa + 8, word_size); + } + /* The sigregs structure looks like this: + long psw_mask; + long psw_addr; + long gprs[16]; + int acrs[16]; + int fpc; + int __pad; + double fprs[16]; */ + /* Let's ignore the PSW mask, it will not be restored anyway. */ + sigreg_ptr += word_size; ! /* Next comes the PSW address. */ ! info->saved_regs[S390_PC_REGNUM].addr = sigreg_ptr; ! sigreg_ptr += word_size; ! /* Then the GPRs. */ ! for (i = 0; i < 16; i++) ! { ! info->saved_regs[S390_R0_REGNUM + i].addr = sigreg_ptr; ! sigreg_ptr += word_size; ! } ! /* Then the ACRs. */ ! for (i = 0; i < 16; i++) { ! info->saved_regs[S390_A0_REGNUM + i].addr = sigreg_ptr; ! sigreg_ptr += 4; ! } ! /* The floating-point control word. */ ! info->saved_regs[S390_FPC_REGNUM].addr = sigreg_ptr; ! sigreg_ptr += 8; ! /* And finally the FPRs. */ ! for (i = 0; i < 16; i++) ! { ! info->saved_regs[S390_F0_REGNUM + i].addr = sigreg_ptr; ! sigreg_ptr += 8; } ! /* Restore the previous frame's SP. */ ! prev_sp = read_memory_unsigned_integer ( ! info->saved_regs[S390_SP_REGNUM].addr, ! word_size); ! /* Determine our frame base. */ ! info->frame_base = prev_sp + 16*word_size + 32; ! return info; ! } ! static void ! s390_sigtramp_frame_this_id (struct frame_info *next_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)); } ! 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, void *bufferp) { ! struct s390_sigtramp_unwind_cache *info ! = s390_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache); ! trad_frame_prev_register (next_frame, info->saved_regs, regnum, ! optimizedp, lvalp, addrp, realnump, bufferp); } + 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) { ! CORE_ADDR pc = frame_pc_unwind (next_frame); ! bfd_byte sigreturn[2]; ! if (read_memory_nobpt (pc, sigreturn, 2)) ! return NULL; ! if (sigreturn[0] != 0x0a /* svc */) ! return NULL; ! if (sigreturn[1] != 119 /* sigreturn */ ! && sigreturn[1] != 173 /* rt_sigreturn */) ! return NULL; ! ! return &s390_sigtramp_frame_unwind; ! } ! ! ! /* Frame base handling. */ ! ! static CORE_ADDR ! s390_frame_base_address (struct frame_info *next_frame, void **this_cache) ! { ! struct s390_unwind_cache *info ! = s390_frame_unwind_cache (next_frame, this_cache); ! return info->frame_base; ! } ! static CORE_ADDR ! s390_local_base_address (struct frame_info *next_frame, void **this_cache) ! { ! struct s390_unwind_cache *info ! = s390_frame_unwind_cache (next_frame, this_cache); ! return info->local_base; } + static const struct frame_base s390_frame_base = { + &s390_frame_unwind, + s390_frame_base_address, + s390_local_base_address, + s390_local_base_address + }; ! static CORE_ADDR ! s390_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) { ! ULONGEST pc; ! pc = frame_unwind_register_unsigned (next_frame, S390_PC_REGNUM); ! return gdbarch_addr_bits_remove (gdbarch, pc); ! } ! ! static CORE_ADDR ! s390_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) ! { ! ULONGEST sp; ! sp = frame_unwind_register_unsigned (next_frame, S390_SP_REGNUM); ! return gdbarch_addr_bits_remove (gdbarch, sp); } *************** s390_push_dummy_call (struct gdbarch *gd *** 2703,2710 **** /* Store updated stack pointer. */ regcache_cooked_write_unsigned (regcache, S390_SP_REGNUM, sp); ! /* Return stack pointer. */ ! return sp; } /* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that --- 2663,2672 ---- /* Store updated stack pointer. */ regcache_cooked_write_unsigned (regcache, S390_SP_REGNUM, sp); ! /* We need to return the 'stack part' of the frame ID, ! which is actually the top of the register save area ! allocated on the original stack. */ ! return orig_sp + 16*word_size + 32; } /* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that *************** s390_push_dummy_call (struct gdbarch *gd *** 2714,2722 **** static struct frame_id s390_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) { ! ULONGEST sp; ! frame_unwind_unsigned_register (next_frame, S390_SP_REGNUM, &sp); ! return frame_id_build (sp, frame_pc_unwind (next_frame)); } static CORE_ADDR --- 2676,2687 ---- static struct frame_id s390_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) { ! int word_size = gdbarch_ptr_bit (gdbarch) / 8; ! CORE_ADDR this_sp = s390_unwind_sp (gdbarch, next_frame); ! CORE_ADDR prev_sp = read_memory_unsigned_integer (this_sp, word_size); ! ! return frame_id_build (prev_sp + 16*word_size + 32, ! frame_pc_unwind (next_frame)); } static CORE_ADDR *************** s390_return_value (struct gdbarch *gdbar *** 2832,2837 **** --- 2797,2804 ---- } + /* Breakpoints. */ + static const unsigned char * s390_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) { *************** s390_breakpoint_from_pc (CORE_ADDR *pcpt *** 2841,2871 **** return breakpoint; } - /* Advance PC across any function entry prologue instructions to reach some - "real" code. */ - static CORE_ADDR - s390_skip_prologue (CORE_ADDR pc) - { - struct frame_extra_info fextra_info; ! s390_get_frame_info (pc, &fextra_info, NULL, 1); ! return fextra_info.skip_prologue_function_start; ! } ! ! /* Immediately after a function call, return the saved pc. ! Can't go through the frames for this because on some machines ! the new frame is not set up until the new function executes ! some instructions. */ ! static CORE_ADDR ! s390_saved_pc_after_call (struct frame_info *frame) ! { ! return ADDR_BITS_REMOVE (read_register (S390_RETADDR_REGNUM)); ! } static CORE_ADDR s390_addr_bits_remove (CORE_ADDR addr) { ! return (addr) & 0x7fffffff; } static int --- 2808,2820 ---- return breakpoint; } ! /* Address handling. */ static CORE_ADDR s390_addr_bits_remove (CORE_ADDR addr) { ! return addr & 0x7fffffff; } static int *************** s390_address_class_name_to_type_flags (s *** 2899,2904 **** --- 2848,2856 ---- return 0; } + + /* Set up gdbarch struct. */ + static struct gdbarch * s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { *************** s390_gdbarch_init (struct gdbarch_info i *** 2918,2960 **** tdep = XCALLOC (1, struct gdbarch_tdep); gdbarch = gdbarch_alloc (&info, tdep); - /* NOTE: cagney/2002-12-06: This can be deleted when this arch is - ready to unwind the PC first (see frame.c:get_prev_frame()). */ - set_gdbarch_deprecated_init_frame_pc (gdbarch, deprecated_init_frame_pc_default); - set_gdbarch_believe_pcc_promotion (gdbarch, 0); set_gdbarch_char_signed (gdbarch, 0); set_gdbarch_frame_args_skip (gdbarch, 0); ! set_gdbarch_deprecated_frame_chain (gdbarch, s390_frame_chain); ! set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, s390_frame_init_saved_regs); /* Amount PC must be decremented by after a breakpoint. This is often the number of bytes returned by BREAKPOINT_FROM_PC but not always. */ set_gdbarch_decr_pc_after_break (gdbarch, 2); - set_gdbarch_deprecated_pop_frame (gdbarch, s390_pop_frame); /* Stack grows downward. */ set_gdbarch_inner_than (gdbarch, core_addr_lessthan); set_gdbarch_breakpoint_from_pc (gdbarch, s390_breakpoint_from_pc); set_gdbarch_skip_prologue (gdbarch, s390_skip_prologue); - set_gdbarch_deprecated_init_extra_frame_info (gdbarch, s390_init_extra_frame_info); - set_gdbarch_deprecated_init_frame_pc_first (gdbarch, s390_init_frame_pc_first); - set_gdbarch_deprecated_target_read_fp (gdbarch, s390_read_fp); set_gdbarch_in_function_epilogue_p (gdbarch, s390_in_function_epilogue_p); ! /* This function that tells us whether the function invocation represented ! by FI does not have a frame on the stack associated with it. If it ! does not, FRAMELESS is set to 1, else 0. */ ! set_gdbarch_frameless_function_invocation (gdbarch, ! s390_frameless_function_invocation); ! /* Return saved PC from a frame */ ! set_gdbarch_deprecated_frame_saved_pc (gdbarch, s390_frame_saved_pc); ! /* DEPRECATED_FRAME_CHAIN takes a frame's nominal address and ! produces the frame's chain-pointer. */ ! set_gdbarch_deprecated_frame_chain (gdbarch, s390_frame_chain); ! set_gdbarch_deprecated_saved_pc_after_call (gdbarch, s390_saved_pc_after_call); set_gdbarch_pc_regnum (gdbarch, S390_PC_REGNUM); set_gdbarch_sp_regnum (gdbarch, S390_SP_REGNUM); - set_gdbarch_deprecated_fp_regnum (gdbarch, S390_SP_REGNUM); set_gdbarch_fp0_regnum (gdbarch, S390_F0_REGNUM); set_gdbarch_num_regs (gdbarch, S390_NUM_REGS); set_gdbarch_num_pseudo_regs (gdbarch, S390_NUM_PSEUDO_REGS); --- 2870,2892 ---- tdep = XCALLOC (1, struct gdbarch_tdep); gdbarch = gdbarch_alloc (&info, tdep); set_gdbarch_believe_pcc_promotion (gdbarch, 0); set_gdbarch_char_signed (gdbarch, 0); set_gdbarch_frame_args_skip (gdbarch, 0); ! /* Amount PC must be decremented by after a breakpoint. This is often the number of bytes returned by BREAKPOINT_FROM_PC but not always. */ set_gdbarch_decr_pc_after_break (gdbarch, 2); /* Stack grows downward. */ set_gdbarch_inner_than (gdbarch, core_addr_lessthan); set_gdbarch_breakpoint_from_pc (gdbarch, s390_breakpoint_from_pc); set_gdbarch_skip_prologue (gdbarch, s390_skip_prologue); set_gdbarch_in_function_epilogue_p (gdbarch, s390_in_function_epilogue_p); ! set_gdbarch_pc_regnum (gdbarch, S390_PC_REGNUM); set_gdbarch_sp_regnum (gdbarch, S390_SP_REGNUM); set_gdbarch_fp0_regnum (gdbarch, S390_F0_REGNUM); set_gdbarch_num_regs (gdbarch, S390_NUM_REGS); set_gdbarch_num_pseudo_regs (gdbarch, S390_NUM_PSEUDO_REGS); *************** s390_gdbarch_init (struct gdbarch_info i *** 2976,2981 **** --- 2908,2922 ---- set_gdbarch_frame_align (gdbarch, s390_frame_align); set_gdbarch_return_value (gdbarch, s390_return_value); + /* Frame handling. */ + set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section); + frame_unwind_append_sniffer (gdbarch, s390_pltstub_frame_sniffer); + frame_unwind_append_sniffer (gdbarch, s390_sigtramp_frame_sniffer); + frame_unwind_append_sniffer (gdbarch, s390_frame_sniffer); + frame_base_set_default (gdbarch, &s390_frame_base); + set_gdbarch_unwind_pc (gdbarch, s390_unwind_pc); + set_gdbarch_unwind_sp (gdbarch, s390_unwind_sp); + switch (info.bfd_arch_info->mach) { case bfd_mach_s390_31: -- Dr. Ulrich Weigand weigand@informatik.uni-erlangen.de