Message-ID: <548343C8.1020109@gmail.com> Date: Sun, 07 Dec 2014 01:58:32 +0800 From: Wei-cheng Wang To: uweigand at de dot ibm dot com, gdb-patches at sourceware dot org Subject: Re: [PATCH 1/3 v2] Process record support for PowerPC 2014-12-06 Wei-cheng Wang * rs6000-tdep.c (rs6000_in_function_epilogue_p): Rename to rs6000_in_function_epilogue_frame_p and add an argument for frame_info. (rs6000_epilogue_frame_cache, rs6000_epilogue_frame_this_id, rs6000_epilogue_frame_prev_register, rs6000_epilogue_frame_sniffer): New functions. (rs6000_epilogue_frame_unwind): New. (rs6000_gdbarch_init): Append epilogue unwinder. commit 2608dbf8a3ee666ac0a7d5d7c45611d489edcda5 Author: Wei-cheng Wang Date: Sat Jan 17 14:29:16 2015 +0800 Epilogue unwinder for PowerPC. Index: gdb-7.6.1/gdb/rs6000-tdep.c =================================================================== --- gdb-7.6.1.orig/gdb/rs6000-tdep.c +++ gdb-7.6.1/gdb/rs6000-tdep.c @@ -873,14 +873,14 @@ insn_changes_sp_or_jumps (unsigned long limit for the size of an epilogue. */ static int -rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) +rs6000_in_function_epilogue_frame_p (struct frame_info *curfrm, + struct gdbarch *gdbarch, CORE_ADDR pc) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); bfd_byte insn_buf[PPC_INSN_SIZE]; CORE_ADDR scan_pc, func_start, func_end, epilogue_start, epilogue_end; unsigned long insn; - struct frame_info *curfrm; /* Find the search limits based on function boundaries and hard limit. */ @@ -893,8 +893,6 @@ rs6000_in_function_epilogue_p (struct gd epilogue_end = pc + PPC_MAX_EPILOGUE_INSTRUCTIONS * PPC_INSN_SIZE; if (epilogue_end > func_end) epilogue_end = func_end; - curfrm = get_current_frame (); - /* Scan forward until next 'blr'. */ for (scan_pc = pc; scan_pc < epilogue_end; scan_pc += PPC_INSN_SIZE) @@ -935,6 +933,15 @@ rs6000_in_function_epilogue_p (struct gd return 0; } +/* Implementation of gdbarch_in_function_epilogue_p. */ + +static int +rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + return rs6000_in_function_epilogue_frame_p (get_current_frame (), + gdbarch, pc); +} + /* Get the ith function argument for the current function. */ static CORE_ADDR rs6000_fetch_pointer_argument (struct frame_info *frame, int argi, @@ -3388,6 +3395,89 @@ static const struct frame_unwind rs6000_ NULL, default_frame_sniffer }; + +static struct rs6000_frame_cache * +rs6000_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache) +{ + volatile struct gdb_exception ex; + struct rs6000_frame_cache *cache; + struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + CORE_ADDR sp; + + if (*this_cache) + return *this_cache; + + cache = FRAME_OBSTACK_ZALLOC (struct rs6000_frame_cache); + (*this_cache) = cache; + cache->saved_regs = trad_frame_alloc_saved_regs (this_frame); + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + /* At this point the stack looks as if we just entered the + function, and the return address is stored in LR. */ + CORE_ADDR sp, lr; + + sp = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch)); + lr = get_frame_register_unsigned (this_frame, tdep->ppc_lr_regnum); + + cache->base = sp; + cache->initial_sp = sp; + + trad_frame_set_value (cache->saved_regs, + gdbarch_pc_regnum (gdbarch), lr); + } + if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); + + return cache; +} + +static void +rs6000_epilogue_frame_this_id (struct frame_info *this_frame, + void **this_cache, struct frame_id *this_id) +{ + CORE_ADDR pc; + struct rs6000_frame_cache *info = + rs6000_epilogue_frame_cache (this_frame, this_cache); + + pc = get_frame_func (this_frame); + if (info->base == 0) + (*this_id) = frame_id_build_unavailable_stack (pc); + else + (*this_id) = frame_id_build (info->base, pc); +} + +static struct value * +rs6000_epilogue_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + struct rs6000_frame_cache *info = + rs6000_epilogue_frame_cache (this_frame, this_cache); + return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum); +} + +static int +rs6000_epilogue_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_prologue_cache) +{ + if (frame_relative_level (this_frame) == 0) + return rs6000_in_function_epilogue_frame_p (this_frame, + get_frame_arch (this_frame), + get_frame_pc (this_frame)); + else + return 0; +} + +static const struct frame_unwind rs6000_epilogue_frame_unwind = +{ + NORMAL_FRAME, + default_frame_unwind_stop_reason, + rs6000_epilogue_frame_this_id, rs6000_epilogue_frame_prev_register, + NULL, + rs6000_epilogue_frame_sniffer +}; static CORE_ADDR @@ -4207,6 +4297,7 @@ rs6000_gdbarch_init (struct gdbarch_info case GDB_OSABI_NETBSD_ELF: case GDB_OSABI_UNKNOWN: set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc); + frame_unwind_append_unwinder (gdbarch, &rs6000_epilogue_frame_unwind); frame_unwind_append_unwinder (gdbarch, &rs6000_frame_unwind); set_gdbarch_dummy_id (gdbarch, rs6000_dummy_id); frame_base_append_sniffer (gdbarch, rs6000_frame_base_sniffer); @@ -4215,6 +4306,7 @@ rs6000_gdbarch_init (struct gdbarch_info set_gdbarch_believe_pcc_promotion (gdbarch, 1); set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc); + frame_unwind_append_unwinder (gdbarch, &rs6000_epilogue_frame_unwind); frame_unwind_append_unwinder (gdbarch, &rs6000_frame_unwind); set_gdbarch_dummy_id (gdbarch, rs6000_dummy_id); frame_base_append_sniffer (gdbarch, rs6000_frame_base_sniffer);