|
|
Message-ID: <548343C8.1020109@gmail.com> |
|
|
Date: Sun, 07 Dec 2014 01:58:32 +0800 |
|
|
From: Wei-cheng Wang <cole945 at gmail dot com> |
|
|
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 <cole945@gmail.com> |
|
|
|
|
|
* 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 <cole945@gmail.com> |
|
|
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);
|
|
|
|