From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by sourceware.org (Postfix) with ESMTPS id B91DE3858C74 for ; Mon, 25 Apr 2022 14:48:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org B91DE3858C74 X-IronPort-AV: E=McAfee;i="6400,9594,10328"; a="328205353" X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="328205353" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:48:23 -0700 X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="532144792" Received: from sugan-001.iul.intel.com (HELO localhost) ([172.28.49.38]) by orsmga006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:48:22 -0700 From: Ari Hannula To: gdb-patches@sourceware.org Cc: Tim Wiederhake , Ari Hannula Subject: [PATCH v2 1/2] [func_call] Add function-call-history-length command to MI. Date: Mon, 25 Apr 2022 16:48:03 +0200 Message-Id: <20220425144804.142691-2-ari.hannula@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220425144804.142691-1-ari.hannula@intel.com> References: <20220425144804.142691-1-ari.hannula@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-11.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 25 Apr 2022 14:48:27 -0000 From: Tim Wiederhake This allows MI clients like Eclipse to retrieve the length of the function call history. gdb/ChangeLog: 2018-12-21 Tim Wiederhake 2022-04-25 Ari Hannula * mi/mi-cmds.c (mi_cmds): Add mi_cmd_record_function_call_history_length. * mi/mi-cmds.h (mi_cmd_record_function_call_history_length): New declaration. * record-btrace.c (record_btrace_target) : New declaration. (record_btrace_target::call_history_length): New function. * mi/mi-cmd-record.c: New file. * mi/mi-cmd-record.h: New file. * Makefile.in (mi/mi-cmd-record.c): New definition. * target-delegates.c: Regenerated. * target.c (target_call_history_length): New function. * target.h (target_ops) : New declaration. (target_call_history_length): New declaration. gdb/testsuite/ChangeLog: 2018-12-21 Tim Wiederhake 2022-04-25 Ari Hannula * gdb.mi/mi-function_call_history.c: New file. * gdb.mi/mi-function_call_history.exp: New file. Signed-off-by: Tim Wiederhake Signed-off-by: Ari Hannula --- gdb/Makefile.in | 1 + gdb/mi/mi-cmd-record.c | 32 +++++++ gdb/mi/mi-cmd-record.h | 27 ++++++ gdb/mi/mi-cmds.c | 2 + gdb/mi/mi-cmds.h | 1 + gdb/record-btrace.c | 24 +++++ gdb/target-delegates.c | 23 +++++ gdb/target.c | 8 ++ gdb/target.h | 7 ++ .../gdb.mi/mi-function_call_history.c | 43 +++++++++ .../gdb.mi/mi-function_call_history.exp | 89 +++++++++++++++++++ 11 files changed, 257 insertions(+) create mode 100644 gdb/mi/mi-cmd-record.c create mode 100644 gdb/mi/mi-cmd-record.h create mode 100644 gdb/testsuite/gdb.mi/mi-function_call_history.c create mode 100644 gdb/testsuite/gdb.mi/mi-function_call_history.exp diff --git a/gdb/Makefile.in b/gdb/Makefile.in index ec0e55dd80..c1de627fc2 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -283,6 +283,7 @@ SUBDIR_MI_SRCS = \ mi/mi-cmd-env.c \ mi/mi-cmd-file.c \ mi/mi-cmd-info.c \ + mi/mi-cmd-record.c \ mi/mi-cmd-stack.c \ mi/mi-cmd-target.c \ mi/mi-cmd-var.c \ diff --git a/gdb/mi/mi-cmd-record.c b/gdb/mi/mi-cmd-record.c new file mode 100644 index 0000000000..63af64aa03 --- /dev/null +++ b/gdb/mi/mi-cmd-record.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2022 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 "defs.h" +#include "target.h" +#include "mi-cmd-record.h" + +void +mi_cmd_record_function_call_history_length (const char *command, + char **argv, + int argc) +{ + if (argc != 0) + error (_("-function-call-history-length: Invalid number of arguments.")); + + target_call_history_length (); +} diff --git a/gdb/mi/mi-cmd-record.h b/gdb/mi/mi-cmd-record.h new file mode 100644 index 0000000000..fbd5052dba --- /dev/null +++ b/gdb/mi/mi-cmd-record.h @@ -0,0 +1,27 @@ +/* Copyright (C) 2022 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#ifndef MI_MI_CMD_RECORD_H +#define MI_MI_CMD_RECORD_H + +/* The MI version of the command to get the length of the function call + history for record targets. */ +extern void mi_cmd_record_function_call_history_length (const char *, + char **, + int); + +#endif /* MI_MI_CMD_RECORD_H */ diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index 0571469302..45a5692ff5 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -284,6 +284,8 @@ add_builtin_mi_commands () add_mi_cmd_cli ("file-symbol-file", "symbol-file", 1); add_mi_cmd_mi ("fix-multi-location-breakpoint-output", mi_cmd_fix_multi_location_breakpoint_output), + add_mi_cmd_mi ("function-call-history-length", + mi_cmd_record_function_call_history_length); add_mi_cmd_mi ("gdb-exit", mi_cmd_gdb_exit); add_mi_cmd_cli ("gdb-set", "set", 1, &mi_suppress_notification.cmd_param_changed); diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index 9ffb11bf99..ba990cf871 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -90,6 +90,7 @@ extern mi_cmd_argv_ftype mi_cmd_interpreter_exec; extern mi_cmd_argv_ftype mi_cmd_list_features; extern mi_cmd_argv_ftype mi_cmd_list_target_features; extern mi_cmd_argv_ftype mi_cmd_list_thread_groups; +extern mi_cmd_argv_ftype mi_cmd_record_function_call_history_length; extern mi_cmd_argv_ftype mi_cmd_remove_inferior; extern mi_cmd_argv_ftype mi_cmd_stack_info_depth; extern mi_cmd_argv_ftype mi_cmd_stack_info_frame; diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index 373d82b8b9..778a4ade0f 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -85,6 +85,7 @@ class record_btrace_target final : public target_ops gdb_disassembly_flags flags) override; void insn_history_range (ULONGEST begin, ULONGEST end, gdb_disassembly_flags flags) override; + void call_history_length () override; void call_history (int size, record_print_flags flags) override; void call_history_from (ULONGEST begin, int size, record_print_flags flags) override; @@ -1217,6 +1218,29 @@ btrace_call_history (struct ui_out *uiout, } } +/* The call_history_length method of target record-btrace. */ + +void +record_btrace_target::call_history_length () +{ + struct btrace_call_iterator end; + btrace_call_end (&end, require_btrace ()); + btrace_call_prev (&end, 1); + const int length = btrace_call_number (&end); + + if (current_uiout->is_mi_like_p ()) + { + ui_out_emit_list list_emitter (current_uiout, "func history length"); + ui_out_emit_tuple tuple_emitter (current_uiout, nullptr); + current_uiout->field_unsigned ("end", length); + } + else + { + ui_out_emit_tuple tuple_emitter (current_uiout, "func history length"); + current_uiout->field_unsigned ("end", length); + } +} + /* The call_history method of target record-btrace. */ void diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c index 4e653e8f42..189036f264 100644 --- a/gdb/target-delegates.c +++ b/gdb/target-delegates.c @@ -185,6 +185,7 @@ struct dummy_target : public target_ops void insn_history (int arg0, gdb_disassembly_flags arg1) override; void insn_history_from (ULONGEST arg0, int arg1, gdb_disassembly_flags arg2) override; void insn_history_range (ULONGEST arg0, ULONGEST arg1, gdb_disassembly_flags arg2) override; + void call_history_length () override; void call_history (int arg0, record_print_flags arg1) override; void call_history_from (ULONGEST arg0, int arg1, record_print_flags arg2) override; void call_history_range (ULONGEST arg0, ULONGEST arg1, record_print_flags arg2) override; @@ -359,6 +360,7 @@ struct debug_target : public target_ops void insn_history (int arg0, gdb_disassembly_flags arg1) override; void insn_history_from (ULONGEST arg0, int arg1, gdb_disassembly_flags arg2) override; void insn_history_range (ULONGEST arg0, ULONGEST arg1, gdb_disassembly_flags arg2) override; + void call_history_length () override; void call_history (int arg0, record_print_flags arg1) override; void call_history_from (ULONGEST arg0, int arg1, record_print_flags arg2) override; void call_history_range (ULONGEST arg0, ULONGEST arg1, record_print_flags arg2) override; @@ -4256,6 +4258,27 @@ debug_target::insn_history_range (ULONGEST arg0, ULONGEST arg1, gdb_disassembly_ gdb_puts (")\n", gdb_stdlog); } +void +target_ops::call_history_length () +{ + this->beneath ()->call_history_length (); +} + +void +dummy_target::call_history_length () +{ + tcomplain (); +} + +void +debug_target::call_history_length () +{ + gdb_printf (gdb_stdlog, "-> %s->call_history_length (...)\n", this->beneath ()->shortname ()); + this->beneath ()->call_history_length (); + gdb_printf (gdb_stdlog, "<- %s->call_history_length (", this->beneath ()->shortname ()); + gdb_puts (")\n", gdb_stdlog); +} + void target_ops::call_history (int arg0, record_print_flags arg1) { diff --git a/gdb/target.c b/gdb/target.c index 7d291fd4d0..3cd1691e30 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -4217,6 +4217,14 @@ target_insn_history_range (ULONGEST begin, ULONGEST end, /* See target.h. */ +void +target_call_history_length () +{ + current_inferior ()->top_target ()->call_history_length (); +} + +/* See target.h. */ + void target_call_history (int size, record_print_flags flags) { diff --git a/gdb/target.h b/gdb/target.h index 093178af0b..6cd7c465cc 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -1249,6 +1249,10 @@ struct target_ops gdb_disassembly_flags flags) TARGET_DEFAULT_NORETURN (tcomplain ()); + /* Print the number of functions in the recorded execution trace. */ + virtual void call_history_length () + TARGET_DEFAULT_NORETURN (tcomplain ()); + /* Print a function trace of the recorded execution trace. If SIZE < 0, print abs (SIZE) preceding functions; otherwise, print SIZE succeeding functions. */ @@ -2555,6 +2559,9 @@ extern void target_insn_history_from (ULONGEST from, int size, extern void target_insn_history_range (ULONGEST begin, ULONGEST end, gdb_disassembly_flags flags); +/* See to_call_history_length. */ +extern void target_call_history_length (); + /* See to_call_history. */ extern void target_call_history (int size, record_print_flags flags); diff --git a/gdb/testsuite/gdb.mi/mi-function_call_history.c b/gdb/testsuite/gdb.mi/mi-function_call_history.c new file mode 100644 index 0000000000..3f82e21f8d --- /dev/null +++ b/gdb/testsuite/gdb.mi/mi-function_call_history.c @@ -0,0 +1,43 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2013-2022 Free Software Foundation, Inc. + + 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 . */ + +int +inc (int i) +{ + return i + 1; +} + +int +fib (int n) +{ + if (n <= 1) + return n; + + return fib (n - 2) + fib (n - 1); +} + +int +main () +{ + int i, j; + + for (i = 0; i < 10; i++) + j += inc (i); + + j += fib (10); /* bp.1 */ + return j; /* bp.2 */ +} diff --git a/gdb/testsuite/gdb.mi/mi-function_call_history.exp b/gdb/testsuite/gdb.mi/mi-function_call_history.exp new file mode 100644 index 0000000000..fcf5afeb35 --- /dev/null +++ b/gdb/testsuite/gdb.mi/mi-function_call_history.exp @@ -0,0 +1,89 @@ +# This testcase is part of GDB, the GNU debugger. +# +# Copyright 2013-2022 Free Software Foundation, Inc. +# +# 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 . + +# Test MI command function-call-history-length. + +load_lib mi-support.exp +set MIFLAGS "-i=mi" + +if { [skip_btrace_tests] } { + untested mi-function_call_history.exp + return 0 +} + +gdb_exit +if [mi_gdb_start separate-inferior-tty] { + continue +} + +standard_testfile mi-function_call_history.c + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested "failed to compile" + return -1 +} + +mi_delete_breakpoints +mi_gdb_reinitialize_dir $srcdir/$subdir +mi_gdb_load ${binfile} + +if {[mi_runto_main] < 0} { + return -1 +} + +# start btrace +send_gdb "record btrace\n" + +gdb_expect { + -re "=record-started,thread-group=\".*\"\r\n\\^done\r\n$mi_gdb_prompt$" { + # Done + } + -re "\\^error,msg=\"Target does not support branch tracing.\"" { + perror "Branch tracing not supported" + return -1 + } + timeout { + perror "Unable to start branch tracing" + return -1 + } +} + +mi_create_breakpoint "-t $testfile.c:41" "insert temp breakpoint at $testfile.c:41" \ + -number 2 -disp del -func main -file "$srcdir/$subdir/$testfile.c" -line 41 + +mi_send_resuming_command "exec-continue" "continue to bp.1" + +mi_expect_stop "breakpoint-hit" "main" ".*" "$testfile.c" 41 \ + {"" "disp=\".*\"" } "run to breakpoint bp.1" + +mi_gdb_test "125-function-call-history-length" \ + "125\\^done,func history length=\\\[\{end=\"21\"\}\\\]" \ + "125 function call history length" + +mi_create_breakpoint "-t $testfile.c:42" "insert temp breakpoint at $testfile.c:42" \ + -number 3 -disp del -func main -file "$srcdir/$subdir/$testfile.c" -line 42 + +mi_send_resuming_command "exec-continue" "continue to bp.2" + +mi_expect_stop "breakpoint-hit" "main" ".*" "$testfile.c" 42 \ + {"" "disp=\".*\"" } "run to breakpoint bp.2" + +mi_gdb_test "225-function-call-history-length" \ + "225\\^done,func history length=\\\[\{end=\"375\"\}\\\]" \ + "225 function call history length" + +mi_gdb_exit -- 2.25.1 Intel Deutschland GmbH Registered Address: Am Campeon 10, 85579 Neubiberg, Germany Tel: +49 89 99 8853-0, www.intel.de Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva Chairperson of the Supervisory Board: Nicole Lau Registered Office: Munich Commercial Register: Amtsgericht Muenchen HRB 186928