From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1541 invoked by alias); 29 Jan 2015 16:28:59 -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 1439 invoked by uid 89); 29 Jan 2015 16:28:58 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.7 required=5.0 tests=AWL,BAYES_00,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mga14.intel.com Received: from mga14.intel.com (HELO mga14.intel.com) (192.55.52.115) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 29 Jan 2015 16:28:40 +0000 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga103.fm.intel.com with ESMTP; 29 Jan 2015 08:22:11 -0800 X-ExtLoop1: 1 Received: from irvmail001.ir.intel.com ([163.33.26.43]) by orsmga002.jf.intel.com with ESMTP; 29 Jan 2015 08:28:24 -0800 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 t0TGSMtW020048; Thu, 29 Jan 2015 16:28:22 GMT Received: from ulvlx001.iul.intel.com (localhost [127.0.0.1]) by ulvlx001.iul.intel.com with ESMTP id t0TGSM9o010113; Thu, 29 Jan 2015 17:28:22 +0100 Received: (from mmetzger@localhost) by ulvlx001.iul.intel.com with œ id t0TGSMaq010109; Thu, 29 Jan 2015 17:28:22 +0100 From: Markus Metzger To: palves@redhat.com Cc: gdb-patches@sourceware.org Subject: [PATCH v3 07/15] btrace: extend struct btrace_insn Date: Thu, 29 Jan 2015 16:29:00 -0000 Message-Id: <1422548899-9789-8-git-send-email-markus.t.metzger@intel.com> In-Reply-To: <1422548899-9789-1-git-send-email-markus.t.metzger@intel.com> References: <1422548899-9789-1-git-send-email-markus.t.metzger@intel.com> X-IsSubscribed: yes X-SW-Source: 2015-01/txt/msg00768.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. 2015-01-29 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 | 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