diff options
author | Pierre-Marie de Rodat <derodat@adacore.com> | 2015-02-05 17:00:06 +0100 |
---|---|---|
committer | Pierre-Marie de Rodat <derodat@adacore.com> | 2015-08-25 08:13:28 -0400 |
commit | 63e43d3aedb8b1112899c2d0ad74cbbee687e5d6 (patch) | |
tree | 9e35fea0ccd74ee5d2d27bc7fe957ec19c360dbb /gdb/testsuite | |
parent | 7c2bea1ad1c779b893eb9cad4c92732583ae0eb5 (diff) | |
download | gdb-63e43d3aedb8b1112899c2d0ad74cbbee687e5d6.zip gdb-63e43d3aedb8b1112899c2d0ad74cbbee687e5d6.tar.gz gdb-63e43d3aedb8b1112899c2d0ad74cbbee687e5d6.tar.bz2 |
DWARF: handle non-local references in nested functions
GDB's current behavior when dealing with non-local references in the
context of nested fuctions is approximative:
- code using valops.c:value_of_variable read the first available stack
frame that holds the corresponding variable (whereas there can be
multiple candidates for this);
- code directly relying on read_var_value will instead read non-local
variables in frames where they are not even defined.
This change adds the necessary context to symbol reads (to get the block
they belong to) and to blocks (the static link property, if any) so that
GDB can make the proper decisions when dealing with non-local varibale
references.
gdb/ChangeLog:
* ada-lang.c (ada_read_var_value): Add a var_block argument
and pass it to default_read_var_value.
* block.c (block_static_link): New accessor.
* block.h (block_static_link): Declare it.
* buildsym.c (finish_block_internal): Add a static_link
argument. If there is a static link, associate it to the new
block.
(finish_block): Add a static link argument and pass it to
finish_block_internal.
(end_symtab_get_static_block): Update calls to finish_block and
to finish_block_internal.
(end_symtab_with_blockvector): Update call to
finish_block_internal.
* buildsym.h: Forward-declare struct dynamic_prop.
(struct context_stack): Add a static_link field.
(finish_block): Add a static link argument.
* c-exp.y: Remove an obsolete comment (evaluation of variables
already start from the selected frame, and now they climb *up*
the call stack) and propagate the block information to the
produced expression.
* d-exp.y: Likewise.
* f-exp.y: Likewise.
* go-exp.y: Likewise.
* jv-exp.y: Likewise.
* m2-exp.y: Likewise.
* p-exp.y: Likewise.
* coffread.c (coff_symtab_read): Update calls to finish_block.
* dbxread.c (process_one_symbol): Likewise.
* xcoffread.c (read_xcoff_symtab): Likewise.
* compile/compile-c-symbols.c (convert_one_symbol): Promote the
"sym" parameter to struct block_symbol, update its uses and pass
its block to calls to read_var_value.
(convert_symbol_sym): Update the calls to convert_one_symbol.
* compile/compile-loc2c.c (do_compile_dwarf_expr_to_c): Update
call to read_var_value.
* dwarf2loc.c (block_op_get_frame_base): New.
(dwarf2_block_frame_base_locexpr_funcs): Implement the
get_frame_base method.
(dwarf2_block_frame_base_loclist_funcs): Likewise.
(dwarf2locexpr_baton_eval): Add a frame argument and use it
instead of the selected frame in order to evaluate the
expression.
(dwarf2_evaluate_property): Add a frame argument. Update call
to dwarf2_locexpr_baton_eval to provide a frame in available and
to handle the absence of address stack.
* dwarf2loc.h (dwarf2_evaluate_property): Add a frame argument.
* dwarf2read.c (attr_to_dynamic_prop): Add a forward
declaration.
(read_func_scope): Record any available static link description.
Update call to finish_block.
(read_lexical_block_scope): Update call to finish_block.
* findvar.c (follow_static_link): New.
(get_hosting_frame): New.
(default_read_var_value): Add a var_block argument. Use
get_hosting_frame to handle non-local references.
(read_var_value): Add a var_block argument and pass it to the
LA_READ_VAR_VALUE method.
* gdbtypes.c (resolve_dynamic_range): Update calls to
dwarf2_evaluate_property.
(resolve_dynamic_type_internal): Likewise.
* guile/scm-frame.c (gdbscm_frame_read_var): Update call to
read_var_value, passing it the block coming from symbol lookup.
* guile/scm-symbol.c (gdbscm_symbol_value): Update call to
read_var_value (TODO).
* infcmd.c (finish_command_continuation): Update call to
read_var_value, passing it the block coming from symbol lookup.
* infrun.c (insert_exception_resume_breakpoint): Likewise.
* language.h (struct language_defn): Add a var_block argument to
the LA_READ_VAR_VALUE method.
* objfiles.c (struct static_link_htab_entry): New.
(static_link_htab_entry_hash): New.
(static_link_htab_entry_eq): New.
(objfile_register_static_link): New.
(objfile_lookup_static_link): New.
(free_objfile): Free the STATIC_LINKS hashed map if needed.
* objfiles.h: Include hashtab.h.
(struct objfile): Add a static_links field.
(objfile_register_static_link): New.
(objfile_lookup_static_link): New.
* printcmd.c (print_variable_and_value): Update call to
read_var_value.
* python/py-finishbreakpoint.c (bpfinishpy_init): Likewise.
* python/py-frame.c (frapy_read_var): Update call to
read_var_value, passing it the block coming from symbol lookup.
* python/py-framefilter.c (extract_sym): Add a sym_block
parameter and set the pointed value to NULL (TODO).
(enumerate_args): Update call to extract_sym.
(enumerate_locals): Update calls to extract_sym and to
read_var_value.
* python/py-symbol.c (sympy_value): Update call to
read_var_value (TODO).
* stack.c (read_frame_local): Update call to read_var_value.
(read_frame_arg): Likewise.
(return_command): Likewise.
* symtab.h (struct symbol_block_ops): Add a get_frame_base
method.
(struct symbol): Add a block field.
(SYMBOL_BLOCK): New accessor.
* valops.c (value_of_variable): Remove frame/block handling and
pass the block argument to read_var_value, which does this job
now.
(value_struct_elt_for_reference): Update calls to
read_var_value.
(value_of_this): Pass the block found to read_var_value.
* value.h (read_var_value): Add a var_block argument.
(default_read_var_value): Likewise.
gdb/testsuite/ChangeLog:
* gdb.base/nested-subp1.exp: New file.
* gdb.base/nested-subp1.c: New file.
* gdb.base/nested-subp2.exp: New file.
* gdb.base/nested-subp2.c: New file.
* gdb.base/nested-subp3.exp: New file.
* gdb.base/nested-subp3.c: New file.
Diffstat (limited to 'gdb/testsuite')
-rw-r--r-- | gdb/testsuite/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/nested-subp1.c | 37 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/nested-subp1.exp | 55 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/nested-subp2.c | 48 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/nested-subp2.exp | 64 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/nested-subp3.c | 66 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/nested-subp3.exp | 55 |
7 files changed, 334 insertions, 0 deletions
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index bf7f1eb..15ad42c 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2015-08-25 Pierre-Marie de Rodat <derodat@adacore.com> + + * gdb.base/nested-subp1.exp: New file. + * gdb.base/nested-subp1.c: New file. + * gdb.base/nested-subp2.exp: New file. + * gdb.base/nested-subp2.c: New file. + * gdb.base/nested-subp3.exp: New file. + * gdb.base/nested-subp3.c: New file. + 2015-08-24 Pedro Alves <palves@redhat.com> * gdb.server/connect-without-multi-process.c: New file. diff --git a/gdb/testsuite/gdb.base/nested-subp1.c b/gdb/testsuite/gdb.base/nested-subp1.c new file mode 100644 index 0000000..967eb2f --- /dev/null +++ b/gdb/testsuite/gdb.base/nested-subp1.c @@ -0,0 +1,37 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 2015 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +int +foo (int i1) +{ + int + nested (int i2) + { + /* Here with i1 and i2, we can test that GDB can fetch both a local and a + non-local variable in the most simple nested function situation: the + parent block instance is accessible as the directly upper frame. */ + return i1 * i2; /* STOP */ + } + + return nested (i1 + 1); +} + +int +main () +{ + return !foo (1); +} diff --git a/gdb/testsuite/gdb.base/nested-subp1.exp b/gdb/testsuite/gdb.base/nested-subp1.exp new file mode 100644 index 0000000..9720f5b --- /dev/null +++ b/gdb/testsuite/gdb.base/nested-subp1.exp @@ -0,0 +1,55 @@ +# Copyright 2015 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file is part of the gdb testsuite. + +# +# Test nested functions related functionality. +# + +standard_testfile + + +set testcase "nested-subp1" + +if { [gdb_compile "${srcdir}/${subdir}/${testcase}.c" \ + [standard_output_file "${testcase}"] \ + "${testcase}" \ + [list debug "additional_flags=-std=gnu99"]] != "" } { + return -1 +} + + +# Run until the variables we are interested in are visible. + +clean_restart "${testcase}" +if ![runto_main] { + perror "could not run to main" + continue +} + +set bp_location [gdb_get_line_number "STOP" "${testcase}.c"] +gdb_test "break ${testcase}.c:${bp_location}" \ + "Breakpoint \[0-9\]+ at 0x\[0-9a-fA-F\]+: .*" \ + "breakpoint to the STOP marker" +gdb_test "continue" \ + "Breakpoint \[0-9\]+, nested .*" \ + "continue to the STOP marker" + + +# Check we get correct values for both local and non-local variable references. + +gdb_test "print i1" "1" +gdb_test "print i2" "2" diff --git a/gdb/testsuite/gdb.base/nested-subp2.c b/gdb/testsuite/gdb.base/nested-subp2.c new file mode 100644 index 0000000..a6449e34 --- /dev/null +++ b/gdb/testsuite/gdb.base/nested-subp2.c @@ -0,0 +1,48 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 2015 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +void +iter_str (const char *str, void (*callback) (char c)) +{ + for (; *str != '\0'; ++str) + callback (*str); +} + +int +length_str (const char *str) +{ + int count = 0; + + void + increment (char c) + { + /* Here with COUNT, we can test that GDB can read a non-local variable even + though it's not directly in the upper stack frame. */ + count += 1; /* STOP */ + } + + iter_str (str, &increment); + return count; +} + +int +main () +{ + if (length_str ("foo") == 3) + return 0; + return 1; +} diff --git a/gdb/testsuite/gdb.base/nested-subp2.exp b/gdb/testsuite/gdb.base/nested-subp2.exp new file mode 100644 index 0000000..a107d1c --- /dev/null +++ b/gdb/testsuite/gdb.base/nested-subp2.exp @@ -0,0 +1,64 @@ +# Copyright 2015 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file is part of the gdb testsuite. + +# +# Test nested functions related functionality. +# + +standard_testfile + + +set testcase "nested-subp2" + +if { [gdb_compile "${srcdir}/${subdir}/${testcase}.c" \ + [standard_output_file "${testcase}"] \ + "${testcase}" \ + [list debug "additional_flags=-std=gnu99"]] != "" } { + return -1 +} + + +# Run until the variables we are interested in are visible. + +clean_restart "${testcase}" +if ![runto_main] { + perror "could not run to main" + continue +} + +set bp_location [gdb_get_line_number "STOP" "${testcase}.c"] +gdb_test "break ${testcase}.c:${bp_location}" \ + "Breakpoint \[0-9\]+ at 0x\[0-9a-fA-F\]+: .*" \ + "breakpoint to the STOP marker" +gdb_test "continue" \ + "Breakpoint \[0-9\]+, increment .*" \ + "continue to the STOP marker" + + +# Check we get correct values for both local and non-local variable references. + +gdb_test "print c" "102 'f'" +gdb_test "print count" "0" + + +# Same but a little later: make sure we were looking at the proper places. + +gdb_test "continue" \ + "Breakpoint \[0-9\]+, increment .*" \ + "continue to the STOP marker" +gdb_test "print c" "111 'o'" +gdb_test "print count" "1" diff --git a/gdb/testsuite/gdb.base/nested-subp3.c b/gdb/testsuite/gdb.base/nested-subp3.c new file mode 100644 index 0000000..a51f417 --- /dev/null +++ b/gdb/testsuite/gdb.base/nested-subp3.c @@ -0,0 +1,66 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 2015 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <stdlib.h> + +typedef void (*callback_t) (void); + +extern void process (callback_t cb); +extern void parent (int first, callback_t cb); + +void +ignore (int unused) +{ + (void) unused; +} + +void +process (callback_t cb) +{ + parent (0, cb); +} + +void +parent (int first, callback_t cb) +{ + void child (void) + { + /* When reaching this, there are two block instances for PARENT on the + stack: the one that is right in the upper frame is not the one actually + used for non-local references, so GDB has to follow the static link in + order to get the correct instance, and thus in order to read the proper + variables. + + As a simple check, we can verify that under GDB, the following is true: + parent_first == first (which should be one: see the IF block below). */ + const int parent_first = first; + ignore (parent_first); /* STOP */ + ignore (first); + } + + if (first) + process (&child); + else + cb (); +} + +int +main () +{ + parent (1, NULL); + return 0; +} diff --git a/gdb/testsuite/gdb.base/nested-subp3.exp b/gdb/testsuite/gdb.base/nested-subp3.exp new file mode 100644 index 0000000..8f9b522 --- /dev/null +++ b/gdb/testsuite/gdb.base/nested-subp3.exp @@ -0,0 +1,55 @@ +# Copyright 2015 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file is part of the gdb testsuite. + +# +# Test nested functions related functionality. +# + +standard_testfile + + +set testcase "nested-subp3" + +if { [gdb_compile "${srcdir}/${subdir}/${testcase}.c" \ + [standard_output_file "${testcase}"] \ + "${testcase}" \ + [list debug "additional_flags=-std=gnu99"]] != "" } { + return -1 +} + + +# Run until the variables we are interested in are visible. + +clean_restart "${testcase}" +if ![runto_main] { + perror "could not run to main" + continue +} + +set bp_location [gdb_get_line_number "STOP" "${testcase}.c"] +gdb_test "break ${testcase}.c:${bp_location}" \ + "Breakpoint \[0-9\]+ at 0x\[0-9a-fA-F\]+: .*" \ + "breakpoint to the STOP marker" +gdb_test "continue" \ + "Breakpoint \[0-9\]+, child .*" \ + "continue to the STOP marker" + + +# Check we get correct values for both local and non-local variable references. + +gdb_test "print first" "1" +gdb_test "print parent_first" "1" |