#include "valprint.h"
#include "gdbthread.h"
#include "cp-support.h"
+#include "disasm.h"
#include "gdb_assert.h"
#include <ctype.h>
static const char *print_frame_arguments_choices[] =
{"all", "scalars", "none", NULL};
-static const char *print_frame_arguments = "all";
+static const char *print_frame_arguments = "scalars";
/* Prototypes for local functions. */
}
}
-/* Return non-zero if the debugger should print the value of the provided
- symbol parameter (SYM). */
-
-static int
-print_this_frame_argument_p (struct symbol *sym)
-{
- struct type *type;
-
- /* If the user asked to print no argument at all, then obviously
- do not print this argument. */
-
- if (strcmp (print_frame_arguments, "none") == 0)
- return 0;
-
- /* If the user asked to print all arguments, then we should print
- that one. */
-
- if (strcmp (print_frame_arguments, "all") == 0)
- return 1;
-
- /* The user asked to print only the scalar arguments, so do not
- print the non-scalar ones. */
-
- type = CHECK_TYPEDEF (SYMBOL_TYPE (sym));
- while (TYPE_CODE (type) == TYPE_CODE_REF)
- type = CHECK_TYPEDEF (TYPE_TARGET_TYPE (type));
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_ARRAY:
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
- case TYPE_CODE_SET:
- case TYPE_CODE_STRING:
- case TYPE_CODE_BITSTRING:
- return 0;
- default:
- return 1;
- }
-}
-
/* Print the arguments of frame FRAME on STREAM, given the function
FUNC running in that frame (as a symbol), where NUM is the number
of arguments according to the stack frame (or -1 if the number of
int args_printed = 0;
struct cleanup *old_chain, *list_chain;
struct ui_stream *stb;
+ /* True if we should print arguments, false otherwise. */
+ int print_args = strcmp (print_frame_arguments, "none");
+ /* True in "summary" mode, false otherwise. */
+ int summary = !strcmp (print_frame_arguments, "scalars");
stb = ui_out_stream_new (uiout);
old_chain = make_cleanup_ui_out_stream_delete (stb);
annotate_arg_name_end ();
ui_out_text (uiout, "=");
- if (print_this_frame_argument_p (sym))
+ if (print_args)
{
/* Avoid value_print because it will deref ref parameters.
We just want to print their addresses. Print ??? for
get_raw_print_options (&opts);
opts.deref_ref = 0;
- common_val_print (val, stb->stream, 2,
- &opts, language);
+ opts.summary = summary;
+ common_val_print (val, stb->stream, 2, &opts, language);
ui_out_field_stream (uiout, "value", stb);
}
else
}
}
+/* If ON, GDB will display disassembly of the next source line when
+ execution of the program being debugged stops.
+ If AUTO (which is the default), or there's no line info to determine
+ the source line of the next instruction, display disassembly of next
+ instruction instead. */
+
+static enum auto_boolean disassemble_next_line;
+
+static void
+show_disassemble_next_line (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ fprintf_filtered (file, _("\
+Debugger's willingness to use disassemble-next-line is %s.\n"),
+ value);
+}
+
+/* Show assembly codes; stub for catch_errors. */
+
+struct gdb_disassembly_stub_args
+{
+ int how_many;
+ CORE_ADDR low;
+ CORE_ADDR high;
+};
+
+static void
+gdb_disassembly_stub (void *args)
+{
+ struct gdb_disassembly_stub_args *p = args;
+ gdb_disassembly (uiout, 0, 0, p->how_many, p->low, p->high);
+}
+
+/* Use TRY_CATCH to catch the exception from the gdb_disassembly
+ because it will be broken by filter sometime. */
+
+static void
+do_gdb_disassembly (int how_many, CORE_ADDR low, CORE_ADDR high)
+{
+ volatile struct gdb_exception exception;
+ struct gdb_disassembly_stub_args args;
+
+ args.how_many = how_many;
+ args.low = low;
+ args.high = high;
+ TRY_CATCH (exception, RETURN_MASK_ALL)
+ {
+ gdb_disassembly_stub (&args);
+ }
+ /* If an exception was thrown while doing the disassembly, print
+ the error message, to give the user a clue of what happened. */
+ if (exception.reason == RETURN_ERROR)
+ exception_print (gdb_stderr, exception);
+}
+
/* Print information about frame FRAME. The output is format according
to PRINT_LEVEL and PRINT_WHAT and PRINT ARGS. The meaning of
PRINT_WHAT is:
source_print = (print_what == SRC_LINE || print_what == SRC_AND_LOC);
+ /* If disassemble-next-line is set to auto or on and doesn't have
+ the line debug messages for $pc, output the next instruction. */
+ if ((disassemble_next_line == AUTO_BOOLEAN_AUTO
+ || disassemble_next_line == AUTO_BOOLEAN_TRUE)
+ && source_print && !sal.symtab)
+ do_gdb_disassembly (1, get_frame_pc (frame), get_frame_pc (frame) + 1);
+
if (source_print && sal.symtab)
{
int done = 0;
print_source_lines (sal.symtab, sal.line, sal.line + 1, 0);
}
}
+
+ /* If disassemble-next-line is set to on and there is line debug
+ messages, output assembly codes for next line. */
+ if (disassemble_next_line == AUTO_BOOLEAN_TRUE)
+ do_gdb_disassembly (-1, get_frame_pc (frame), sal.end);
}
if (print_what != LOCATION)
gdb_flush (gdb_stdout);
}
-static void
-print_frame (struct frame_info *frame, int print_level,
- enum print_what print_what, int print_args,
- struct symtab_and_line sal)
+/* Attempt to obtain the FUNNAME and FUNLANG of the function corresponding
+ to FRAME. */
+void
+find_frame_funname (struct frame_info *frame, char **funname,
+ enum language *funlang)
{
struct symbol *func;
- char *funname = NULL;
- enum language funlang = language_unknown;
- struct ui_stream *stb;
- struct cleanup *old_chain, *list_chain;
- struct value_print_options opts;
- stb = ui_out_stream_new (uiout);
- old_chain = make_cleanup_ui_out_stream_delete (stb);
+ *funname = NULL;
+ *funlang = language_unknown;
func = find_pc_function (get_frame_address_in_block (frame));
if (func)
/* We also don't know anything about the function besides
its address and name. */
func = 0;
- funname = SYMBOL_PRINT_NAME (msymbol);
- funlang = SYMBOL_LANGUAGE (msymbol);
+ *funname = SYMBOL_PRINT_NAME (msymbol);
+ *funlang = SYMBOL_LANGUAGE (msymbol);
}
else
{
- funname = SYMBOL_PRINT_NAME (func);
- funlang = SYMBOL_LANGUAGE (func);
- if (funlang == language_cplus)
+ *funname = SYMBOL_PRINT_NAME (func);
+ *funlang = SYMBOL_LANGUAGE (func);
+ if (*funlang == language_cplus)
{
/* It seems appropriate to use SYMBOL_PRINT_NAME() here,
to display the demangled name that we already have
stored in the symbol table, but we stored a version
with DMGL_PARAMS turned on, and here we don't want to
display parameters. So remove the parameters. */
- char *func_only = cp_remove_params (funname);
+ char *func_only = cp_remove_params (*funname);
if (func_only)
{
- funname = func_only;
+ *funname = func_only;
make_cleanup (xfree, func_only);
}
}
if (msymbol != NULL)
{
- funname = SYMBOL_PRINT_NAME (msymbol);
- funlang = SYMBOL_LANGUAGE (msymbol);
+ *funname = SYMBOL_PRINT_NAME (msymbol);
+ *funlang = SYMBOL_LANGUAGE (msymbol);
}
}
+}
+
+static void
+print_frame (struct frame_info *frame, int print_level,
+ enum print_what print_what, int print_args,
+ struct symtab_and_line sal)
+{
+ char *funname = NULL;
+ enum language funlang = language_unknown;
+ struct ui_stream *stb;
+ struct cleanup *old_chain, *list_chain;
+ struct value_print_options opts;
+
+ stb = ui_out_stream_new (uiout);
+ old_chain = make_cleanup_ui_out_stream_delete (stb);
+
+ find_frame_funname (frame, &funname, &funlang);
annotate_frame_begin (print_level ? frame_relative_level (frame) : 0,
get_frame_pc (frame));
struct print_args_args args;
struct cleanup *args_list_chain;
args.frame = frame;
- args.func = func;
+ args.func = find_pc_function (get_frame_address_in_block (frame));
args.stream = gdb_stdout;
args_list_chain = make_cleanup_ui_out_list_begin_end (uiout, "args");
catch_errors (print_args_stub, &args, "", RETURN_MASK_ERROR);
#ifdef PC_SOLIB
char *lib = PC_SOLIB (get_frame_pc (frame));
#else
- char *lib = solib_address (get_frame_pc (frame));
+ char *lib = solib_name_from_address (get_frame_pc (frame));
#endif
if (lib)
{
struct block *
get_selected_block (CORE_ADDR *addr_in_block)
{
- if (!target_has_stack)
- return 0;
-
- if (is_exited (inferior_ptid))
- return 0;
-
- if (is_executing (inferior_ptid))
+ if (!has_stack_frames ())
return 0;
return get_frame_block (get_selected_frame (NULL), addr_in_block);
return_command (char *retval_exp, int from_tty)
{
struct frame_info *thisframe;
+ struct gdbarch *gdbarch;
struct symbol *thisfun;
struct value *return_value = NULL;
const char *query_prefix = "";
thisframe = get_selected_frame ("No selected frame.");
thisfun = get_frame_function (thisframe);
+ gdbarch = get_frame_arch (thisframe);
/* Compute the return value. If the computation triggers an error,
let it bail. If the return type can't be handled, set
message. */
if (retval_exp)
{
+ struct expression *retval_expr = parse_expression (retval_exp);
+ struct cleanup *old_chain = make_cleanup (xfree, retval_expr);
struct type *return_type = NULL;
/* Compute the return value. Should the computation fail, this
call throws an error. */
- return_value = parse_and_eval (retval_exp);
+ return_value = evaluate_expression (retval_expr);
/* Cast return value to the return type of the function. Should
the cast fail, this call throws an error. */
if (thisfun != NULL)
return_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (thisfun));
if (return_type == NULL)
- return_type = builtin_type (get_frame_arch (thisframe))->builtin_int;
+ {
+ if (retval_expr->elts[0].opcode != UNOP_CAST)
+ error (_("Return value type not available for selected "
+ "stack frame.\n"
+ "Please use an explicit cast of the value to return."));
+ return_type = value_type (return_value);
+ }
+ do_cleanups (old_chain);
CHECK_TYPEDEF (return_type);
return_value = value_cast (return_type, return_value);
is discarded, side effects such as "return i++" still
occur. */
return_value = NULL;
- else if (using_struct_return (SYMBOL_TYPE (thisfun), return_type))
+ else if (thisfun != NULL
+ && using_struct_return (gdbarch,
+ SYMBOL_TYPE (thisfun), return_type))
{
query_prefix = "\
The location at which to store the function's return value is unknown.\n\
{
struct type *return_type = value_type (return_value);
struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ());
- gdb_assert (gdbarch_return_value (gdbarch, SYMBOL_TYPE (thisfun),
- return_type, NULL, NULL, NULL)
+ struct type *func_type = thisfun == NULL ? NULL : SYMBOL_TYPE (thisfun);
+
+ gdb_assert (gdbarch_return_value (gdbarch, func_type, return_type, NULL,
+ NULL, NULL)
== RETURN_VALUE_REGISTER_CONVENTION);
- gdbarch_return_value (gdbarch, SYMBOL_TYPE (thisfun), return_type,
+ gdbarch_return_value (gdbarch, func_type, return_type,
get_current_regcache (), NULL /*read*/,
value_contents (return_value) /*write*/);
}
_("Show printing of non-scalar frame arguments"),
NULL, NULL, NULL, &setprintlist, &showprintlist);
+ add_setshow_auto_boolean_cmd ("disassemble-next-line", class_stack,
+ &disassemble_next_line, _("\
+Set whether to disassemble next source line or insn when execution stops."), _("\
+Show whether to disassemble next source line or insn when execution stops."), _("\
+If ON, GDB will display disassembly of the next source line, in addition\n\
+to displaying the source line itself. If the next source line cannot\n\
+be displayed (e.g., source is unavailable or there's no line info), GDB\n\
+will display disassembly of next instruction instead of showing the\n\
+source line.\n\
+If AUTO, display disassembly of next instruction only if the source line\n\
+cannot be displayed.\n\
+If OFF (which is the default), never display the disassembly of the next\n\
+source line."),
+ NULL,
+ show_disassemble_next_line,
+ &setlist, &showlist);
+ disassemble_next_line = AUTO_BOOLEAN_FALSE;
+
#if 0
add_cmd ("backtrace-limit", class_stack, set_backtrace_limit_command, _(\
"Specify maximum number of frames for \"backtrace\" to print by default."),