X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fstack.c;h=830fd41c7cf1815af0668001dc751985808c42f0;hb=53a71c068156f7c35e07ddd5c0cce97bf98c025c;hp=d0ea3bf8330a1e7ad3aae069261a275bf4ddd9db;hpb=61ff14c69a7cb2870f9dd2792690a1fbc8967f29;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/stack.c b/gdb/stack.c index d0ea3bf833..830fd41c7c 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -2,7 +2,7 @@ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, - 2009 Free Software Foundation, Inc. + 2009, 2010 Free Software Foundation, Inc. This file is part of GDB. @@ -45,11 +45,16 @@ #include "valprint.h" #include "gdbthread.h" #include "cp-support.h" +#include "disasm.h" +#include "inline-frame.h" #include "gdb_assert.h" #include #include "gdb_string.h" +#include "psymtab.h" +#include "symfile.h" + void (*deprecated_selected_frame_level_changed_hook) (int); /* The possible choices of "set print frame-arguments, and the value @@ -57,7 +62,7 @@ void (*deprecated_selected_frame_level_changed_hook) (int); 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. */ @@ -98,6 +103,30 @@ print_stack_frame_stub (void *args) return 0; } +/* Return 1 if we should display the address in addition to the location, + because we are in the middle of a statement. */ + +static int +frame_show_address (struct frame_info *frame, + struct symtab_and_line sal) +{ + /* If there is a line number, but no PC, then there is no location + information associated with this sal. The only way that should + happen is for the call sites of inlined functions (SAL comes from + find_frame_sal). Otherwise, we would have some PC range if the + SAL came from a line table. */ + if (sal.line != 0 && sal.pc == 0 && sal.end == 0) + { + if (get_next_frame (frame) == NULL) + gdb_assert (inline_skipped_frames (inferior_ptid) > 0); + else + gdb_assert (get_frame_type (get_next_frame (frame)) == INLINE_FRAME); + return 0; + } + + return get_frame_pc (frame) != sal.pc; +} + /* Show or print a stack frame FRAME briefly. The output is format according to PRINT_LEVEL and PRINT_WHAT printing the frame's relative level, function name, argument list, and file name and @@ -138,6 +167,8 @@ static void print_frame_nameless_args (struct frame_info *frame, long start, int num, int first, struct ui_file *stream) { + struct gdbarch *gdbarch = get_frame_arch (frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int i; CORE_ADDR argsaddr; long arg_value; @@ -148,7 +179,8 @@ print_frame_nameless_args (struct frame_info *frame, long start, int num, argsaddr = get_frame_args_address (frame); if (!argsaddr) return; - arg_value = read_memory_integer (argsaddr + start, sizeof (int)); + arg_value = read_memory_integer (argsaddr + start, + sizeof (int), byte_order); if (!first) fprintf_filtered (stream, ", "); fprintf_filtered (stream, "%ld", arg_value); @@ -157,46 +189,6 @@ print_frame_nameless_args (struct frame_info *frame, long start, int num, } } -/* 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 @@ -219,6 +211,10 @@ print_frame_args (struct symbol *func, struct frame_info *frame, 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); @@ -291,6 +287,7 @@ print_frame_args (struct symbol *func, struct frame_info *frame, if (*SYMBOL_LINKAGE_NAME (sym)) { struct symbol *nsym; + nsym = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), b, VAR_DOMAIN, NULL); gdb_assert (nsym != NULL); @@ -353,7 +350,7 @@ print_frame_args (struct symbol *func, struct frame_info *frame, 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 @@ -380,8 +377,8 @@ print_frame_args (struct symbol *func, struct frame_info *frame, 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 @@ -456,6 +453,68 @@ set_current_sal_from_frame (struct frame_info *frame, int center) } } +/* 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 +{ + struct gdbarch *gdbarch; + 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 (p->gdbarch, uiout, 0, + DISASSEMBLY_RAW_INSN, 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 (struct gdbarch *gdbarch, + int how_many, CORE_ADDR low, CORE_ADDR high) +{ + volatile struct gdb_exception exception; + struct gdb_disassembly_stub_args args; + + args.gdbarch = gdbarch; + 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: @@ -471,18 +530,20 @@ void print_frame_info (struct frame_info *frame, int print_level, enum print_what print_what, int print_args) { + struct gdbarch *gdbarch = get_frame_arch (frame); struct symtab_and_line sal; int source_print; int location_print; if (get_frame_type (frame) == DUMMY_FRAME - || get_frame_type (frame) == SIGTRAMP_FRAME) + || get_frame_type (frame) == SIGTRAMP_FRAME + || get_frame_type (frame) == ARCH_FRAME) { struct cleanup *uiout_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, "frame"); annotate_frame_begin (print_level ? frame_relative_level (frame) : 0, - get_frame_pc (frame)); + gdbarch, get_frame_pc (frame)); /* Do this regardless of SOURCE because we don't have any source to list for this frame. */ @@ -495,7 +556,8 @@ print_frame_info (struct frame_info *frame, int print_level, if (ui_out_is_mi_like_p (uiout)) { annotate_frame_address (); - ui_out_field_core_addr (uiout, "addr", get_frame_pc (frame)); + ui_out_field_core_addr (uiout, "addr", + gdbarch, get_frame_pc (frame)); annotate_frame_address_end (); } @@ -509,6 +571,10 @@ print_frame_info (struct frame_info *frame, int print_level, annotate_signal_handler_caller (); ui_out_field_string (uiout, "func", ""); } + else if (get_frame_type (frame) == ARCH_FRAME) + { + ui_out_field_string (uiout, "func", ""); + } ui_out_text (uiout, "\n"); annotate_frame_end (); @@ -533,11 +599,19 @@ print_frame_info (struct frame_info *frame, int print_level, 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 (get_frame_arch (frame), 1, + get_frame_pc (frame), get_frame_pc (frame) + 1); + if (source_print && sal.symtab) { int done = 0; int mid_statement = ((print_what == SRC_LINE) - && (get_frame_pc (frame) != sal.pc)); + && frame_show_address (frame, sal)); if (annotation_level) done = identify_source_line (sal.symtab, sal.line, mid_statement, @@ -551,6 +625,7 @@ print_frame_info (struct frame_info *frame, int print_level, else { struct value_print_options opts; + get_user_print_options (&opts); /* We used to do this earlier, but that is clearly wrong. This function is used by many different @@ -562,39 +637,42 @@ print_frame_info (struct frame_info *frame, int print_level, ability to decide for themselves if it is desired. */ if (opts.addressprint && mid_statement) { - ui_out_field_core_addr (uiout, "addr", get_frame_pc (frame)); + ui_out_field_core_addr (uiout, "addr", + gdbarch, get_frame_pc (frame)); ui_out_text (uiout, "\t"); } 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 (get_frame_arch (frame), -1, sal.pc, sal.end); } if (print_what != LOCATION) - set_default_breakpoint (1, get_frame_pc (frame), sal.symtab, sal.line); + set_default_breakpoint (1, sal.pspace, + get_frame_pc (frame), sal.symtab, sal.line); annotate_frame_end (); 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)); + func = get_frame_function (frame); if (func) { /* In certain pathological cases, the symtabs give the wrong @@ -615,8 +693,13 @@ print_frame (struct frame_info *frame, int print_level, changed (and we'll create a find_pc_minimal_function or some such). */ - struct minimal_symbol *msymbol = - lookup_minimal_symbol_by_pc (get_frame_address_in_block (frame)); + struct minimal_symbol *msymbol = NULL; + + /* Don't attempt to do this for inlined functions, which do not + have a corresponding minimal symbol. */ + if (!block_inlined_p (SYMBOL_BLOCK_VALUE (func))) + msymbol + = lookup_minimal_symbol_by_pc (get_frame_address_in_block (frame)); if (msymbol != NULL && (SYMBOL_VALUE_ADDRESS (msymbol) @@ -625,24 +708,25 @@ print_frame (struct frame_info *frame, int print_level, /* 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); } } @@ -655,13 +739,31 @@ print_frame (struct frame_info *frame, int print_level, 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) +{ + struct gdbarch *gdbarch = get_frame_arch (frame); + 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)); + gdbarch, get_frame_pc (frame)); list_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "frame"); @@ -673,11 +775,11 @@ print_frame (struct frame_info *frame, int print_level, } get_user_print_options (&opts); if (opts.addressprint) - if (get_frame_pc (frame) != sal.pc || !sal.symtab + if (frame_show_address (frame, sal) || !sal.symtab || print_what == LOC_AND_ADDRESS) { annotate_frame_address (); - ui_out_field_core_addr (uiout, "addr", get_frame_pc (frame)); + ui_out_field_core_addr (uiout, "addr", gdbarch, get_frame_pc (frame)); annotate_frame_address_end (); ui_out_text (uiout, " in "); } @@ -693,8 +795,9 @@ print_frame (struct frame_info *frame, int print_level, { 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); @@ -715,6 +818,7 @@ print_frame (struct frame_info *frame, int print_level, if (ui_out_is_mi_like_p (uiout)) { const char *fullname = symtab_to_fullname (sal.symtab); + if (fullname != NULL) ui_out_field_string (uiout, "fullname", fullname); } @@ -730,7 +834,8 @@ print_frame (struct frame_info *frame, int print_level, #ifdef PC_SOLIB char *lib = PC_SOLIB (get_frame_pc (frame)); #else - char *lib = solib_name_from_address (get_frame_pc (frame)); + char *lib = solib_name_from_address (get_frame_program_space (frame), + get_frame_pc (frame)); #endif if (lib) { @@ -766,9 +871,6 @@ parse_frame_specification_1 (const char *frame_exp, const char *message, numargs = 0; else { - char *addr_string; - struct cleanup *tmp_cleanup; - numargs = 0; while (1) { @@ -822,6 +924,7 @@ parse_frame_specification_1 (const char *frame_exp, const char *message, { struct frame_info *fid; int level = value_as_long (args[0]); + fid = find_relative_frame (get_current_frame (), &level); if (level == 0) /* find_relative_frame was successful */ @@ -831,6 +934,7 @@ parse_frame_specification_1 (const char *frame_exp, const char *message, /* Convert each value into a corresponding address. */ { int i; + for (i = 0; i < numargs; i++) addrs[i] = value_as_address (args[i]); } @@ -853,8 +957,16 @@ parse_frame_specification_1 (const char *frame_exp, const char *message, { if (frame_id_eq (id, get_frame_id (fid))) { - while (frame_id_eq (id, frame_unwind_id (fid))) - fid = get_prev_frame (fid); + struct frame_info *prev_frame; + + while (1) + { + prev_frame = get_prev_frame (fid); + if (!prev_frame + || !frame_id_eq (id, get_frame_id (prev_frame))) + break; + fid = prev_frame; + } return fid; } } @@ -887,7 +999,7 @@ frame_info (char *addr_exp, int from_tty) struct symbol *func; struct symtab *s; struct frame_info *calling_frame_info; - int i, count, numregs; + int numregs; char *funname = 0; enum language funlang = language_unknown; const char *pc_regname; @@ -929,6 +1041,7 @@ frame_info (char *addr_exp, int from_tty) 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); + if (func_only) { funname = func_only; @@ -958,10 +1071,10 @@ frame_info (char *addr_exp, int from_tty) { printf_filtered (_("Stack frame at ")); } - fputs_filtered (paddress (get_frame_base (fi)), gdb_stdout); + fputs_filtered (paddress (gdbarch, get_frame_base (fi)), gdb_stdout); printf_filtered (":\n"); printf_filtered (" %s = ", pc_regname); - fputs_filtered (paddress (get_frame_pc (fi)), gdb_stdout); + fputs_filtered (paddress (gdbarch, get_frame_pc (fi)), gdb_stdout); wrap_here (" "); if (funname) @@ -976,7 +1089,7 @@ frame_info (char *addr_exp, int from_tty) puts_filtered ("; "); wrap_here (" "); printf_filtered ("saved %s ", pc_regname); - fputs_filtered (paddress (frame_pc_unwind (fi)), gdb_stdout); + fputs_filtered (paddress (gdbarch, frame_unwind_caller_pc (fi)), gdb_stdout); printf_filtered ("\n"); if (calling_frame_info == NULL) @@ -988,11 +1101,13 @@ frame_info (char *addr_exp, int from_tty) printf_filtered (_(" Outermost frame: %s\n"), frame_stop_reason_string (reason)); } - - if (calling_frame_info) + else if (get_frame_type (fi) == INLINE_FRAME) + printf_filtered (" inlined into frame %d", + frame_relative_level (get_prev_frame (fi))); + else { printf_filtered (" called by frame at "); - fputs_filtered (paddress (get_frame_base (calling_frame_info)), + fputs_filtered (paddress (gdbarch, get_frame_base (calling_frame_info)), gdb_stdout); } if (get_next_frame (fi) && calling_frame_info) @@ -1001,7 +1116,7 @@ frame_info (char *addr_exp, int from_tty) if (get_next_frame (fi)) { printf_filtered (" caller of frame at "); - fputs_filtered (paddress (get_frame_base (get_next_frame (fi))), + fputs_filtered (paddress (gdbarch, get_frame_base (get_next_frame (fi))), gdb_stdout); } if (get_next_frame (fi) || calling_frame_info) @@ -1022,7 +1137,7 @@ frame_info (char *addr_exp, int from_tty) else { printf_filtered (" Arglist at "); - fputs_filtered (paddress (arg_list), gdb_stdout); + fputs_filtered (paddress (gdbarch, arg_list), gdb_stdout); printf_filtered (","); if (!gdbarch_frame_num_args_p (gdbarch)) @@ -1054,7 +1169,7 @@ frame_info (char *addr_exp, int from_tty) else { printf_filtered (" Locals at "); - fputs_filtered (paddress (arg_list), gdb_stdout); + fputs_filtered (paddress (gdbarch, arg_list), gdb_stdout); printf_filtered (","); } } @@ -1084,26 +1199,27 @@ frame_info (char *addr_exp, int from_tty) &realnum, NULL); if (!optimized && lval == not_lval) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + int sp_size = register_size (gdbarch, gdbarch_sp_regnum (gdbarch)); gdb_byte value[MAX_REGISTER_SIZE]; CORE_ADDR sp; + frame_register_unwind (fi, gdbarch_sp_regnum (gdbarch), &optimized, &lval, &addr, &realnum, value); /* NOTE: cagney/2003-05-22: This is assuming that the stack pointer was packed as an unsigned integer. That may or may not be valid. */ - sp = extract_unsigned_integer (value, - register_size (gdbarch, - gdbarch_sp_regnum (gdbarch))); + sp = extract_unsigned_integer (value, sp_size, byte_order); printf_filtered (" Previous frame's sp is "); - fputs_filtered (paddress (sp), gdb_stdout); + fputs_filtered (paddress (gdbarch, sp), gdb_stdout); printf_filtered ("\n"); need_nl = 0; } else if (!optimized && lval == lval_memory) { printf_filtered (" Previous frame's sp at "); - fputs_filtered (paddress (addr), gdb_stdout); + fputs_filtered (paddress (gdbarch, addr), gdb_stdout); printf_filtered ("\n"); need_nl = 0; } @@ -1138,7 +1254,7 @@ frame_info (char *addr_exp, int from_tty) wrap_here (" "); printf_filtered (" %s at ", gdbarch_register_name (gdbarch, i)); - fputs_filtered (paddress (addr), gdb_stdout); + fputs_filtered (paddress (gdbarch, addr), gdb_stdout); count++; } } @@ -1170,11 +1286,6 @@ backtrace_command_1 (char *count_exp, int show_locals, int from_tty) of frames which we should print, or -1 if all of them. */ trailing = get_current_frame (); - /* The target can be in a state where there is no valid frames - (e.g., just connected). */ - if (trailing == NULL) - error (_("No stack.")); - trailing_level = 0; if (count_exp) { @@ -1210,8 +1321,6 @@ backtrace_command_1 (char *count_exp, int show_locals, int from_tty) if (info_verbose) { - struct partial_symtab *ps; - /* Read in symbols for all of the frames. Need to do this in a separate pass so that "Reading in symbols for xxx" messages don't screw up the appearance of the backtrace. Also if @@ -1220,10 +1329,11 @@ backtrace_command_1 (char *count_exp, int show_locals, int from_tty) i = count; for (fi = trailing; fi != NULL && i--; fi = get_prev_frame (fi)) { + CORE_ADDR pc; + QUIT; - ps = find_pc_psymtab (get_frame_address_in_block (fi)); - if (ps) - PSYMTAB_TO_SYMTAB (ps); /* Force syms to come in. */ + pc = get_frame_address_in_block (fi); + find_pc_sect_symtab_via_partial (pc, find_pc_mapped_section (pc)); } } @@ -1273,6 +1383,7 @@ static int backtrace_command_stub (void *data) { struct backtrace_command_args *args = data; + backtrace_command_1 (args->count_exp, args->show_locals, args->from_tty); return 0; } @@ -1344,6 +1455,7 @@ static void backtrace_full_command (char *arg, int from_tty) { struct backtrace_command_args btargs; + btargs.count_exp = arg; btargs.show_locals = 1; btargs.from_tty = from_tty; @@ -1351,17 +1463,16 @@ backtrace_full_command (char *arg, int from_tty) } -/* Print the local variables of a block B active in FRAME on STREAM. - Return 1 if any variables were printed; 0 otherwise. */ +/* Iterate over the local variables of a block B, calling CB with + CB_DATA. */ -static int -print_block_frame_locals (struct block *b, struct frame_info *frame, - int num_tabs, struct ui_file *stream) +static void +iterate_over_block_locals (struct block *b, + iterate_over_block_arg_local_vars_cb cb, + void *cb_data) { struct dict_iterator iter; struct symbol *sym; - int values_printed = 0; - int j; ALL_BLOCK_SYMBOLS (b, iter, sym) { @@ -1373,8 +1484,7 @@ print_block_frame_locals (struct block *b, struct frame_info *frame, case LOC_COMPUTED: if (SYMBOL_IS_ARGUMENT (sym)) break; - values_printed = 1; - print_variable_and_value (NULL, sym, frame, stream, 4 * num_tabs); + (*cb) (SYMBOL_PRINT_NAME (sym), sym, cb_data); break; default: @@ -1382,15 +1492,21 @@ print_block_frame_locals (struct block *b, struct frame_info *frame, break; } } - - return values_printed; } + /* Same, but print labels. */ +#if 0 +/* Commented out, as the code using this function has also been + commented out. FIXME:brobecker/2009-01-13: Find out why the code + was commented out in the first place. The discussion introducing + this change (2007-12-04: Support lexical blocks and function bodies + that occupy non-contiguous address ranges) did not explain why + this change was made. */ static int -print_block_frame_labels (struct block *b, int *have_default, - struct ui_file *stream) +print_block_frame_labels (struct gdbarch *gdbarch, struct block *b, + int *have_default, struct ui_file *stream) { struct dict_iterator iter; struct symbol *sym; @@ -1408,6 +1524,7 @@ print_block_frame_labels (struct block *b, int *have_default, { struct symtab_and_line sal; struct value_print_options opts; + sal = find_pc_line (SYMBOL_VALUE_ADDRESS (sym), 0); values_printed = 1; fputs_filtered (SYMBOL_PRINT_NAME (sym), stream); @@ -1415,7 +1532,8 @@ print_block_frame_labels (struct block *b, int *have_default, if (opts.addressprint) { fprintf_filtered (stream, " "); - fputs_filtered (paddress (SYMBOL_VALUE_ADDRESS (sym)), stream); + fputs_filtered (paddress (gdbarch, SYMBOL_VALUE_ADDRESS (sym)), + stream); } fprintf_filtered (stream, " in file %s, line %d\n", sal.symtab->filename, sal.line); @@ -1424,38 +1542,77 @@ print_block_frame_labels (struct block *b, int *have_default, return values_printed; } +#endif + +/* Iterate over all the local variables in block B, including all its + superblocks, stopping when the top-level block is reached. */ + +void +iterate_over_block_local_vars (struct block *block, + iterate_over_block_arg_local_vars_cb cb, + void *cb_data) +{ + while (block) + { + iterate_over_block_locals (block, cb, cb_data); + /* After handling the function's top-level block, stop. Don't + continue to its superblock, the block of per-file + symbols. */ + if (BLOCK_FUNCTION (block)) + break; + block = BLOCK_SUPERBLOCK (block); + } +} + +/* Data to be passed around in the calls to the locals and args + iterators. */ + +struct print_variable_and_value_data +{ + struct frame_info *frame; + int num_tabs; + struct ui_file *stream; + int values_printed; +}; + +/* The callback for the locals and args iterators */ -/* Print on STREAM all the local variables in frame FRAME, including - all the blocks active in that frame at its current PC. +static void +do_print_variable_and_value (const char *print_name, + struct symbol *sym, + void *cb_data) +{ + struct print_variable_and_value_data *p = cb_data; - Returns 1 if the job was done, or 0 if nothing was printed because - we have no info on the function running in FRAME. */ + print_variable_and_value (print_name, sym, + p->frame, p->stream, p->num_tabs); + p->values_printed = 1; +} static void print_frame_local_vars (struct frame_info *frame, int num_tabs, struct ui_file *stream) { - struct block *block = get_frame_block (frame, 0); - int values_printed = 0; + struct print_variable_and_value_data cb_data; + struct block *block; + block = get_frame_block (frame, 0); if (block == 0) { fprintf_filtered (stream, "No symbol table info available.\n"); return; } - while (block) - { - if (print_block_frame_locals (block, frame, num_tabs, stream)) - values_printed = 1; - /* After handling the function's top-level block, stop. Don't - continue to its superblock, the block of per-file symbols. */ - if (BLOCK_FUNCTION (block)) - break; - block = BLOCK_SUPERBLOCK (block); - } + cb_data.frame = frame; + cb_data.num_tabs = 4 * num_tabs; + cb_data.stream = stream; + cb_data.values_printed = 0; - if (!values_printed) + iterate_over_block_local_vars (block, + do_print_variable_and_value, + &cb_data); + + if (!cb_data.values_printed) fprintf_filtered (stream, _("No locals.\n")); } @@ -1470,6 +1627,7 @@ print_frame_label_vars (struct frame_info *frame, int this_level_only, #else struct blockvector *bl; struct block *block = get_frame_block (frame, 0); + struct gdbarch *gdbarch = get_frame_arch (frame); int values_printed = 0; int index, have_default = 0; char *blocks_printed; @@ -1507,7 +1665,8 @@ print_frame_label_vars (struct frame_info *frame, int this_level_only, { if (blocks_printed[index] == 0) { - if (print_block_frame_labels (BLOCKVECTOR_BLOCK (bl, index), + if (print_block_frame_labels (gdbarch, + BLOCKVECTOR_BLOCK (bl, index), &have_default, stream)) values_printed = 1; blocks_printed[index] = 1; @@ -1520,7 +1679,9 @@ print_frame_label_vars (struct frame_info *frame, int this_level_only, return; /* After handling the function's top-level block, stop. Don't - continue to its superblock, the block of per-file symbols. */ + continue to its superblock, the block of per-file symbols. + Also do not continue to the containing function of an inlined + function. */ if (BLOCK_FUNCTION (block)) break; block = BLOCK_SUPERBLOCK (block); @@ -1541,36 +1702,28 @@ locals_info (char *args, int from_tty) static void catch_info (char *ignore, int from_tty) { - struct symtab_and_line *sal; - /* Assume g++ compiled code; old GDB 4.16 behaviour. */ print_frame_label_vars (get_selected_frame (_("No frame selected.")), 0, gdb_stdout); } -static void -print_frame_arg_vars (struct frame_info *frame, struct ui_file *stream) +/* Iterate over all the argument variables in block B. + + Returns 1 if any argument was walked; 0 otherwise. */ + +void +iterate_over_block_arg_vars (struct block *b, + iterate_over_block_arg_local_vars_cb cb, + void *cb_data) { - struct symbol *func = get_frame_function (frame); - struct block *b; struct dict_iterator iter; struct symbol *sym, *sym2; - int values_printed = 0; - - if (func == 0) - { - fprintf_filtered (stream, _("No symbol table info available.\n")); - return; - } - b = SYMBOL_BLOCK_VALUE (func); ALL_BLOCK_SYMBOLS (b, iter, sym) { /* Don't worry about things which aren't arguments. */ if (SYMBOL_IS_ARGUMENT (sym)) { - values_printed = 1; - /* We have to look up the symbol because arguments can have two entries (one a parameter, one a local) and the one we want is the local, which lookup_symbol will find for us. @@ -1584,12 +1737,33 @@ print_frame_arg_vars (struct frame_info *frame, struct ui_file *stream) sym2 = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), b, VAR_DOMAIN, NULL); - print_variable_and_value (SYMBOL_PRINT_NAME (sym), sym2, - frame, stream, 0); + (*cb) (SYMBOL_PRINT_NAME (sym), sym2, cb_data); } } +} + +static void +print_frame_arg_vars (struct frame_info *frame, struct ui_file *stream) +{ + struct print_variable_and_value_data cb_data; + struct symbol *func; - if (!values_printed) + func = get_frame_function (frame); + if (func == NULL) + { + fprintf_filtered (stream, _("No symbol table info available.\n")); + return; + } + + cb_data.frame = frame; + cb_data.num_tabs = 0; + cb_data.stream = gdb_stdout; + cb_data.values_printed = 0; + + iterate_over_block_arg_vars (SYMBOL_BLOCK_VALUE (func), + do_print_variable_and_value, &cb_data); + + if (!cb_data.values_printed) fprintf_filtered (stream, _("No arguments.\n")); } @@ -1629,13 +1803,7 @@ select_and_print_frame (struct frame_info *frame) 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); @@ -1658,6 +1826,7 @@ find_relative_frame (struct frame_info *frame, int *level_offset_ptr) while (*level_offset_ptr > 0) { struct frame_info *prev = get_prev_frame (frame); + if (!prev) break; (*level_offset_ptr)--; @@ -1668,6 +1837,7 @@ find_relative_frame (struct frame_info *frame, int *level_offset_ptr) while (*level_offset_ptr < 0) { struct frame_info *next = get_next_frame (frame); + if (!next) break; (*level_offset_ptr)++; @@ -1748,6 +1918,7 @@ down_silently_base (char *count_exp) { struct frame_info *frame; int count = -1; + if (count_exp) count = -parse_and_eval_long (count_exp); @@ -1783,12 +1954,17 @@ void 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); + + if (get_frame_type (get_current_frame ()) == INLINE_FRAME) + error (_("Can not force return from an inlined function.")); /* Compute the return value. If the computation triggers an error, let it bail. If the return type can't be handled, set @@ -1833,7 +2009,8 @@ return_command (char *retval_exp, int from_tty) occur. */ return_value = NULL; else if (thisfun != NULL - && using_struct_return (SYMBOL_TYPE (thisfun), return_type)) + && 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\ @@ -1848,6 +2025,7 @@ If you continue, the return value that you specified will be ignored.\n"; if (from_tty) { int confirmed; + if (thisfun == NULL) confirmed = query (_("%sMake selected stack frame return now? "), query_prefix); @@ -1980,10 +2158,6 @@ void _initialize_stack (void); void _initialize_stack (void) { -#if 0 - backtrace_limit = 30; -#endif - add_com ("return", class_stack, return_command, _("\ Make selected stack frame return to its caller.\n\ Control remains in the debugger, but when you continue\n\ @@ -2036,7 +2210,7 @@ Use of the 'full' qualifier also prints the values of the local variables.\n")); { 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\ +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 \n")); @@ -2071,11 +2245,21 @@ Usage: func \n")); _("Show printing of non-scalar frame arguments"), NULL, NULL, NULL, &setprintlist, &showprintlist); -#if 0 - add_cmd ("backtrace-limit", class_stack, set_backtrace_limit_command, _(\ -"Specify maximum number of frames for \"backtrace\" to print by default."), - &setlist); - add_info ("backtrace-limit", backtrace_limit_info, _("\ -The maximum number of frames for \"backtrace\" to print by default.")); -#endif + 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; }