Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
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


  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