diff options
author | David Taylor <taylor@redhat.com> | 1998-12-31 21:58:30 +0000 |
---|---|---|
committer | David Taylor <taylor@redhat.com> | 1998-12-31 21:58:30 +0000 |
commit | 65b07ddca8832033e0e102c3a2a0d9f9f5922a9d (patch) | |
tree | 7fc8cee254f271f4cc57e64bcb23576fa121e706 /gdb/stack.c | |
parent | c450a7fe3f5214f42118a04639074d0e3883582c (diff) | |
download | gdb-65b07ddca8832033e0e102c3a2a0d9f9f5922a9d.zip gdb-65b07ddca8832033e0e102c3a2a0d9f9f5922a9d.tar.gz gdb-65b07ddca8832033e0e102c3a2a0d9f9f5922a9d.tar.bz2 |
all remaining *.c *.h files from hp merge.
Diffstat (limited to 'gdb/stack.c')
-rw-r--r-- | gdb/stack.c | 644 |
1 files changed, 575 insertions, 69 deletions
diff --git a/gdb/stack.c b/gdb/stack.c index 5338938..685d491 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - +#include <ctype.h> #include "defs.h" #include "gdb_string.h" #include "value.h" @@ -53,13 +53,17 @@ static void return_command PARAMS ((char *, int)); static void down_command PARAMS ((char *, int)); +static void down_silently_base PARAMS ((char *)); + static void down_silently_command PARAMS ((char *, int)); static void up_command PARAMS ((char *, int)); +static void up_silently_base PARAMS ((char *)); + static void up_silently_command PARAMS ((char *, int)); -static void frame_command PARAMS ((char *, int)); +void frame_command PARAMS ((char *, int)); static void select_frame_command PARAMS ((char *, int)); @@ -67,21 +71,31 @@ static void print_frame_arg_vars PARAMS ((struct frame_info *, GDB_FILE *)); static void catch_info PARAMS ((char *, int)); -static void print_frame_label_vars PARAMS ((struct frame_info *, int, +static void args_plus_locals_info PARAMS ((char *, int)); + +static void print_frame_label_vars PARAMS ((struct frame_info *, + int, GDB_FILE *)); -static void print_frame_local_vars PARAMS ((struct frame_info *, GDB_FILE *)); +static void print_frame_local_vars PARAMS ((struct frame_info *, + int, + GDB_FILE *)); static int print_block_frame_labels PARAMS ((struct block *, int *, GDB_FILE *)); static int print_block_frame_locals PARAMS ((struct block *, struct frame_info *, + int, GDB_FILE *)); +static void print_frame_info_base PARAMS ((struct frame_info *, int, int, int)); + +static void print_stack_frame_base PARAMS ((struct frame_info *, int, int)); + static void backtrace_command PARAMS ((char *, int)); -static struct frame_info *parse_frame_specification PARAMS ((char *)); +struct frame_info *parse_frame_specification PARAMS ((char *)); static void frame_info PARAMS ((char *, int)); @@ -116,16 +130,64 @@ struct print_stack_frame_args { int args; }; -static int print_stack_frame_stub PARAMS ((char *)); +static int print_stack_frame_base_stub PARAMS ((char *)); -/* Pass the args the way catch_errors wants them. */ +/* Show and print the frame arguments. + Pass the args the way catch_errors wants them. */ static int -print_stack_frame_stub (args) +show_and_print_stack_frame_stub (args) char *args; { struct print_stack_frame_args *p = (struct print_stack_frame_args *)args; + /* Reversed order of these so tuiDo() doesn't occur + * in the middle of "Breakpoint 1 ... [location]" printing = RT + */ + if (tui_version) + print_frame_info_base (p->fi, p->level, p->source, p->args); print_frame_info (p->fi, p->level, p->source, p->args); + + return 0; +} + +/* Show or print the frame arguments. + Pass the args the way catch_errors wants them. */ +static int +print_stack_frame_stub (args) + char *args; +{ + struct print_stack_frame_args *p = (struct print_stack_frame_args *)args; + + if (tui_version) + print_frame_info (p->fi, p->level, p->source, p->args); + else + print_frame_info_base (p->fi, p->level, p->source, p->args); + return 0; +} + +/* Print a stack frame briefly. FRAME_INFI should be the frame info + and LEVEL should be its level in the stack (or -1 for level not defined). + +/* Pass the args the way catch_errors wants them. */ +static int +print_stack_frame_base_stub (args) + char *args; +{ + struct print_stack_frame_args *p = (struct print_stack_frame_args *)args; + + print_frame_info_base (p->fi, p->level, p->source, p->args); + return 0; +} + +/* print the frame arguments to the terminal. + Pass the args the way catch_errors wants them. */ +static int +print_only_stack_frame_stub (args) + char *args; +{ + struct print_stack_frame_args *p = (struct print_stack_frame_args *)args; + + print_frame_info_base (p->fi, p->level, p->source, p->args); return 0; } @@ -139,6 +201,59 @@ print_stack_frame_stub (args) If SOURCE is 1, print the source line as well. If SOURCE is -1, print ONLY the source line. */ +static void +print_stack_frame_base (fi, level, source) + struct frame_info *fi; + int level; + int source; +{ + struct print_stack_frame_args args; + + args.fi = fi; + args.level = level; + args.source = source; + args.args = 1; + + catch_errors (print_stack_frame_stub, (char *)&args, "", RETURN_MASK_ALL); +} + +/* Show and print a stack frame briefly. FRAME_INFI should be the frame info + and LEVEL should be its level in the stack (or -1 for level not defined). + This prints the level, the function executing, the arguments, + and the file name and line number. + If the pc is not at the beginning of the source line, + the actual pc is printed at the beginning. + + If SOURCE is 1, print the source line as well. + If SOURCE is -1, print ONLY the source line. */ + +void +show_and_print_stack_frame (fi, level, source) + struct frame_info *fi; + int level; + int source; +{ + struct print_stack_frame_args args; + + args.fi = fi; + args.level = level; + args.source = source; + args.args = 1; + + catch_errors (show_and_print_stack_frame_stub, (char *)&args, "", RETURN_MASK_ALL); +} + + +/* Show or print a stack frame briefly. FRAME_INFI should be the frame info + and LEVEL should be its level in the stack (or -1 for level not defined). + This prints the level, the function executing, the arguments, + and the file name and line number. + If the pc is not at the beginning of the source line, + the actual pc is printed at the beginning. + + If SOURCE is 1, print the source line as well. + If SOURCE is -1, print ONLY the source line. */ + void print_stack_frame (fi, level, source) struct frame_info *fi; @@ -155,6 +270,33 @@ print_stack_frame (fi, level, source) catch_errors (print_stack_frame_stub, (char *)&args, "", RETURN_MASK_ALL); } +/* Print a stack frame briefly. FRAME_INFI should be the frame info + and LEVEL should be its level in the stack (or -1 for level not defined). + This prints the level, the function executing, the arguments, + and the file name and line number. + If the pc is not at the beginning of the source line, + the actual pc is printed at the beginning. + + If SOURCE is 1, print the source line as well. + If SOURCE is -1, print ONLY the source line. */ + +void +print_only_stack_frame (fi, level, source) + struct frame_info *fi; + int level; + int source; +{ + struct print_stack_frame_args args; + + args.fi = fi; + args.level = level; + args.source = source; + args.args = 1; + + catch_errors (print_only_stack_frame_stub, + (char *)&args, "", RETURN_MASK_ALL); +} + struct print_args_args { struct symbol *func; struct frame_info *fi; @@ -176,13 +318,20 @@ print_args_stub (args) return 0; } -/* LEVEL is the level of the frame, or -1 if it is the innermost frame - but we don't want to print the level. */ +/* Print information about a frame for frame "fi" at level "level". + * Used in "where" output, also used to emit breakpoint or step messages. + * LEVEL is the level of the frame, or -1 if it is the innermost frame + * but we don't want to print the level. + * The meaning of the SOURCE argument is: + * -1: Print only source line + * 0: Print only location + * 1: Print location and source line + */ -void -print_frame_info (fi, level, source, args) +static void +print_frame_info_base (fi, level, source, args) struct frame_info *fi; - register int level; + int level; int source; int args; { @@ -288,8 +437,31 @@ print_frame_info (fi, level, source, args) } else { + /* I'd like to use SYMBOL_SOURCE_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 call the demangler again, + * with DMGL_ANSI only. RT + * (Yes, I know that printf_symbol_filtered() will + * again try to demangle the name on the fly, but + * the issue is that if cplus_demangle() fails here, + * it'll fail there too. So we want to catch the failure + * ("demangled==NULL" case below) here, while we still + * have our hands on the function symbol.) + */ + char * demangled; funname = SYMBOL_NAME (func); funlang = SYMBOL_LANGUAGE (func); + if (funlang == language_cplus) { + demangled = cplus_demangle (funname, DMGL_ANSI); + if (demangled == NULL) + /* If the demangler fails, try the demangled name + * from the symbol table. This'll have parameters, + * but that's preferable to diplaying a mangled name. + */ + funname = SYMBOL_SOURCE_NAME (func); + } } } else @@ -357,7 +529,7 @@ print_frame_info (fi, level, source, args) } #endif #ifdef PC_SOLIB - if (!funname) + if (!funname || (!sal.symtab || !sal.symtab->filename)) { char *lib = PC_SOLIB (fi->pc); if (lib) @@ -380,14 +552,14 @@ print_frame_info (fi, level, source, args) fi->pc); if (!done) { - if (addressprint && mid_statement) + if (addressprint && mid_statement && !tui_version) { print_address_numeric (fi->pc, 1, gdb_stdout); printf_filtered ("\t"); } if (print_frame_info_listing_hook) print_frame_info_listing_hook (sal.symtab, sal.line, sal.line + 1, 0); - else + else if (!tui_version) print_source_lines (sal.symtab, sal.line, sal.line + 1, 0); } current_source_line = max (sal.line - lines_to_list/2, 1); @@ -399,12 +571,53 @@ print_frame_info (fi, level, source, args) gdb_flush (gdb_stdout); } + + +void +stack_publish_stopped_with_no_frame() +{ + TUIDO(((TuiOpaqueFuncPtr)tuiUpdateOnEnd)); + + return; +} +/* Show or print the frame info. If this is the tui, it will be shown in + the source display */ +void +print_frame_info(fi, level, source, args) + struct frame_info *fi; + register int level; + int source; + int args; +{ + if (!tui_version) + print_frame_info_base(fi, level, source, args); + else + { + if (fi && (frame_in_dummy(fi) || fi->signal_handler_caller)) + print_frame_info_base(fi, level, source, args); + else + { + TUIDO(((TuiOpaqueFuncPtr)tui_vShowFrameInfo, fi)); + } + } +} + +/* Show the frame info. If this is the tui, it will be shown in + the source display otherwise, nothing is done */ +void +show_stack_frame(fi) + struct frame_info *fi; +{ + TUIDO(((TuiOpaqueFuncPtr)tui_vShowFrameInfo, fi)); +} + + /* Read a frame specification in whatever the appropriate format is. Call error() if the specification is in any way invalid (i.e. this function never returns NULL). */ -static struct frame_info * +struct frame_info * parse_frame_specification (frame_exp) char *frame_exp; { @@ -525,7 +738,6 @@ frame_info (addr_exp, from_tty) int from_tty; { struct frame_info *fi; - struct frame_saved_regs fsr; struct symtab_and_line sal; struct symbol *func; struct symtab *s; @@ -549,8 +761,32 @@ frame_info (addr_exp, from_tty) s = find_pc_symtab(fi->pc); if (func) { - funname = SYMBOL_NAME (func); - funlang = SYMBOL_LANGUAGE (func); + /* I'd like to use SYMBOL_SOURCE_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 call the demangler again, + * with DMGL_ANSI only. RT + * (Yes, I know that printf_symbol_filtered() will + * again try to demangle the name on the fly, but + * the issue is that if cplus_demangle() fails here, + * it'll fail there too. So we want to catch the failure + * ("demangled==NULL" case below) here, while we still + * have our hands on the function symbol.) + */ + char * demangled; + funname = SYMBOL_NAME (func); + funlang = SYMBOL_LANGUAGE (func); + if (funlang == language_cplus) + { + demangled = cplus_demangle (funname, DMGL_ANSI); + /* If the demangler fails, try the demangled name + * from the symbol table. This'll have parameters, + * but that's preferable to diplaying a mangled name. + */ + if (demangled == NULL) + funname = SYMBOL_SOURCE_NAME (func); + } } else { @@ -666,36 +902,39 @@ frame_info (addr_exp, from_tty) } } -#if defined (FRAME_FIND_SAVED_REGS) - get_frame_saved_regs (fi, &fsr); - /* The sp is special; what's returned isn't the save address, but - actually the value of the previous frame's sp. */ - printf_filtered (" Previous frame's sp is "); - print_address_numeric (fsr.regs[SP_REGNUM], 1, gdb_stdout); - printf_filtered ("\n"); - count = 0; - numregs = ARCH_NUM_REGS; - for (i = 0; i < numregs; i++) - if (fsr.regs[i] && i != SP_REGNUM) - { - if (count == 0) - puts_filtered (" Saved registers:\n "); - else - puts_filtered (","); - wrap_here (" "); - printf_filtered (" %s at ", REGISTER_NAME (i)); - print_address_numeric (fsr.regs[i], 1, gdb_stdout); - count++; - } - if (count) - puts_filtered ("\n"); -#else /* Have FRAME_FIND_SAVED_REGS. */ - /* We could get some information about saved registers by calling - get_saved_register on each register. Which info goes with which frame - is necessarily lost, however, and I suspect that the users don't care - whether they get the info. */ - puts_filtered ("\n"); -#endif /* Have FRAME_FIND_SAVED_REGS. */ + FRAME_INIT_SAVED_REGS (fi); + if (fi->saved_regs != NULL) + { + /* The sp is special; what's returned isn't the save address, but + actually the value of the previous frame's sp. */ + printf_filtered (" Previous frame's sp is "); + print_address_numeric (fi->saved_regs[SP_REGNUM], 1, gdb_stdout); + printf_filtered ("\n"); + count = 0; + numregs = ARCH_NUM_REGS; + for (i = 0; i < numregs; i++) + if (fi->saved_regs[i] && i != SP_REGNUM) + { + if (count == 0) + puts_filtered (" Saved registers:\n "); + else + puts_filtered (","); + wrap_here (" "); + printf_filtered (" %s at ", REGISTER_NAME (i)); + print_address_numeric (fi->saved_regs[i], 1, gdb_stdout); + count++; + } + if (count) + puts_filtered ("\n"); + } + else + { + /* We could get some information about saved registers by + calling get_saved_register on each register. Which info goes + with which frame is necessarily lost, however, and I suspect + that the users don't care whether they get the info. */ + puts_filtered ("\n"); + } } #if 0 @@ -732,8 +971,9 @@ backtrace_limit_info (arg, from_tty) /* Print briefly all stack frames or just the innermost COUNT frames. */ static void -backtrace_command (count_exp, from_tty) +backtrace_command_1 (count_exp, show_locals, from_tty) char *count_exp; + int show_locals; int from_tty; { struct frame_info *fi; @@ -814,25 +1054,104 @@ backtrace_command (count_exp, from_tty) means further attempts to backtrace would fail (on the other hand, perhaps the code does or could be fixed to make sure the frame->prev field gets set to NULL in that case). */ - print_frame_info (fi, trailing_level + i, 0, 1); + print_frame_info_base (fi, trailing_level + i, 0, 1); + if (show_locals) + print_frame_local_vars(fi, 1, gdb_stdout); } /* If we've stopped before the end, mention that. */ if (fi && from_tty) printf_filtered ("(More stack frames follow...)\n"); } + +static void +backtrace_command (arg, from_tty) + char *arg; + int from_tty; +{ + struct cleanup *old_chain = (struct cleanup *)NULL; + char **argv = (char **)NULL; + int argIndicatingFullTrace = (-1), totArgLen = 0, argc = 0; + char *argPtr = arg; + + if (arg != (char *)NULL) + { + int i; + + argv = buildargv(arg); + old_chain = make_cleanup(freeargv, (char *)argv); + argc = 0; + for (i = 0; (argv[i] != (char *)NULL); i++) + { + int j; + + for (j = 0; (j < strlen(argv[i])); j++) + argv[i][j] = tolower(argv[i][j]); + + if (argIndicatingFullTrace < 0 && subsetCompare(argv[i], "full")) + argIndicatingFullTrace = argc; + else + { + argc++; + totArgLen += strlen(argv[i]); + } + } + totArgLen += argc; + if (argIndicatingFullTrace >= 0) + { + if (totArgLen > 0) + { + argPtr = (char *)xmalloc(totArgLen + 1); + if (!argPtr) + nomem(0); + else + { + memset(argPtr, 0, totArgLen + 1); + for (i = 0; (i < (argc + 1)); i++) + { + if (i != argIndicatingFullTrace) + { + strcat(argPtr, argv[i]); + strcat(argPtr, " "); + } + } + } + } + else + argPtr = (char *)NULL; + } + } + + backtrace_command_1 (argPtr, (argIndicatingFullTrace >= 0), from_tty); + + if (argIndicatingFullTrace >= 0 && totArgLen > 0) + free(argPtr); + + if (old_chain) + do_cleanups(old_chain); +} + +static void +backtrace_full_command (arg, from_tty) + char *arg; + int from_tty; +{ + backtrace_command_1 (arg, 1, from_tty); +} + /* Print the local variables of a block B active in FRAME. Return 1 if any variables were printed; 0 otherwise. */ static int -print_block_frame_locals (b, fi, stream) +print_block_frame_locals (b, fi, num_tabs, stream) struct block *b; register struct frame_info *fi; + int num_tabs; register GDB_FILE *stream; { int nsyms; - register int i; + register int i, j; register struct symbol *sym; register int values_printed = 0; @@ -848,6 +1167,8 @@ print_block_frame_locals (b, fi, stream) case LOC_STATIC: case LOC_BASEREG: values_printed = 1; + for (j = 0; j < num_tabs; j++) + fputs_filtered("\t", stream); fputs_filtered (SYMBOL_SOURCE_NAME (sym), stream); fputs_filtered (" = ", stream); print_variable_value (sym, fi, stream); @@ -913,8 +1234,9 @@ print_block_frame_labels (b, have_default, stream) on the function running in FRAME. */ static void -print_frame_local_vars (fi, stream) +print_frame_local_vars (fi, num_tabs, stream) register struct frame_info *fi; + register int num_tabs; register GDB_FILE *stream; { register struct block *block = get_frame_block (fi); @@ -928,7 +1250,7 @@ print_frame_local_vars (fi, stream) while (block != 0) { - if (print_block_frame_locals (block, fi, stream)) + if (print_block_frame_locals (block, fi, num_tabs, stream)) values_printed = 1; /* After handling the function's top-level block, stop. Don't continue to its superblock, the block of @@ -1024,7 +1346,7 @@ locals_info (args, from_tty) { if (!selected_frame) error ("No frame selected."); - print_frame_local_vars (selected_frame, gdb_stdout); + print_frame_local_vars (selected_frame, 0, gdb_stdout); } static void @@ -1032,9 +1354,29 @@ catch_info (ignore, from_tty) char *ignore; int from_tty; { + struct symtab_and_line * sal; + + /* Check for target support for exception handling */ + sal = target_enable_exception_callback (EX_EVENT_CATCH, 1); + if (sal) + { + /* Currently not handling this */ + /* Ideally, here we should interact with the C++ runtime + system to find the list of active handlers, etc. */ + fprintf_filtered (gdb_stdout, "Info catch not supported with this target/compiler combination.\n"); +#if 0 if (!selected_frame) error ("No frame selected."); - print_frame_label_vars (selected_frame, 0, gdb_stdout); +#endif + } + else + { + /* Assume g++ compiled code -- old v 4.16 behaviour */ + if (!selected_frame) + error ("No frame selected."); + + print_frame_label_vars (selected_frame, 0, gdb_stdout); + } } static void @@ -1112,6 +1454,16 @@ args_info (ignore, from_tty) print_frame_arg_vars (selected_frame, gdb_stdout); } + +static void +args_plus_locals_info(ignore, from_tty) + char *ignore; + int from_tty; +{ + args_info(ignore, from_tty); + locals_info(ignore, from_tty); +} + /* Select frame FI, and note that its stack level is LEVEL. LEVEL may be -1 if an actual level number is not known. */ @@ -1139,9 +1491,48 @@ select_frame (fi, level) && language_mode == language_mode_auto) { set_language(s->language); } + /* elz: this if here fixes the problem with the pc not being displayed + in the tui asm layout, with no debug symbols. The value of s + would be 0 here, and select_source_symtab would abort the + command by calling the 'error' function*/ + if (s) + { + TUIDO(((TuiOpaqueFuncPtr)tui_vSelectSourceSymtab, s)); + } } } + +/* Select frame FI, noting that its stack level is LEVEL. Also print + the stack frame and show the source if this is the tui version. */ +void +select_and_print_frame(fi, level) + struct frame_info *fi; + int level; +{ + select_frame(fi, level); + if (fi) + { + print_stack_frame(fi, level, 1); + TUIDO(((TuiOpaqueFuncPtr)tui_vCheckDataValues, fi)); + } +} + + +/* Select frame FI, noting that its stack level is LEVEL. Be silent if + not the TUI */ +void +select_and_maybe_print_frame(fi, level) + struct frame_info *fi; + int level; +{ + if (!tui_version) + select_frame(fi, level); + else + select_and_print_frame(fi, level); +} + + /* Store the selected frame and its level into *FRAMEP and *LEVELP. If there is no selected frame, *FRAMEP is set to NULL. */ @@ -1249,23 +1640,34 @@ select_frame_command (level_exp, from_tty) With arg, behaves like select_frame and then prints the selected frame. */ -static void +void frame_command (level_exp, from_tty) char *level_exp; int from_tty; { select_frame_command (level_exp, from_tty); - print_stack_frame (selected_frame, selected_frame_level, 1); + show_and_print_stack_frame (selected_frame, selected_frame_level, 1); } +/* The XDB Compatibility command to print the current frame. */ + +void +current_frame_command (level_exp, from_tty) + char *level_exp; + int from_tty; +{ + if (target_has_stack == 0 || selected_frame == 0) + error ("No stack."); + print_only_stack_frame (selected_frame, selected_frame_level, 1); + } + /* Select the frame up one or COUNT stack levels from the previously selected frame, and print it briefly. */ /* ARGSUSED */ static void -up_silently_command (count_exp, from_tty) +up_silently_base (count_exp) char *count_exp; - int from_tty; { register struct frame_info *fi; int count = 1, count1; @@ -1283,12 +1685,22 @@ up_silently_command (count_exp, from_tty) } static void +up_silently_command (count_exp, from_tty) + char *count_exp; + int from_tty; +{ + up_silently_base(count_exp); + if (tui_version) + print_stack_frame (selected_frame, selected_frame_level, 1); +} + +static void up_command (count_exp, from_tty) char *count_exp; int from_tty; { - up_silently_command (count_exp, from_tty); - print_stack_frame (selected_frame, selected_frame_level, 1); + up_silently_base (count_exp); + show_and_print_stack_frame (selected_frame, selected_frame_level, 1); } /* Select the frame down one or COUNT stack levels @@ -1296,9 +1708,8 @@ up_command (count_exp, from_tty) /* ARGSUSED */ static void -down_silently_command (count_exp, from_tty) +down_silently_base (count_exp) char *count_exp; - int from_tty; { register struct frame_info *frame; int count = -1, count1; @@ -1324,14 +1735,24 @@ down_silently_command (count_exp, from_tty) select_frame (frame, selected_frame_level + count - count1); } +/* ARGSUSED */ +static void +down_silently_command (count_exp, from_tty) + char *count_exp; + int from_tty; +{ + down_silently_base (count_exp); + if (tui_version) + print_stack_frame (selected_frame, selected_frame_level, 1); +} static void down_command (count_exp, from_tty) char *count_exp; int from_tty; { - down_silently_command (count_exp, from_tty); - print_stack_frame (selected_frame, selected_frame_level, 1); + down_silently_base (count_exp); + show_and_print_stack_frame (selected_frame, selected_frame_level, 1); } static void @@ -1416,6 +1837,66 @@ return_command (retval_exp, from_tty) select_frame_command ("0", 0); } +/* Sets the scope to input function name, provided that the + function is within the current stack frame */ +typedef struct function_bounds +{ + CORE_ADDR low, high; +}; + +static void +func_command (arg, from_tty) + char *arg; + int from_tty; +{ + if (arg != (char *)NULL) + { + struct frame_info *fp; + int found = 0; + struct symtabs_and_lines sals; + int i; + int level = 1; + struct function_bounds *funcBounds = (struct function_bounds *)NULL; + + fp = parse_frame_specification("0"); + sals = decode_line_spec(arg, 1); + funcBounds = (struct function_bounds *)xmalloc( + sizeof(struct function_bounds) * sals.nelts); + for (i = 0; (i < sals.nelts && !found); i++) + { + if (sals.sals[i].pc == (CORE_ADDR)0 || + find_pc_partial_function(sals.sals[i].pc, + (char **)NULL, + &funcBounds[i].low, + &funcBounds[i].high) == 0) + { + funcBounds[i].low = + funcBounds[i].high = (CORE_ADDR)NULL; + } + } + + do + { + for (i = 0; (i < sals.nelts && !found); i++) + found = (fp->pc >= funcBounds[i].low && + fp->pc < funcBounds[i].high); + if (!found) + { + level = 1; + fp = find_relative_frame(fp, &level); + } + } while (!found && level == 0); + + if (funcBounds) + free(funcBounds); + + if (!found) + printf_filtered("'%s' not within current stack frame.\n", arg); + else if (fp != selected_frame) /* set the stack frame here! */ + select_and_print_frame(fp); + } +} + /* Gets the language of the current frame. */ enum language @@ -1477,6 +1958,12 @@ a command file or a user-defined command."); 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\ @@ -1484,8 +1971,19 @@ It can be a stack frame number or the address of the frame.\n"); add_com ("backtrace", class_stack, backtrace_command, "Print backtrace of all stack frames, or innermost COUNT frames.\n\ -With a negative argument, print outermost -COUNT frames."); +With a negative argument, print outermost -COUNT frames.\n\ +Use of the 'full' qualifier also prints the values of the local variables.\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, "Backtrace of the stack, or innermost COUNT frames."); @@ -1497,6 +1995,14 @@ With a negative argument, print outermost -COUNT frames."); "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, + "Select the stack frame that contains <func>.\nUsage: func <name>\n"); + add_info ("catch", catch_info, "Exceptions that can be caught in the current stack frame."); |