/* Python frame filters
- Copyright (C) 2013-2018 Free Software Foundation, Inc.
+ Copyright (C) 2013-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "demangle.h"
#include "mi/mi-cmds.h"
#include "python-internal.h"
-#include "py-ref.h"
-#include "common/gdb_optional.h"
+#include "gdbsupport/gdb_optional.h"
enum mi_print_types
{
static enum ext_lang_bt_status
extract_sym (PyObject *obj, gdb::unique_xmalloc_ptr<char> *name,
- struct symbol **sym, struct block **sym_block,
+ struct symbol **sym, const struct block **sym_block,
const struct language_defn **language)
{
gdbpy_ref<> result (PyObject_CallMethod (obj, "symbol", NULL));
/* Helper function which outputs a type name extracted from VAL to a
"type" field in the output stream OUT. 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 EXT_LANG_BT_ERROR on error, with
- any GDB exceptions converted to a Python exception, or EXT_LANG_BT_OK on
- success. */
+ type will be extracted from. */
-static enum ext_lang_bt_status
+static void
py_print_type (struct ui_out *out, struct value *val)
{
+ check_typedef (value_type (val));
- TRY
- {
- check_typedef (value_type (val));
-
- string_file stb;
- type_print (value_type (val), "", &stb, -1);
- out->field_stream ("type", stb);
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
-
- return EXT_LANG_BT_OK;
+ string_file stb;
+ type_print (value_type (val), "", &stb, -1);
+ out->field_stream ("type", stb);
}
/* Helper function which outputs a value to an output field in a
VAL is the value that will be printed, OPTS contains the value
printing options, ARGS_TYPE is an enumerator describing the
argument format, and LANGUAGE is the language_defn that the value
- will be printed with. Returns EXT_LANG_BT_ERROR on error, with any GDB
- exceptions converted to a Python exception, or EXT_LANG_BT_OK on
- success. */
+ will be printed with. */
-static enum ext_lang_bt_status
+static void
py_print_value (struct ui_out *out, struct value *val,
const struct value_print_options *opts,
int indent,
if (args_type == MI_PRINT_SIMPLE_VALUES
|| args_type == MI_PRINT_ALL_VALUES)
{
- struct type *type = NULL;
-
- TRY
- {
- type = check_typedef (value_type (val));
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ struct type *type = check_typedef (value_type (val));
if (args_type == MI_PRINT_ALL_VALUES)
should_print = 1;
if (should_print)
{
- TRY
- {
- string_file stb;
+ string_file stb;
- common_val_print (val, &stb, indent, opts, language);
- out->field_stream ("value", stb);
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ common_val_print (val, &stb, indent, opts, language);
+ out->field_stream ("value", stb);
}
-
- return EXT_LANG_BT_OK;
}
/* Helper function to call a Python method and extract an iterator
ARGS_TYPE is an enumerator describing the argument format,
PRINT_ARGS_FIELD is a flag which indicates if we output "ARGS=1"
in MI output in commands where both arguments and locals are
- printed. Returns EXT_LANG_BT_ERROR on error, with any GDB exceptions
- converted to a Python exception, or EXT_LANG_BT_OK on success. */
+ printed. */
-static enum ext_lang_bt_status
+static void
py_print_single_arg (struct ui_out *out,
const char *sym_name,
struct frame_arg *fa,
const struct language_defn *language)
{
struct value *val;
- enum ext_lang_bt_status retval = EXT_LANG_BT_OK;
if (fa != NULL)
{
if (fa->val == NULL && fa->error == NULL)
- return EXT_LANG_BT_OK;
+ return;
language = language_def (SYMBOL_LANGUAGE (fa->sym));
val = fa->val;
}
else
val = fv;
- TRY
- {
- gdb::optional<ui_out_emit_tuple> maybe_tuple;
+ gdb::optional<ui_out_emit_tuple> maybe_tuple;
- /* MI has varying rules for tuples, but generally if there is only
+ /* MI has varying rules for tuples, but generally if there is only
one element in each item in the list, do not start a tuple. The
exception is -stack-list-variables which emits an ARGS="1" field
if the value is a frame argument. This is denoted in this
function with PRINT_ARGS_FIELD which is flag from the caller to
emit the ARGS field. */
- if (out->is_mi_like_p ())
- {
- if (print_args_field || args_type != NO_VALUES)
- maybe_tuple.emplace (out, nullptr);
- }
+ if (out->is_mi_like_p ())
+ {
+ if (print_args_field || args_type != NO_VALUES)
+ maybe_tuple.emplace (out, nullptr);
+ }
+
+ annotate_arg_begin ();
- annotate_arg_begin ();
+ /* If frame argument is populated, check for entry-values and the
+ entry value options. */
+ if (fa != NULL)
+ {
+ string_file stb;
- /* If frame argument is populated, check for entry-values and the
- entry value options. */
- if (fa != NULL)
+ 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)
{
- string_file stb;
+ stb.puts ("=");
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)
- {
- stb.puts ("=");
-
- 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)
- stb.puts ("@entry");
- out->field_stream ("name", stb);
}
- else
- /* Otherwise, just output the name. */
- out->field_string ("name", sym_name);
+ if (fa->entry_kind == print_entry_values_only
+ || fa->entry_kind == print_entry_values_compact)
+ stb.puts ("@entry");
+ out->field_stream ("name", stb);
+ }
+ else
+ /* Otherwise, just output the name. */
+ out->field_string ("name", sym_name);
- annotate_arg_name_end ();
+ annotate_arg_name_end ();
- if (! out->is_mi_like_p ())
- out->text ("=");
+ out->text ("=");
- if (print_args_field)
- out->field_int ("arg", 1);
+ if (print_args_field)
+ out->field_int ("arg", 1);
- /* For MI print the type, but only for simple values. This seems
- weird, but this is how MI choose to format the various output
- types. */
- if (args_type == MI_PRINT_SIMPLE_VALUES && val != NULL)
- {
- if (py_print_type (out, val) == EXT_LANG_BT_ERROR)
- retval = EXT_LANG_BT_ERROR;
- }
+ /* For MI print the type, but only for simple values. This seems
+ weird, but this is how MI choose to format the various output
+ types. */
+ if (args_type == MI_PRINT_SIMPLE_VALUES && val != NULL)
+ py_print_type (out, val);
- if (retval != EXT_LANG_BT_ERROR)
- {
- if (val != NULL)
- annotate_arg_value (value_type (val));
+ if (val != NULL)
+ annotate_arg_value (value_type (val));
- /* If the output is to the CLI, and the user option "set print
- frame-arguments" is set to none, just output "...". */
- if (! out->is_mi_like_p () && args_type == NO_VALUES)
- out->field_string ("value", "...");
- else
+ /* If the output is to the CLI, and the user option "set print
+ frame-arguments" is set to none, just output "...". */
+ if (! out->is_mi_like_p () && args_type == NO_VALUES)
+ out->field_string ("value", "...");
+ else
+ {
+ /* Otherwise, print the value for both MI and the CLI, except
+ for the case of MI_PRINT_NO_VALUES. */
+ if (args_type != NO_VALUES)
+ {
+ if (val == NULL)
{
- /* Otherwise, print the value for both MI and the CLI, except
- for the case of MI_PRINT_NO_VALUES. */
- if (args_type != NO_VALUES)
- {
- if (val == NULL)
- {
- gdb_assert (fa != NULL && fa->error != NULL);
- out->field_fmt ("value",
- _("<error reading variable: %s>"),
- fa->error);
- }
- else if (py_print_value (out, val, opts, 0, args_type, language)
- == EXT_LANG_BT_ERROR)
- retval = EXT_LANG_BT_ERROR;
- }
+ gdb_assert (fa != NULL && fa->error != NULL);
+ out->field_fmt ("value",
+ _("<error reading variable: %s>"),
+ fa->error);
}
+ else
+ py_print_value (out, val, opts, 0, args_type, language);
}
}
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- retval = EXT_LANG_BT_ERROR;
- }
- END_CATCH
-
- return retval;
}
/* Helper function to loop over frame arguments provided by the
opts.deref_ref = 1;
- TRY
- {
- annotate_frame_args ();
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ annotate_frame_args ();
/* Collect the first argument outside of the loop, so output of
commas in the argument output is correct. At the end of the
const struct language_defn *language;
gdb::unique_xmalloc_ptr<char> sym_name;
struct symbol *sym;
- struct block *sym_block;
+ const struct block *sym_block;
struct value *val;
enum ext_lang_bt_status success = EXT_LANG_BT_ERROR;
return EXT_LANG_BT_ERROR;
}
- TRY
- {
- read_frame_arg (sym, frame, &arg, &entryarg);
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ read_frame_arg (user_frame_print_options,
+ sym, frame, &arg, &entryarg);
gdb::unique_xmalloc_ptr<char> arg_holder (arg.error);
gdb::unique_xmalloc_ptr<char> entry_holder (entryarg.error);
if (arg.entry_kind != print_entry_values_only)
{
- if (py_print_single_arg (out, NULL, &arg,
- NULL, &opts,
- args_type,
- print_args_field,
- NULL) == EXT_LANG_BT_ERROR)
- return EXT_LANG_BT_ERROR;
+ py_print_single_arg (out, NULL, &arg,
+ NULL, &opts,
+ args_type,
+ print_args_field,
+ NULL);
}
if (entryarg.entry_kind != print_entry_values_no)
{
if (arg.entry_kind != print_entry_values_only)
{
- TRY
- {
- out->text (", ");
- out->wrap_hint (" ");
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ out->text (", ");
+ out->wrap_hint (" ");
}
- if (py_print_single_arg (out, NULL, &entryarg, NULL, &opts,
- args_type, print_args_field, NULL)
- == EXT_LANG_BT_ERROR)
- return EXT_LANG_BT_ERROR;
+ py_print_single_arg (out, NULL, &entryarg, NULL, &opts,
+ args_type, print_args_field, NULL);
}
}
else
{
/* If the object has provided a value, we just print that. */
if (val != NULL)
- {
- if (py_print_single_arg (out, sym_name.get (), NULL, val, &opts,
- args_type, print_args_field,
- language) == EXT_LANG_BT_ERROR)
- return EXT_LANG_BT_ERROR;
- }
+ py_print_single_arg (out, sym_name.get (), NULL, val, &opts,
+ args_type, print_args_field,
+ language);
}
/* Collect the next item from the iterator. If
comma. */
item.reset (PyIter_Next (iter));
if (item != NULL)
- {
- TRY
- {
- out->text (", ");
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
- }
+ out->text (", ");
else if (PyErr_Occurred ())
return EXT_LANG_BT_ERROR;
- TRY
- {
- annotate_arg_end ();
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ annotate_arg_end ();
}
return EXT_LANG_BT_OK;
struct value *val;
enum ext_lang_bt_status success = EXT_LANG_BT_ERROR;
struct symbol *sym;
- struct block *sym_block;
+ const struct block *sym_block;
int local_indent = 8 + (8 * indent);
gdb::optional<ui_out_emit_tuple> tuple;
/* If the object did not provide a value, read it. */
if (val == NULL)
- {
- TRY
- {
- val = read_var_value (sym, sym_block, frame);
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
- }
+ val = read_var_value (sym, sym_block, frame);
/* With PRINT_NO_VALUES, MI does not emit a tuple normally as
each output contains only one field. The exception is
if (print_args_field || args_type != NO_VALUES)
tuple.emplace (out, nullptr);
}
- TRY
- {
- if (! out->is_mi_like_p ())
- {
- /* If the output is not MI we indent locals. */
- out->spaces (local_indent);
- }
- out->field_string ("name", sym_name.get ());
-
- if (! out->is_mi_like_p ())
- out->text (" = ");
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ /* If the output is not MI we indent locals. */
+ out->spaces (local_indent);
+ out->field_string ("name", sym_name.get ());
+ out->text (" = ");
if (args_type == MI_PRINT_SIMPLE_VALUES)
- {
- if (py_print_type (out, val) == EXT_LANG_BT_ERROR)
- return EXT_LANG_BT_ERROR;
- }
+ py_print_type (out, val);
/* CLI always prints values for locals. MI uses the
simple/no/all system. */
{
int val_indent = (indent + 1) * 4;
- if (py_print_value (out, val, &opts, val_indent, args_type,
- language) == EXT_LANG_BT_ERROR)
- return EXT_LANG_BT_ERROR;
+ py_print_value (out, val, &opts, val_indent, args_type,
+ language);
}
else
{
if (args_type != NO_VALUES)
- {
- if (py_print_value (out, val, &opts, 0, args_type,
- language) == EXT_LANG_BT_ERROR)
- return EXT_LANG_BT_ERROR;
- }
+ py_print_value (out, val, &opts, 0, args_type,
+ language);
}
- TRY
- {
- out->text ("\n");
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ out->text ("\n");
}
if (!PyErr_Occurred ())
ui_out_emit_list list_emitter (out, "args");
- TRY
- {
- annotate_frame_args ();
- if (! out->is_mi_like_p ())
- out->text (" (");
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ out->wrap_hint (" ");
+ annotate_frame_args ();
+ out->text (" (");
if (args_iter != Py_None
&& (enumerate_args (args_iter.get (), out, args_type, 0, frame)
== EXT_LANG_BT_ERROR))
return EXT_LANG_BT_ERROR;
- TRY
- {
- if (! out->is_mi_like_p ())
- out->text (")");
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ out->text (")");
return EXT_LANG_BT_OK;
}
if (frame == NULL)
return EXT_LANG_BT_ERROR;
- TRY
- {
- gdbarch = get_frame_arch (frame);
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ gdbarch = get_frame_arch (frame);
/* stack-list-variables. */
if (print_locals && print_args && ! print_frame_info)
/* Elided frames are also printed with this function (recursively)
and are printed with indention. */
if (indent > 0)
- {
- TRY
- {
- out->spaces (indent * 4);
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
- }
+ out->spaces (indent * 4);
/* The address is required for frame annotations, and also for
address printing. */
slot = (struct frame_info **) htab_find_slot (levels_printed,
frame, INSERT);
- TRY
- {
- level = frame_relative_level (frame);
-
- /* Check if this frame has already been printed (there are cases
- where elided synthetic dummy-frames have to 'borrow' the frame
- architecture from the eliding frame. If that is the case, do
- not print 'level', but print spaces. */
- if (*slot == frame)
- out->field_skip ("level");
- else
- {
- *slot = frame;
- annotate_frame_begin (print_level ? level : 0,
- gdbarch, address);
- out->text ("#");
- out->field_fmt_int (2, ui_left, "level",
- level);
- }
- }
- CATCH (except, RETURN_MASK_ERROR)
+
+ level = frame_relative_level (frame);
+
+ /* Check if this frame has already been printed (there are cases
+ where elided synthetic dummy-frames have to 'borrow' the frame
+ architecture from the eliding frame. If that is the case, do
+ not print 'level', but print spaces. */
+ if (*slot == frame)
+ out->field_skip ("level");
+ else
{
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
+ *slot = frame;
+ annotate_frame_begin (print_level ? level : 0,
+ gdbarch, address);
+ out->text ("#");
+ out->field_fmt_int (2, ui_left, "level",
+ level);
}
- END_CATCH
}
if (print_frame_info)
print nothing. */
if (opts.addressprint && has_addr)
{
- TRY
- {
- annotate_frame_address ();
- out->field_core_addr ("addr", gdbarch, address);
- annotate_frame_address_end ();
- out->text (" in ");
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ annotate_frame_address ();
+ out->field_core_addr ("addr", gdbarch, address);
+ annotate_frame_address_end ();
+ out->text (" in ");
}
/* Print frame function name. */
return EXT_LANG_BT_ERROR;
}
- TRY
- {
- annotate_frame_function_name ();
- if (function == NULL)
- out->field_skip ("func");
- else
- out->field_string ("func", function);
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ annotate_frame_function_name ();
+ if (function == NULL)
+ out->field_skip ("func");
+ else
+ out->field_string ("func", function, ui_out_style_kind::FUNCTION);
}
}
/* File name/source/line number information. */
if (print_frame_info)
{
- TRY
- {
- annotate_frame_source_begin ();
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ annotate_frame_source_begin ();
if (PyObject_HasAttrString (filter, "filename"))
{
if (filename == NULL)
return EXT_LANG_BT_ERROR;
- TRY
- {
- out->wrap_hint (" ");
- out->text (" at ");
- annotate_frame_source_file ();
- out->field_string ("file", filename.get ());
- annotate_frame_source_file_end ();
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ out->wrap_hint (" ");
+ out->text (" at ");
+ annotate_frame_source_file ();
+ out->field_string ("file", filename.get (),
+ ui_out_style_kind::FILE);
+ annotate_frame_source_file_end ();
}
}
if (PyErr_Occurred ())
return EXT_LANG_BT_ERROR;
- TRY
- {
- out->text (":");
- annotate_frame_source_line ();
- out->field_int ("line", line);
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ out->text (":");
+ annotate_frame_source_line ();
+ out->field_int ("line", line);
}
}
+ if (out->is_mi_like_p ())
+ out->field_string ("arch",
+ (gdbarch_bfd_arch_info (gdbarch))->printable_name);
}
/* For MI we need to deal with the "children" list population of
elided frames, so if MI output detected do not send newline. */
if (! out->is_mi_like_p ())
{
- TRY
- {
- annotate_frame_end ();
- out->text ("\n");
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- gdbpy_convert_exception (except);
- return EXT_LANG_BT_ERROR;
- }
- END_CATCH
+ annotate_frame_end ();
+ out->text ("\n");
}
if (print_locals)
ui_out_emit_list inner_list_emiter (out, "children");
- if (! out->is_mi_like_p ())
- indent++;
+ indent++;
while ((item = PyIter_Next (elided.get ())))
{
return iterable.release ();
}
-/* A helper function that will either print an exception or, if it is
- a KeyboardException, throw a quit. This can only be called when
- the Python exception is set. */
-
-static void
-throw_quit_or_print_exception ()
-{
- if (PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
- {
- PyErr_Clear ();
- throw_quit ("Quit");
- }
- gdbpy_print_stack ();
-}
-
/* This is the only publicly exported function in this file. FRAME
is the source frame to start frame-filter invocation. FLAGS is an
integer holding the flags for printing. The following elements of
if (!gdb_python_initialized)
return EXT_LANG_BT_NO_FILTERS;
- TRY
+ try
{
gdbarch = get_frame_arch (frame);
}
- CATCH (except, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &except)
{
/* Let gdb try to print the stack trace. */
return EXT_LANG_BT_NO_FILTERS;
}
- END_CATCH
gdbpy_enter enter_py (gdbarch, current_language);
initialization error. This return code will trigger a
default backtrace. */
- throw_quit_or_print_exception ();
+ gdbpy_print_stack_or_quit ();
return EXT_LANG_BT_NO_FILTERS;
}
{
if (PyErr_Occurred ())
{
- throw_quit_or_print_exception ();
+ gdbpy_print_stack_or_quit ();
return EXT_LANG_BT_ERROR;
}
break;
}
}
- success = py_print_frame (item.get (), flags, args_type, out, 0,
- levels_printed.get ());
+ try
+ {
+ success = py_print_frame (item.get (), flags, args_type, out, 0,
+ levels_printed.get ());
+ }
+ catch (const gdb_exception_error &except)
+ {
+ gdbpy_convert_exception (except);
+ success = EXT_LANG_BT_ERROR;
+ }
/* Do not exit on error printing a single frame. Print the
error and continue with other frames. */
if (success == EXT_LANG_BT_ERROR)
- throw_quit_or_print_exception ();
+ gdbpy_print_stack_or_quit ();
}
return success;