From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26898 invoked by alias); 20 Jul 2012 13:33:08 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 26869 invoked by uid 9514); 20 Jul 2012 13:33:07 -0000 Date: Fri, 20 Jul 2012 13:33:00 -0000 Message-ID: <20120720133307.26854.qmail@sourceware.org> From: pmuldoon@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] archer-pmuldoon-python-backtrace: Add MI support X-Git-Refname: refs/heads/archer-pmuldoon-python-backtrace X-Git-Reftype: branch X-Git-Oldrev: 69d2d6b96038fb7177007f1999f6a7e8905bd6e1 X-Git-Newrev: 33561fe62ab2936dceda596fd2115807a8b16f15 X-SW-Source: 2012-q3/txt/msg00013.txt.bz2 List-Id: The branch, archer-pmuldoon-python-backtrace has been updated via 33561fe62ab2936dceda596fd2115807a8b16f15 (commit) from 69d2d6b96038fb7177007f1999f6a7e8905bd6e1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 33561fe62ab2936dceda596fd2115807a8b16f15 Author: Phil Muldoon Date: Fri Jul 20 14:32:46 2012 +0100 Add MI support ----------------------------------------------------------------------- Summary of changes: gdb/mi/mi-cmd-stack.c | 74 ++++++++++++++---- gdb/mi/mi-cmd-var.c | 9 ++ gdb/mi/mi-cmds.c | 1 + gdb/mi/mi-cmds.h | 4 + gdb/python/py-framefilter.c | 41 +++++++--- gdb/testsuite/gdb.python/py-framefilter-mi.c | 102 ++++++++++++++++++++++++ gdb/testsuite/gdb.python/py-framefilter-mi.exp | 68 ++++++++++++++++ gdb/testsuite/gdb.python/py-framefilter.exp | 6 ++ 8 files changed, 278 insertions(+), 27 deletions(-) create mode 100644 gdb/testsuite/gdb.python/py-framefilter-mi.c create mode 100644 gdb/testsuite/gdb.python/py-framefilter-mi.exp First 500 lines of diff: diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index fe3e0bf..82451bc 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -32,13 +32,24 @@ #include "language.h" #include "valprint.h" #include "exceptions.h" - +#include "utils.h" +#include "python/python.h" +#include enum what_to_list { locals, arguments, all }; static void list_args_or_locals (enum what_to_list what, enum print_values values, struct frame_info *fi); +/* True if we want to allow Python-based frame filters. */ +static int frame_filters = 0; + +void +stack_enable_frame_filters (void) +{ + frame_filters = 1; +} + /* Print a list of the stack frames. Args can be none, in which case we want to print the whole backtrace, or a pair of numbers specifying the frame numbers at which to start and stop the @@ -53,14 +64,28 @@ mi_cmd_stack_list_frames (char *command, char **argv, int argc) int i; struct cleanup *cleanup_stack; struct frame_info *fi; + int result = 0; + int raw_arg = 0; + int j; - if (argc > 2 || argc == 1) - error (_("-stack-list-frames: Usage: [FRAME_LOW FRAME_HIGH]")); + if (argc) + { + /* Find 'raw-frames' at argv[0] if passed as an argument */ + for (j = 0; j < strlen (argv[0]); j++) + argv[0][j] = tolower (argv[0][j]); + + if (subset_compare (argv[0], "raw-frames")) + raw_arg = 1; + } - if (argc == 2) + if ((argc > 3 && ! raw_arg) || (argc == 1 && ! raw_arg) + || (argc == 2 && raw_arg)) + error (_("-stack-list-frames: Usage: [RAW-FRAMES FRAME_LOW FRAME_HIGH]")); + + if (argc == 3 || argc == 2) { - frame_low = atoi (argv[0]); - frame_high = atoi (argv[1]); + frame_low = atoi (argv[0 + raw_arg]); + frame_high = atoi (argv[1 + raw_arg]); } else { @@ -82,16 +107,35 @@ mi_cmd_stack_list_frames (char *command, char **argv, int argc) cleanup_stack = make_cleanup_ui_out_list_begin_end (current_uiout, "stack"); - /* Now let's print the frames up to frame_high, or until there are - frames in the stack. */ - for (; - fi && (i <= frame_high || frame_high == -1); - i++, fi = get_prev_frame (fi)) + if (! raw_arg && frame_filters) { - QUIT; - /* Print the location and the address always, even for level 0. - If args is 0, don't print the arguments. */ - print_frame_info (fi, 1, LOC_AND_ADDRESS, 0 /* args */ ); + int count = frame_high; + + if (frame_high != -1) + count = (frame_high - frame_low) + 1; + result = apply_frame_filter (fi, 1, LOC_AND_ADDRESS, 0, + 0 /* print args */, current_uiout, + 0 /* show locals */, count); + } + + /* Run the inbuilt backtrace if there are no filters registered, or + if there was an error in the Python backtracing output, or if + frame-filters are disabled. */ + if (! frame_filters || raw_arg || result == PY_BT_ERROR + || result == PY_BT_NO_FILTERS) + + { + /* Now let's print the frames up to frame_high, or until there are + frames in the stack. */ + for (; + fi && (i <= frame_high || frame_high == -1); + i++, fi = get_prev_frame (fi)) + { + QUIT; + /* Print the location and the address always, even for level 0. + If args is 0, don't print the arguments. */ + print_frame_info (fi, 1, LOC_AND_ADDRESS, 0 /* args */ ); + } } do_cleanups (cleanup_stack); diff --git a/gdb/mi/mi-cmd-var.c b/gdb/mi/mi-cmd-var.c index 0603679..ce125db 100644 --- a/gdb/mi/mi-cmd-var.c +++ b/gdb/mi/mi-cmd-var.c @@ -835,6 +835,15 @@ mi_cmd_enable_pretty_printing (char *command, char **argv, int argc) } void +mi_cmd_enable_frame_filters (char *command, char **argv, int argc) +{ + if (argc != 0) + error (_("-enable-frame-filters: no arguments allowed")); + + stack_enable_frame_filters (); +} + +void mi_cmd_var_set_update_range (char *command, char **argv, int argc) { struct varobj *var; diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index 79fbba1..ba56994 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -60,6 +60,7 @@ struct mi_cmd mi_cmds[] = mi_cmd_data_write_register_values}, { "enable-timings", { NULL, 0 }, mi_cmd_enable_timings}, { "enable-pretty-printing", { NULL, 0 }, mi_cmd_enable_pretty_printing}, + { "enable-frame-filters", { NULL, 0 }, mi_cmd_enable_frame_filters}, { "environment-cd", { NULL, 0 }, mi_cmd_env_cd}, { "environment-directory", { NULL, 0 }, mi_cmd_env_dir}, { "environment-path", { NULL, 0 }, mi_cmd_env_path}, diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index 4d0fc9d..ed2959b 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -117,6 +117,7 @@ extern mi_cmd_argv_ftype mi_cmd_var_show_attributes; extern mi_cmd_argv_ftype mi_cmd_var_show_format; extern mi_cmd_argv_ftype mi_cmd_var_update; extern mi_cmd_argv_ftype mi_cmd_enable_pretty_printing; +extern mi_cmd_argv_ftype mi_cmd_enable_frame_filters; extern mi_cmd_argv_ftype mi_cmd_var_set_update_range; /* Description of a single command. */ @@ -140,6 +141,9 @@ struct mi_cmd mi_cmd_argv_ftype *argv_func; }; +extern void +stack_enable_frame_filters (void); + /* Lookup a command in the MI command table. */ extern struct mi_cmd *mi_lookup (const char *command); diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c index d10fb63..bb4d4a0 100644 --- a/gdb/python/py-framefilter.c +++ b/gdb/python/py-framefilter.c @@ -548,13 +548,15 @@ py_print_frame (PyObject *filter, else goto error; } - - annotate_frame_source_end (); - - ui_out_text (out, "\n"); - - if (has_addr) - annotate_frame_end (); + + /* For MI we need to deal with the children population of elided + frames, so if MI output detected do not send newline. */ + if (! ui_out_is_mi_like_p (out)) + { + if (has_addr) + annotate_frame_end (); + ui_out_text (out, "\n"); + } if (print_locals) { @@ -583,11 +585,21 @@ py_print_frame (PyObject *filter, { PyObject *iterator = PyObject_GetIter (result); PyObject *item; - + struct cleanup *cleanup_stack; + if (iterator == NULL) goto error; - - indent = indent + 4; + + if (ui_out_is_mi_like_p (out)) + { + cleanup_stack = make_cleanup_ui_out_list_begin_end (out, "children"); + } + else + { + cleanup_stack = make_cleanup (null_cleanup, NULL); + indent = indent + 4; + } + while ((item = PyIter_Next (iterator))) { int success = py_print_frame (item, print_level, print_what, @@ -595,8 +607,13 @@ py_print_frame (PyObject *filter, print_locals, out, opts, indent, levels_printed); if (success == 0 && PyErr_Occurred ()) - goto error; + { + do_cleanups (cleanup_stack); + goto error; + } } + + do_cleanups (cleanup_stack); } } } @@ -676,7 +693,7 @@ apply_frame_filter (struct frame_info *frame, int print_level, eq_printed_frame_entry, NULL); - while ((item = PyIter_Next (iterator))) + while ((item = PyIter_Next (iterator)) && count--) { success = py_print_frame (item, print_level, print_what, print_args, print_args_type, diff --git a/gdb/testsuite/gdb.python/py-framefilter-mi.c b/gdb/testsuite/gdb.python/py-framefilter-mi.c new file mode 100644 index 0000000..25a8a6e --- /dev/null +++ b/gdb/testsuite/gdb.python/py-framefilter-mi.c @@ -0,0 +1,102 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008-2012 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 . */ + + +void funca(void); +int count = 0; + +void end_func (void) +{ + const char *str = "The End"; + const char *st2 = "Is Near"; + int b = 12; + short c = 5; + + return; /* Backtrace end breakpoint */ +} + +void funcb(int j) +{ + struct foo + { + int a; + int b; + }; + + struct foo bar; + + bar.a = 42; + bar.b = 84; + + funca(); + return; +} + +void funca(void) +{ + if (count < 10) + { + count++; + funcb(count); + } + + end_func(); + return; +} + + +void func1(void) +{ + funca(); + return; +} + +int func2(void) +{ + + func1(); + return 1; +} + +void func3(int i) +{ + func2(); + + return; +} + +int func4(int j) +{ + func3(j); + + return 2; +} + +int func5(int f, int d) +{ + int i = 0; + char *random = "random"; + i=i+f; + + func4(i); + return i; +} + +main() +{ + func5(3,5); +} diff --git a/gdb/testsuite/gdb.python/py-framefilter-mi.exp b/gdb/testsuite/gdb.python/py-framefilter-mi.exp new file mode 100644 index 0000000..f6e3444 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-framefilter-mi.exp @@ -0,0 +1,68 @@ +# Copyright (C) 2012 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 . + +# This file is part of the GDB testsuite. It tests Python-based +# frame-filters. +load_lib mi-support.exp +load_lib gdb-python.exp + +set MIFLAGS "-i=mi2" +global hex + +gdb_exit +if [mi_gdb_start] { + continue +} + +standard_testfile py-framefilter-mi.c +set pyfile py-framefilter.py + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DMI}] != "" } { + untested ${testfile}.exp + return -1 +} + +mi_delete_breakpoints +mi_gdb_reinitialize_dir $srcdir/$subdir +mi_gdb_load ${binfile} + +if {[lsearch -exact [mi_get_features] python] < 0} { + unsupported "python support is disabled" + return -1 +} + +mi_runto main + +set remote_python_file [remote_download host ${srcdir}/${subdir}/${pyfile}] + +mi_gdb_test "python execfile ('${remote_python_file}')" "" + +mi_continue_to_line [gdb_get_line_number {Backtrace end breakpoint} ${srcfile}] \ + "step to breakpoint" + +mi_gdb_test "-enable-frame-filters" "" +mi_gdb_test "-stack-list-frames" \ + "\\^done,stack=\\\[level=\"0\",addr=\"$hex\",func=\"cnuf_dne\".*,level=\"1\",addr=\"$hex\",func=\"acnuf\".*,level=\"2\",addr=\"$hex\",func=\"bcnuf\".*,level=\"3\",addr=\"$hex\",func=\"acnuf\".*,level=\"22\",addr=\"$hex\",func=\"1cnuf\".*,children=\\\[level=\"23\",addr=\"$hex\",func=\"func2\".*\\\],level=\"24\",addr=\"$hex\",func=\"3cnuf\".*,level=\"27\",addr=\"$hex\",func=\"niam\".*\\\]" \ + "filtered stack listing" +mi_gdb_test "-stack-list-frames 0 3" \ + "\\^done,stack=\\\[level=\"0\",addr=\"$hex\",func=\"cnuf_dne\".*,level=\"1\",addr=\"$hex\",func=\"acnuf\".*,level=\"2\",addr=\"$hex\",func=\"bcnuf\".*,level=\"3\",addr=\"$hex\",func=\"acnuf\".*\\\]" \ + "filtered stack list 0 3" +mi_gdb_test "-stack-list-frames 22 24" \ + "\\^done,stack=\\\[level=\"22\",addr=\"$hex\",func=\"1cnuf\".*,children=\\\[level=\"23\",addr=\"$hex\",func=\"func2\".*\\\],level=\"24\",addr=\"$hex\",func=\"3cnuf\".*\\\]" \ + "filtered stack list 0 3" + + +remote_file host delete ${remote_python_file} + diff --git a/gdb/testsuite/gdb.python/py-framefilter.exp b/gdb/testsuite/gdb.python/py-framefilter.exp index 0b998a1..c845ebe 100644 --- a/gdb/testsuite/gdb.python/py-framefilter.exp +++ b/gdb/testsuite/gdb.python/py-framefilter.exp @@ -75,5 +75,11 @@ gdb_test_no_output "set python frame-filter disable global Reverse" gdb_test "bt" \ {.*#0.*end_func.*#22.*in func1.*#27.*in main ().*} +gdb_test "bt -2" \ + {.*#26.*func5.*#27.*in main ().*} + +gdb_test "bt 3" \ + {.*#0.*end_func.*#1.*in funca ().*#2.*in funcb ().*} + remote_file host delete ${remote_python_file} hooks/post-receive -- Repository for Project Archer.