summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Snyder <msnyder@specifix.com>2008-06-10 18:06:04 +0000
committerMichael Snyder <msnyder@specifix.com>2008-06-10 18:06:04 +0000
commitbda6cccc45f8b4eb6142d5ffb1a46772ba74d916 (patch)
tree535c9fc1d04d3e74c6bd112393e3952bd8a0fe60
parent86055fff591e0c7673385893a9895937f9e6b112 (diff)
downloadgdb-bda6cccc45f8b4eb6142d5ffb1a46772ba74d916.tar.gz
2007-04-18 Daniel Jacobowitz <dan@codesourcery.com>
* arm-tdep.c (arm_scan_epilogue): New. (arm_make_prologue_cache): Use it. (arm_epilogue_unwind_sniffer): New. (arm_gdbarch_init): Register it.
-rw-r--r--gdb/ChangeLog7
-rw-r--r--gdb/arm-tdep.c96
2 files changed, 103 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3deec46401b..8a9b31ae3c4 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -34,6 +34,13 @@
* Makefile.in (reverse.c): New file.
* reverse.c: New file. User interface for reverse execution.
+2007-04-18 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * arm-tdep.c (arm_scan_epilogue): New.
+ (arm_make_prologue_cache): Use it.
+ (arm_epilogue_unwind_sniffer): New.
+ (arm_gdbarch_init): Register it.
+
2008-06-09 Doug Evans <dje@google.com>
* remote.c (remote_wait): Include beginning of malformed packet
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index fd732a87e45..0d4d1fe55b0 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -1011,6 +1011,84 @@ arm_scan_prologue (struct frame_info *this_frame,
do_cleanups (back_to);
}
+/* This function tries to guess whether we are in the epilogue of an
+ ARM function. We need to detect whether the stack frame has
+ already been destroyed - if it has, then neither the prologue
+ scanner nor GCC's unwind tables will be valid. This is very hokey
+ and generally unsafe. */
+
+static int
+arm_scan_epilogue (struct frame_info *next_frame,
+ struct arm_prologue_cache *cache)
+{
+ unsigned int insn;
+ gdb_byte buf[4];
+ CORE_ADDR prev_pc = frame_pc_unwind (next_frame);
+
+ /* Assume there is no frame until proven otherwise. */
+ if (cache != NULL)
+ {
+ cache->framereg = ARM_SP_REGNUM;
+ cache->framesize = 0;
+ cache->frameoffset = 0;
+ }
+
+ /* Check for Thumb epilogue. */
+ if (arm_pc_is_thumb (prev_pc))
+ /* Not yet implemented. */
+ return 0;
+
+ if (target_read_memory (prev_pc, buf, 4) != 0)
+ return 0;
+ insn = extract_unsigned_integer (buf, 4);
+
+ if (insn == 0xe12fff1e) /* bx lr */
+ /* If this is a return, we have no frame left and no saved
+ registers. */
+ return 1;
+
+ return 0;
+}
+
+/* This function tries to guess whether we are in the epilogue of an
+ ARM function. We need to detect whether the stack frame has
+ already been destroyed - if it has, then neither the prologue
+ scanner nor GCC's unwind tables will be valid. This is very hokey
+ and generally unsafe. */
+
+static int
+arm_scan_epilogue (struct frame_info *next_frame,
+ struct arm_prologue_cache *cache)
+{
+ unsigned int insn;
+ gdb_byte buf[4];
+ CORE_ADDR prev_pc = frame_pc_unwind (next_frame);
+
+ /* Assume there is no frame until proven otherwise. */
+ if (cache != NULL)
+ {
+ cache->framereg = ARM_SP_REGNUM;
+ cache->framesize = 0;
+ cache->frameoffset = 0;
+ }
+
+ /* Check for Thumb epilogue. */
+ if (arm_pc_is_thumb (prev_pc))
+ /* Not yet implemented. */
+ return 0;
+
+ if (target_read_memory (prev_pc, buf, 4) != 0)
+ return 0;
+ insn = extract_unsigned_integer (buf, 4);
+
+ if (insn == 0xe12fff1e) /* bx lr */
+ /* If this is a return, we have no frame left and no saved
+ registers. */
+ return 1;
+
+ return 0;
+}
+
static struct arm_prologue_cache *
arm_make_prologue_cache (struct frame_info *this_frame)
{
@@ -1132,6 +1210,24 @@ struct frame_unwind arm_prologue_unwind = {
default_frame_sniffer
};
+static const struct frame_unwind *
+arm_epilogue_unwind_sniffer (struct frame_info *next_frame)
+{
+ if (arm_scan_epilogue (next_frame, NULL))
+ return &arm_prologue_unwind;
+ else
+ return NULL;
+}
+
+static const struct frame_unwind *
+arm_epilogue_unwind_sniffer (struct frame_info *next_frame)
+{
+ if (arm_scan_epilogue (next_frame, NULL))
+ return &arm_prologue_unwind;
+ else
+ return NULL;
+}
+
static struct arm_prologue_cache *
arm_make_stub_cache (struct frame_info *this_frame)
{