From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4367 invoked by alias); 23 Aug 2012 14:53:46 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 4333 invoked by uid 9514); 23 Aug 2012 14:53:44 -0000 Date: Thu, 23 Aug 2012 14:53:00 -0000 Message-ID: <20120823145344.4318.qmail@sourceware.org> From: pmuldoon@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] archer-pmuldoon-python-backtrace: Add support for entry arguments and initial support for -stack-list-arguments. X-Git-Refname: refs/heads/archer-pmuldoon-python-backtrace X-Git-Reftype: branch X-Git-Oldrev: ce126c971ee4f1908c026de832cedd633c4028b5 X-Git-Newrev: 8a1e1772259968d49dd6a96c4e9b86fdbce3e130 X-SW-Source: 2012-q3/txt/msg00030.txt.bz2 List-Id: The branch, archer-pmuldoon-python-backtrace has been updated via 8a1e1772259968d49dd6a96c4e9b86fdbce3e130 (commit) from ce126c971ee4f1908c026de832cedd633c4028b5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 8a1e1772259968d49dd6a96c4e9b86fdbce3e130 Author: Phil Muldoon Date: Thu Aug 23 15:52:41 2012 +0100 Add support for entry arguments and initial support for -stack-list-arguments. ----------------------------------------------------------------------- Summary of changes: gdb/python/lib/gdb/BaseFrameWrapper.py | 4 +- gdb/python/py-framefilter.c | 460 ++++++++++++++++++------ gdb/testsuite/gdb.python/py-framefilter-mi.c | 27 ++- gdb/testsuite/gdb.python/py-framefilter-mi.exp | 40 ++- 4 files changed, 403 insertions(+), 128 deletions(-) First 500 lines of diff: diff --git a/gdb/python/lib/gdb/BaseFrameWrapper.py b/gdb/python/lib/gdb/BaseFrameWrapper.py index e4ca58d..aa49ad1 100644 --- a/gdb/python/lib/gdb/BaseFrameWrapper.py +++ b/gdb/python/lib/gdb/BaseFrameWrapper.py @@ -133,7 +133,7 @@ class FrameVars (): if sym.is_argument: continue; if self.fetch_b (sym): - lvars.append(BaseSymValueWrapper(sym, self.get_value(sym,block))) + lvars.append(BaseSymValueWrapper(sym, None)) if len(lvars) == 0: return None @@ -148,7 +148,7 @@ class FrameVars (): if not sym.is_argument: continue; if self.fetch_b (sym): - args.append(BaseSymValueWrapper(sym,self.get_value (sym,block))) + args.append(BaseSymValueWrapper(sym,None)) if len(args) == 0: return None diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c index fd6e26e..9183c54 100644 --- a/gdb/python/py-framefilter.c +++ b/gdb/python/py-framefilter.c @@ -23,32 +23,33 @@ #include "language.h" #include "exceptions.h" #include "arch-utils.h" -#include "language.h" #include "python.h" #include "ui-out.h" #include "valprint.h" #include "annotate.h" #include "hashtab.h" #include "mi/mi-cmds.h" +#include "demangle.h" #ifdef HAVE_PYTHON #include "python-internal.h" -/* 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 + +/* Helper function to extract a symbol, name and language definition + from a Python object that conforms to the 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) -{ + **SYM is a pass-through argument where the symbol will be written. + In the case of the API returning a string, this will be set to + NULL. **LANGUAGE is also a pass-through argument denoting the + language attributed to the Symbol. In the case of **SYM being NULL, + this will be set to the current language. Returns 0 on error with + the appropriate Python exception set, and 1 on success. */ +static int +extract_sym (PyObject *obj, char **name, struct symbol **sym, + const struct language_defn **language) +{ if (PyObject_HasAttrString (obj, "symbol")) { PyObject *result = PyObject_CallMethod (obj, "symbol", NULL); @@ -66,14 +67,15 @@ static int extract_sym_and_value (PyObject *obj, if (! *name) return 0; *language = current_language; + *sym = NULL; } else { - struct symbol *symbol = symbol_object_to_symbol (result); + *sym = symbol_object_to_symbol (result); Py_DECREF (result); - if (! symbol) + if (! *sym) { PyErr_SetString (PyExc_RuntimeError, _("Unexpected value. Expecting a " \ @@ -81,10 +83,10 @@ static int extract_sym_and_value (PyObject *obj, return 0; } - *name = xstrdup (SYMBOL_PRINT_NAME (symbol)); + *name = xstrdup (SYMBOL_PRINT_NAME (*sym)); if (language_mode == language_mode_auto) - *language = language_def (SYMBOL_LANGUAGE (symbol)); + *language = language_def (SYMBOL_LANGUAGE (*sym)); else *language = current_language; } @@ -92,37 +94,52 @@ static int extract_sym_and_value (PyObject *obj, else { PyErr_SetString (PyExc_RuntimeError, - _("Mandatory function 'symbol' not " \ + _("Mandatory function 'symbol' not " \ "implemented.")); return 0; } + return 1; +} + +/* Helper function to extract a value from an object that conforms to + the SymbolValue interface. OBJ is the Python object to extract the + value from. **VALUE is a pass-through argument where the value + will be written. If the object does not have the value attribute, + or provides the Python None for a value, **VALUE will be set to + NULL and this function will return as successful. Returns 0 on + error with the appropriate Python exception set, and 1 on + success. */ + +static int +extract_value (PyObject *obj, struct value **value) +{ if (PyObject_HasAttrString (obj, "value")) { - PyObject *result = PyObject_CallMethod (obj, "value", NULL); + PyObject *vresult = PyObject_CallMethod (obj, "value", NULL); - if (! result) + if (! vresult) + return 0; + + if (vresult == Py_None) { - xfree (*name); - return 0; + Py_DECREF (vresult); + *value = NULL; + return 1; } + else + { + *value = convert_value_from_python (vresult); + Py_DECREF (vresult); - *value = convert_value_from_python (result); + if (*value == NULL) + return 0; - Py_DECREF (result); - if (! *value) - { - xfree (*name); - return 0; + return 1; } } else - { - PyErr_SetString (PyExc_RuntimeError, - _("Mandatory function 'value' not " \ - "implemented.")); - return 0; - } + *value = NULL; return 1; } @@ -145,7 +162,7 @@ py_print_type (struct ui_out *out, struct value *val) stb = mem_fileopen (); cleanup = make_cleanup_ui_file_delete (stb); type = check_typedef (value_type (val)); - type_print (type, "", stb, -1); + type_print (value_type (val), "", stb, -1); ui_out_field_stream (out, "type", stb); do_cleanups (cleanup); } @@ -166,30 +183,54 @@ py_print_type (struct ui_out *out, struct value *val) static int py_print_value (struct ui_out *out, struct value *val, + struct value_print_options opts, + int mi_print_type, const struct language_defn *language) { - volatile struct gdb_exception except; + int should_print = 0; - TRY_CATCH (except, RETURN_MASK_ALL) + /* MI disallows different value types against different options the + client passes, so test type against option. For CLI print all + values. */ + if (ui_out_is_mi_like_p (out)) { - struct ui_file *stb; - struct cleanup *cleanup; - struct value_print_options opts; + struct type *type; - 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); + type = value_type (val); + check_typedef (type); + if (mi_print_type == PRINT_ALL_VALUES + || (mi_print_type == PRINT_SIMPLE_VALUES + && TYPE_CODE (type) != TYPE_CODE_ARRAY + && TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION)) + should_print = 1; } - if (except.reason > 0) + else + should_print = 1; + + if (should_print) { - PyErr_SetString (PyExc_RuntimeError, - except.message); - return 0; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + struct ui_file *stb; + struct cleanup *cleanup; + + stb = mem_fileopen (); + cleanup = make_cleanup_ui_file_delete (stb); + common_val_print (val, stb, 0, &opts, language); + ui_out_field_stream (out, "value", stb); + do_cleanups (cleanup); + } + if (except.reason > 0) + { + PyErr_SetString (PyExc_RuntimeError, + except.message); + return 0; + } } + return 1; } @@ -239,12 +280,113 @@ get_py_iter_from_func (PyObject *filter, char *func) } static int +py_print_single_arg (struct ui_out *out, + char *sym_name, + struct frame_arg *fa, + struct value *fv, + struct value_print_options opts, + int mi_print_type, + const char *print_args_type, + int print_mi_args_flag, + const struct language_defn *language) +{ + struct value *val; + struct cleanup *inner_cleanup = + make_cleanup (null_cleanup, NULL); + + if (fa) + { + language = language_def (SYMBOL_LANGUAGE (fa->sym)); + val = fa->val; + } + else + val = fv; + + if (print_mi_args_flag || mi_print_type != PRINT_NO_VALUES) + { + inner_cleanup = + make_cleanup_ui_out_tuple_begin_end (out, + NULL); + } + + annotate_arg_begin (); + + if (fa) + { + struct ui_file *stb; + + stb = mem_fileopen (); + + fprintf_symbol_filtered (stb, SYMBOL_PRINT_NAME (fa->sym), + SYMBOL_LANGUAGE (fa->sym), + DMGL_PARAMS | DMGL_ANSI); + if (fa->entry_kind == print_entry_values_compact) + { + fputs_filtered ("=", stb); + + fprintf_symbol_filtered (stb, SYMBOL_PRINT_NAME (fa->sym), + SYMBOL_LANGUAGE (fa->sym), + DMGL_PARAMS | DMGL_ANSI); + } + if (fa->entry_kind == print_entry_values_only + || fa->entry_kind == print_entry_values_compact) + { + fputs_filtered ("@entry", stb); + } + ui_out_field_stream (out, "name", stb); + ui_file_delete (stb); + } + else + ui_out_field_string (out, "name", sym_name); + + annotate_arg_name_end (); + + if (! ui_out_is_mi_like_p (out)) + ui_out_text (out, "="); + + if (print_mi_args_flag) + ui_out_field_int (out, "arg", 1); + + opts.deref_ref = 1; + 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)) + { + opts.summary = !strcmp (print_args_type, "scalars"); + } + + annotate_arg_value (value_type (val)); + if (! ui_out_is_mi_like_p (out) + || (ui_out_is_mi_like_p (out) + && mi_print_type != PRINT_NO_VALUES)) + { + + if (! py_print_value (out, val, opts, mi_print_type, language)) + goto error; + } + + do_cleanups (inner_cleanup); + + return 1; + + error: + do_cleanups (inner_cleanup); + return 0; +} + +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) + int print_mi_args_flag, + struct frame_info *frame) { PyObject *item; @@ -258,63 +400,103 @@ enumerate_args (PyObject *iter, { const struct language_defn *language; char *sym_name; + struct symbol *sym; struct value *val; - int value_success = 0; + int success = 0; volatile struct gdb_exception except; - struct cleanup *inner_cleanup = - make_cleanup (null_cleanup, NULL); + struct frame_arg arg, entryarg; + + success = extract_sym (item, &sym_name, &sym, &language); + if (! success) + { + Py_DECREF (item); + goto error; + } + + success = extract_value (item, &val); + if (! success) + { + xfree (sym_name); + Py_DECREF (item); + goto error; + } - 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 the object did not provide a value, read it. */ + if (! val) { - if(mi_print_type != PRINT_NO_VALUES) + + /* If there is no value, and also no symbol, set error and + exit. */ + if (! sym) { - inner_cleanup = - make_cleanup_ui_out_tuple_begin_end (out, - NULL); + PyErr_SetString (PyExc_RuntimeError, + _("No symbol or value provided.")); + xfree (sym_name); + goto error; } - } - annotate_arg_begin (); - ui_out_field_string (out, "name", sym_name); + read_frame_arg (sym, frame, &arg, &entryarg); + } - if (! ui_out_is_mi_like_p (out)) - ui_out_text (out, "="); - if (print_mi_args_flag) - ui_out_field_int (out, "arg", 1); + /* If the object has provided a value, we print that. */ + if (val) + py_print_single_arg (out, + sym_name, + NULL, + val, + opts, + mi_print_type, + print_args_type, + print_mi_args_flag, + language); + else + { + /* The object has not provided a value, so this is a frame + argument read by GDB. In this case we have to account + for entry-values. */ + + if (arg.entry_kind != print_entry_values_only) + py_print_single_arg (out, + NULL, + &arg, + NULL, + opts, + mi_print_type, + print_args_type, + print_mi_args_flag, + NULL); + + + if (entryarg.entry_kind != print_entry_values_no) + { + if (arg.entry_kind != print_entry_values_only) + { + ui_out_text (out, ", "); + ui_out_wrap_hint (out, " "); + } - annotate_arg_value (value_type (val)); - opts.deref_ref = 1; + py_print_single_arg (out, + NULL, + &entryarg, + NULL, + opts, + mi_print_type, + print_args_type, + print_mi_args_flag, + NULL); - 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"); + xfree (arg.error); + xfree (entryarg.error); } hooks/post-receive -- Repository for Project Archer.