diff options
author | Michael Snyder <msnyder@specifix.com> | 2008-06-10 00:13:15 +0000 |
---|---|---|
committer | Michael Snyder <msnyder@specifix.com> | 2008-06-10 00:13:15 +0000 |
commit | ce119b4142eb7b70f580c8830fa2a1832b2de019 (patch) | |
tree | 9b8363b2417351934cd03581624454c5b122e1e4 /gdb/arm-tdep.c | |
parent | ea9e838749c0f6f20a7a12423efb0ef2a422e487 (diff) | |
download | gdb-cvs/drow-reverse-20070409-branch.tar.gz |
Daniel Jacobowitz' update to Michael Snyder's reverse debugging patchesdrow-reverse-20070409-branchcvs/drow-reverse-20070409-branch
Diffstat (limited to 'gdb/arm-tdep.c')
-rw-r--r-- | gdb/arm-tdep.c | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 22a08f845b2..899dd06da87 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -888,6 +888,45 @@ arm_scan_prologue (struct frame_info *next_frame, struct arm_prologue_cache *cac cache->frameoffset = 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 *next_frame) { @@ -898,7 +937,8 @@ arm_make_prologue_cache (struct frame_info *next_frame) cache = FRAME_OBSTACK_ZALLOC (struct arm_prologue_cache); cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); - arm_scan_prologue (next_frame, cache); + if (arm_scan_epilogue (next_frame, cache) == 0) + arm_scan_prologue (next_frame, cache); unwound_fp = frame_unwind_register_unsigned (next_frame, cache->framereg); if (unwound_fp == 0) @@ -995,6 +1035,15 @@ arm_prologue_unwind_sniffer (struct frame_info *next_frame) return &arm_prologue_unwind; } +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 *next_frame) { @@ -2996,6 +3045,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Add some default predicates. */ frame_unwind_append_sniffer (gdbarch, arm_stub_unwind_sniffer); + frame_unwind_append_sniffer (gdbarch, arm_epilogue_unwind_sniffer); frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer); frame_unwind_append_sniffer (gdbarch, arm_prologue_unwind_sniffer); |