From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29746 invoked by alias); 3 Jul 2013 09:14:48 -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 29619 invoked by uid 89); 3 Jul 2013 09:14:48 -0000 X-Spam-SWARE-Status: No, score=-6.6 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,KHOP_THREADED,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL,RP_MATCHES_RCVD autolearn=ham version=3.3.1 Received: from mga02.intel.com (HELO mga02.intel.com) (134.134.136.20) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Wed, 03 Jul 2013 09:14:45 +0000 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP; 03 Jul 2013 02:14:42 -0700 X-ExtLoop1: 1 Received: from irvmail001.ir.intel.com ([163.33.26.43]) by orsmga001.jf.intel.com with ESMTP; 03 Jul 2013 02:14:41 -0700 Received: from ulslx001.iul.intel.com (ulslx001.iul.intel.com [172.28.207.63]) by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id r639Eeub009856; Wed, 3 Jul 2013 10:14:40 +0100 Received: from ulslx001.iul.intel.com (localhost [127.0.0.1]) by ulslx001.iul.intel.com with ESMTP id r639Eeme029377; Wed, 3 Jul 2013 11:14:40 +0200 Received: (from mmetzger@localhost) by ulslx001.iul.intel.com with id r639EepA029373; Wed, 3 Jul 2013 11:14:40 +0200 From: Markus Metzger To: jan.kratochvil@redhat.com Cc: gdb-patches@sourceware.org Subject: [patch v4 24/24] record-btrace: skip tail calls in back trace Date: Wed, 03 Jul 2013 09:14:00 -0000 Message-Id: <1372842874-28951-25-git-send-email-markus.t.metzger@intel.com> In-Reply-To: <1372842874-28951-1-git-send-email-markus.t.metzger@intel.com> References: <1372842874-28951-1-git-send-email-markus.t.metzger@intel.com> X-SW-Source: 2013-07/txt/msg00120.txt.bz2 The branch trace represents the caller/callee relationship of tail calls. The caller of a tail call is shown in the back trace and in the function-call history. This is not consistent with GDB's normal behavior, where the tail caller is not shown in the back trace. It further causes the finish command to fail for tail calls. This patch skips tail calls when computing the back trace during replay. The finish command now works also for tail calls. The tail caller is still shown in the function-call history. I'm not sure which is the better behavior. I liked seeing the tail caller in the call stack and I'm not using the finish command very often. On the other hand, reverse/replay should be as close to live debugging as possible. 2013-07-03 Markus Metzger * record-btrace.c (record_btrace_frame_sniffer): Skip tail calls. testsuite/ * gdb.btrace/tailcall.exp: Update. Add stepping tests. * gdb.btrace/rn-dl-bind.c: New. * gdb.btrace/rn-dl-bind.exp: New. --- gdb/record-btrace.c | 15 ++++++---- gdb/testsuite/gdb.btrace/rn-dl-bind.c | 37 +++++++++++++++++++++++ gdb/testsuite/gdb.btrace/rn-dl-bind.exp | 48 +++++++++++++++++++++++++++++++ gdb/testsuite/gdb.btrace/tailcall.exp | 25 +++++++++++++-- 4 files changed, 115 insertions(+), 10 deletions(-) create mode 100644 gdb/testsuite/gdb.btrace/rn-dl-bind.c create mode 100644 gdb/testsuite/gdb.btrace/rn-dl-bind.exp diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index b45a5fb..9feda30 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -1026,7 +1026,7 @@ record_btrace_frame_this_id (struct frame_info *this_frame, void **this_cache, cache = *this_cache; stack = 0; - code = get_frame_func (this_frame); + code = cache->pc; special = (CORE_ADDR) cache->bfun; *this_id = frame_id_build_special (stack, code, special); @@ -1120,6 +1120,13 @@ record_btrace_frame_sniffer (const struct frame_unwind *self, caller = bfun->up; pc = 0; + /* Skip tail calls. */ + while (caller != NULL && (bfun->flags & BFUN_UP_LINKS_TO_TAILCALL) != 0) + { + bfun = caller; + caller = bfun->up; + } + /* Determine where to find the PC in the upper function segment. */ if (caller != NULL) { @@ -1133,11 +1140,7 @@ record_btrace_frame_sniffer (const struct frame_unwind *self, insn = VEC_last (btrace_insn_s, caller->insn); pc = insn->pc; - /* We link directly to the jump instruction in the case of a tail - call, since the next instruction will likely be outside of the - caller function. */ - if ((bfun->flags & BFUN_UP_LINKS_TO_TAILCALL) == 0) - pc += gdb_insn_length (get_frame_arch (this_frame), pc); + pc += gdb_insn_length (get_frame_arch (this_frame), pc); } DEBUG ("[frame] sniffed frame for %s on level %d", diff --git a/gdb/testsuite/gdb.btrace/rn-dl-bind.c b/gdb/testsuite/gdb.btrace/rn-dl-bind.c new file mode 100644 index 0000000..4930297 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/rn-dl-bind.c @@ -0,0 +1,37 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2013 Free Software Foundation, Inc. + + Contributed by Intel Corp. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +int test (void) +{ + int ret; + + ret = strtoul ("42", NULL, 10); /* test.1 */ + return ret; /* test.2 */ +} /* test.3 */ + +int +main (void) +{ + int ret; + + ret = test (); /* main.1 */ + return ret; /* main.2 */ +} /* main.3 */ diff --git a/gdb/testsuite/gdb.btrace/rn-dl-bind.exp b/gdb/testsuite/gdb.btrace/rn-dl-bind.exp new file mode 100644 index 0000000..4d803f9 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/rn-dl-bind.exp @@ -0,0 +1,48 @@ +# This testcase is part of GDB, the GNU debugger. +# +# Copyright 2013 Free Software Foundation, Inc. +# +# Contributed by Intel Corp. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# check for btrace support +if { [skip_btrace_tests] } { return -1 } + +# start inferior +standard_testfile +if [prepare_for_testing $testfile.exp $testfile $srcfile {c++ debug}] { + return -1 +} +if ![runto_main] { + return -1 +} + +# trace the code for the call to test +gdb_test_no_output "record btrace" "rn-dl-bind, 0.1" +gdb_test "next" ".*main\.2.*" "rn-dl-bind, 0.2" + +# just dump the function-call-history to help debugging +gdb_test_no_output "set record function-call-history-size 0" "rn-dl-bind, 0.3" +gdb_test "record function-call-history /cli 1" ".*" "rn-dl-bind, 0.4" + +# check that we can reverse-next and next +gdb_test "reverse-next" ".*main\.1.*" "rn-dl-bind, 1.1" +gdb_test "next" ".*main\.2.*" "rn-dl-bind, 1.2" + +# now go into test and try to reverse-next and next over the library call +gdb_test "reverse-step" ".*test\.3.*" "rn-dl-bind, 2.1" +gdb_test "reverse-step" ".*test\.2.*" "rn-dl-bind, 2.2" +gdb_test "reverse-next" ".*test\.1.*" "rn-dl-bind, 2.3" +gdb_test "next" ".*test\.2.*" "rn-dl-bind, 2.4" diff --git a/gdb/testsuite/gdb.btrace/tailcall.exp b/gdb/testsuite/gdb.btrace/tailcall.exp index 5cadee0..df8d66a 100644 --- a/gdb/testsuite/gdb.btrace/tailcall.exp +++ b/gdb/testsuite/gdb.btrace/tailcall.exp @@ -57,12 +57,29 @@ gdb_test "record goto 4" " # check the backtrace gdb_test "backtrace" " #0.*bar.*at .*x86-tailcall.c:24.*\r -#1.*foo.*at .*x86-tailcall.c:29.*\r -#2.*main.*at .*x86-tailcall.c:37.*\r +#1.*main.*at .*x86-tailcall.c:37.*\r Backtrace stopped: not enough registers or memory available to unwind further" "backtrace in bar" # walk the backtrace gdb_test "up" " -.*foo \\(\\) at .*x86-tailcall.c:29.*" "up to foo" -gdb_test "up" " .*main \\(\\) at .*x86-tailcall.c:37.*" "up to main" +gdb_test "down" " +#0.*bar.*at .*x86-tailcall.c:24.*" "down to bar" + +# test stepping into and out of tailcalls. +gdb_test "finish" " +.*main.*at .*x86-tailcall.c:37.*" "step, 1.1" +gdb_test "reverse-step" " +.*bar.*at .*x86-tailcall.c:24.*" "step, 1.2" +gdb_test "reverse-finish" " +.*foo \\(\\) at .*x86-tailcall.c:29.*" "step, 1.3" +gdb_test "reverse-step" " +.*main.*at .*x86-tailcall.c:37.*" "step, 1.4" +gdb_test "next" " +.*main.*at .*x86-tailcall.c:39.*" "step, 1.5" +gdb_test "reverse-next" " +.*main.*at .*x86-tailcall.c:37.*" "step, 1.6" +gdb_test "step" " +.*foo \\(\\) at .*x86-tailcall.c:29.*" "step, 1.7" +gdb_test "finish" " +.*main.*at .*x86-tailcall.c:37.*" "step, 1.8" -- 1.7.1