diff options
author | Michael Snyder <msnyder@vmware.com> | 2008-06-10 18:06:04 +0000 |
---|---|---|
committer | Michael Snyder <msnyder@vmware.com> | 2008-06-10 18:06:04 +0000 |
commit | 9ea36100a546a93c1f4f378b66000e46a2038c93 (patch) | |
tree | 949b93844c4e43b05477ec910aa1ca009689328b | |
parent | 0d07eec401e947d49a5086b5c55e2f4511a2dece (diff) | |
download | fsf-binutils-gdb-9ea36100a546a93c1f4f378b66000e46a2038c93.zip fsf-binutils-gdb-9ea36100a546a93c1f4f378b66000e46a2038c93.tar.gz fsf-binutils-gdb-9ea36100a546a93c1f4f378b66000e46a2038c93.tar.bz2 |
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/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/arm-tdep.c | 96 |
2 files changed, 103 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3deec46..8a9b31a 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 fd732a8..0d4d1fe 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) { |