aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog8
-rw-r--r--gdb/Makefile.in3
-rw-r--r--gdb/eval.c24
-rw-r--r--gdb/testsuite/ChangeLog4
-rw-r--r--gdb/testsuite/gdb.mi/mi-var-cmd.exp43
-rw-r--r--gdb/varobj.c2
6 files changed, 80 insertions, 4 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e5b5743..854e573 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
2007-01-04 Daniel Jacobowitz <dan@codesourcery.com>
+ * Makefile.in (eval.o): Update dependencies.
+ * eval.c: Include "ui-out.h" and "exceptions.h".
+ (evaluate_subexp_standard): Use TRY_CATCH around value_of_variable.
+ Use value_zero if an error occurs when avoiding side effects.
+ * varobj.c (c_value_of_root): Initialize new_val.
+
+2007-01-04 Daniel Jacobowitz <dan@codesourcery.com>
+
* varobj.c (varobj_list_children): Stop if the number of children is
unknown.
(c_number_of_children):
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 491e7d4..928cd77 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1968,7 +1968,8 @@ environ.o: environ.c $(defs_h) $(environ_h) $(gdb_string_h)
eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \
$(f_lang_h) $(cp_abi_h) $(infcall_h) $(objc_lang_h) $(block_h) \
- $(parser_defs_h) $(cp_support_h) $(gdb_assert_h)
+ $(parser_defs_h) $(cp_support_h) $(gdb_assert_h) $(exceptions_h) \
+ $(uiout_h)
event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
$(gdb_string_h) $(exceptions_h) $(gdb_assert_h) $(gdb_select_h)
event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
diff --git a/gdb/eval.c b/gdb/eval.c
index 1a3d72a..4954e9f 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -37,6 +37,8 @@
#include "block.h"
#include "parser-defs.h"
#include "cp-support.h"
+#include "ui-out.h"
+#include "exceptions.h"
#include "gdb_assert.h"
@@ -469,8 +471,26 @@ evaluate_subexp_standard (struct type *expect_type,
value_rtti_target_type () if we are dealing with a pointer
or reference to a base class and print object is on. */
- return value_of_variable (exp->elts[pc + 2].symbol,
- exp->elts[pc + 1].block);
+ {
+ volatile struct gdb_exception except;
+ struct value *ret = NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ERROR)
+ {
+ ret = value_of_variable (exp->elts[pc + 2].symbol,
+ exp->elts[pc + 1].block);
+ }
+
+ if (except.reason < 0)
+ {
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ ret = value_zero (SYMBOL_TYPE (exp->elts[pc + 2].symbol), not_lval);
+ else
+ throw_exception (except);
+ }
+
+ return ret;
+ }
case OP_LAST:
(*pos) += 2;
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 6966dce..d8b8c35 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2007-01-04 Daniel Jacobowitz <dan@codesourcery.com>
+ * gdb.mi/mi-var-cmd.exp: Add tests for unreadable varobjs.
+
+2007-01-04 Daniel Jacobowitz <dan@codesourcery.com>
+
* lib/mi-support.exp (mi_runto_helper): Expect two prompts
when continuing.
diff --git a/gdb/testsuite/gdb.mi/mi-var-cmd.exp b/gdb/testsuite/gdb.mi/mi-var-cmd.exp
index d7cd4e9..9dfcc52 100644
--- a/gdb/testsuite/gdb.mi/mi-var-cmd.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-cmd.exp
@@ -586,5 +586,48 @@ mi_gdb_test "-var-update selected_a" \
"\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",new_type=\"int\",new_num_children=\"0\"\}\\\]" \
"update selected_a in do_special_tests"
+# Test whether bad varobjs crash GDB.
+
+# A varobj we fail to read during -var-update should be considered
+# out of scope.
+mi_gdb_test "-var-create null_ptr * **0" \
+ {\^done,name="null_ptr",numchild="0",type="int"} \
+ "create null_ptr"
+
+# Allow this to succeed, if address zero is readable, although it
+# will not test what it was meant to. Most important is that GDB
+# does not crash.
+mi_gdb_test "-var-update null_ptr" \
+ {\^done,changelist=\[{.*}\]} \
+ "update null_ptr"
+
+mi_gdb_test "-var-delete null_ptr" \
+ "\\^done,ndeleted=\"1\"" \
+ "delete null_ptr"
+
+# When we fail to read a varobj created from a named variable,
+# we evaluate its type instead. Make sure that doesn't blow
+# up by trying to read it again. We can use _end when not running
+# the program to simulate an unreadable variable, if this platform
+# provides _end, but cope if it's missing.
+
+mi_gdb_test "kill" \
+ {&"kill\\n".*\^done} \
+ "kill program before endvar"
+
+mi_gdb_test "-var-create endvar * _end" \
+ {(\^done,name="endvar",numchild="0",type=".*"|&".*unable to.*".*\^error,msg=".*")} \
+ "create endvar"
+
+# Allow this to succeed whether the value is readable, unreadable, or
+# missing. Most important is that GDB does not crash.
+mi_gdb_test "-var-update endvar" \
+ {(\^done,changelist=\[.*\]|^".*".*\^error,msg=".*not found")} \
+ "update endvar"
+
+mi_gdb_test "-var-delete endvar" \
+ "\\^done,ndeleted=\"1\"" \
+ "delete endvar"
+
mi_gdb_exit
return 0
diff --git a/gdb/varobj.c b/gdb/varobj.c
index a9f8ee0..33cea73 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -1908,7 +1908,7 @@ c_name_of_child (struct varobj *parent, int index)
static struct value *
c_value_of_root (struct varobj **var_handle)
{
- struct value *new_val;
+ struct value *new_val = NULL;
struct varobj *var = *var_handle;
struct frame_info *fi;
int within_scope;