diff options
-rw-r--r-- | gdb/ChangeLog | 23 | ||||
-rw-r--r-- | gdb/stack.c | 141 | ||||
-rw-r--r-- | gdb/stack.h | 12 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.trace/collection.c | 1 | ||||
-rw-r--r-- | gdb/tracepoint.c | 82 |
6 files changed, 195 insertions, 69 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 58b54dd..b29508e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,26 @@ +2010-04-01 Pedro Alves <pedro@codesourcery.com> + + * tracepoint.c: Include stack.h. + (struct add_local_symbols_data): New. + (do_collect_symbol): New. + (add_local_symbols): Rewrite using iterate_over_block_arg_vars and + iterate_over_block_local_vars. + * stack.c (print_block_frame_locals): Rewrite as ... + (iterate_over_block_locals): ... this. Take a callback function + pointer and generic data pointer, and call that instead of + print_variable_and_value. + (struct print_variable_and_value_data): New. + (do_print_variable_and_value): New. + (iterate_over_block_local_vars): New, abstracted out from + print_frame_local_vars. + (print_frame_local_vars): Rewrite using + iterate_over_block_local_vars. + (iterate_over_block_arg_vars): New, abstracted out from + print_frame_arg_vars. + (print_frame_arg_vars): Rewrite using iterate_over_block_arg_vars. + * stack.h (iterate_over_block_arg_local_vars_cb): New typedef. + (iterate_over_block_arg_vars, iterate_over_block_local_vars): Declare. + 2010-03-31 Richard Earnshaw <rearnsha@arm.com> * arm-tdep.c (thumb_get_next_pc_raw): Correctly detect TBH diff --git a/gdb/stack.c b/gdb/stack.c index 12b23cc..53d4aeb 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -1455,17 +1455,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) { @@ -1477,8 +1476,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: @@ -1486,8 +1484,6 @@ print_block_frame_locals (struct block *b, struct frame_info *frame, break; } } - - return values_printed; } @@ -1539,39 +1535,75 @@ print_block_frame_labels (struct gdbarch *gdbarch, struct block *b, } #endif -/* Print on STREAM all the local variables in frame FRAME, including - all the blocks active in that frame at its current PC. +/* 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. */ - Returns 1 if the job was done, or 0 if nothing was printed because - we have no info on the function running in FRAME. */ +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 */ + +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; + + 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. - Also do not continue to the containing function of an inlined - function. */ - 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; + + iterate_over_block_local_vars (block, + do_print_variable_and_value, + &cb_data); - if (!values_printed) + if (!cb_data.values_printed) fprintf_filtered (stream, _("No locals.\n")); } @@ -1668,29 +1700,23 @@ catch_info (char *ignore, int from_tty) 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. @@ -1704,12 +1730,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; + + 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 (!values_printed) + if (!cb_data.values_printed) fprintf_filtered (stream, _("No arguments.\n")); } diff --git a/gdb/stack.h b/gdb/stack.h index 618783d..5e874b4 100644 --- a/gdb/stack.h +++ b/gdb/stack.h @@ -27,4 +27,16 @@ void select_frame_command (char *level_exp, int from_tty); void find_frame_funname (struct frame_info *frame, char **funname, enum language *funlang); +typedef void (*iterate_over_block_arg_local_vars_cb) (const char *symbol_print_name, + struct symbol *sym, + void *cb_data); + +void iterate_over_block_arg_vars (struct block *block, + iterate_over_block_arg_local_vars_cb cb, + void *cb_data); + +void iterate_over_block_local_vars (struct block *block, + iterate_over_block_arg_local_vars_cb cb, + void *cb_data); + #endif /* #ifndef STACK_H */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 83be424..5f48f55 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2010-04-01 Pedro Alves <pedro@codesourcery.com> + * gdb.trace/collection.c (local_test_func): Define a local struct, + and instanciate it. + +2010-04-01 Pedro Alves <pedro@codesourcery.com> + * gdb.trace/collection.exp (gdb_collect_args_test) (gdb_collect_argarray_test): XFAIL the tests that assume the argarray argument's elements are collected. diff --git a/gdb/testsuite/gdb.trace/collection.c b/gdb/testsuite/gdb.trace/collection.c index 3986332..6fb7133 100644 --- a/gdb/testsuite/gdb.trace/collection.c +++ b/gdb/testsuite/gdb.trace/collection.c @@ -93,6 +93,7 @@ int local_test_func () /* test collecting locals */ test_struct locst; int locar[4]; int i; + struct localstruct {} locdefst; locst.memberc = 15; locst.memberi = 16; diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index acba11f..f82e05e 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -44,6 +44,7 @@ #include "objfiles.h" #include "filenames.h" #include "gdbthread.h" +#include "stack.h" #include "ax.h" #include "ax-gdb.h" @@ -1008,40 +1009,77 @@ collect_symbol (struct collection_list *collect, } } +/* Data to be passed around in the calls to the locals and args + iterators. */ + +struct add_local_symbols_data +{ + struct collection_list *collect; + struct gdbarch *gdbarch; + CORE_ADDR pc; + long frame_regno; + long frame_offset; + int count; +}; + +/* The callback for the locals and args iterators */ + +static void +do_collect_symbol (const char *print_name, + struct symbol *sym, + void *cb_data) +{ + struct add_local_symbols_data *p = cb_data; + + collect_symbol (p->collect, sym, p->gdbarch, p->frame_regno, + p->frame_offset, p->pc); + p->count++; +} + /* Add all locals (or args) symbols to collection list */ static void add_local_symbols (struct collection_list *collect, struct gdbarch *gdbarch, CORE_ADDR pc, long frame_regno, long frame_offset, int type) { - struct symbol *sym; struct block *block; - struct dict_iterator iter; - int count = 0; + struct add_local_symbols_data cb_data; - block = block_for_pc (pc); - while (block != 0) + cb_data.collect = collect; + cb_data.gdbarch = gdbarch; + cb_data.pc = pc; + cb_data.frame_regno = frame_regno; + cb_data.frame_offset = frame_offset; + cb_data.count = 0; + + if (type == 'L') { - QUIT; /* allow user to bail out with ^C */ - ALL_BLOCK_SYMBOLS (block, iter, sym) + block = block_for_pc (pc); + if (block == NULL) { - if (SYMBOL_IS_ARGUMENT (sym) - ? type == 'A' /* collecting Arguments */ - : type == 'L') /* collecting Locals */ - { - count++; - collect_symbol (collect, sym, gdbarch, - frame_regno, frame_offset, pc); - } + warning (_("Can't collect locals; " + "no symbol table info available.\n")); + return; } - if (BLOCK_FUNCTION (block)) - break; - else - block = BLOCK_SUPERBLOCK (block); + + iterate_over_block_local_vars (block, do_collect_symbol, &cb_data); + if (cb_data.count == 0) + warning (_("No locals found in scope.")); + } + else + { + pc = get_pc_function_start (pc); + block = block_for_pc (pc); + if (block == NULL) + { + warning (_("Can't collect args; no symbol table info available.\n")); + return; + } + + iterate_over_block_arg_vars (block, do_collect_symbol, &cb_data); + if (cb_data.count == 0) + warning (_("No args found in scope.")); } - if (count == 0) - warning (_("No %s found in scope."), - type == 'L' ? "locals" : "args"); } /* worker function */ |