aboutsummaryrefslogtreecommitdiff
path: root/gdb/ada-exp.y
diff options
context:
space:
mode:
authorJoel Brobecker <brobecker@adacore.com>2017-03-03 17:31:13 +0100
committerJoel Brobecker <brobecker@adacore.com>2017-11-08 19:52:28 -0500
commit286acbb5c25c5895832d3dd3be3398d3f2d64fad (patch)
treef674472939f4612a6a1cb8eb2cf4989fff93e9ce /gdb/ada-exp.y
parentb44ec61915f10a953ca85da5bf7a97911554f1aa (diff)
downloadfsf-binutils-gdb-286acbb5c25c5895832d3dd3be3398d3f2d64fad.zip
fsf-binutils-gdb-286acbb5c25c5895832d3dd3be3398d3f2d64fad.tar.gz
fsf-binutils-gdb-286acbb5c25c5895832d3dd3be3398d3f2d64fad.tar.bz2
local variable watchpoint not deleted after leaving scope
When debugging an Ada program, and inserting a watchpoint tracking a local variable, the watchpoint doesn't get automatically deleted upon leaving that variable's scope. This watchpoint then starts creating problems later on, when trying to resume the program's execution from a location outside of the watchpoint's scope: (gdb) c Continuing. Breakpoint 2, foo_p708_025 () at foo_p708_025.adb:7 7 Do_Nothing (Val); (gdb) n No frame is currently executing in block pck.get_val. Command aborted. (gdb) c Continuing. No frame is currently executing in block pck.get_val. Command aborted. The expected output is the following: - The program's execution after the first continue should stop as soon as we reach the end of the watchpoint's scope, and the debugger should be deleting it. - Then we can continue until reaching breakpoint 2 above; - After which we should be able to do next/continue as usual. The reason the watchpoint is not automatically deleted at scope exit is because the watchpoint is not marked as being scope-specific (b->exp_valid_block is equal NULL), and this is because the symbol lookup for our local variable failed to set the innermost_block global variable during the lookup. More precisely, if we look at watch_command_1, we do the following: innermost_block = NULL; [...] exp = parse_exp_1 (&arg, 0, 0, 0); [...] exp_valid_block = innermost_block; Currently, innermost_block stays NULL after the call to parse_exp_1. Digging further, this innermost_block is typically set during symbol lookup when the symbol is considered to have a frame-relative address. For instance, in c-exp.y, we see some code like the following: if (symbol_read_needs_frame (sym.symbol)) { if (innermost_block == 0 || contained_in (sym.block, innermost_block)) innermost_block = sym.block; } We actually have the exact same mechanism in ada-exp.y, except that it vhas accidently been turned off. See write_var_from_sym, where we start with: if (orig_left_context == NULL && symbol_read_needs_frame (sym)) { if (innermost_block == 0 || contained_in (block, innermost_block)) innermost_block = block; } In this case, orig_left_context is a parameter, and looking at the point of call in write_var_or_type, we see: if (nsyms == 1) { write_var_from_sym (par_state, block, syms[0].block, syms[0].symbol); In the call above, the paramater we are interested in is "block", which is a parameter for write_var_or_type as well, except we explicitly override its value at the beginning when found to be NULL: if (block == NULL) block = expression_context_block; So the block we pass to write_var_from_sym is not NULL, and we therefore don't set innermost_block, which leads to the watchpoint no longer being marked as scope-specific. The handling of orig_left_context in write_var_from_sym was there to handle the case where a user writes an expression where the symbol is qualified with a scope (Eg: "function::variable"). But it appears that handling this is specifically here is no longer necessary, so this patch simply removes that parameter and the associated check, and then updates all the points of calls. Interestingly, this also affects GDB/MI, and in particular varobjs, because local variables are now properly reported as having a block, which causes the associated varob to have a "thread-id" field. This patch also adjusts a couple of Ada/gdb-mi tests. gdb/ChangeLog: * ada-exp.y (write_var_from_sym): Remove parameter "orig_left_context". Update all callers. gdb/testsuite/ChangeLog: * gdb.ada/scoped_watch: New testcase. * gdb.ada/watch_arg.exp: Adjust expected behavior to the behavior which is actually correct. * gdb.ada/mi_interface.exp: Add missing thread-id in expected varobj. * gdb.ada/mi_var_array.exp: Add missing thread-id in expected varobj.
Diffstat (limited to 'gdb/ada-exp.y')
-rw-r--r--gdb/ada-exp.y16
1 files changed, 7 insertions, 9 deletions
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 3014a31..004d58b 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -749,14 +749,14 @@ yyerror (const char *msg)
}
/* Emit expression to access an instance of SYM, in block BLOCK (if
- * non-NULL), and with :: qualification ORIG_LEFT_CONTEXT. */
+ non-NULL). */
+
static void
write_var_from_sym (struct parser_state *par_state,
- const struct block *orig_left_context,
const struct block *block,
struct symbol *sym)
{
- if (orig_left_context == NULL && symbol_read_needs_frame (sym))
+ if (symbol_read_needs_frame (sym))
{
if (innermost_block == 0
|| contained_in (block, innermost_block))
@@ -837,8 +837,7 @@ write_object_renaming (struct parser_state *par_state,
&inner_renaming_expr))
{
case ADA_NOT_RENAMING:
- write_var_from_sym (par_state, orig_left_context, sym_info.block,
- sym_info.symbol);
+ write_var_from_sym (par_state, sym_info.block, sym_info.symbol);
break;
case ADA_OBJECT_RENAMING:
write_object_renaming (par_state, sym_info.block,
@@ -899,7 +898,7 @@ write_object_renaming (struct parser_state *par_state,
else if (SYMBOL_CLASS (index_sym_info.symbol) == LOC_TYPEDEF)
/* Index is an old-style renaming symbol. */
index_sym_info.block = orig_left_context;
- write_var_from_sym (par_state, NULL, index_sym_info.block,
+ write_var_from_sym (par_state, index_sym_info.block,
index_sym_info.symbol);
}
if (slice_state == SIMPLE_INDEX)
@@ -1310,8 +1309,7 @@ write_var_or_type (struct parser_state *par_state,
if (nsyms == 1)
{
- write_var_from_sym (par_state, block, syms[0].block,
- syms[0].symbol);
+ write_var_from_sym (par_state, syms[0].block, syms[0].symbol);
write_selectors (par_state, encoded_name + tail_index);
return NULL;
}
@@ -1384,7 +1382,7 @@ write_name_assoc (struct parser_state *par_state, struct stoken name)
if (nsyms != 1 || SYMBOL_CLASS (syms[0].symbol) == LOC_TYPEDEF)
write_exp_op_with_string (par_state, OP_NAME, name);
else
- write_var_from_sym (par_state, NULL, syms[0].block, syms[0].symbol);
+ write_var_from_sym (par_state, syms[0].block, syms[0].symbol);
}
else
if (write_var_or_type (par_state, NULL, name) != NULL)