diff options
-rw-r--r-- | gdb/testsuite/gdb.mi/mi-var-invalidate-shlib.c | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.mi/mi-var-invalidate-shlib.exp | 44 | ||||
-rw-r--r-- | gdb/varobj.c | 20 |
3 files changed, 59 insertions, 7 deletions
diff --git a/gdb/testsuite/gdb.mi/mi-var-invalidate-shlib.c b/gdb/testsuite/gdb.mi/mi-var-invalidate-shlib.c index f9237c3..2cb7010 100644 --- a/gdb/testsuite/gdb.mi/mi-var-invalidate-shlib.c +++ b/gdb/testsuite/gdb.mi/mi-var-invalidate-shlib.c @@ -17,6 +17,8 @@ #include <dlfcn.h> +int global_var = 5; + static void no_varobj_in_scope (void) { diff --git a/gdb/testsuite/gdb.mi/mi-var-invalidate-shlib.exp b/gdb/testsuite/gdb.mi/mi-var-invalidate-shlib.exp index b405c83..87d1d4a 100644 --- a/gdb/testsuite/gdb.mi/mi-var-invalidate-shlib.exp +++ b/gdb/testsuite/gdb.mi/mi-var-invalidate-shlib.exp @@ -61,6 +61,7 @@ proc do_test { separate_debuginfo } { mi_runto foo -pending + mi_create_varobj global_var global_var "create global global_var" mi_create_varobj global_shlib_var global_shlib_var "create global gloal_shlib_var" mi_create_floating_varobj floating_local local_var "create floating local_var" @@ -79,6 +80,10 @@ proc do_test { separate_debuginfo } { "\\^done,changelist=\\\[{name=\"floating_local\",in_scope=\"false\",type_changed=\"false\",has_more=\"0\"}\\\]" \ "floating_local still valid but not in scope" + mi_gdb_test "-var-update global_var" \ + "\\^done,changelist=\\\[\\\]" \ + "global_var still valid" + # The varobj can be re-evaluated if the expression is valid in the current # frame. mi_continue_to "floating_varobj_in_scope" @@ -86,6 +91,45 @@ proc do_test { separate_debuginfo } { "\\^done,changelist=\\\[{name=\"floating_local\",in_scope=\"true\",type_changed=\"true\",new_type=\"int\",new_num_children=\"0\",has_more=\"0\"}\\\]" \ "floating_local in scope with new type and value" } + + # Reload the entire process + with_test_prefix "restart process" { + mi_delete_breakpoints + mi_gdb_load ${::binfile} + mi_runto_main + } + + with_test_prefix "in new process" { + # When reloading the symbol file, only the var for the global in the main + # executable is re-created. + mi_gdb_test "-var-update global_var" \ + "\\^done,changelist=\\\[{name=\"global_var\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"}\\\]" \ + "global_var recreated" + mi_gdb_test "-var-update global_shlib_var" \ + "\\^done,changelist=\\\[{name=\"global_shlib_var\",in_scope=\"invalid\",has_more=\"0\"}\\\]" \ + "global_shlib_var invalid" + + # Floating varobj should still be valid, but out of scope at the moment. + mi_gdb_test "-var-update floating_local" \ + "\\^done,changelist=\\\[{name=\"floating_local\",in_scope=\"false\",type_changed=\"false\",has_more=\"0\"}\\\]" \ + "floating_local still valid but not in scope" + + # Continue inside foo + mi_gdb_test "299-break-insert -f -t foo" \ + "&\"Function \\\\\"foo\\\\\" not defined.\\\\n\"\r\n299\\^done,[mi_make_breakpoint_pending -type breakpoint -disp del -pending foo]" + mi_send_resuming_command "exec-continue" "continue to foo" + mi_expect_stop "breakpoint-hit" foo ".*" ".*" "\[0-9\]+" { "" "disp=\"del\"" } "arrived at foo" + + # Floating varobj is still valid, and now in scope. + mi_gdb_test "-var-update floating_local" \ + "\\^done,changelist=\\\[{name=\"floating_local\",in_scope=\"true\",type_changed=\"true\",new_type=\"struct bar\",new_num_children=\"2\",has_more=\"0\"}\\\]" \ + "floating_local still valid and in scope" + + # The var for the global in the shlib stays invalid even after reloading the shlib. + mi_gdb_test "-var-update global_shlib_var" \ + "\\^done,changelist=\\\[{name=\"global_shlib_var\",in_scope=\"invalid\",has_more=\"0\"}\\\]" \ + "global_shlib_var invalid after shlib loaded" + } } foreach_with_prefix separate_debuginfo {0 1} { diff --git a/gdb/varobj.c b/gdb/varobj.c index 2b6dfff..e558794 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -2359,22 +2359,28 @@ static void varobj_invalidate_iter (struct varobj *var) { /* global and floating var must be re-evaluated. */ - if (var->root->floating || var->root->valid_block == NULL) + if (var->root->floating || var->root->valid_block == nullptr) { struct varobj *tmp_var; /* Try to create a varobj with same expression. If we succeed replace the old varobj, otherwise invalidate it. */ - tmp_var = varobj_create (NULL, var->name.c_str (), (CORE_ADDR) 0, - USE_CURRENT_FRAME); - if (tmp_var != NULL) - { + tmp_var = varobj_create (nullptr, var->name.c_str (), (CORE_ADDR) 0, + var->root->floating + ? USE_SELECTED_FRAME : USE_CURRENT_FRAME); + if (tmp_var != nullptr) + { + gdb_assert (var->root->floating == tmp_var->root->floating); tmp_var->obj_name = var->obj_name; varobj_delete (var, 0); install_variable (tmp_var); } - else - var->root->is_valid = false; + else if (!var->root->floating) + { + /* Only invalidate globals as floating vars might still be valid in + some other frame. */ + var->root->is_valid = false; + } } else /* locals must be invalidated. */ var->root->is_valid = false; |