Index: gdb/ChangeLog =================================================================== RCS file: /cvs/src/src/gdb/ChangeLog,v retrieving revision 1.9247 diff -u -p -r1.9247 ChangeLog --- gdb/ChangeLog 23 Mar 2008 17:29:32 -0000 1.9247 +++ gdb/ChangeLog 24 Mar 2008 17:31:09 -0000 @@ -1,3 +1,15 @@ +2008-03-24 Nick Roberts + Vladimir Prus + + * 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 PR gdb/544 Index: gdb/varobj.c =================================================================== RCS file: /cvs/src/src/gdb/varobj.c,v retrieving revision 1.105 diff -u -p -r1.105 varobj.c --- gdb/varobj.c 23 Mar 2008 09:53:52 -0000 1.105 +++ gdb/varobj.c 24 Mar 2008 17:31:11 -0000 @@ -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 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 *chi 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_han /* 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) - { - 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); - } + ptid_t ptid = thread_id_to_pid (var->root->thread_id); + if (in_thread_list (ptid)) + { + switch_to_thread (ptid); + within_scope = check_scope (var); + } } if (within_scope) Index: gdb/varobj.h =================================================================== RCS file: /cvs/src/src/gdb/varobj.h,v retrieving revision 1.15 diff -u -p -r1.15 varobj.h --- gdb/varobj.h 30 Jan 2008 07:17:31 -0000 1.15 +++ gdb/varobj.h 24 Mar 2008 17:31:11 -0000 @@ -89,6 +89,8 @@ extern enum varobj_display_formats varob 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); Index: gdb/mi/mi-cmd-var.c =================================================================== RCS file: /cvs/src/src/gdb/mi/mi-cmd-var.c,v retrieving revision 1.45 diff -u -p -r1.45 mi-cmd-var.c --- gdb/mi/mi-cmd-var.c 30 Jan 2008 07:17:31 -0000 1.45 +++ gdb/mi/mi-cmd-var.c 24 Mar 2008 17:31:13 -0000 @@ -50,6 +50,7 @@ print_varobj (struct varobj *var, enum p { 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 p 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); }