From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30208 invoked by alias); 14 Aug 2012 15:38:37 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 30178 invoked by uid 9514); 14 Aug 2012 15:38:36 -0000 Date: Tue, 14 Aug 2012 15:38:00 -0000 Message-ID: <20120814153836.30163.qmail@sourceware.org> From: pmuldoon@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] archer-pmuldoon-python-backtrace: Add initial support for -stack-list-variables. Rewrite locals and argument aquisition and prining to account for the combined nature of -stack-list-variables X-Git-Refname: refs/heads/archer-pmuldoon-python-backtrace X-Git-Reftype: branch X-Git-Oldrev: ee73819ce0a91fd1e20670770445f5a50d7d7ec6 X-Git-Newrev: 12f3ffcbc3530fb011af47e03f6dabfb96f42147 X-SW-Source: 2012-q3/txt/msg00028.txt.bz2 List-Id: The branch, archer-pmuldoon-python-backtrace has been updated via 12f3ffcbc3530fb011af47e03f6dabfb96f42147 (commit) from ee73819ce0a91fd1e20670770445f5a50d7d7ec6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 12f3ffcbc3530fb011af47e03f6dabfb96f42147 Author: Phil Muldoon Date: Tue Aug 14 16:37:49 2012 +0100 Add initial support for -stack-list-variables. Rewrite locals and argument aquisition and prining to account for the combined nature of -stack-list-variables ----------------------------------------------------------------------- Summary of changes: gdb/mi/mi-cmd-stack.c | 44 +++- gdb/python/py-framefilter.c | 563 ++++++++++++++++++++++++------------------ gdb/python/py-utils.c | 27 ++ gdb/python/python-internal.h | 1 + 4 files changed, 395 insertions(+), 240 deletions(-) First 500 lines of diff: diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index 92ab4c2..f3e1309 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -353,13 +353,49 @@ void mi_cmd_stack_list_variables (char *command, char **argv, int argc) { struct frame_info *frame; + int raw_arg = 0; + int result = 0; - if (argc != 1) - error (_("Usage: PRINT_VALUES")); + if (argc == 2) + { + int j; + /* Find 'raw-frames' at argv[1] if passed as an argument */ + for (j = 0; j < strlen (argv[1]); j++) + argv[1][j] = tolower (argv[1][j]); - frame = get_selected_frame (NULL); + if (subset_compare (argv[1], "raw-frames")) + raw_arg = 1; + } - list_args_or_locals (all, parse_print_values (argv[0]), frame); + if (argc < 1 || argc > 2 || (argc == 2 && ! raw_arg) + || (argc == 1 && raw_arg)) + error (_("-stack-list-arguments: Usage: PRINT_VALUES [RAW-FRAMES]")); + + frame = get_selected_frame (NULL); + + if (! raw_arg && frame_filters) + { + int count = 1; + int arg = atoi (argv[0]); + + result = apply_frame_filter (frame,/* frame */ + 1, /* print_level */ + LOC_AND_ADDRESS, /* print_what */ + 0, /* print_frame_info */ + 1, /* print_args */ + arg, /* mi_print_args_type */ + 0, /* cli_print_args_type */ + current_uiout, /* out */ + 1, /* print_locals */ + count /* count */); + } + + if (! frame_filters || raw_arg || result == PY_BT_ERROR + || result == PY_BT_NO_FILTERS) + { + + list_args_or_locals (all, parse_print_values (argv[0]), frame); + } } /* Print single local or argument. ARG must be already read in. For diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c index 14217f3..fd6e26e 100644 --- a/gdb/python/py-framefilter.c +++ b/gdb/python/py-framefilter.c @@ -34,11 +34,21 @@ #ifdef HAVE_PYTHON #include "python-internal.h" -static int -extract_sym_and_value (PyObject *obj, char **name, - struct value **value, - const struct language_defn **language) +/* Helper function to extract a name, value and language definition + from a Python object that conforms SymbolValue interface. OBJ is + the Python object to extract the values from. **NAME is a + pass-through argument where the name of the symbol will be written. + **VALUE is a pass-through argument where the value corresponding + the to the Symbol will be written, and LANGUAGE is also a + pass-through argument denoting the language attributed to the + Symbol. Returns 0 on error with the appropriate Python exception + set, and 1 on success. */ + +static int extract_sym_and_value (PyObject *obj, + char **name, struct value **value, + const struct language_defn **language) { + if (PyObject_HasAttrString (obj, "symbol")) { PyObject *result = PyObject_CallMethod (obj, "symbol", NULL); @@ -62,6 +72,7 @@ extract_sym_and_value (PyObject *obj, char **name, struct symbol *symbol = symbol_object_to_symbol (result); Py_DECREF (result); + if (! symbol) { PyErr_SetString (PyExc_RuntimeError, @@ -112,12 +123,16 @@ extract_sym_and_value (PyObject *obj, char **name, "implemented.")); return 0; } + return 1; } +/* Helper function which outputs a type name to a stream. OUT is the + ui-out structure the type name will be output too, and VAL is the + value that the type will be extracted from. Returns 0 on error, + with any GDB exceptions converted to a Python exception. */ static int -py_print_type (struct ui_out *out, - struct value *val) +py_print_type (struct ui_out *out, struct value *val) { volatile struct gdb_exception except; @@ -140,132 +155,318 @@ py_print_type (struct ui_out *out, except.message); return 0; } - return 1; } +/* Helper function which outputs a value name to a stream. OUT is the + ui-out structure the value will be output too, and VAL is the value + that will be printed. LANGUAGE is the language_defn that the value + will be printed with. Returns 0 on error, with any GDB exceptions + converted to a Python exception. */ + static int -py_print_locals (PyObject *filter, - struct ui_out *out, - struct value_print_options opts, - int mi_print_type, - int indent) +py_print_value (struct ui_out *out, struct value *val, + const struct language_defn *language) { - /* In traditional bt full backtraces this is num_tabs (4) * 2 = 8. It - never appears to deviate from this. */ - struct cleanup *old_chain = make_cleanup_ui_out_list_begin_end (out, - "locals"); + volatile struct gdb_exception except; + TRY_CATCH (except, RETURN_MASK_ALL) + { + struct ui_file *stb; + struct cleanup *cleanup; + struct value_print_options opts; - if (PyObject_HasAttrString (filter, "frame_locals")) + stb = mem_fileopen (); + cleanup = make_cleanup_ui_file_delete (stb); + get_user_print_options (&opts); + opts.deref_ref = 1; + common_val_print (val, stb, 2, &opts, language); + ui_out_field_stream (out, "value", stb); + do_cleanups (cleanup); + } + if (except.reason > 0) { - PyObject *result = PyObject_CallMethod (filter, "frame_locals", - NULL); + PyErr_SetString (PyExc_RuntimeError, + except.message); + return 0; + } + return 1; +} + +/* Helper function to call a Python method and extract an iterator + from the result, error checking for Python exception and returns + that are not iterators. FILTER is the Python object to call, and + FUNC is the name of the method. Returns a PyObject, or NULL on + error with the appropriate exception set. */ + +static PyObject * +get_py_iter_from_func (PyObject *filter, char *func) +{ + if (PyObject_HasAttrString (filter, func)) + { + PyObject *result = PyObject_CallMethod (filter, func, NULL); if (result) { - make_cleanup_py_decref (result); - if (result != Py_None) { if (! PyIter_Check (result)) { PyErr_SetString (PyExc_RuntimeError, - _("'frame_locals' function must " \ - "return an iterator.")); - goto locals_error; + strcat (func, _(" function must " \ + "return an iterator."))); + Py_DECREF (result); + return NULL; } else { PyObject *iterator = PyObject_GetIter (result); - PyObject *item; + + Py_DECREF (result); if (! iterator) - goto locals_error; + return NULL; + else + return iterator; + } + } + } + else + return NULL; + } - make_cleanup_py_decref (iterator); - while ((item = PyIter_Next (iterator))) - { - const struct language_defn *language; - char *sym_name; - struct value *val; - int value_success = 0; - volatile struct gdb_exception except; - struct cleanup *inner_cleanup = - make_cleanup (null_cleanup, NULL); - - value_success = extract_sym_and_value (item, &sym_name, - &val, - &language); + Py_RETURN_NONE; +} - Py_DECREF (item); +static int +enumerate_args (PyObject *iter, + struct ui_out *out, + struct value_print_options opts, + int mi_print_type, + const char *print_args_type, + int print_mi_args_flag) +{ + PyObject *item; - if (! value_success) - goto locals_error; - - if (ui_out_is_mi_like_p (out)) - { - if (mi_print_type != PRINT_NO_VALUES) - { - inner_cleanup = - make_cleanup_ui_out_tuple_begin_end (out, - NULL); - } - } - else - ui_out_spaces (out, (8 + (indent * 2))); - - ui_out_field_string (out, "name", sym_name); - xfree (sym_name); - - if (! ui_out_is_mi_like_p (out)) - ui_out_text (out, " = "); - - if (ui_out_is_mi_like_p (out) - && mi_print_type == PRINT_SIMPLE_VALUES) - { - if (! py_print_type (out, val)) - goto locals_error; - } - - if (! ui_out_is_mi_like_p (out) - || (ui_out_is_mi_like_p (out) - && mi_print_type != PRINT_NO_VALUES)) - { - struct ui_file *stb; - stb = mem_fileopen (); - make_cleanup_ui_file_delete (stb); - - TRY_CATCH (except, RETURN_MASK_ALL) - { - get_user_print_options (&opts); - opts.deref_ref = 1; - common_val_print (val, stb, 2, &opts, language); - } - if (except.reason > 0) - { - PyErr_SetString (PyExc_RuntimeError, - except.message); - goto locals_error; - } - - ui_out_field_stream (out, "value", stb); - } - - ui_out_text (out, "\n"); - do_cleanups (inner_cleanup); + annotate_frame_args (); - } + item = PyIter_Next (iter); + if (! item && PyErr_Occurred ()) + goto error; - if (! item && PyErr_Occurred()) - goto locals_error; - } + while (item) + { + const struct language_defn *language; + char *sym_name; + struct value *val; + int value_success = 0; + volatile struct gdb_exception except; + struct cleanup *inner_cleanup = + make_cleanup (null_cleanup, NULL); + + value_success = extract_sym_and_value (item, + &sym_name, + &val, + &language); + Py_DECREF (item); + item = NULL; + + if (! value_success) + goto error; + + if (ui_out_is_mi_like_p (out)) + { + if(mi_print_type != PRINT_NO_VALUES) + { + inner_cleanup = + make_cleanup_ui_out_tuple_begin_end (out, + NULL); + } + } + + annotate_arg_begin (); + ui_out_field_string (out, "name", sym_name); + + if (! ui_out_is_mi_like_p (out)) + ui_out_text (out, "="); + + if (print_mi_args_flag) + ui_out_field_int (out, "arg", 1); + + annotate_arg_value (value_type (val)); + opts.deref_ref = 1; + + if (ui_out_is_mi_like_p (out) + && mi_print_type == PRINT_SIMPLE_VALUES) + { + py_print_type (out, val); + } + + if (! ui_out_is_mi_like_p (out)) + { + opts.summary = !strcmp (print_args_type, "scalars"); + } + + if (! ui_out_is_mi_like_p (out) + || (ui_out_is_mi_like_p (out) + && mi_print_type != PRINT_NO_VALUES)) + { + py_print_value (out, val, language); + } + + do_cleanups (inner_cleanup); + + /* Collect the next item from the iterator. If + this is the last item, we do not print the + ",". */ + item = PyIter_Next (iter); + if (item) + ui_out_text (out, ", "); + else + if (PyErr_Occurred ()) + goto error; + + annotate_arg_end (); + } + + return 1; + + error: + return 0; +} + +static int +enumerate_locals (PyObject *iter, + struct ui_out *out, + struct value_print_options opts, + int mi_print_type, + int indent) +{ + PyObject *item; + + while ((item = PyIter_Next (iter))) + { + const struct language_defn *language; + char *sym_name; + struct value *val; + int value_success = 0; + volatile struct gdb_exception except; + struct cleanup *inner_cleanup = + make_cleanup (null_cleanup, NULL); + + value_success = extract_sym_and_value (item, &sym_name, + &val, + &language); + + Py_DECREF (item); + + if (! value_success) + goto error; + + if (ui_out_is_mi_like_p (out)) + { + if (mi_print_type != PRINT_NO_VALUES) + { + inner_cleanup = + make_cleanup_ui_out_tuple_begin_end (out, + NULL); } } else - goto locals_error; + ui_out_spaces (out, (8 + (indent * 2))); + + ui_out_field_string (out, "name", sym_name); + xfree (sym_name); + + if (! ui_out_is_mi_like_p (out)) + ui_out_text (out, " = "); + + if (ui_out_is_mi_like_p (out) + && mi_print_type == PRINT_SIMPLE_VALUES) + { + if (! py_print_type (out, val)) + goto error; + } + + if (! ui_out_is_mi_like_p (out) + || (ui_out_is_mi_like_p (out) + && mi_print_type != PRINT_NO_VALUES)) + { + py_print_value (out, val, language); + } + + ui_out_text (out, "\n"); + do_cleanups (inner_cleanup); } + if (! item && PyErr_Occurred()) + goto error; + + done: + return 1; + + error: + return 0; +} + +static int +py_mi_print_variables (PyObject *filter, struct ui_out *out, + struct value_print_options opts, + int mi_print_type, const char *print_args_type) +{ + struct cleanup *old_chain; + PyObject *args_iter; + PyObject *locals_iter; + + args_iter = get_py_iter_from_func (filter, "frame_args"); + old_chain = make_cleanup_py_xdecref (args_iter); + if (! args_iter) + goto error; + + locals_iter = get_py_iter_from_func (filter, "frame_locals"); + if (! locals_iter) + goto error; + + make_cleanup_py_decref (locals_iter); + make_cleanup_ui_out_list_begin_end (out, "variables"); + + if (args_iter != Py_None) + if (! enumerate_args (args_iter, out, opts, mi_print_type, + print_args_type, 1)) + goto error; + + if (locals_iter != Py_None) + if (! enumerate_locals (locals_iter, out, opts, + mi_print_type, 0)) + goto error; + + do_cleanups (old_chain); + return 1; hooks/post-receive -- Repository for Project Archer.