aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog12
-rw-r--r--gdb/mi/mi-cmd-var.c5
-rw-r--r--gdb/varobj.c72
-rw-r--r--gdb/varobj.h2
4 files changed, 78 insertions, 13 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ed25beb..16a6c62 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,15 @@
+2008-03-24 Nick Roberts <nickrob@snap.net.nz>
+ Vladimir Prus <vladimir@codesourcery.com>
+
+ * varobj.c (struct varobj_root): New component thread_id.
+ (varobj_get_thread_id, check_scope): New functions.
+ (c_value_of_root): Use check_scope. Switch to the
+ proper thread if necessary.
+
+ * varobj.h (varobj_get_thread_id): New extern.
+
+ * mi/mi-cmd-var.c (print_varobj): Add thread-id field.
+
2008-03-23 Daniel Jacobowitz <dan@codesourcery.com>
PR gdb/544
diff --git a/gdb/mi/mi-cmd-var.c b/gdb/mi/mi-cmd-var.c
index 7dfa1f0..dc873ca 100644
--- a/gdb/mi/mi-cmd-var.c
+++ b/gdb/mi/mi-cmd-var.c
@@ -50,6 +50,7 @@ print_varobj (struct varobj *var, enum print_values print_values,
{
struct type *gdb_type;
char *type;
+ int thread_id;
ui_out_field_string (uiout, "name", varobj_get_objname (var));
if (print_expression)
@@ -66,6 +67,10 @@ print_varobj (struct varobj *var, enum print_values print_values,
xfree (type);
}
+ thread_id = varobj_get_thread_id (var);
+ if (thread_id > 0)
+ ui_out_field_int (uiout, "thread-id", thread_id);
+
if (varobj_get_frozen (var))
ui_out_field_int (uiout, "frozen", 1);
}
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 3f08dfc..c8d85a9 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -68,6 +68,13 @@ struct varobj_root
not NULL. */
struct frame_id frame;
+ /* The thread ID that this varobj_root belong to. This field
+ is only valid if valid_block is not NULL.
+ When not 0, indicates which thread 'frame' belongs to.
+ When 0, indicates that the thread list was empty when the varobj_root
+ was created. */
+ int thread_id;
+
/* If 1, "update" always recomputes the frame & valid block
using the currently selected frame. */
int use_selected_frame;
@@ -503,8 +510,9 @@ varobj_create (char *objname,
if (innermost_block && fi != NULL)
{
var->root->frame = get_frame_id (fi);
+ var->root->thread_id = pid_to_thread_id (inferior_ptid);
old_fi = get_selected_frame (NULL);
- select_frame (fi);
+ select_frame (fi);
}
/* We definitely need to catch errors here.
@@ -692,6 +700,19 @@ varobj_get_display_format (struct varobj *var)
return var->format;
}
+/* If the variable object is bound to a specific thread, that
+ is its evaluation can always be done in context of a frame
+ inside that thread, returns GDB id of the thread -- which
+ is always positive. Otherwise, returns -1. */
+int
+varobj_get_thread_id (struct varobj *var)
+{
+ if (var->root->valid_block && var->root->thread_id > 0)
+ return var->root->thread_id;
+ else
+ return -1;
+}
+
void
varobj_set_frozen (struct varobj *var, int frozen)
{
@@ -2138,13 +2159,36 @@ c_path_expr_of_child (struct varobj *child)
return child->path_expr;
}
+/* If frame associated with VAR can be found, switch
+ to it and return 1. Otherwise, return 0. */
+static int
+check_scope (struct varobj *var)
+{
+ struct frame_info *fi;
+ int scope;
+
+ fi = frame_find_by_id (var->root->frame);
+ scope = fi != NULL;
+
+ if (fi)
+ {
+ CORE_ADDR pc = get_frame_pc (fi);
+ if (pc < BLOCK_START (var->root->valid_block) ||
+ pc >= BLOCK_END (var->root->valid_block))
+ scope = 0;
+ else
+ select_frame (fi);
+ }
+ return scope;
+}
+
static struct value *
c_value_of_root (struct varobj **var_handle)
{
struct value *new_val = NULL;
struct varobj *var = *var_handle;
struct frame_info *fi;
- int within_scope;
+ int within_scope = 0;
struct cleanup *back_to;
/* Only root variables can be updated... */
@@ -2158,20 +2202,22 @@ c_value_of_root (struct varobj **var_handle)
/* Determine whether the variable is still around. */
if (var->root->valid_block == NULL || var->root->use_selected_frame)
within_scope = 1;
+ else if (var->root->thread_id == 0)
+ {
+ /* The program was single-threaded when the variable object was
+ created. Technically, it's possible that the program became
+ multi-threaded since then, but we don't support such
+ scenario yet. */
+ within_scope = check_scope (var);
+ }
else
{
- fi = frame_find_by_id (var->root->frame);
- within_scope = fi != NULL;
- /* FIXME: select_frame could fail */
- if (fi)
+ ptid_t ptid = thread_id_to_pid (var->root->thread_id);
+ if (in_thread_list (ptid))
{
- CORE_ADDR pc = get_frame_pc (fi);
- if (pc < BLOCK_START (var->root->valid_block) ||
- pc >= BLOCK_END (var->root->valid_block))
- within_scope = 0;
- else
- select_frame (fi);
- }
+ switch_to_thread (ptid);
+ within_scope = check_scope (var);
+ }
}
if (within_scope)
diff --git a/gdb/varobj.h b/gdb/varobj.h
index e0a5c17..4033b4b 100644
--- a/gdb/varobj.h
+++ b/gdb/varobj.h
@@ -89,6 +89,8 @@ extern enum varobj_display_formats varobj_set_display_format (
extern enum varobj_display_formats varobj_get_display_format (
struct varobj *var);
+extern int varobj_get_thread_id (struct varobj *var);
+
extern void varobj_set_frozen (struct varobj *var, int frozen);
extern int varobj_get_frozen (struct varobj *var);