Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Pierre Langlois <pierre.langlois@arm.com>
To: gdb-patches@sourceware.org
Cc: Pierre Langlois <pierre.langlois@arm.com>
Subject: [PATCH 4/8] [AArch64] Teach prologue unwinder to terminate gracefully
Date: Tue, 07 Jul 2015 12:53:00 -0000	[thread overview]
Message-ID: <1436273518-5959-5-git-send-email-pierre.langlois@arm.com> (raw)
In-Reply-To: <1436273518-5959-1-git-send-email-pierre.langlois@arm.com>

Without debugging information, we have the following issue when
examining a trace buffer:

~~~
...
(gdb) trace f
Tracepoint 3 at 0x7fb7fc28c0
(gdb) tstart
(gdb) continue
...
(gdb) tstop
(gdb) tfind start
Register 31 is not available.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Found trace frame 0, tracepoint 3
#-1 0x0000007fb7fc28c0 in f () ...
^^^
~~~

The reason for this is that the target's stack pointer is unavailable
when examining the trace buffer.  What we are seeing is due to the
'tfind' command creating a sentinel frame and unwinding it.  If an
exception is thrown, we are left with the sentinel frame being displayed
at level #-1.  The exception is thrown when the prologue unwinder tries
to read the stack pointer to construct an ID for the frame.

This patch fixes this by making the prologue unwinder catch
NOT_AVAILABLE_ERROR exceptions when either registers or memory is
unreadable and report back to the frame core code with
UNWIND_UNAVAILABLE.

The following test cases now pass when enabling tracepoints:

PASS: gdb.trace/report.exp: live: 9.1: tdump, args collected
PASS: gdb.trace/report.exp: live: 9.1: tdump, locals collected
PASS: gdb.trace/report.exp: live: 12.3: trace report #3
PASS: gdb.trace/report.exp: tfile: 9.1: tdump, args collected
PASS: gdb.trace/report.exp: tfile: 9.1: tdump, locals collected
PASS: gdb.trace/report.exp: tfile: 12.3: trace report #3
PASS: gdb.trace/collection.exp: collect local string: collected local string
PASS: gdb.trace/collection.exp: collect long local string: collected local string
PASS: gdb.trace/unavailable-dwarf-piece.exp: tracing foo: tfind 0
PASS: gdb.trace/unavailable-dwarf-piece.exp: tracing foo: p/d x
PASS: gdb.trace/unavailable-dwarf-piece.exp: tracing foo: p/d y
PASS: gdb.trace/unavailable-dwarf-piece.exp: tracing foo: p/d z
PASS: gdb.trace/unavailable-dwarf-piece.exp: tracing foo: tfind none
PASS: gdb.trace/unavailable-dwarf-piece.exp: tracing bar: trace bar
PASS: gdb.trace/unavailable-dwarf-piece.exp: tracing bar: tstart
PASS: gdb.trace/unavailable-dwarf-piece.exp: tracing bar: continue
PASS: gdb.trace/unavailable-dwarf-piece.exp: tracing bar: tstop
PASS: gdb.trace/unavailable-dwarf-piece.exp: tracing bar: tfind 0
PASS: gdb.trace/unavailable-dwarf-piece.exp: tracing bar: p/d x
PASS: gdb.trace/unavailable-dwarf-piece.exp: tracing bar: p/d y
PASS: gdb.trace/unavailable-dwarf-piece.exp: tracing bar: p/d z
PASS: gdb.trace/unavailable-dwarf-piece.exp: tracing bar: tfind none

gdb/ChangeLog:

	* aarch64-tdep.c (aarch64_prologue_cache) <available_p>: New
	field.
	(aarch64_make_prologue_cache_1): New function, factored out from
	aarch64_make_prologue_cache.  Do not allocate cache.  Set
	available_p.
	(aarch64_make_prologue_cache): Reimplement wrapping
	aarch64_make_prologue_cache_1, and swallowing
	NOT_AVAILABLE_ERROR.

	(aarch64_prologue_frame_unwind_stop_reason): New function.
	Return UNWIND_UNAVAILABLE if available_p is not set.
	(aarch64_prologue_unwind): Install it.
	(aarch64_prologue_this_id): Move prev_pc and prev_sp limit
	checks into aarch64_prologue_frame_unwind_stop_reason.  Call
	frame_id_build_unavailable_stack if available_p is not set.
---
 gdb/aarch64-tdep.c | 82 +++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 60 insertions(+), 22 deletions(-)

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 6a38f18..87a6d61 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -162,6 +162,9 @@ struct aarch64_prologue_cache
      to identify this frame.  */
   CORE_ADDR prev_sp;
 
+  /* Is the target available to read from?  */
+  int available_p;
+
   /* The frame base for this frame is just prev_sp - frame size.
      FRAMESIZE is the distance from the frame pointer to the
      initial stack pointer.  */
@@ -944,28 +947,21 @@ aarch64_scan_prologue (struct frame_info *this_frame,
 /* Allocate an aarch64_prologue_cache and fill it with information
    about the prologue of *THIS_FRAME.  */
 
-static struct aarch64_prologue_cache *
-aarch64_make_prologue_cache (struct frame_info *this_frame, void **this_cache)
+static void
+aarch64_make_prologue_cache_1 (struct frame_info *this_frame,
+			       struct aarch64_prologue_cache *cache)
 {
-  struct aarch64_prologue_cache *cache;
   CORE_ADDR unwound_fp;
   int reg;
 
-  if (*this_cache)
-    return *this_cache;
-
-  cache = FRAME_OBSTACK_ZALLOC (struct aarch64_prologue_cache);
-  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
-  *this_cache = cache;
-
   aarch64_scan_prologue (this_frame, cache);
 
   if (cache->framereg == -1)
-    return cache;
+    return;
 
   unwound_fp = get_frame_register_unsigned (this_frame, cache->framereg);
   if (unwound_fp == 0)
-    return cache;
+    return;
 
   cache->prev_sp = unwound_fp + cache->framesize;
 
@@ -977,9 +973,56 @@ aarch64_make_prologue_cache (struct frame_info *this_frame, void **this_cache)
 
   cache->func = get_frame_func (this_frame);
 
+  cache->available_p = 1;
+}
+
+static struct aarch64_prologue_cache *
+aarch64_make_prologue_cache (struct frame_info *this_frame, void **this_cache)
+{
+  struct aarch64_prologue_cache *cache;
+
+  if (*this_cache)
+    return *this_cache;
+
+  cache = FRAME_OBSTACK_ZALLOC (struct aarch64_prologue_cache);
+  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+  *this_cache = cache;
+
+  TRY
+    {
+      aarch64_make_prologue_cache_1 (this_frame, cache);
+    }
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      if (ex.error != NOT_AVAILABLE_ERROR)
+	throw_exception (ex);
+    }
+  END_CATCH
+
   return cache;
 }
 
+static enum unwind_stop_reason
+aarch64_prologue_frame_unwind_stop_reason (struct frame_info *this_frame,
+					   void **this_cache)
+{
+  struct aarch64_prologue_cache *cache
+    = aarch64_make_prologue_cache (this_frame, this_cache);
+
+  if (!cache->available_p)
+    return UNWIND_UNAVAILABLE;
+
+  /* Halt the backtrace at "_start".  */
+  if (cache->prev_pc <= gdbarch_tdep (get_frame_arch (this_frame))->lowest_pc)
+    return UNWIND_OUTERMOST;
+
+  /* We've hit a wall, stop.  */
+  if (cache->prev_sp == 0)
+      return UNWIND_OUTERMOST;
+
+  return UNWIND_NO_REASON;
+}
+
 /* Our frame ID for a normal frame is the current function's starting
    PC and the caller's SP when we were called.  */
 
@@ -990,15 +1033,10 @@ aarch64_prologue_this_id (struct frame_info *this_frame,
   struct aarch64_prologue_cache *cache
     = aarch64_make_prologue_cache (this_frame, this_cache);
 
-  /* This is meant to halt the backtrace at "_start".  */
-  if (cache->prev_pc <= gdbarch_tdep (get_frame_arch (this_frame))->lowest_pc)
-    return;
-
-  /* If we've hit a wall, stop.  */
-  if (cache->prev_sp == 0)
-    return;
-
-  *this_id = frame_id_build (cache->prev_sp, cache->func);
+  if (!cache->available_p)
+    *this_id = frame_id_build_unavailable_stack (cache->func);
+  else
+    *this_id = frame_id_build (cache->prev_sp, cache->func);
 }
 
 /* Implement the "prev_register" frame_unwind method.  */
@@ -1049,7 +1087,7 @@ aarch64_prologue_prev_register (struct frame_info *this_frame,
 struct frame_unwind aarch64_prologue_unwind =
 {
   NORMAL_FRAME,
-  default_frame_unwind_stop_reason,
+  aarch64_prologue_frame_unwind_stop_reason,
   aarch64_prologue_this_id,
   aarch64_prologue_prev_register,
   NULL,
-- 
2.1.0


  parent reply	other threads:[~2015-07-07 12:53 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-07 12:52 [PATCH 0/8] [AArch64] Add support for tracepoints Pierre Langlois
2015-07-07 12:52 ` [PATCH 3/8] [AArch64] Only access inferior registers when creating a frame cache Pierre Langlois
2015-07-08 16:15   ` Yao Qi
2015-07-09 15:40     ` Pierre Langlois
2015-07-07 12:52 ` [PATCH 7/8] [testsuite][AArch64] Port gdb.trace Pierre Langlois
2015-07-08 16:39   ` Yao Qi
2015-07-09 12:25     ` [PATCH v2 " Pierre Langlois
2015-07-09 15:46       ` Pierre Langlois
2015-07-07 12:53 ` [PATCH 1/8] [AArch64] Refactor aarch64_make_prologue_cache Pierre Langlois
2015-07-08 16:09   ` Yao Qi
2015-07-09 10:36     ` [PATCH] " Pierre Langlois
2015-07-09 15:38       ` Pierre Langlois
2015-07-07 12:53 ` Pierre Langlois [this message]
2015-07-08 16:24   ` [PATCH 4/8] [AArch64] Teach prologue unwinder to terminate gracefully Yao Qi
2015-07-09 10:49     ` [PATCH v2 " Pierre Langlois
2015-07-09 10:53       ` Pierre Langlois
2015-07-09 10:56         ` [PATCH v3 " Pierre Langlois
2015-07-09 15:41           ` Pierre Langlois
2015-07-09 12:47       ` [PATCH v2 " Yao Qi
2015-07-09 12:51         ` Pierre Langlois
2015-07-07 12:53 ` [PATCH 2/8] [AArch64] Refactor aarch64_make_stub_cache Pierre Langlois
2015-07-08 16:10   ` Yao Qi
2015-07-09 10:41     ` [PATCH v2 " Pierre Langlois
2015-07-09 15:39       ` Pierre Langlois
2015-07-07 12:53 ` [PATCH 5/8] [AArch64] Teach stub unwinder to terminate gracefully Pierre Langlois
2015-07-08 16:34   ` Yao Qi
2015-07-09 11:12     ` [PATCH v2 " Pierre Langlois
2015-07-09 15:45       ` Pierre Langlois
2015-07-07 12:54 ` [PATCH 6/8] [AArch64] Implement gdbarch_gen_return_address gdbarch method Pierre Langlois
2015-07-08 16:35   ` Yao Qi
2015-07-09 15:45     ` Pierre Langlois
2015-07-07 12:58 ` [PATCH 8/8] [GDBServer][AArch64] Enable support for tracepoints Pierre Langlois
2015-07-08 16:40   ` Yao Qi
2015-07-09 15:46     ` Pierre Langlois
2015-07-08 10:57 ` [PATCH 0/8] [AArch64] Add " Pedro Alves
2015-07-08 16:42 ` Yao Qi
2015-07-09 13:16   ` [PATCH] Add NEWS entry for tracepoints support on aarch64-linux Pierre Langlois
2015-07-09 14:44     ` Eli Zaretskii
2015-07-09 15:46       ` Pierre Langlois

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=1436273518-5959-5-git-send-email-pierre.langlois@arm.com \
    --to=pierre.langlois@arm.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