[PATCH v3 12/12] btrace: Store function segments as objects.

Tim Wiederhake tim.wiederhake@intel.com
Tue May 9 07:01:00 GMT 2017


2017-05-09  Tim Wiederhake  <tim.wiederhake@intel.com>

gdb/ChangeLog:
	* btrace.c:
	* btrace.h:
	* record-btrace.c:

---
 gdb/btrace.c        | 94 ++++++++++++++++++++++++++---------------------------
 gdb/btrace.h        |  7 ++--
 gdb/record-btrace.c | 10 +++---
 3 files changed, 56 insertions(+), 55 deletions(-)

diff --git a/gdb/btrace.c b/gdb/btrace.c
index 7b82000..4c7020d 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -155,14 +155,27 @@ ftrace_call_num_insn (const struct btrace_function* bfun)
 /* Return the function segment with the given NUMBER or NULL if no such segment
    exists.  BTINFO is the branch trace information for the current thread.  */
 
-static struct btrace_function *
+const static struct btrace_function *
 ftrace_find_call_by_number (const struct btrace_thread_info *btinfo,
 			    unsigned int number)
 {
   if (number == 0 || number > btinfo->functions.size ())
     return NULL;
 
-  return btinfo->functions[number - 1];
+  return &btinfo->functions[number - 1];
+}
+
+/* Return the function segment with the given NUMBER or NULL if no such segment
+   exists.  BTINFO is the branch trace information for the current thread.  */
+
+static struct btrace_function *
+ftrace_find_call_by_number (struct btrace_thread_info *btinfo,
+			    unsigned int number)
+{
+  if (number == 0 || number > btinfo->functions.size ())
+    return NULL;
+
+  return &btinfo->functions[number - 1];
 }
 
 /* Return non-zero if BFUN does not match MFUN and FUN,
@@ -214,37 +227,33 @@ ftrace_function_switched (const struct btrace_function *bfun,
 /* Allocate and initialize a new branch trace function segment at the end of
    the trace.
    BTINFO is the branch trace information for the current thread.
-   MFUN and FUN are the symbol information we have for this function.  */
+   MFUN and FUN are the symbol information we have for this function.
+   This invalidates all struct btrace_function pointer currently held.  */
 
 static struct btrace_function *
 ftrace_new_function (struct btrace_thread_info *btinfo,
 		     struct minimal_symbol *mfun,
 		     struct symbol *fun)
 {
-  struct btrace_function *bfun;
-
-  bfun = XCNEW (struct btrace_function);
-
-  bfun->msym = mfun;
-  bfun->sym = fun;
+  struct btrace_function bfun {mfun, fun, 0, 0, 0, NULL, 0, 0, 0, 0, 0};
 
   if (btinfo->functions.empty ())
     {
       /* Start counting at one.  */
-      bfun->number = 1;
-      bfun->insn_offset = 1;
+      bfun.number = 1;
+      bfun.insn_offset = 1;
     }
   else
     {
-      struct btrace_function *prev = btinfo->functions.back ();
+      struct btrace_function *prev = &btinfo->functions.back ();
 
-      bfun->number = prev->number + 1;
-      bfun->insn_offset = prev->insn_offset + ftrace_call_num_insn (prev);
-      bfun->level = prev->level;
+      bfun.number = prev->number + 1;
+      bfun.insn_offset = prev->insn_offset + ftrace_call_num_insn (prev);
+      bfun.level = prev->level;
     }
 
-  btinfo->functions.push_back (bfun);
-  return bfun;
+  btinfo->functions.push_back (std::move (bfun));
+  return &btinfo->functions.back ();
 }
 
 /* Update the UP field of a function segment.  */
@@ -406,10 +415,10 @@ ftrace_new_return (struct btrace_thread_info *btinfo,
 		   struct minimal_symbol *mfun,
 		   struct symbol *fun)
 {
-  struct btrace_function *prev = btinfo->functions.back ();
-  struct btrace_function *bfun, *caller;
+  struct btrace_function *prev, *bfun, *caller;
 
   bfun = ftrace_new_function (btinfo, mfun, fun);
+  prev = ftrace_find_call_by_number (btinfo, bfun->number - 1);
 
   /* It is important to start at PREV's caller.  Otherwise, we might find
      PREV itself, if PREV is a recursive function.  */
@@ -488,12 +497,12 @@ ftrace_new_switch (struct btrace_thread_info *btinfo,
 		   struct minimal_symbol *mfun,
 		   struct symbol *fun)
 {
-  struct btrace_function *prev = btinfo->functions.back ();
-  struct btrace_function *bfun;
+  struct btrace_function *prev, *bfun;
 
   /* This is an unexplained function switch.  We can't really be sure about the
      call stack, yet the best I can think of right now is to preserve it.  */
   bfun = ftrace_new_function (btinfo, mfun, fun);
+  prev = ftrace_find_call_by_number (btinfo, bfun->number - 1);
   bfun->up = prev->up;
   bfun->flags = prev->flags;
 
@@ -518,7 +527,7 @@ ftrace_new_gap (struct btrace_thread_info *btinfo, int errcode,
   else
     {
       /* We hijack the previous function segment if it was empty.  */
-      bfun = btinfo->functions.back ();
+      bfun = &btinfo->functions.back ();
       if (bfun->errcode != 0 || !VEC_empty (btrace_insn_s, bfun->insn))
 	bfun = ftrace_new_function (btinfo, NULL, NULL);
     }
@@ -559,7 +568,7 @@ ftrace_update_function (struct btrace_thread_info *btinfo, CORE_ADDR pc)
     return ftrace_new_function (btinfo, mfun, fun);
 
   /* If we had a gap before, we create a function.  */
-  bfun = btinfo->functions.back ();
+  bfun = &btinfo->functions.back ();
   if (bfun->errcode != 0)
     return ftrace_new_function (btinfo, mfun, fun);
 
@@ -738,10 +747,10 @@ ftrace_compute_global_level_offset (struct btrace_thread_info *btinfo)
       /* The last function segment contains the current instruction, which is
 	 not really part of the trace.  If it contains just this one
 	 instruction, we ignore the segment.  */
-      if (bfun->number == length && VEC_length (btrace_insn_s, bfun->insn) == 1)
+      if (bfun.number == length && VEC_length (btrace_insn_s, bfun.insn) == 1)
 	continue;
 
-      level = std::min (level, bfun->level);
+      level = std::min (level, bfun.level);
     }
 
   DEBUG_FTRACE ("setting global level offset: %d", -level);
@@ -1610,7 +1619,7 @@ btrace_stitch_bts (struct btrace_data_bts *btrace, struct thread_info *tp)
   gdb_assert (!btinfo->functions.empty ());
   gdb_assert (!VEC_empty (btrace_block_s, btrace->blocks));
 
-  last_bfun = btinfo->functions.back ();
+  last_bfun = &btinfo->functions.back ();
 
   /* If the existing trace ends with a gap, we just glue the traces
      together.  We need to drop the last (i.e. chronologically first) block
@@ -1902,10 +1911,7 @@ btrace_clear (struct thread_info *tp)
 
   btinfo = &tp->btrace;
   for (auto &bfun : btinfo->functions)
-    {
-      VEC_free (btrace_insn_s, bfun->insn);
-      xfree (bfun);
-    }
+    VEC_free (btrace_insn_s, bfun.insn);
 
   btinfo->functions.clear ();
   btinfo->ngaps = 0;
@@ -2254,7 +2260,7 @@ btrace_insn_get (const struct btrace_insn_iterator *it)
   unsigned int index, end;
 
   index = it->insn_index;
-  bfun = it->btinfo->functions[it->call_index];
+  bfun = &it->btinfo->functions[it->call_index];
 
   /* Check if the iterator points to a gap in the trace.  */
   if (bfun->errcode != 0)
@@ -2273,10 +2279,7 @@ btrace_insn_get (const struct btrace_insn_iterator *it)
 int
 btrace_insn_get_error (const struct btrace_insn_iterator *it)
 {
-  const struct btrace_function *bfun;
-
-  bfun = it->btinfo->functions[it->call_index];
-  return bfun->errcode;
+  return it->btinfo->functions[it->call_index].errcode;
 }
 
 /* See btrace.h.  */
@@ -2284,10 +2287,7 @@ btrace_insn_get_error (const struct btrace_insn_iterator *it)
 unsigned int
 btrace_insn_number (const struct btrace_insn_iterator *it)
 {
-  const struct btrace_function *bfun;
-
-  bfun = it->btinfo->functions[it->call_index];
-  return bfun->insn_offset + it->insn_index;
+  return it->btinfo->functions[it->call_index].insn_offset + it->insn_index;
 }
 
 /* See btrace.h.  */
@@ -2316,7 +2316,7 @@ btrace_insn_end (struct btrace_insn_iterator *it,
   if (btinfo->functions.empty ())
     error (_("No trace."));
 
-  bfun = btinfo->functions.back ();
+  bfun = &btinfo->functions.back ();
   length = VEC_length (btrace_insn_s, bfun->insn);
 
   /* The last function may either be a gap or it contains the current
@@ -2338,7 +2338,7 @@ btrace_insn_next (struct btrace_insn_iterator *it, unsigned int stride)
   const struct btrace_function *bfun;
   unsigned int index, steps;
 
-  bfun = it->btinfo->functions[it->call_index];
+  bfun = &it->btinfo->functions[it->call_index];
   steps = 0;
   index = it->insn_index;
 
@@ -2420,7 +2420,7 @@ btrace_insn_prev (struct btrace_insn_iterator *it, unsigned int stride)
   const struct btrace_function *bfun;
   unsigned int index, steps;
 
-  bfun = it->btinfo->functions[it->call_index];
+  bfun = &it->btinfo->functions[it->call_index];
   steps = 0;
   index = it->insn_index;
 
@@ -2507,12 +2507,12 @@ btrace_find_insn_by_number (struct btrace_insn_iterator *it,
       return 0;
 
   lower = 0;
-  bfun = btinfo->functions[lower];
+  bfun = &btinfo->functions[lower];
   if (number < bfun->insn_offset)
     return 0;
 
   upper = btinfo->functions.size () - 1;
-  bfun = btinfo->functions[upper];
+  bfun = &btinfo->functions[upper];
   if (number >= bfun->insn_offset + ftrace_call_num_insn (bfun))
     return 0;
 
@@ -2521,7 +2521,7 @@ btrace_find_insn_by_number (struct btrace_insn_iterator *it,
     {
       const unsigned int average = lower + (upper - lower) / 2;
 
-      bfun = btinfo->functions[average];
+      bfun = &btinfo->functions[average];
 
       if (number < bfun->insn_offset)
 	{
@@ -2555,7 +2555,7 @@ btrace_ends_with_single_insn (const struct btrace_thread_info *btinfo)
   if (btinfo->functions.empty ())
     return 0;
 
-  bfun = btinfo->functions.back ();
+  bfun = &btinfo->functions.back ();
   if (bfun->errcode != 0)
     return 0;
 
@@ -2570,7 +2570,7 @@ btrace_call_get (const struct btrace_call_iterator *it)
   if (it->index >= it->btinfo->functions.size ())
     return NULL;
 
-  return it->btinfo->functions[it->index];
+  return &it->btinfo->functions[it->index];
 }
 
 /* See btrace.h.  */
diff --git a/gdb/btrace.h b/gdb/btrace.h
index 0acd2fb..d400a3c 100644
--- a/gdb/btrace.h
+++ b/gdb/btrace.h
@@ -325,9 +325,10 @@ struct btrace_thread_info
   /* The raw branch trace data for the below branch trace.  */
   struct btrace_data data;
 
-  /* Vector of pointer to decoded function segments.  These are in execution
-     order with the first element == BEGIN and the last element == END.  */
-  std::vector<btrace_function *> functions;
+  /* Vector of decoded function segments in execution flow order.  Note that
+     the numbering for btrace function segments starts with 1, so function
+     segment i will be at index (i - 1).  */
+  std::vector<btrace_function> functions;
 
   /* The function level offset.  When added to each function's LEVEL,
      this normalizes the function levels such that the smallest level
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index a66d32a..d00ffce 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1592,7 +1592,7 @@ record_btrace_frame_this_id (struct frame_info *this_frame, void **this_cache,
   gdb_assert (bfun != NULL);
 
   while (bfun->prev != 0)
-    bfun = cache->tp->btrace.functions[bfun->prev - 1];
+    bfun = &cache->tp->btrace.functions[bfun->prev - 1];
 
   code = get_frame_func (this_frame);
   special = bfun->number;
@@ -1633,7 +1633,7 @@ record_btrace_frame_prev_register (struct frame_info *this_frame,
     throw_error (NOT_AVAILABLE_ERROR,
 		 _("No caller in btrace record history"));
 
-  caller = cache->tp->btrace.functions[bfun->up - 1];
+  caller = &cache->tp->btrace.functions[bfun->up - 1];
 
   if ((bfun->flags & BFUN_UP_LINKS_TO_RET) != 0)
     {
@@ -1679,7 +1679,7 @@ record_btrace_frame_sniffer (const struct frame_unwind *self,
 
       replay = tp->btrace.replay;
       if (replay != NULL)
-	bfun = replay->btinfo->functions[replay->call_index];
+	bfun = &replay->btinfo->functions[replay->call_index];
     }
   else
     {
@@ -1687,7 +1687,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 = tp->btrace.functions[callee->up - 1];
+	bfun = &tp->btrace.functions[callee->up - 1];
     }
 
   if (bfun == NULL)
@@ -1732,7 +1732,7 @@ record_btrace_tailcall_frame_sniffer (const struct frame_unwind *self,
     return 0;
 
   tinfo = find_thread_ptid (inferior_ptid);
-  bfun = tinfo->btrace.functions[callee->up - 1];
+  bfun = &tinfo->btrace.functions[callee->up - 1];
 
   DEBUG ("[frame] sniffed tailcall frame for %s on level %d",
 	 btrace_get_bfun_name (bfun), bfun->level);
-- 
2.7.4



More information about the Gdb-patches mailing list