From: Jan Kratochvil <jan.kratochvil@redhat.com>
To: Markus Metzger <markus.t.metzger@intel.com>
Cc: gdb-patches@sourceware.org
Subject: Re: [patch v4 24/24] record-btrace: skip tail calls in back trace
Date: Sun, 18 Aug 2013 19:10:00 -0000 [thread overview]
Message-ID: <20130818190949.GS24153@host2.jankratochvil.net> (raw)
In-Reply-To: <1372842874-28951-25-git-send-email-markus.t.metzger@intel.com>
On Wed, 03 Jul 2013 11:14:34 +0200, Markus Metzger wrote:
> 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.
This depends on the compiler and its options. With recent GCCs and -O2 -g
compilation tail calls are shown. They are even tested for (full) reverse
execution:
Running ./gdb.reverse/amd64-tailcall-reverse.exp ...
Running ./gdb.arch/amd64-tailcall-ret.exp ...
Running ./gdb.arch/amd64-tailcall-cxx.exp ...
Running ./gdb.arch/amd64-tailcall-noret.exp ...
In the -O0 -g mode they are not shown just because of the lack of debug info.
AFAIK it is too expensive for GCC to produce it while -O0 -g compilation
should be fast.
Surprisingly this gives in some cases -O2 -g compilation better debugging
experience than -O0 -g compilation.
Still the missing tailcalls in -O0 -g mode is a defect of the compiler and GDB
should not try to mimick it when it can provide better debugging output.
If you find the reverse execution should be really equal to the forward
execution you could suppress the tail calls only if symtab->call_site_htab is
NULL (and therefore the compiler did not provide tail calls info).
Still when I revert this GDB code patch then gdb.btrace/rn-dl-bind.exp does not
reverse-next properly - what is the reason?
reverse-next^M
__GI_____strtoul_l_internal (nptr=<unavailable>, endptr=<unavailable>, base=<optimized out>, group=<optimized out>, loc=<optimized out>) at ../stdlib/strtol_l.c:531^M
531 }^M
(gdb) FAIL: gdb.btrace/rn-dl-bind.exp: rn-dl-bind, 2.3
bt^M
#0 __GI_____strtoul_l_internal (nptr=<unavailable>, endptr=<unavailable>, base=<optimized out>, group=<optimized out>, loc=<optimized out>) at ../stdlib/strtol_l.c:531^M
#1 0x00007ffff7228f8d in __GI_strtoul (nptr=<error reading variable: Registers are not available in btrace record history>, endptr=<error reading variable: Registers are not available in btrace record history>, base=<error reading variable: Registers are not available in btrace record history>) at ../stdlib/strtol.c:108^M
#2 _dl_runtime_resolve () at ../sysdeps/x86_64/dl-trampoline.S:56^M
#3 0x00000000004004c6 in ?? ()^M
#4 0x00000000004004fb in strtoul@plt ()^M
#5 0x000000000040060c in test () at ./gdb.btrace/rn-dl-bind.c:26^M
#6 0x0000000000400621 in main () at ./gdb.btrace/rn-dl-bind.c:35^M
Backtrace stopped: not enough registers or memory available to unwind further^M
> 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 <markus.t.metzger@intel.com>
>
> * 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. <markus.t.metzger@intel.com>
> +
> + 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 <http://www.gnu.org/licenses/>. */
> +
> +#include <stdlib.h>
> +
> +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. <markus.t.metzger@intel.com>
> +#
> +# 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 <http://www.gnu.org/licenses/>.
> +
> +# 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"
You should use \[^\r\n\]* instead of .* in all your testcases but it is
everywhere. Normally it is not so serious so I did not require a change but
for example here it produces false positive as it will still incorrectly match:
backtrace
#0 0x00000000004005b5 in bar () at gdb/testsuite/gdb.btrace/x86-tailcall.c:24
#1 foo () at gdb/testsuite/gdb.btrace/x86-tailcall.c:29
#2 0x00000000004005d5 in main () at gdb/testsuite/gdb.btrace/x86-tailcall.c:37
Backtrace stopped: not enough registers or memory available to unwind further
(gdb) PASS: gdb.btrace/tailcall.exp: backtrace in bar
In fact it would be better to fix it wherever you can.
>
> # 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
next prev parent reply other threads:[~2013-08-18 19:10 UTC|newest]
Thread overview: 88+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-03 9:15 [patch v4 00/24] record-btrace: reverse Markus Metzger
2013-07-03 9:14 ` [patch v4 09/24] btrace: add replay position to btrace thread info Markus Metzger
2013-08-18 19:07 ` Jan Kratochvil
2013-09-10 13:24 ` Metzger, Markus T
2013-09-12 20:19 ` Jan Kratochvil
2013-07-03 9:14 ` [patch v4 05/24] record-btrace: start counting at one Markus Metzger
2013-08-18 19:11 ` Jan Kratochvil
2013-07-03 9:14 ` [patch v4 02/24] record: upcase record_print_flag enumeration constants Markus Metzger
2013-08-18 19:11 ` Jan Kratochvil
2013-07-03 9:14 ` [patch v4 14/24] record-btrace: provide xfer_partial target method Markus Metzger
2013-08-18 19:08 ` Jan Kratochvil
2013-09-16 9:30 ` Metzger, Markus T
2013-09-22 14:18 ` Jan Kratochvil
2013-07-03 9:14 ` [patch v4 22/24] infrun: reverse stepping from unknown functions Markus Metzger
2013-08-18 19:09 ` Jan Kratochvil
2013-07-03 9:14 ` [patch v4 07/24] record-btrace: optionally indent function call history Markus Metzger
2013-08-18 19:06 ` Jan Kratochvil
2013-09-10 13:06 ` Metzger, Markus T
2013-09-10 13:08 ` Jan Kratochvil
2013-07-03 9:14 ` [patch v4 08/24] record-btrace: make ranges include begin and end Markus Metzger
2013-08-18 19:12 ` Jan Kratochvil
2013-07-03 9:14 ` [patch v4 16/24] record-btrace: provide target_find_new_threads method Markus Metzger
2013-08-18 19:15 ` Jan Kratochvil
2013-07-03 9:14 ` [patch v4 11/24] record-btrace: supply register target methods Markus Metzger
2013-08-18 19:07 ` Jan Kratochvil
2013-09-16 9:19 ` Metzger, Markus T
2013-09-22 13:55 ` Jan Kratochvil
2013-09-23 6:55 ` Metzger, Markus T
2013-07-03 9:14 ` [patch v4 20/24] btrace, gdbserver: read branch trace incrementally Markus Metzger
2013-08-18 19:09 ` Jan Kratochvil
2013-09-16 12:48 ` Metzger, Markus T
2013-09-22 14:42 ` Jan Kratochvil
2013-09-23 7:09 ` Metzger, Markus T
2013-09-25 19:05 ` Jan Kratochvil
2013-09-26 6:27 ` Metzger, Markus T
2013-07-03 9:14 ` [patch v4 24/24] record-btrace: skip tail calls in back trace Markus Metzger
2013-08-18 19:10 ` Jan Kratochvil [this message]
2013-09-17 14:28 ` Metzger, Markus T
2013-09-18 8:28 ` Metzger, Markus T
2013-09-18 9:52 ` Metzger, Markus T
2013-07-03 9:14 ` [patch v4 03/24] btrace: change branch trace data structure Markus Metzger
2013-08-18 19:05 ` Jan Kratochvil
2013-09-10 9:11 ` Metzger, Markus T
2013-09-12 20:09 ` Jan Kratochvil
2013-09-16 9:01 ` Metzger, Markus T
2013-09-21 19:44 ` Jan Kratochvil
2013-09-23 6:54 ` Metzger, Markus T
2013-09-23 7:15 ` Jan Kratochvil
2013-09-23 7:27 ` Metzger, Markus T
2013-09-22 16:57 ` Jan Kratochvil
2013-09-22 17:16 ` Jan Kratochvil
2013-07-03 9:14 ` [patch v4 19/24] btrace, linux: fix memory leak when reading branch trace Markus Metzger
2013-08-18 19:09 ` Jan Kratochvil
2013-07-03 9:14 ` [patch v4 10/24] target: add ops parameter to to_prepare_to_store method Markus Metzger
2013-08-18 19:07 ` Jan Kratochvil
2013-07-03 9:15 ` [patch v4 13/24] record-btrace, frame: supply target-specific unwinder Markus Metzger
2013-08-18 19:07 ` Jan Kratochvil
2013-07-03 9:15 ` [patch v4 17/24] record-btrace: add record goto target methods Markus Metzger
2013-08-18 19:08 ` Jan Kratochvil
2013-07-03 9:15 ` [patch v4 15/24] record-btrace: add to_wait and to_resume " Markus Metzger
2013-08-18 19:08 ` Jan Kratochvil
2013-07-03 9:15 ` [patch v4 23/24] record-btrace: add (reverse-)stepping support Markus Metzger
2013-08-18 19:09 ` Jan Kratochvil
2013-09-17 9:43 ` Metzger, Markus T
2013-09-29 17:24 ` Jan Kratochvil
2013-09-30 9:30 ` Metzger, Markus T
2013-09-30 10:25 ` Jan Kratochvil
2013-07-03 9:15 ` [patch v4 06/24] btrace: increase buffer size Markus Metzger
2013-08-18 19:06 ` Jan Kratochvil
2013-07-03 9:15 ` [patch v4 01/24] gdbarch: add instruction predicate methods Markus Metzger
2013-07-03 9:49 ` Mark Kettenis
2013-07-03 11:10 ` Metzger, Markus T
2013-08-18 19:04 ` Jan Kratochvil
2013-07-03 9:15 ` [patch v4 12/24] frame, backtrace: allow targets to supply a frame unwinder Markus Metzger
2013-08-18 19:14 ` Jan Kratochvil
2013-07-03 9:15 ` [patch v4 18/24] record-btrace: extend unwinder Markus Metzger
2013-08-18 19:08 ` Jan Kratochvil
2013-09-16 11:21 ` Metzger, Markus T
2013-09-27 13:55 ` Jan Kratochvil
2013-09-30 9:45 ` Metzger, Markus T
2013-09-30 10:26 ` Jan Kratochvil
2013-07-03 9:15 ` [patch v4 21/24] record-btrace: show trace from enable location Markus Metzger
2013-08-18 19:10 ` instruction_history.exp unset variable [Re: [patch v4 21/24] record-btrace: show trace from enable location] Jan Kratochvil
2013-09-16 14:11 ` Metzger, Markus T
2013-08-18 19:16 ` [patch v4 21/24] record-btrace: show trace from enable location Jan Kratochvil
2013-07-03 9:15 ` [patch v4 04/24] record-btrace: fix insn range in function call history Markus Metzger
2013-08-18 19:06 ` Jan Kratochvil
2013-08-18 19:04 ` [patch v4 00/24] record-btrace: reverse Jan Kratochvil
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=20130818190949.GS24153@host2.jankratochvil.net \
--to=jan.kratochvil@redhat.com \
--cc=gdb-patches@sourceware.org \
--cc=markus.t.metzger@intel.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