This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 07/11] [SQUASH] btrace: Adjust struct btrace_function::up.


This patch stands alone for easier review and is meant to be squashed together
for committing.  ChangeLog will be added to the squashed commit.


2017-02-17  Tim Wiederhake  <tim.wiederhake@intel.com>
---
 gdb/btrace.c                  | 138 ++++++++++++++++++++++++------------------
 gdb/btrace.h                  |   6 +-
 gdb/python/py-record-btrace.c |   4 +-
 gdb/record-btrace.c           |  18 +++---
 4 files changed, 97 insertions(+), 69 deletions(-)

diff --git a/gdb/btrace.c b/gdb/btrace.c
index cc22737..880a703 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -156,6 +156,16 @@ ftrace_call_num_insn (const struct btrace_function* bfun)
   return VEC_length (btrace_insn_s, bfun->insn);
 }
 
+static struct btrace_function *
+ftrace_find_call_by_number (const struct btrace_thread_info *btinfo,
+			    unsigned int number)
+{
+  if (number == 0 || number > VEC_length (btrace_fun_s, btinfo->functions))
+    return NULL;
+
+  return VEC_index (btrace_fun_s, btinfo->functions, number - 1);
+}
+
 /* Return non-zero if BFUN does not match MFUN and FUN,
    return zero otherwise.  */
 
@@ -249,10 +259,10 @@ ftrace_update_caller (struct btrace_function *bfun,
 		      struct btrace_function *caller,
 		      enum btrace_function_flag flags)
 {
-  if (bfun->up != NULL)
+  if (bfun->up != 0)
     ftrace_debug (bfun, "updating caller");
 
-  bfun->up = caller;
+  bfun->up = caller->number;
   bfun->flags = flags;
 
   ftrace_debug (bfun, "set caller");
@@ -287,10 +297,10 @@ ftrace_new_call (struct btrace_thread_info *btinfo,
 		 struct minimal_symbol *mfun,
 		 struct symbol *fun)
 {
-  struct btrace_function *bfun;
+  const unsigned int last = VEC_length (btrace_fun_s, btinfo->functions);
+  struct btrace_function *bfun = ftrace_new_function (btinfo, mfun, fun);
 
-  bfun = ftrace_new_function (btinfo, mfun, fun);
-  bfun->up = btinfo->end;
+  bfun->up = last;
   bfun->level += 1;
 
   ftrace_debug (bfun, "new call");
@@ -306,10 +316,10 @@ ftrace_new_tailcall (struct btrace_thread_info *btinfo,
 		     struct minimal_symbol *mfun,
 		     struct symbol *fun)
 {
-  struct btrace_function *bfun;
+  const unsigned int last = VEC_length (btrace_fun_s, btinfo->functions);
+  struct btrace_function *bfun = ftrace_new_function (btinfo, mfun, fun);
 
-  bfun = ftrace_new_function (btinfo, mfun, fun);
-  bfun->up = btinfo->end;
+  bfun->up = last;
   bfun->level += 1;
   bfun->flags |= BFUN_UP_LINKS_TO_TAILCALL;
 
@@ -321,57 +331,58 @@ ftrace_new_tailcall (struct btrace_thread_info *btinfo,
 /* Return the caller of BFUN or NULL if there is none.  This function skips
    tail calls in the call chain.  */
 static struct btrace_function *
-ftrace_get_caller (struct btrace_function *bfun)
+ftrace_get_caller (struct btrace_thread_info *btinfo,
+		   struct btrace_function *bfun)
 {
-  for (; bfun != NULL; bfun = bfun->up)
+  for (; bfun != NULL; bfun = ftrace_find_call_by_number (btinfo, bfun->up))
     if ((bfun->flags & BFUN_UP_LINKS_TO_TAILCALL) == 0)
-      return bfun->up;
+      return ftrace_find_call_by_number (btinfo, bfun->up);
 
   return NULL;
 }
 
-/* Find the innermost caller in the back trace of BFUN with MFUN/FUN
-   symbol information.  */
+/* Find the innermost caller with MFUN/FUN symbol information in the back trace
+   of the function call segment with number NUMBER.  */
 
 static struct btrace_function *
 ftrace_find_caller (struct btrace_thread_info *btinfo,
-		    struct btrace_function *bfun,
+		    unsigned int number,
 		    struct minimal_symbol *mfun,
 		    struct symbol *fun)
 {
-  for (; bfun != NULL; bfun = bfun->up)
+  struct btrace_function *bfun;
+
+  while ((bfun = ftrace_find_call_by_number (btinfo, number)) != NULL)
     {
-      /* Skip functions with incompatible symbol information.  */
-      if (ftrace_function_switched (bfun, mfun, fun))
-	continue;
+      if (!ftrace_function_switched (bfun, mfun, fun))
+	break;
 
-      /* This is the function segment we're looking for.  */
-      break;
+      number = bfun->up;
     }
 
   return bfun;
 }
 
-/* Find the innermost caller in the back trace of BFUN, skipping all
-   function segments that do not end with a call instruction (e.g.
-   tail calls ending with a jump).  */
+/* Find the innermost caller in the back trace of the function call segment
+   with number NUMBER, skipping all function call segments that do not end
+   with a call instruction (e.g. tail calls ending with a jump).  */
 
 static struct btrace_function *
-ftrace_find_call (struct btrace_thread_info *btinfo,
-		  struct btrace_function *bfun)
+ftrace_find_call (struct btrace_thread_info *btinfo, unsigned int number)
 {
-  for (; bfun != NULL; bfun = bfun->up)
-    {
-      struct btrace_insn *last;
+  struct btrace_function *bfun;
 
-      /* Skip gaps.  */
-      if (bfun->errcode != 0)
-	continue;
+  while ((bfun = ftrace_find_call_by_number (btinfo, number)) != NULL)
+    {
+      if (bfun->errcode == 0)
+	{
+	  struct btrace_insn *last = VEC_last (btrace_insn_s, bfun->insn);
 
-      last = VEC_last (btrace_insn_s, bfun->insn);
+	  if (last->iclass == BTRACE_INSN_CALL)
+	    break;
+	}
 
-      if (last->iclass == BTRACE_INSN_CALL)
-	break;
+      number = bfun->up;
     }
 
   return bfun;
@@ -425,8 +436,9 @@ ftrace_new_return (struct btrace_thread_info *btinfo,
 
 	  /* Let's find the topmost function and add a new caller for it.
 	     This should handle a series of initial tail calls.  */
-	  while (prev->up != NULL)
-	    prev = prev->up;
+	  for (caller = prev; caller != NULL;
+	       caller = ftrace_find_call_by_number (btinfo, prev->up))
+	    prev = caller;
 
 	  bfun->level = prev->level - 1;
 
@@ -446,7 +458,7 @@ ftrace_new_return (struct btrace_thread_info *btinfo,
 	     on the same level as they are.
 	     This should handle things like schedule () correctly where we're
 	     switching contexts.  */
-	  prev->up = bfun;
+	  prev->up = bfun->number;
 	  prev->flags = BFUN_UP_LINKS_TO_RET;
 
 	  ftrace_debug (bfun, "new return - unknown caller");
@@ -649,7 +661,8 @@ ftrace_classify_insn (struct gdbarch *gdbarch, CORE_ADDR pc)
    match.  */
 
 static int
-ftrace_match_backtrace (struct btrace_function *lhs,
+ftrace_match_backtrace (struct btrace_thread_info *btinfo,
+			struct btrace_function *lhs,
 			struct btrace_function *rhs)
 {
   int matches;
@@ -659,8 +672,8 @@ ftrace_match_backtrace (struct btrace_function *lhs,
       if (ftrace_function_switched (lhs, rhs->msym, rhs->sym))
 	return 0;
 
-      lhs = ftrace_get_caller (lhs);
-      rhs = ftrace_get_caller (rhs);
+      lhs = ftrace_get_caller (btinfo, lhs);
+      rhs = ftrace_get_caller (btinfo, rhs);
     }
 
   return matches;
@@ -735,20 +748,26 @@ ftrace_connect_bfun (struct btrace_thread_info *btinfo,
   ftrace_fixup_level (next, prev->level - next->level);
 
   /* If we run out of back trace for one, let's use the other's.  */
-  if (prev->up == NULL)
+  if (prev->up == 0)
     {
-      if (next->up != NULL)
+      btrace_function_flags flags = next->flags;
+
+      next = ftrace_find_call_by_number (btinfo, next->up);
+      if (next != NULL)
 	{
 	  DEBUG_FTRACE ("using next's callers");
-	  ftrace_fixup_caller (btinfo, prev, next->up, next->flags);
+	  ftrace_fixup_caller (btinfo, prev, next, flags);
 	}
     }
-  else if (next->up == NULL)
+  else if (next->up == 0)
     {
-      if (prev->up != NULL)
+      btrace_function_flags flags = prev->flags;
+
+      prev = ftrace_find_call_by_number (btinfo, prev->up);
+      if (prev != NULL)
 	{
 	  DEBUG_FTRACE ("using prev's callers");
-	  ftrace_fixup_caller (btinfo, next, prev->up, prev->flags);
+	  ftrace_fixup_caller (btinfo, next, prev, flags);
 	}
     }
   else
@@ -766,26 +785,27 @@ ftrace_connect_bfun (struct btrace_thread_info *btinfo,
       if ((prev->flags & BFUN_UP_LINKS_TO_TAILCALL) != 0)
 	{
 	  struct btrace_function *caller;
-	  btrace_function_flags flags;
+	  btrace_function_flags flags = prev->flags;
 
 	  /* We checked NEXT->UP above so CALLER can't be NULL.  */
-	  caller = next->up;
-	  flags = next->flags;
+	  caller = ftrace_find_call_by_number (btinfo, next->up);
 
 	  DEBUG_FTRACE ("adding prev's tail calls to next");
 
-	  ftrace_fixup_caller (btinfo, next, prev->up, prev->flags);
+	  prev = ftrace_find_call_by_number (btinfo, prev->up);
+	  ftrace_fixup_caller (btinfo, next, prev, flags);
 
-	  for (prev = prev->up; prev != NULL; prev = prev->up)
+	  for (; prev != NULL;
+	       prev = ftrace_find_call_by_number (btinfo, prev->up))
 	    {
 	      /* At the end of PREV's back trace, continue with CALLER.  */
-	      if (prev->up == NULL)
+	      if (prev->up == 0)
 		{
 		  DEBUG_FTRACE ("fixing up link for tailcall chain");
 		  ftrace_debug (prev, "..top");
 		  ftrace_debug (caller, "..up");
 
-		  ftrace_fixup_caller (btinfo, prev, caller, flags);
+		  ftrace_fixup_caller (btinfo, prev, caller, next->flags);
 
 		  /* If we skipped any tail calls, this may move CALLER to a
 		     different function level.
@@ -830,8 +850,8 @@ ftrace_connect_backtrace (struct btrace_thread_info *btinfo,
       prev = lhs;
       next = rhs;
 
-      lhs = ftrace_get_caller (lhs);
-      rhs = ftrace_get_caller (rhs);
+      lhs = ftrace_get_caller (btinfo, lhs);
+      rhs = ftrace_get_caller (btinfo, rhs);
 
       ftrace_connect_bfun (btinfo, prev, next);
     }
@@ -860,12 +880,14 @@ ftrace_bridge_gap (struct btrace_thread_info *btinfo,
   /* We search the back traces of LHS and RHS for valid connections and connect
      the two functon segments that give the longest combined back trace.  */
 
-  for (cand_l = lhs; cand_l != NULL; cand_l = ftrace_get_caller (cand_l))
-    for (cand_r = rhs; cand_r != NULL; cand_r = ftrace_get_caller (cand_r))
+  for (cand_l = lhs; cand_l != NULL;
+       cand_l = ftrace_get_caller (btinfo, cand_l))
+    for (cand_r = rhs; cand_r != NULL;
+	 cand_r = ftrace_get_caller (btinfo, cand_r))
       {
 	int matches;
 
-	matches = ftrace_match_backtrace (cand_l, cand_r);
+	matches = ftrace_match_backtrace (btinfo, cand_l, cand_r);
 	if (best_matches < matches)
 	  {
 	    best_matches = matches;
diff --git a/gdb/btrace.h b/gdb/btrace.h
index 92435e7..2b28ff8 100644
--- a/gdb/btrace.h
+++ b/gdb/btrace.h
@@ -152,8 +152,10 @@ struct btrace_function
   /* The previous and next function in control flow order.  */
   struct btrace_func_link flow;
 
-  /* The directly preceding function segment in a (fake) call stack.  */
-  struct btrace_function *up;
+  /* The function segment number of the directly preceding function segment in
+     a (fake) call stack.  Will be zero if there is no such function segment in
+     the record.  */
+  unsigned int up;
 
   /* The instructions in this function segment.
      The instruction vector will be empty if the function segment
diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c
index 6158f31..14ad5b7 100644
--- a/gdb/python/py-record-btrace.c
+++ b/gdb/python/py-record-btrace.c
@@ -456,10 +456,10 @@ btpy_call_up (PyObject *self, void *closure)
   if (func == NULL)
     Py_RETURN_NONE;
 
-  if (func->up == NULL)
+  if (func->up == 0)
     Py_RETURN_NONE;
 
-  return btpy_call_new (obj->ptid, func->up->number);
+  return btpy_call_new (obj->ptid, func->up);
 }
 
 /* Implementation of BtraceFunctionCall.prev_sibling [BtraceFunctionCall].
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 87fbcba..791963c 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1584,7 +1584,7 @@ record_btrace_frame_unwind_stop_reason (struct frame_info *this_frame,
   bfun = cache->bfun;
   gdb_assert (bfun != NULL);
 
-  if (bfun->up == NULL)
+  if (bfun->up == 0)
     return UNWIND_UNAVAILABLE;
 
   return UNWIND_NO_REASON;
@@ -1643,11 +1643,12 @@ record_btrace_frame_prev_register (struct frame_info *this_frame,
   bfun = cache->bfun;
   gdb_assert (bfun != NULL);
 
-  caller = bfun->up;
-  if (caller == NULL)
+  if (bfun->up == 0)
     throw_error (NOT_AVAILABLE_ERROR,
 		 _("No caller in btrace record history"));
 
+  caller = VEC_index (btrace_fun_s, cache->tp->btrace.functions, bfun->up - 1);
+
   if ((bfun->flags & BFUN_UP_LINKS_TO_RET) != 0)
     {
       insn = VEC_index (btrace_insn_s, caller->insn, 0);
@@ -1701,7 +1702,7 @@ record_btrace_frame_sniffer (const struct frame_unwind *self,
 
       callee = btrace_get_frame_function (next);
       if (callee != NULL && (callee->flags & BFUN_UP_LINKS_TO_TAILCALL) == 0)
-	bfun = callee->up;
+	bfun = VEC_index (btrace_fun_s, tp->btrace.functions, callee->up - 1);
     }
 
   if (bfun == NULL)
@@ -1728,6 +1729,7 @@ record_btrace_tailcall_frame_sniffer (const struct frame_unwind *self,
 {
   const struct btrace_function *bfun, *callee;
   struct btrace_frame_cache *cache;
+  struct thread_info *tinfo;
   struct frame_info *next;
 
   next = get_next_frame (this_frame);
@@ -1741,16 +1743,18 @@ record_btrace_tailcall_frame_sniffer (const struct frame_unwind *self,
   if ((callee->flags & BFUN_UP_LINKS_TO_TAILCALL) == 0)
     return 0;
 
-  bfun = callee->up;
-  if (bfun == NULL)
+  if (callee->up == 0)
     return 0;
 
+  tinfo = find_thread_ptid (inferior_ptid);
+  bfun = VEC_index (btrace_fun_s, tinfo->btrace.functions, callee->up - 1);
+
   DEBUG ("[frame] sniffed tailcall frame for %s on level %d",
 	 btrace_get_bfun_name (bfun), bfun->level);
 
   /* This is our frame.  Initialize the frame cache.  */
   cache = bfcache_new (this_frame);
-  cache->tp = find_thread_ptid (inferior_ptid);
+  cache->tp = tinfo;
   cache->bfun = bfun;
 
   *this_cache = cache;
-- 
2.7.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]