/* 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 "python.h"
#include "ui-out.h"
#include "valprint.h"
+#include "stack.h"
+#include "source.h"
#include "annotate.h"
#include "hashtab.h"
#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"
+#include "cli/cli-style.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));
/* Duplicate the symbol name, so the caller has consistency
in garbage collection. */
- name->reset (xstrdup (SYMBOL_PRINT_NAME (*sym)));
+ name->reset (xstrdup ((*sym)->print_name ()));
/* If a symbol is specified attempt to determine the language
from the symbol. If mode is not "auto", then the language
has been explicitly set, use that. */
if (language_mode == language_mode_auto)
- *language = language_def (SYMBOL_LANGUAGE (*sym));
+ *language = language_def ((*sym)->language ());
else
*language = current_language;
}
{
if (fa->val == NULL && fa->error == NULL)
return;
- language = language_def (SYMBOL_LANGUAGE (fa->sym));
+ language = language_def (fa->sym->language ());
val = fa->val;
}
else
{
string_file stb;
- fprintf_symbol_filtered (&stb, SYMBOL_PRINT_NAME (fa->sym),
- SYMBOL_LANGUAGE (fa->sym),
+ fprintf_symbol_filtered (&stb, fa->sym->print_name (),
+ fa->sym->language (),
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),
+ fprintf_symbol_filtered (&stb, fa->sym->print_name (),
+ fa->sym->language (),
DMGL_PARAMS | DMGL_ANSI);
}
if (fa->entry_kind == print_entry_values_only
out->text ("=");
if (print_args_field)
- out->field_int ("arg", 1);
+ out->field_signed ("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
if (val == NULL)
{
gdb_assert (fa != NULL && fa->error != NULL);
- out->field_fmt ("value",
+ out->field_fmt ("value", metadata_style.style (),
_("<error reading variable: %s>"),
- fa->error);
+ fa->error.get ());
}
else
py_print_value (out, val, opts, 0, args_type, language);
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;
}
- read_frame_arg (sym, frame, &arg, &entryarg);
-
- gdb::unique_xmalloc_ptr<char> arg_holder (arg.error);
- gdb::unique_xmalloc_ptr<char> entry_holder (entryarg.error);
+ read_frame_arg (user_frame_print_options,
+ sym, frame, &arg, &entryarg);
/* The object has not provided a value, so this is a frame
argument to be read by GDB. In this case we have to
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;
annotate_frame_args ();
out->text (" (");
- if (args_iter != Py_None
- && (enumerate_args (args_iter.get (), out, args_type, 0, frame)
- == EXT_LANG_BT_ERROR))
+ if (args_type == CLI_PRESENCE)
+ {
+ if (args_iter != Py_None)
+ {
+ gdbpy_ref<> item (PyIter_Next (args_iter.get ()));
+
+ if (item != NULL)
+ out->text ("...");
+ else if (PyErr_Occurred ())
+ return EXT_LANG_BT_ERROR;
+ }
+ }
+ else if (args_iter != Py_None
+ && (enumerate_args (args_iter.get (), out, args_type, 0, frame)
+ == EXT_LANG_BT_ERROR))
return EXT_LANG_BT_ERROR;
out->text (")");
struct gdbarch *gdbarch = NULL;
struct frame_info *frame = NULL;
struct value_print_options opts;
+
int print_level, print_frame_info, print_args, print_locals;
+ /* Note that the below default in non-mi mode is the same as the
+ default value for the backtrace command (see the call to print_frame_info
+ in backtrace_command_1).
+ Having the same default ensures that 'bt' and 'bt no-filters'
+ have the same behaviour when some filters exist but do not apply
+ to a frame. */
+ enum print_what print_what
+ = out->is_mi_like_p () ? LOC_AND_ADDRESS : LOCATION;
gdb::unique_xmalloc_ptr<char> function_to_free;
/* Extract print settings from FLAGS. */
print_locals = (flags & PRINT_LOCALS) ? 1 : 0;
get_user_print_options (&opts);
+ if (print_frame_info)
+ {
+ gdb::optional<enum print_what> user_frame_info_print_what;
+
+ get_user_print_what_frame_info (&user_frame_info_print_what);
+ if (!out->is_mi_like_p () && user_frame_info_print_what.has_value ())
+ {
+ /* Use the specific frame information desired by the user. */
+ print_what = *user_frame_info_print_what;
+ }
+ }
/* Get the underlying frame. This is needed to determine GDB
architecture, and also, in the cases of frame variables/arguments to
if (frame == NULL)
return EXT_LANG_BT_ERROR;
+ symtab_and_line sal = find_frame_sal (frame);
+
gdbarch = get_frame_arch (frame);
/* stack-list-variables. */
}
}
+ /* For MI, each piece is controlled individually. */
+ bool location_print = (print_frame_info
+ && !out->is_mi_like_p ()
+ && (print_what == LOCATION
+ || print_what == SRC_AND_LOC
+ || print_what == LOC_AND_ADDRESS
+ || print_what == SHORT_LOCATION));
+
/* Print frame level. MI does not require the level if
locals/variables only are being printed. */
- if ((print_frame_info || print_args) && print_level)
+ if (print_level
+ && (location_print
+ || (out->is_mi_like_p () && (print_frame_info || print_args))))
{
struct frame_info **slot;
int level;
annotate_frame_begin (print_level ? level : 0,
gdbarch, address);
out->text ("#");
- out->field_fmt_int (2, ui_left, "level",
- level);
+ out->field_fmt_signed (2, ui_left, "level", level);
}
}
- if (print_frame_info)
+ if (location_print || (out->is_mi_like_p () && print_frame_info))
{
/* Print address to the address field. If an address is not provided,
print nothing. */
if (opts.addressprint && has_addr)
{
- annotate_frame_address ();
- out->field_core_addr ("addr", gdbarch, address);
- annotate_frame_address_end ();
- out->text (" in ");
+ if (!sal.symtab
+ || frame_show_address (frame, sal)
+ || print_what == LOC_AND_ADDRESS)
+ {
+ annotate_frame_address ();
+ out->field_core_addr ("addr", gdbarch, address);
+ if (get_frame_pc_masked (frame))
+ out->field_string ("pac", " [PAC]");
+ annotate_frame_address_end ();
+ out->text (" in ");
+ }
}
/* Print frame function name. */
msymbol = lookup_minimal_symbol_by_pc (addr);
if (msymbol.minsym != NULL)
- function = MSYMBOL_PRINT_NAME (msymbol.minsym);
+ function = msymbol.minsym->print_name ();
}
else if (py_func != Py_None)
{
if (function == NULL)
out->field_skip ("func");
else
- out->field_string ("func", function);
+ out->field_string ("func", function, function_name_style.style ());
}
}
/* Frame arguments. Check the result, and error if something went
wrong. */
- if (print_args)
+ if (print_args && (location_print || out->is_mi_like_p ()))
{
if (py_print_args (filter, out, args_type, frame) == EXT_LANG_BT_ERROR)
return EXT_LANG_BT_ERROR;
}
/* File name/source/line number information. */
- if (print_frame_info)
+ bool print_location_source
+ = ((location_print && print_what != SHORT_LOCATION)
+ || (out->is_mi_like_p () && print_frame_info));
+ if (print_location_source)
{
annotate_frame_source_begin ();
out->wrap_hint (" ");
out->text (" at ");
annotate_frame_source_file ();
- out->field_string ("file", filename.get ());
+ out->field_string ("file", filename.get (),
+ file_name_style.style ());
annotate_frame_source_file_end ();
}
}
out->text (":");
annotate_frame_source_line ();
- out->field_int ("line", line);
+ out->field_signed ("line", line);
}
}
+ if (out->is_mi_like_p ())
+ out->field_string ("arch",
+ (gdbarch_bfd_arch_info (gdbarch))->printable_name);
+ }
+
+ bool source_print
+ = (! out->is_mi_like_p ()
+ && (print_what == SRC_LINE || print_what == SRC_AND_LOC));
+ if (source_print)
+ {
+ if (print_location_source)
+ out->text ("\n"); /* Newline after the location source. */
+ print_source_lines (sal.symtab, sal.line, sal.line + 1, 0);
}
/* For MI we need to deal with the "children" list population of
if (! out->is_mi_like_p ())
{
annotate_frame_end ();
- out->text ("\n");
+ /* print_source_lines has already printed a newline. */
+ if (!source_print)
+ out->text ("\n");
}
if (print_locals)
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;
}
}
- TRY
+ try
{
success = py_print_frame (item.get (), flags, args_type, out, 0,
levels_printed.get ());
}
- CATCH (except, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &except)
{
gdbpy_convert_exception (except);
success = EXT_LANG_BT_ERROR;
}
- END_CATCH
/* 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;