From: Yao Qi <qiyaoltc@gmail.com>
To: gdb-patches@sourceware.org
Subject: [PATCH 5/9] Handle unwinding exceptions
Date: Mon, 31 Jul 2017 22:22:00 -0000 [thread overview]
Message-ID: <1501539715-8049-6-git-send-email-yao.qi@linaro.org> (raw)
In-Reply-To: <1501539715-8049-1-git-send-email-yao.qi@linaro.org>
unwinder methods (sniffer, this_id, stop_reason, etc) can throw
exceptions, at least when some data is unavailable during examining
traceframes. We deal with this problem by catching exceptions in each
unwinders, dwarf unwinders and different arch-specific prologue unwinders.
done by https://www.sourceware.org/ml/gdb-patches/2011-02/msg00611.html
This requires each arch-specific prologue unwinder needs to catch
exceptions.
This patch centralizes the exception handling in the callers of unwinders
methods, and the following patches remove the exception handling in each
arch prologue unwinders. This patch is a follow-up to discussion
https://sourceware.org/ml/gdb-patches/2016-02/msg00778.html
This patch not only catches exceptions from unwinder methods, but also
catches exceptions from frame_base methods, because they call
arch-specific prologue analyzer, which can throw exceptions.
gdb:
2017-07-27 Yao Qi <yao.qi@linaro.org>
* frame.c (compute_frame_id): Catch exception, if it is
NOT_AVAILABLE_ERROR, call frame_id_build_unavailable_stack,
otherwise throw the exception again.
(frame_unwind_register_value): Catch exception from
unwind->prev_register, if it is NOT_AVAILABLE_ERROR, set value
unavailable, otherwise throw the exception again.
(get_prev_frame_always_1): Catch exception from
unwind->stop_reason, if it is NOT_AVAILABLE_ERROR, set stop_reason
to UNWIND_UNAVAILABLE, otherwise throw the exception.
(get_frame_locals_address): Catch exception base->this_locals.
(get_frame_args_address): Likewise.
---
gdb/frame.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 93 insertions(+), 16 deletions(-)
diff --git a/gdb/frame.c b/gdb/frame.c
index 30e4aea..f5037d5 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -502,7 +502,32 @@ compute_frame_id (struct frame_info *fi)
/* Find THIS frame's ID. */
/* Default to outermost if no ID is found. */
fi->this_id.value = outer_frame_id;
- fi->unwind->this_id (fi, &fi->prologue_cache, &fi->this_id.value);
+
+ TRY
+ {
+ fi->unwind->this_id (fi, &fi->prologue_cache, &fi->this_id.value);
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ if (ex.error == NOT_AVAILABLE_ERROR)
+ {
+ CORE_ADDR pc;
+
+ /* Use function start address as part of the frame ID. If we
+ can't find the start address (due to missing symbol
+ information), faill back to just using the current PC. If
+ PC isn't available, we can't construct any meaningful frame
+ ID, so do nothing here, and the frame id is
+ outer_frame_id. */
+ if ((get_frame_func_if_available (fi, &pc) && pc != 0)
+ || get_frame_pc_if_available (fi, &pc))
+ fi->this_id.value = frame_id_build_unavailable_stack (pc);
+ }
+ else
+ throw_exception (ex);
+ }
+ END_CATCH
+
gdb_assert (frame_id_p (fi->this_id.value));
fi->this_id.p = 1;
if (frame_debug)
@@ -1196,8 +1221,25 @@ frame_unwind_register_value (struct frame_info *frame, int regnum)
if (frame->unwind == NULL)
frame_unwind_find_by_frame (frame, &frame->prologue_cache);
- /* Ask this frame to unwind its register. */
- value = frame->unwind->prev_register (frame, &frame->prologue_cache, regnum);
+ TRY
+ {
+ /* Ask this frame to unwind its register. */
+ value = frame->unwind->prev_register (frame, &frame->prologue_cache,
+ regnum);
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ if (ex.error == NOT_AVAILABLE_ERROR)
+ {
+ value = frame_unwind_got_register (frame, regnum, regnum);
+ set_value_lazy (value, 0);
+ mark_value_bytes_unavailable (value, 0,
+ TYPE_LENGTH (value_type (value)));
+ }
+ else
+ throw_exception (ex);
+ }
+ END_CATCH
if (frame_debug)
{
@@ -2009,9 +2051,20 @@ get_prev_frame_always_1 (struct frame_info *this_frame)
/* Check that this frame is unwindable. If it isn't, don't try to
unwind to the prev frame. */
- this_frame->stop_reason
- = this_frame->unwind->stop_reason (this_frame,
- &this_frame->prologue_cache);
+ TRY
+ {
+ this_frame->stop_reason
+ = this_frame->unwind->stop_reason (this_frame,
+ &this_frame->prologue_cache);
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ if (ex.error == NOT_AVAILABLE_ERROR)
+ this_frame->stop_reason = UNWIND_UNAVAILABLE;
+ else
+ throw_exception (ex);
+ }
+ END_CATCH
if (this_frame->stop_reason != UNWIND_NO_REASON)
{
@@ -2596,11 +2649,23 @@ get_frame_locals_address (struct frame_info *fi)
/* If there isn't a frame address method, find it. */
if (fi->base == NULL)
fi->base = frame_base_find_by_frame (fi);
- /* Sneaky: If the low-level unwind and high-level base code share a
- common unwinder, let them share the prologue cache. */
- if (fi->base->unwind == fi->unwind)
- return fi->base->this_locals (fi, &fi->prologue_cache);
- return fi->base->this_locals (fi, &fi->base_cache);
+
+ TRY
+ {
+ /* Sneaky: If the low-level unwind and high-level base code share a
+ common unwinder, let them share the prologue cache. */
+ if (fi->base->unwind == fi->unwind)
+ return fi->base->this_locals (fi, &fi->prologue_cache);
+ return fi->base->this_locals (fi, &fi->base_cache);
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ if (ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
+ }
+ END_CATCH
+
+ return 0;
}
CORE_ADDR
@@ -2611,11 +2676,23 @@ get_frame_args_address (struct frame_info *fi)
/* If there isn't a frame address method, find it. */
if (fi->base == NULL)
fi->base = frame_base_find_by_frame (fi);
- /* Sneaky: If the low-level unwind and high-level base code share a
- common unwinder, let them share the prologue cache. */
- if (fi->base->unwind == fi->unwind)
- return fi->base->this_args (fi, &fi->prologue_cache);
- return fi->base->this_args (fi, &fi->base_cache);
+
+ TRY
+ {
+ /* Sneaky: If the low-level unwind and high-level base code share a
+ common unwinder, let them share the prologue cache. */
+ if (fi->base->unwind == fi->unwind)
+ return fi->base->this_args (fi, &fi->prologue_cache);
+ return fi->base->this_args (fi, &fi->base_cache);
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ if (ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
+ }
+ END_CATCH
+
+ return 0;
}
/* Return true if the frame unwinder for frame FI is UNWINDER; false
--
1.9.1
next prev parent reply other threads:[~2017-07-31 22:22 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-07-31 22:22 [PATCH 0/9] Centralize unwinder api exceptions handling Yao Qi
2017-07-31 22:22 ` [PATCH 4/9] Reset *THIS_CACHE in frame_unwind_try_unwinder in case of exception Yao Qi
2017-08-11 16:47 ` Pedro Alves
2017-08-17 15:27 ` Yao Qi
2017-07-31 22:22 ` [PATCH 7/9] Throw exception in amd64 unwinders Yao Qi
2017-07-31 22:22 ` [PATCH 2/9] Class-fy dwarf2_frame_state Yao Qi
2017-07-31 22:22 ` [PATCH 6/9] Throw exception in dwarf2 unwinders Yao Qi
2017-07-31 22:22 ` [PATCH 8/9] Throw exception in i386 unwinders Yao Qi
2017-07-31 22:22 ` [PATCH 1/9] Move dwarf2_frame_state_reg.exp_len to union .loc Yao Qi
2017-07-31 22:22 ` [PATCH 3/9] Class-fy dwarf2_frame_state_reg_info Yao Qi
2017-07-31 22:22 ` [PATCH 9/9] Throw exception in aarch64 unwinder Yao Qi
2017-07-31 22:22 ` Yao Qi [this message]
2017-08-11 8:35 ` [PATCH 0/9] Centralize unwinder api exceptions handling Yao Qi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1501539715-8049-6-git-send-email-yao.qi@linaro.org \
--to=qiyaoltc@gmail.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox