diff options
author | Pierre Langlois <pierre.langlois@arm.com> | 2015-07-09 16:35:11 +0100 |
---|---|---|
committer | Pierre Langlois <pierre.langlois@arm.com> | 2015-07-09 16:35:11 +0100 |
commit | 02a2a705aa71646a47c955388491523a989516c5 (patch) | |
tree | 5b3a2a68e6a27d639aa35aa7c8808d2b1110cdeb | |
parent | 7dfa3edc033c443036d9f2a3e01120f7fb54f498 (diff) | |
download | gdb-02a2a705aa71646a47c955388491523a989516c5.zip gdb-02a2a705aa71646a47c955388491523a989516c5.tar.gz gdb-02a2a705aa71646a47c955388491523a989516c5.tar.bz2 |
[AArch64] Teach stub unwinder to terminate gracefully
The stub unwinder is used on AArch64 if the target's memory is not
readable at the current PC. For example, the user could try to call at
an invalid address such as 0x0, as covered in the gdb.base/signull.exp
test case. Many GDB ports use a similar unwinder to handle this case
too.
If we purposely kill the inferior before examining the trace then we get
the following issue:
~~~
...
(gdb) trace f
Tracepoint 3 at 0x7fb7fc28c0
(gdb) tstart
(gdb) continue
...
(gdb) tstop
(gdb) tsave /tmp/trace
(gdb) kill
...
(gdb) target tfile /tmp/trace
...
(gdb) tfind
Register 31 is not available.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Found trace frame 0, tracepoint 3
#-1 0x0000007fb7fc28c0 in f () ...
^^^
~~~
This patch teaches the stub unwinder to report to the core frame code
with UNWIND_UNAVAILABLE when either the stack pointer of the return
address are unavailable to read from the target.
gdb/ChangeLog:
* aarch64-tdep.c (aarch64_make_stub_cache): Set available_p and
swallow NOT_AVAILABLE_ERROR.
(aarch64_stub_this_id): Call frame_id_build_unavailable_stack if
available_p is not set.
(aarch64_stub_frame_unwind_stop_reason): New function.
(aarch64_stub_unwind): Install it.
-rw-r--r-- | gdb/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/aarch64-tdep.c | 38 |
2 files changed, 42 insertions, 5 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f715fcd..5899173 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,14 @@ 2015-07-09 Pierre Langlois <pierre.langlois@arm.com> + * aarch64-tdep.c (aarch64_make_stub_cache): Set available_p and + swallow NOT_AVAILABLE_ERROR. + (aarch64_stub_this_id): Call frame_id_build_unavailable_stack if + available_p is not set. + (aarch64_stub_frame_unwind_stop_reason): New function. + (aarch64_stub_unwind): Install it. + +2015-07-09 Pierre Langlois <pierre.langlois@arm.com> + * aarch64-tdep.c (aarch64_prologue_cache) <available_p>: New field. (aarch64_make_prologue_cache_1): New function, factored out from diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 37d3eb3..db9ea76 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -1119,13 +1119,38 @@ aarch64_make_stub_cache (struct frame_info *this_frame, void **this_cache) cache->saved_regs = trad_frame_alloc_saved_regs (this_frame); *this_cache = cache; - cache->prev_sp - = get_frame_register_unsigned (this_frame, AARCH64_SP_REGNUM); - cache->prev_pc = get_frame_pc (this_frame); + TRY + { + cache->prev_sp = get_frame_register_unsigned (this_frame, + AARCH64_SP_REGNUM); + cache->prev_pc = get_frame_pc (this_frame); + cache->available_p = 1; + } + CATCH (ex, RETURN_MASK_ERROR) + { + if (ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); + } + END_CATCH return cache; } +/* Implement the "stop_reason" frame_unwind method. */ + +static enum unwind_stop_reason +aarch64_stub_frame_unwind_stop_reason (struct frame_info *this_frame, + void **this_cache) +{ + struct aarch64_prologue_cache *cache + = aarch64_make_stub_cache (this_frame, this_cache); + + if (!cache->available_p) + return UNWIND_UNAVAILABLE; + + return UNWIND_NO_REASON; +} + /* Our frame ID for a stub frame is the current SP and LR. */ static void @@ -1135,7 +1160,10 @@ aarch64_stub_this_id (struct frame_info *this_frame, struct aarch64_prologue_cache *cache = aarch64_make_stub_cache (this_frame, this_cache); - *this_id = frame_id_build (cache->prev_sp, cache->prev_pc); + if (cache->available_p) + *this_id = frame_id_build (cache->prev_sp, cache->prev_pc); + else + *this_id = frame_id_build_unavailable_stack (cache->prev_pc); } /* Implement the "sniffer" frame_unwind method. */ @@ -1162,7 +1190,7 @@ aarch64_stub_unwind_sniffer (const struct frame_unwind *self, struct frame_unwind aarch64_stub_unwind = { NORMAL_FRAME, - default_frame_unwind_stop_reason, + aarch64_stub_frame_unwind_stop_reason, aarch64_stub_this_id, aarch64_prologue_prev_register, NULL, |