From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10137 invoked by alias); 14 Jul 2014 13:57:02 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 10063 invoked by uid 89); 14 Jul 2014 13:57:01 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.8 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mga09.intel.com Received: from mga09.intel.com (HELO mga09.intel.com) (134.134.136.24) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 14 Jul 2014 13:56:57 +0000 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP; 14 Jul 2014 06:51:20 -0700 X-ExtLoop1: 1 Received: from irvmail001.ir.intel.com ([163.33.26.43]) by orsmga001.jf.intel.com with ESMTP; 14 Jul 2014 06:56:39 -0700 Received: from ulvlx001.iul.intel.com (ulvlx001.iul.intel.com [172.28.207.17]) by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id s6EDuc3C009234; Mon, 14 Jul 2014 14:56:38 +0100 Received: from ulvlx001.iul.intel.com (localhost [127.0.0.1]) by ulvlx001.iul.intel.com with ESMTP id s6EDuc2W002127; Mon, 14 Jul 2014 15:56:38 +0200 Received: (from mmetzger@localhost) by ulvlx001.iul.intel.com with œ id s6EDucEE002123; Mon, 14 Jul 2014 15:56:38 +0200 From: Markus Metzger To: palves@redhat.com Cc: gdb-patches@sourceware.org Subject: [PATCH 07/12] btrace: extend struct btrace_insn Date: Mon, 14 Jul 2014 13:57:00 -0000 Message-Id: <1405346196-1804-8-git-send-email-markus.t.metzger@intel.com> In-Reply-To: <1405346196-1804-1-git-send-email-markus.t.metzger@intel.com> References: <1405346196-1804-1-git-send-email-markus.t.metzger@intel.com> X-IsSubscribed: yes X-SW-Source: 2014-07/txt/msg00329.txt.bz2 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. 2014-07-14 Markus Metzger * btrace.h (btrace_insn_class): New. (btrace_insn) : 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 | 109 ++++++++++++++++++++++++++++++++--------------------------- gdb/btrace.h | 22 ++++++++++++ 2 files changed, 81 insertions(+), 50 deletions(-) diff --git a/gdb/btrace.c b/gdb/btrace.c index d96994d..0171352 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,35 @@ 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"); } +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_ALL) + { + 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 +617,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 +629,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 +638,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_ALL) + 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 8656cda..3de7b73 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