/* Print and select stack frames for GDB, the GNU debugger.
- Copyright (C) 1986-2013 Free Software Foundation, Inc.
+ Copyright (C) 1986-2015 Free Software Foundation, Inc.
This file is part of GDB.
#include "block.h"
#include "stack.h"
#include "dictionary.h"
-#include "exceptions.h"
#include "reggroups.h"
#include "regcache.h"
#include "solib.h"
#include "inline-frame.h"
#include "linespec.h"
#include "cli/cli-utils.h"
+#include "objfiles.h"
-#include "gdb_assert.h"
#include <ctype.h>
-#include <string.h>
-
#include "symfile.h"
-#include "python/python.h"
-
-void (*deprecated_selected_frame_level_changed_hook) (int);
+#include "extension.h"
/* The possible choices of "set print frame-arguments", and the value
of this setting. */
enum print_what print_what,
int set_current_sal)
{
- volatile struct gdb_exception e;
/* For mi, alway print location and address. */
if (ui_out_is_mi_like_p (current_uiout))
print_what = LOC_AND_ADDRESS;
- TRY_CATCH (e, RETURN_MASK_ERROR)
+ TRY
{
- int center = (print_what == SRC_LINE || print_what == SRC_AND_LOC);
-
print_frame_info (frame, print_level, print_what, 1 /* print_args */,
set_current_sal);
if (set_current_sal)
- set_current_sal_from_frame (frame, center);
+ set_current_sal_from_frame (frame);
}
+ CATCH (e, RETURN_MASK_ERROR)
+ {
+ }
+ END_CATCH
}
/* Print nameless arguments of frame FRAME on STREAM, where START is
print_frame_arg (const struct frame_arg *arg)
{
struct ui_out *uiout = current_uiout;
- volatile struct gdb_exception except;
struct cleanup *old_chain;
struct ui_file *stb;
+ const char *error_message = NULL;
stb = mem_fileopen ();
old_chain = make_cleanup_ui_file_delete (stb);
else
{
if (arg->error)
- except.message = arg->error;
+ error_message = arg->error;
else
{
- /* TRY_CATCH has two statements, wrap it in a block. */
-
- TRY_CATCH (except, RETURN_MASK_ERROR)
+ TRY
{
const struct language_defn *language;
struct value_print_options opts;
common_val_print (arg->val, stb, 2, &opts, language);
}
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ error_message = except.message;
+ }
+ END_CATCH
}
- if (except.message)
+ if (error_message != NULL)
fprintf_filtered (stb, _("<error reading variable: %s>"),
- except.message);
+ error_message);
}
ui_out_field_stream (uiout, "value", stb);
read_frame_local (struct symbol *sym, struct frame_info *frame,
struct frame_arg *argp)
{
- volatile struct gdb_exception except;
struct value *val = NULL;
- TRY_CATCH (except, RETURN_MASK_ERROR)
+ argp->sym = sym;
+ argp->val = NULL;
+ argp->error = NULL;
+
+ TRY
{
- val = read_var_value (sym, frame);
+ argp->val = read_var_value (sym, NULL, frame);
}
-
- argp->error = (val == NULL) ? xstrdup (except.message) : NULL;
- argp->sym = sym;
- argp->val = val;
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ argp->error = xstrdup (except.message);
+ }
+ END_CATCH
}
/* Read in inferior function parameter SYM at FRAME into ARGP. Caller is
struct value *val = NULL, *entryval = NULL;
char *val_error = NULL, *entryval_error = NULL;
int val_equal = 0;
- volatile struct gdb_exception except;
if (print_entry_values != print_entry_values_only
&& print_entry_values != print_entry_values_preferred)
{
- TRY_CATCH (except, RETURN_MASK_ERROR)
+ TRY
{
- val = read_var_value (sym, frame);
+ val = read_var_value (sym, NULL, frame);
}
- if (!val)
+ CATCH (except, RETURN_MASK_ERROR)
{
val_error = alloca (strlen (except.message) + 1);
strcpy (val_error, except.message);
}
+ END_CATCH
}
if (SYMBOL_COMPUTED_OPS (sym) != NULL
&& (print_entry_values != print_entry_values_if_needed
|| !val || value_optimized_out (val)))
{
- TRY_CATCH (except, RETURN_MASK_ERROR)
+ TRY
{
const struct symbol_computed_ops *ops;
ops = SYMBOL_COMPUTED_OPS (sym);
entryval = ops->read_variable_at_entry (sym, frame);
}
- if (!entryval)
+ CATCH (except, RETURN_MASK_ERROR)
{
- entryval_error = alloca (strlen (except.message) + 1);
- strcpy (entryval_error, except.message);
+ if (except.error != NO_ENTRY_VALUE_ERROR)
+ {
+ entryval_error = (char *) alloca (strlen (except.message) + 1);
+ strcpy (entryval_error, except.message);
+ }
}
+ END_CATCH
- if (except.error == NO_ENTRY_VALUE_ERROR
- || (entryval && value_optimized_out (entryval)))
- {
- entryval = NULL;
- entryval_error = NULL;
- }
+ if (entryval != NULL && value_optimized_out (entryval))
+ entryval = NULL;
if (print_entry_values == print_entry_values_compact
|| print_entry_values == print_entry_values_default)
{
struct type *type = value_type (val);
- if (!value_optimized_out (val)
- && value_available_contents_eq (val, 0, entryval, 0,
- TYPE_LENGTH (type)))
+ if (value_lazy (val))
+ value_fetch_lazy (val);
+ if (value_lazy (entryval))
+ value_fetch_lazy (entryval);
+
+ if (value_contents_eq (val, 0, entryval, 0, TYPE_LENGTH (type)))
{
/* Initialize it just to avoid a GCC false warning. */
struct value *val_deref = NULL, *entryval_deref;
dereferenced DW_AT_GNU_call_site_data_value does not
differ. */
- TRY_CATCH (except, RETURN_MASK_ERROR)
+ TRY
{
struct type *type_deref;
/* If the reference addresses match but dereferenced
content does not match print them. */
if (val != val_deref
- && value_available_contents_eq (val_deref, 0,
- entryval_deref, 0,
- TYPE_LENGTH (type_deref)))
+ && value_contents_eq (val_deref, 0,
+ entryval_deref, 0,
+ TYPE_LENGTH (type_deref)))
+ val_equal = 1;
+ }
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ /* If the dereferenced content could not be
+ fetched do not display anything. */
+ if (except.error == NO_ENTRY_VALUE_ERROR)
val_equal = 1;
+ else if (except.message != NULL)
+ {
+ entryval_error = (char *) alloca (strlen (except.message) + 1);
+ strcpy (entryval_error, except.message);
+ }
}
+ END_CATCH
/* Value was not a reference; and its content matches. */
if (val == val_deref)
val_equal = 1;
- /* If the dereferenced content could not be fetched do not
- display anything. */
- else if (except.error == NO_ENTRY_VALUE_ERROR)
- val_equal = 1;
- else if (except.message)
- {
- entryval_error = alloca (strlen (except.message) + 1);
- strcpy (entryval_error, except.message);
- }
if (val_equal)
entryval = NULL;
{
if (print_entry_values == print_entry_values_preferred)
{
- TRY_CATCH (except, RETURN_MASK_ERROR)
+ gdb_assert (val == NULL);
+
+ TRY
{
- val = read_var_value (sym, frame);
+ val = read_var_value (sym, NULL, frame);
}
- if (!val)
+ CATCH (except, RETURN_MASK_ERROR)
{
val_error = alloca (strlen (except.message) + 1);
strcpy (val_error, except.message);
}
+ END_CATCH
}
if (print_entry_values == print_entry_values_only
|| print_entry_values == print_entry_values_both
if (func)
{
- struct block *b = SYMBOL_BLOCK_VALUE (func);
+ const struct block *b = SYMBOL_BLOCK_VALUE (func);
struct block_iterator iter;
struct symbol *sym;
struct symbol *nsym;
nsym = lookup_symbol (SYMBOL_LINKAGE_NAME (sym),
- b, VAR_DOMAIN, NULL);
+ b, VAR_DOMAIN, NULL).symbol;
gdb_assert (nsym != NULL);
if (SYMBOL_CLASS (nsym) == LOC_REGISTER
&& !SYMBOL_IS_ARGUMENT (nsym))
line is in the center of the next 'list'. */
void
-set_current_sal_from_frame (struct frame_info *frame, int center)
+set_current_sal_from_frame (struct frame_info *frame)
{
struct symtab_and_line sal;
find_frame_sal (frame, &sal);
- if (sal.symtab)
- {
- if (center)
- sal.line = max (sal.line - get_lines_to_list () / 2, 1);
- set_current_source_symtab_and_line (&sal);
- }
+ if (sal.symtab != NULL)
+ set_current_source_symtab_and_line (&sal);
}
/* If ON, GDB will display disassembly of the next source line when
do_gdb_disassembly (struct gdbarch *gdbarch,
int how_many, CORE_ADDR low, CORE_ADDR high)
{
- volatile struct gdb_exception exception;
- TRY_CATCH (exception, RETURN_MASK_ERROR)
+ TRY
{
gdb_disassembly (gdbarch, current_uiout, 0,
DISASSEMBLY_RAW_INSN, how_many,
low, high);
}
- if (exception.reason < 0)
+ CATCH (exception, RETURN_MASK_ERROR)
{
/* If an exception was thrown while doing the disassembly, print
the error message, to give the user a clue of what happened. */
exception_print (gdb_stderr, exception);
}
+ END_CATCH
}
/* Print information about frame FRAME. The output is format according
ui_out_text (uiout, "\n");
annotate_frame_end ();
+ /* If disassemble-next-line is set to auto or on output the next
+ instruction. */
+ if (disassemble_next_line == AUTO_BOOLEAN_AUTO
+ || disassemble_next_line == AUTO_BOOLEAN_TRUE)
+ do_gdb_disassembly (get_frame_arch (frame), 1,
+ get_frame_pc (frame), get_frame_pc (frame) + 1);
+
do_cleanups (uiout_cleanup);
return;
}
memset (&msymbol, 0, sizeof (msymbol));
if (msymbol.minsym != NULL
- && (SYMBOL_VALUE_ADDRESS (msymbol.minsym)
+ && (BMSYMBOL_VALUE_ADDRESS (msymbol)
> BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
{
/* We also don't know anything about the function besides
its address and name. */
func = 0;
- *funname = xstrdup (SYMBOL_PRINT_NAME (msymbol.minsym));
- *funlang = SYMBOL_LANGUAGE (msymbol.minsym);
+ *funname = xstrdup (MSYMBOL_PRINT_NAME (msymbol.minsym));
+ *funlang = MSYMBOL_LANGUAGE (msymbol.minsym);
}
else
{
msymbol = lookup_minimal_symbol_by_pc (pc);
if (msymbol.minsym != NULL)
{
- *funname = xstrdup (SYMBOL_PRINT_NAME (msymbol.minsym));
- *funlang = SYMBOL_LANGUAGE (msymbol.minsym);
+ *funname = xstrdup (MSYMBOL_PRINT_NAME (msymbol.minsym));
+ *funlang = MSYMBOL_LANGUAGE (msymbol.minsym);
}
}
}
struct gdbarch *gdbarch = get_frame_arch (frame);
int numargs;
struct cleanup *args_list_chain;
- volatile struct gdb_exception e;
if (gdbarch_frame_num_args_p (gdbarch))
{
numargs = -1;
args_list_chain = make_cleanup_ui_out_list_begin_end (uiout, "args");
- TRY_CATCH (e, RETURN_MASK_ERROR)
+ TRY
{
print_frame_args (func, frame, numargs, gdb_stdout);
}
+ CATCH (e, RETURN_MASK_ERROR)
+ {
+ }
+ END_CATCH
+
/* FIXME: ARGS must be a list. If one argument is a string it
will have " that will not be properly escaped. */
/* Invoke ui_out_tuple_end. */
struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
CORE_ADDR frame_pc;
int frame_pc_p;
- CORE_ADDR caller_pc;
+ /* Initialize it to avoid "may be used uninitialized" warning. */
+ CORE_ADDR caller_pc = 0;
+ int caller_pc_p = 0;
fi = parse_frame_specification_1 (addr_exp, "No stack.", &selected_frame_p);
gdbarch = get_frame_arch (fi);
msymbol = lookup_minimal_symbol_by_pc (frame_pc);
if (msymbol.minsym != NULL)
{
- funname = SYMBOL_PRINT_NAME (msymbol.minsym);
- funlang = SYMBOL_LANGUAGE (msymbol.minsym);
+ funname = MSYMBOL_PRINT_NAME (msymbol.minsym);
+ funlang = MSYMBOL_LANGUAGE (msymbol.minsym);
}
}
calling_frame_info = get_prev_frame (fi);
sal.line);
puts_filtered ("; ");
wrap_here (" ");
- printf_filtered ("saved %s ", pc_regname);
- if (frame_unwind_caller_pc_if_available (fi, &caller_pc))
+ printf_filtered ("saved %s = ", pc_regname);
+
+ TRY
+ {
+ caller_pc = frame_unwind_caller_pc (fi);
+ caller_pc_p = 1;
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ switch (ex.error)
+ {
+ case NOT_AVAILABLE_ERROR:
+ val_print_unavailable (gdb_stdout);
+ break;
+ case OPTIMIZED_OUT_ERROR:
+ val_print_not_saved (gdb_stdout);
+ break;
+ default:
+ fprintf_filtered (gdb_stdout, _("<error: %s>"), ex.message);
+ break;
+ }
+ }
+ END_CATCH
+
+ if (caller_pc_p)
fputs_filtered (paddress (gdbarch, caller_pc), gdb_stdout);
- else
- fputs_filtered ("<unavailable>", gdb_stdout);
printf_filtered ("\n");
if (calling_frame_info == NULL)
reason = get_frame_unwind_stop_reason (fi);
if (reason != UNWIND_NO_REASON)
printf_filtered (_(" Outermost frame: %s\n"),
- frame_stop_reason_string (reason));
+ frame_stop_reason_string (fi));
}
else if (get_frame_type (fi) == TAILCALL_FRAME)
puts_filtered (" tail call frame");
int i;
struct frame_info *trailing;
int trailing_level, py_start = 0, py_end = 0;
- enum py_bt_status result = PY_BT_ERROR;
+ enum ext_lang_bt_status result = EXT_LANG_BT_ERROR;
if (!target_has_stack)
error (_("No stack."));
QUIT;
pc = get_frame_address_in_block (fi);
- find_pc_sect_symtab_via_partial (pc, find_pc_mapped_section (pc));
+ expand_symtab_containing_pc (pc, find_pc_mapped_section (pc));
}
}
if (! no_filters)
{
int flags = PRINT_LEVEL | PRINT_FRAME_INFO | PRINT_ARGS;
- enum py_frame_args arg_type;
+ enum ext_lang_frame_args arg_type;
if (show_locals)
flags |= PRINT_LOCALS;
else
arg_type = NO_VALUES;
- result = apply_frame_filter (get_current_frame (), flags, arg_type,
- current_uiout, py_start, py_end);
-
+ result = apply_ext_lang_frame_filter (get_current_frame (), flags,
+ arg_type, current_uiout,
+ py_start, py_end);
}
+
/* Run the inbuilt backtrace if there are no filters registered, or
"no-filters" has been specified from the command. */
- if (no_filters || result == PY_BT_NO_FILTERS)
+ if (no_filters || result == EXT_LANG_BT_NO_FILTERS)
{
for (i = 0, fi = trailing; fi && count--; i++, fi = get_prev_frame (fi))
{
reason = get_frame_unwind_stop_reason (trailing);
if (reason >= UNWIND_FIRST_ERROR)
printf_filtered (_("Backtrace stopped: %s\n"),
- frame_stop_reason_string (reason));
+ frame_stop_reason_string (trailing));
}
}
}
do_cleanups (old_chain);
}
-static void
-backtrace_full_command (char *arg, int from_tty)
-{
- backtrace_command_1 (arg, 1 /* show_locals */, 0, from_tty);
-}
-\f
-
/* Iterate over the local variables of a block B, calling CB with
CB_DATA. */
static void
-iterate_over_block_locals (struct block *b,
+iterate_over_block_locals (const struct block *b,
iterate_over_block_arg_local_vars_cb cb,
void *cb_data)
{
superblocks, stopping when the top-level block is reached. */
void
-iterate_over_block_local_vars (struct block *block,
+iterate_over_block_local_vars (const struct block *block,
iterate_over_block_arg_local_vars_cb cb,
void *cb_data)
{
struct ui_file *stream)
{
struct print_variable_and_value_data cb_data;
- struct block *block;
+ const struct block *block;
CORE_ADDR pc;
if (!get_frame_pc_if_available (frame, &pc))
Returns 1 if any argument was walked; 0 otherwise. */
void
-iterate_over_block_arg_vars (struct block *b,
+iterate_over_block_arg_vars (const struct block *b,
iterate_over_block_arg_local_vars_cb cb,
void *cb_data)
{
are not combined in symbol-reading. */
sym2 = lookup_symbol (SYMBOL_LINKAGE_NAME (sym),
- b, VAR_DOMAIN, NULL);
+ b, VAR_DOMAIN, NULL).symbol;
(*cb) (SYMBOL_PRINT_NAME (sym), sym2, cb_data);
}
}
gdb_stdout);
}
-
-static void
-args_plus_locals_info (char *ignore, int from_tty)
-{
- args_info (ignore, from_tty);
- locals_info (ignore, from_tty);
-}
-\f
-
/* Select frame FRAME. Also print the stack frame and show the source
if this is the tui version. */
static void
code address within the block returned. We use this to decide
which macros are in scope. */
-struct block *
+const struct block *
get_selected_block (CORE_ADDR *addr_in_block)
{
if (!has_stack_frames ())
print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
}
-/* The XDB Compatibility command to print the current frame. */
-
-static void
-current_frame_command (char *level_exp, int from_tty)
-{
- print_stack_frame (get_selected_frame (_("No stack.")), 1, SRC_AND_LOC, 1);
-}
-
/* Select the frame up one or COUNT_EXP stack levels from the
previously selected frame, and print it briefly. */
static void
-up_silently_base (char *count_exp)
+up_silently_base (const char *count_exp)
{
struct frame_info *frame;
int count = 1;
selected frame, and print it briefly. */
static void
-down_silently_base (char *count_exp)
+down_silently_base (const char *count_exp)
{
struct frame_info *frame;
int count = -1;
return_type = value_type (return_value);
}
do_cleanups (old_chain);
- CHECK_TYPEDEF (return_type);
+ return_type = check_typedef (return_type);
return_value = value_cast (return_type, return_value);
/* Make sure the value is fully evaluated. It may live in the
value_fetch_lazy (return_value);
if (thisfun != NULL)
- function = read_var_value (thisfun, thisframe);
+ function = read_var_value (thisfun, NULL, thisframe);
rv_conv = RETURN_VALUE_REGISTER_CONVENTION;
if (TYPE_CODE (return_type) == TYPE_CODE_VOID)
confirmed = query (_("%sMake selected stack frame return now? "),
query_prefix);
else
- confirmed = query (_("%sMake %s return now? "), query_prefix,
- SYMBOL_PRINT_NAME (thisfun));
+ {
+ if (TYPE_NO_RETURN (thisfun->type))
+ warning (_("Function does not return normally to caller."));
+ confirmed = query (_("%sMake %s return now? "), query_prefix,
+ SYMBOL_PRINT_NAME (thisfun));
+ }
if (!confirmed)
error (_("Not confirmed"));
}
frame = parse_frame_specification ("0");
sals = decode_line_with_current_source (arg, DECODE_LINE_FUNFIRSTLINE);
cleanups = make_cleanup (xfree, sals.sals);
- func_bounds = (struct function_bounds *) xmalloc (
- sizeof (struct function_bounds) * sals.nelts);
+ func_bounds = XNEWVEC (struct function_bounds, sals.nelts);
make_cleanup (xfree, func_bounds);
for (i = 0; (i < sals.nelts && !found); i++)
{
else if (frame != get_selected_frame (NULL))
select_and_print_frame (frame);
}
-
-/* Gets the language of the current frame. */
-
-enum language
-get_frame_language (void)
-{
- struct frame_info *frame = deprecated_safe_get_selected_frame ();
-
- if (frame)
- {
- volatile struct gdb_exception ex;
- CORE_ADDR pc = 0;
- struct symtab *s;
-
- /* We determine the current frame language by looking up its
- associated symtab. To retrieve this symtab, we use the frame
- PC. However we cannot use the frame PC as is, because it
- usually points to the instruction following the "call", which
- is sometimes the first instruction of another function. So
- we rely on get_frame_address_in_block(), it provides us with
- a PC that is guaranteed to be inside the frame's code
- block. */
-
- TRY_CATCH (ex, RETURN_MASK_ERROR)
- {
- pc = get_frame_address_in_block (frame);
- }
- if (ex.reason < 0)
- {
- if (ex.error != NOT_AVAILABLE_ERROR)
- throw_exception (ex);
- }
- else
- {
- s = find_pc_symtab (pc);
- if (s != NULL)
- return s->language;
- }
- }
-
- return language_unknown;
-}
\f
/* Provide a prototype to silence -Wmissing-prototypes. */
add_com_alias ("f", "frame", class_stack, 1);
- if (xdb_commands)
- {
- add_com ("L", class_stack, current_frame_command,
- _("Print the current stack frame.\n"));
- add_com_alias ("V", "frame", class_stack, 1);
- }
add_com ("select-frame", class_stack, select_frame_command, _("\
Select a stack frame without printing anything.\n\
An argument specifies the frame to select.\n\
Use of the 'no-filters' qualifier prohibits frame filters from executing\n\
on this backtrace.\n"));
add_com_alias ("bt", "backtrace", class_stack, 0);
- if (xdb_commands)
- {
- add_com_alias ("t", "backtrace", class_stack, 0);
- add_com ("T", class_stack, backtrace_full_command, _("\
-Print backtrace of all stack frames, or innermost COUNT frames\n\
-and the values of the local variables.\n\
-With a negative argument, print outermost -COUNT frames.\n\
-Usage: T <count>\n"));
- }
add_com_alias ("where", "backtrace", class_alias, 0);
add_info ("stack", backtrace_command,
_("Local variables of current stack frame."));
add_info ("args", args_info,
_("Argument variables of current stack frame."));
- if (xdb_commands)
- add_com ("l", class_info, args_plus_locals_info,
- _("Argument and local variables of current stack frame."));
if (dbx_commands)
add_com ("func", class_stack, func_command, _("\