From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 913 invoked by alias); 17 Feb 2017 13:27:20 -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 744 invoked by uid 89); 17 Feb 2017 13:27:19 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-23.6 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_LAZY_DOMAIN_SECURITY,RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=functon, *cache, squash, our X-HELO: mga05.intel.com Received: from mga05.intel.com (HELO mga05.intel.com) (192.55.52.43) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 17 Feb 2017 13:27:12 +0000 Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga105.fm.intel.com with ESMTP; 17 Feb 2017 05:27:11 -0800 X-ExtLoop1: 1 Received: from irvmail001.ir.intel.com ([163.33.26.43]) by fmsmga004.fm.intel.com with ESMTP; 17 Feb 2017 05:27:10 -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 v1HDR9gj001620; Fri, 17 Feb 2017 13:27:09 GMT Received: from ulvlx001.iul.intel.com (localhost [127.0.0.1]) by ulvlx001.iul.intel.com with ESMTP id v1HDR9Px006672; Fri, 17 Feb 2017 14:27:09 +0100 Received: (from twiederh@localhost) by ulvlx001.iul.intel.com with œ id v1HDR9pc006668; Fri, 17 Feb 2017 14:27:09 +0100 From: Tim Wiederhake To: gdb-patches@sourceware.org Cc: markus.t.metzger@intel.com Subject: [PATCH 07/11] [SQUASH] btrace: Adjust struct btrace_function::up. Date: Fri, 17 Feb 2017 13:27:00 -0000 Message-Id: <1487337989-6367-8-git-send-email-tim.wiederhake@intel.com> In-Reply-To: <1487337989-6367-1-git-send-email-tim.wiederhake@intel.com> References: <1487337989-6367-1-git-send-email-tim.wiederhake@intel.com> X-IsSubscribed: yes X-SW-Source: 2017-02/txt/msg00489.txt.bz2 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 --- 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