Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Markus Metzger <markus.t.metzger@intel.com>
To: palves@redhat.com
Cc: gdb-patches@sourceware.org
Subject: [PATCH v4 7/9] btrace: extend struct btrace_insn
Date: Thu, 05 Feb 2015 15:28:00 -0000	[thread overview]
Message-ID: <1423150072-21229-8-git-send-email-markus.t.metzger@intel.com> (raw)
In-Reply-To: <1423150072-21229-1-git-send-email-markus.t.metzger@intel.com>

Add the instruction's size as well as a coarse classification to struct
btrace_insn.  Use the information in ftrace_update_function and
ftrace_find_call.

2015-02-05  Markus Metzger  <markus.t.metzger@intel.com>

	* btrace.h (btrace_insn_class): New.
	(btrace_insn) <size, iclass>: New.
	* btrace.c (ftrace_find_call): Update parameters.  Update users.
	Use instruction classification.
	(ftrace_new_return): Update parameters.  Update users.
	(ftrace_update_function): Update parameters.  Update users.  Use
	instruction classification.
	(ftrace_update_insns): Update parameters.  Update users.
	(ftrace_classify_insn): New.
	(btrace_compute_ftrace_bts): Fill in new btrace_insn fields.  Add
	TRY_CATCH around call to gdb_insn_length.
---
 gdb/btrace.c | 111 ++++++++++++++++++++++++++++++++---------------------------
 gdb/btrace.h |  22 ++++++++++++
 2 files changed, 83 insertions(+), 50 deletions(-)

diff --git a/gdb/btrace.c b/gdb/btrace.c
index e96499e..72e8567 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -330,20 +330,18 @@ ftrace_find_caller (struct btrace_function *bfun,
    tail calls ending with a jump).  */
 
 static struct btrace_function *
-ftrace_find_call (struct gdbarch *gdbarch, struct btrace_function *bfun)
+ftrace_find_call (struct btrace_function *bfun)
 {
   for (; bfun != NULL; bfun = bfun->up)
     {
       struct btrace_insn *last;
-      CORE_ADDR pc;
 
       /* We do not allow empty function segments.  */
       gdb_assert (!VEC_empty (btrace_insn_s, bfun->insn));
 
       last = VEC_last (btrace_insn_s, bfun->insn);
-      pc = last->pc;
 
-      if (gdbarch_insn_is_call (gdbarch, pc))
+      if (last->iclass == BTRACE_INSN_CALL)
 	break;
     }
 
@@ -355,8 +353,7 @@ ftrace_find_call (struct gdbarch *gdbarch, struct btrace_function *bfun)
    MFUN and FUN are the symbol information we have for this function.  */
 
 static struct btrace_function *
-ftrace_new_return (struct gdbarch *gdbarch,
-		   struct btrace_function *prev,
+ftrace_new_return (struct btrace_function *prev,
 		   struct minimal_symbol *mfun,
 		   struct symbol *fun)
 {
@@ -391,7 +388,7 @@ ftrace_new_return (struct gdbarch *gdbarch,
 	 wrong or that the call is simply not included in the trace.  */
 
       /* Let's search for some actual call.  */
-      caller = ftrace_find_call (gdbarch, prev->up);
+      caller = ftrace_find_call (prev->up);
       if (caller == NULL)
 	{
 	  /* There is no call in PREV's back trace.  We assume that the
@@ -454,8 +451,7 @@ ftrace_new_switch (struct btrace_function *prev,
    Return the chronologically latest function segment, never NULL.  */
 
 static struct btrace_function *
-ftrace_update_function (struct gdbarch *gdbarch,
-			struct btrace_function *bfun, CORE_ADDR pc)
+ftrace_update_function (struct btrace_function *bfun, CORE_ADDR pc)
 {
   struct bound_minimal_symbol bmfun;
   struct minimal_symbol *mfun;
@@ -485,24 +481,29 @@ ftrace_update_function (struct gdbarch *gdbarch,
 
   if (last != NULL)
     {
-      CORE_ADDR lpc;
+      switch (last->iclass)
+	{
+	case BTRACE_INSN_RETURN:
+	  return ftrace_new_return (bfun, mfun, fun);
 
-      lpc = last->pc;
+	case BTRACE_INSN_CALL:
+	  /* Ignore calls to the next instruction.  They are used for PIC.  */
+	  if (last->pc + last->size == pc)
+	    break;
 
-      /* Check for returns.  */
-      if (gdbarch_insn_is_ret (gdbarch, lpc))
-	return ftrace_new_return (gdbarch, bfun, mfun, fun);
+	  return ftrace_new_call (bfun, mfun, fun);
 
-      /* Check for calls.  */
-      if (gdbarch_insn_is_call (gdbarch, lpc))
-	{
-	  int size;
+	case BTRACE_INSN_JUMP:
+	  {
+	    CORE_ADDR start;
 
-	  size = gdb_insn_length (gdbarch, lpc);
+	    start = get_pc_function_start (pc);
 
-	  /* Ignore calls to the next instruction.  They are used for PIC.  */
-	  if (lpc + size != pc)
-	    return ftrace_new_call (bfun, mfun, fun);
+	    /* If we can't determine the function for PC, we treat a jump at
+	       the end of the block as tail call.  */
+	    if (start == 0 || start == pc)
+	      return ftrace_new_tailcall (bfun, mfun, fun);
+	  }
 	}
     }
 
@@ -514,24 +515,6 @@ ftrace_update_function (struct gdbarch *gdbarch,
 		    ftrace_print_function_name (bfun),
 		    ftrace_print_filename (bfun));
 
-      if (last != NULL)
-	{
-	  CORE_ADDR start, lpc;
-
-	  start = get_pc_function_start (pc);
-
-	  /* If we can't determine the function for PC, we treat a jump at
-	     the end of the block as tail call.  */
-	  if (start == 0)
-	    start = pc;
-
-	  lpc = last->pc;
-
-	  /* Jumps indicate optimized tail calls.  */
-	  if (start == pc && gdbarch_insn_is_jump (gdbarch, lpc))
-	    return ftrace_new_tailcall (bfun, mfun, fun);
-	}
-
       return ftrace_new_switch (bfun, mfun, fun);
     }
 
@@ -574,17 +557,37 @@ ftrace_update_lines (struct btrace_function *bfun, CORE_ADDR pc)
 /* Add the instruction at PC to BFUN's instructions.  */
 
 static void
-ftrace_update_insns (struct btrace_function *bfun, CORE_ADDR pc)
+ftrace_update_insns (struct btrace_function *bfun,
+		     const struct btrace_insn *insn)
 {
-  struct btrace_insn *insn;
-
-  insn = VEC_safe_push (btrace_insn_s, bfun->insn, NULL);
-  insn->pc = pc;
+  VEC_safe_push (btrace_insn_s, bfun->insn, insn);
 
   if (record_debug > 1)
     ftrace_debug (bfun, "update insn");
 }
 
+/* Classify the instruction at PC.  */
+
+static enum btrace_insn_class
+ftrace_classify_insn (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  volatile struct gdb_exception error;
+  enum btrace_insn_class iclass;
+
+  iclass = BTRACE_INSN_OTHER;
+  TRY_CATCH (error, RETURN_MASK_ERROR)
+    {
+      if (gdbarch_insn_is_call (gdbarch, pc))
+	iclass = BTRACE_INSN_CALL;
+      else if (gdbarch_insn_is_ret (gdbarch, pc))
+	iclass = BTRACE_INSN_RETURN;
+      else if (gdbarch_insn_is_jump (gdbarch, pc))
+	iclass = BTRACE_INSN_JUMP;
+    }
+
+  return iclass;
+}
+
 /* Compute the function branch trace from BTS trace.  */
 
 static void
@@ -616,6 +619,8 @@ btrace_compute_ftrace_bts (struct thread_info *tp,
 
       for (;;)
 	{
+	  volatile struct gdb_exception error;
+	  struct btrace_insn insn;
 	  int size;
 
 	  /* We should hit the end of the block.  Warn if we went too far.  */
@@ -626,7 +631,7 @@ btrace_compute_ftrace_bts (struct thread_info *tp,
 	      break;
 	    }
 
-	  end = ftrace_update_function (gdbarch, end, pc);
+	  end = ftrace_update_function (end, pc);
 	  if (begin == NULL)
 	    begin = end;
 
@@ -635,16 +640,22 @@ btrace_compute_ftrace_bts (struct thread_info *tp,
 	  if (blk != 0)
 	    level = min (level, end->level);
 
-	  ftrace_update_insns (end, pc);
+	  size = 0;
+	  TRY_CATCH (error, RETURN_MASK_ERROR)
+	    size = gdb_insn_length (gdbarch, pc);
+
+	  insn.pc = pc;
+	  insn.size = size;
+	  insn.iclass = ftrace_classify_insn (gdbarch, pc);
+
+	  ftrace_update_insns (end, &insn);
 	  ftrace_update_lines (end, pc);
 
 	  /* We're done once we pushed the instruction at the end.  */
 	  if (block->end == pc)
 	    break;
 
-	  size = gdb_insn_length (gdbarch, pc);
-
-	  /* Make sure we terminate if we fail to compute the size.  */
+	  /* We can't continue if we fail to compute the size.  */
 	  if (size <= 0)
 	    {
 	      warning (_("Recorded trace may be incomplete around %s."),
diff --git a/gdb/btrace.h b/gdb/btrace.h
index fde0619..694d504 100644
--- a/gdb/btrace.h
+++ b/gdb/btrace.h
@@ -31,6 +31,22 @@
 struct thread_info;
 struct btrace_function;
 
+/* A coarse instruction classification.  */
+enum btrace_insn_class
+{
+  /* The instruction is something not listed below.  */
+  BTRACE_INSN_OTHER,
+
+  /* The instruction is a function call.  */
+  BTRACE_INSN_CALL,
+
+  /* The instruction is a function return.  */
+  BTRACE_INSN_RETURN,
+
+  /* The instruction is an unconditional jump.  */
+  BTRACE_INSN_JUMP
+};
+
 /* A branch trace instruction.
 
    This represents a single instruction in a branch trace.  */
@@ -38,6 +54,12 @@ struct btrace_insn
 {
   /* The address of this instruction.  */
   CORE_ADDR pc;
+
+  /* The size of this instruction in bytes.  */
+  gdb_byte size;
+
+  /* The instruction class of this instruction.  */
+  enum btrace_insn_class iclass;
 };
 
 /* A vector of branch trace instructions.  */
-- 
1.8.3.1


  parent reply	other threads:[~2015-02-05 15:28 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-02-05 15:27 [PATCH v4 0/9] record btrace: prepare for a new trace format Markus Metzger
2015-02-05 15:28 ` [PATCH v4 4/9] record btrace: add configuration struct Markus Metzger
2015-02-05 16:27   ` Eli Zaretskii
2015-02-05 18:31   ` Pedro Alves
2015-02-05 15:28 ` [PATCH v4 1/9] btrace: add struct btrace_data Markus Metzger
2015-02-05 15:28 ` [PATCH v4 9/9] record-btrace: indicate gaps Markus Metzger
2015-02-05 15:28 ` [PATCH v4 6/9] btrace: update btrace_compute_ftrace parameters Markus Metzger
2015-02-05 15:28 ` [PATCH v4 2/9] btrace: add format argument to supports_btrace Markus Metzger
2015-02-05 15:28 ` [PATCH v4 5/9] record-btrace: add bts buffer size configuration option Markus Metzger
2015-02-05 16:25   ` Eli Zaretskii
2015-02-05 15:28 ` Markus Metzger [this message]
2015-02-05 15:28 ` [PATCH v4 8/9] btrace: identify cpu Markus Metzger
2015-02-05 18:31   ` Pedro Alves
2015-02-05 15:28 ` [PATCH v4 3/9] btrace, linux: add perf event buffer abstraction Markus Metzger
2015-02-05 18:33 ` [PATCH v4 0/9] record btrace: prepare for a new trace format Pedro Alves

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=1423150072-21229-8-git-send-email-markus.t.metzger@intel.com \
    --to=markus.t.metzger@intel.com \
    --cc=gdb-patches@sourceware.org \
    --cc=palves@redhat.com \
    /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