[PATCH v3 1/2] [func_call] Add function-call-history-length command to MI.
Ari Hannula
ari.hannula@intel.com
Wed Jul 6 13:36:38 GMT 2022
From: Tim Wiederhake <tim.wiederhake@intel.com>
This allows MI clients like Eclipse to retrieve the length of the function
call history.
Adds documentation for the command.
Adds tests for the command.
Signed-off-by: Tim Wiederhake <tim.wiederhake@intel.com>
Signed-off-by: Ari Hannula <ari.hannula@intel.com>
---
gdb/Makefile.in | 1 +
gdb/doc/gdb.texinfo | 28 ++++++
gdb/mi/mi-cmd-record.c | 34 +++++++
gdb/mi/mi-cmd-record.h | 27 ++++++
gdb/mi/mi-cmds.c | 2 +
gdb/mi/mi-cmds.h | 1 +
gdb/record-btrace.c | 12 +++
gdb/target-delegates.c | 27 ++++++
gdb/target.c | 8 ++
gdb/target.h | 7 ++
.../gdb.mi/mi-function_call_history.c | 43 +++++++++
.../gdb.mi/mi-function_call_history.exp | 89 +++++++++++++++++++
12 files changed, 279 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 911daa2607b..387a70a75ab 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/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 7a4e337d15b..5e7e0138a27 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -37760,6 +37760,34 @@ The corresponding @value{GDBN} command is @samp{complete}.
@end smallexample
+@subheading The @code{-function-call-history-length} Command
+@findex -function-call-history-length
+
+@subheading Synopsis
+
+@smallexample
+-function-call-history-length
+@end smallexample
+
+Return the number of functions in the recorded execution trace.
+
+@subheading Result
+
+The result contains length field with the value.
+
+@subheading @value{GDBN} Command
+
+No equivalent.
+
+@subheading Example
+
+@smallexample
+(gdb)
+-function-call-history-length
+^done,length="18"
+(gdb)
+@end smallexample
+
@node Annotations
@chapter @value{GDBN} Annotations
diff --git a/gdb/mi/mi-cmd-record.c b/gdb/mi/mi-cmd-record.c
new file mode 100644
index 00000000000..7c5019e2616
--- /dev/null
+++ b/gdb/mi/mi-cmd-record.c
@@ -0,0 +1,34 @@
+/* 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 <http://www.gnu.org/licenses/>. */
+
+
+#include "defs.h"
+#include "target.h"
+#include "mi-cmd-record.h"
+#include "mi-out.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."));
+
+ ui_out *uiout = current_uiout;
+ uiout->field_unsigned ("length", 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 00000000000..fbd5052dba6
--- /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 <http://www.gnu.org/licenses/>. */
+
+#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 05714693023..45a5692ff52 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 9ffb11bf997..ba990cf871b 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 3f8a69dd04f..f2f70fad9c5 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;
+ int 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,17 @@ btrace_call_history (struct ui_out *uiout,
}
}
+/* The call_history_length method of target record-btrace. */
+
+int
+record_btrace_target::call_history_length ()
+{
+ struct btrace_call_iterator end;
+ btrace_call_end (&end, require_btrace ());
+ btrace_call_prev (&end, 1);
+ return (int)btrace_call_number (&end);
+}
+
/* The call_history method of target record-btrace. */
void
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index 8a9986454dd..32ae1e6d803 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;
+ int 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;
+ int 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,31 @@ debug_target::insn_history_range (ULONGEST arg0, ULONGEST arg1, gdb_disassembly_
gdb_puts (")\n", gdb_stdlog);
}
+int
+target_ops::call_history_length ()
+{
+ return this->beneath ()->call_history_length ();
+}
+
+int
+dummy_target::call_history_length ()
+{
+ return -1;
+}
+
+int
+debug_target::call_history_length ()
+{
+ int result;
+ gdb_printf (gdb_stdlog, "-> %s->call_history_length (...)\n", this->beneath ()->shortname ());
+ result = this->beneath ()->call_history_length ();
+ gdb_printf (gdb_stdlog, "<- %s->call_history_length (", this->beneath ()->shortname ());
+ gdb_puts (") = ", gdb_stdlog);
+ target_debug_print_int (result);
+ gdb_puts ("\n", gdb_stdlog);
+ return result;
+}
+
void
target_ops::call_history (int arg0, record_print_flags arg1)
{
diff --git a/gdb/target.c b/gdb/target.c
index 18e53aa5d27..c9c27c67e9a 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -4220,6 +4220,14 @@ target_insn_history_range (ULONGEST begin, ULONGEST end,
/* See target.h. */
+int
+target_call_history_length ()
+{
+ return 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 18559feef89..39b08af9da9 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1249,6 +1249,10 @@ struct target_ops
gdb_disassembly_flags flags)
TARGET_DEFAULT_NORETURN (tcomplain ());
+ /* Return the number of functions in the recorded execution trace. */
+ virtual int call_history_length ()
+ TARGET_DEFAULT_RETURN (-1);
+
/* Print a function trace of the recorded execution trace.
If SIZE < 0, print abs (SIZE) preceding functions; otherwise, print SIZE
succeeding functions. */
@@ -2564,6 +2568,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 int 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 00000000000..3f82e21f8d3
--- /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 <http://www.gnu.org/licenses/>. */
+
+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 00000000000..c839f4d35d1
--- /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 <http://www.gnu.org/licenses/>.
+
+# 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,length=\"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,length=\"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 <http://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
More information about the Gdb-patches
mailing list