+2020-10-27 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
+
+ * breakpoint.h (set_breakpoint_condition): Add a new bool parameter.
+ * breakpoint.c: Update the help text of the 'condition' and 'break'
+ commands.
+ (set_breakpoint_condition): Take a new bool parameter
+ to control whether condition definition should be forced even when
+ the condition expression is invalid in all of the current locations.
+ (condition_command): Update the call to 'set_breakpoint_condition'.
+ (find_condition_and_thread): Take the "-force-condition" flag into
+ account.
+ * linespec.c (linespec_keywords): Add "-force-condition" as an
+ element.
+ (FORCE_KEYWORD_INDEX): New #define.
+ (linespec_lexer_lex_keyword): Update to consider "-force-condition"
+ as a keyword.
+ * ada-lang.c (create_ada_exception_catchpoint): Ditto.
+ * guile/scm-breakpoint.c (gdbscm_set_breakpoint_condition_x): Ditto.
+ * python/py-breakpoint.c (bppy_set_condition): Ditto.
+ * NEWS: Mention the changes to the 'break' and 'condition' commands.
+
2020-10-27 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* breakpoint.h (class bp_location) <disabled_by_cond>: New field.
show debug event-loop
Control the display of debug output about GDB's event loop.
+* Changed commands
+
+break [PROBE_MODIFIER] [LOCATION] [thread THREADNUM]
+ [-force-condition] [if CONDITION]
+ This command would previously refuse setting a breakpoint if the
+ CONDITION expression is invalid at a location. It now accepts and
+ defines the breakpoint if there is at least one location at which
+ the CONDITION is valid. The locations for which the CONDITION is
+ invalid, are automatically disabled. If CONDITION is invalid at all
+ of the locations, setting the breakpoint is still rejected. However,
+ the '-force-condition' flag can be used in this case for forcing GDB to
+ define the breakpoint, making all the current locations automatically
+ disabled. This may be useful if the user knows the condition will
+ become meaningful at a future location, e.g. due to a shared library
+ load.
+
+condition [-force] N COND
+ The behavior of this command is changed the same way for the 'break'
+ command as explained above. The '-force' flag can be used to force
+ GDB into defining the condition even when COND is invalid for all the
+ current locations of breakpoint N.
+
*** Changes in GDB 10
* There are new feature names for ARC targets: "org.gnu.gdb.arc.core"
c->excep_string = excep_string;
create_excep_cond_exprs (c.get (), ex_kind);
if (!cond_string.empty ())
- set_breakpoint_condition (c.get (), cond_string.c_str (), from_tty);
+ set_breakpoint_condition (c.get (), cond_string.c_str (), from_tty, false);
install_breakpoint (0, std::move (c), 1);
}
void
set_breakpoint_condition (struct breakpoint *b, const char *exp,
- int from_tty)
+ int from_tty, bool force)
{
if (*exp == 0)
{
catch (const gdb_exception_error &e)
{
/* Condition string is invalid. If this happens to
- be the last loc, abandon. */
- if (loc->next == nullptr)
+ be the last loc, abandon (if not forced) or continue
+ (if forced). */
+ if (loc->next == nullptr && !force)
throw;
}
}
error_no_arg (_("breakpoint number"));
p = arg;
+
+ /* Check if the "-force" flag was passed. */
+ bool force = false;
+ const char *tok = skip_spaces (p);
+ const char *end_tok = skip_to_space (tok);
+ int toklen = end_tok - tok;
+ if (toklen >= 1 && strncmp (tok, "-force", toklen) == 0)
+ {
+ force = true;
+ p = end_tok + 1;
+ }
+
bnum = get_number (&p);
if (bnum == 0)
error (_("Bad breakpoint argument: '%s'"), arg);
" a %s stop condition defined for this breakpoint."),
ext_lang_capitalized_name (extlang));
}
- set_breakpoint_condition (b, p, from_tty);
+ set_breakpoint_condition (b, p, from_tty, force);
if (is_breakpoint (b))
update_global_location_list (UGLL_MAY_INSERT);
*thread = -1;
*task = 0;
*rest = NULL;
+ bool force = false;
while (tok && *tok)
{
if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
{
tok = cond_start = end_tok + 1;
- parse_exp_1 (&tok, pc, block_for_pc (pc), 0);
+ try
+ {
+ parse_exp_1 (&tok, pc, block_for_pc (pc), 0);
+ }
+ catch (const gdb_exception_error &)
+ {
+ if (!force)
+ throw;
+ else
+ tok = tok + strlen (tok);
+ }
cond_end = tok;
*cond_string = savestring (cond_start, cond_end - cond_start);
}
+ else if (toklen >= 1 && strncmp (tok, "-force-condition", toklen) == 0)
+ {
+ tok = cond_start = end_tok + 1;
+ force = true;
+ }
else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
{
const char *tmptok;
command. */
#define BREAK_ARGS_HELP(command) \
-command" [PROBE_MODIFIER] [LOCATION] [thread THREADNUM] [if CONDITION]\n\
+command" [PROBE_MODIFIER] [LOCATION] [thread THREADNUM]\n\
+\t[-force-condition] [if CONDITION]\n\
PROBE_MODIFIER shall be present if the command is to be placed in a\n\
probe point. Accepted values are `-probe' (for a generic, automatically\n\
guessed probe type), `-probe-stap' (for a SystemTap probe) or \n\
\n\
THREADNUM is the number from \"info threads\".\n\
CONDITION is a boolean expression.\n\
+\n\
+With the \"-force-condition\" flag, the condition is defined even when\n\
+it is invalid for all current locations.\n\
\n" LOCATION_HELP_STRING "\n\n\
Multiple breakpoints at one place are permitted, and useful if their\n\
conditions are different.\n\
c = add_com ("condition", class_breakpoint, condition_command, _("\
Specify breakpoint number N to break only if COND is true.\n\
-Usage is `condition N COND', where N is an integer and COND is an\n\
-expression to be evaluated whenever breakpoint N is reached."));
+Usage is `condition [-force] N COND', where N is an integer and COND\n\
+is an expression to be evaluated whenever breakpoint N is reached.\n\
+With the \"-force\" flag, the condition is defined even when it is\n\
+invalid for all current locations."));
set_cmd_completer (c, condition_completer);
c = add_com ("tbreak", class_breakpoint, tbreak_command, _("\
in our opinion won't ever trigger. */
extern void breakpoint_retire_moribund (void);
-/* Set break condition of breakpoint B to EXP. */
+/* Set break condition of breakpoint B to EXP.
+ If FORCE, define the condition even if it is invalid in
+ all of the breakpoint locations. */
extern void set_breakpoint_condition (struct breakpoint *b, const char *exp,
- int from_tty);
+ int from_tty, bool force);
/* Checks if we are catching syscalls or not.
Returns 0 if not, greater than 0 if we are. */
+2020-10-27 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
+
+ * gdb.texinfo (Set Breaks): Document the '-force-condition' flag
+ of the 'break'command.
+ * gdb.texinfo (Conditions): Document the '-force' flag of the
+ 'condition' command.
+
2020-10-27 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* gdb.texinfo (Set Breaks): Document disabling of breakpoint
No symbol "foo" in current context.
@end smallexample
+@item break @dots{} -force-condition if @var{cond}
+There may be cases where the condition @var{cond} is invalid at all
+the current locations, but the user knows that it will be valid at a
+future location; for example, because of a library load. In such
+cases, by using the @code{-force-condition} keyword before @samp{if},
+@value{GDBN} can be forced to define the breakpoint with the given
+condition expression instead of refusing it.
+
+@smallexample
+(@value{GDBP}) break func -force-condition if foo
+warning: failed to validate condition at location 1, disabling:
+ No symbol "foo" in current context.
+warning: failed to validate condition at location 2, disabling:
+ No symbol "foo" in current context.
+warning: failed to validate condition at location 3, disabling:
+ No symbol "foo" in current context.
+Breakpoint 1 at 0x1158: test.c:18. (3 locations)
+@end smallexample
+
+This causes all the present locations where the breakpoint would
+otherwise be inserted, to be disabled, as seen in the example above.
+However, if there exist locations at which the condition is valid, the
+@code{-force-condition} keyword has no effect.
+
@kindex tbreak
@item tbreak @var{args}
Set a breakpoint enabled only for one stop. The @var{args} are the
command (or a command that sets a breakpoint with a condition, like
@code{break if @dots{}}) is given, however. @xref{Expressions, ,Expressions}.
+@item condition -force @var{bnum} @var{expression}
+When the @code{-force} flag is used, define the condition even if
+@var{expression} is invalid at all the current locations of breakpoint
+@var{bnum}. This is similar to the @code{-force-condition} option
+of the @code{break} command.
+
@item condition @var{bnum}
Remove the condition from breakpoint number @var{bnum}. It becomes
an ordinary unconditional breakpoint.
? nullptr
: gdbscm_scm_to_c_string (newvalue));
- set_breakpoint_condition (bp_smob->bp, exp ? exp.get () : "", 0);
+ set_breakpoint_condition (bp_smob->bp, exp ? exp.get () : "", 0, false);
return SCM_UNSPECIFIED;
});
/* An expression. E.g., "break foo if EXPR", or "break *EXPR". */
EXPRESSION,
- /* A linespec keyword ("if"/"thread"/"task").
+ /* A linespec keyword ("if"/"thread"/"task"/"-force-condition").
E.g., "break func threa<tab>". */
KEYWORD,
};
/* List of keywords. This is NULL-terminated so that it can be used
as enum completer. */
-const char * const linespec_keywords[] = { "if", "thread", "task", NULL };
+const char * const linespec_keywords[] = { "if", "thread", "task", "-force-condition", NULL };
#define IF_KEYWORD_INDEX 0
+#define FORCE_KEYWORD_INDEX 3
/* A token of the linespec lexer */
{
int j;
+ /* Special case: "-force" is always followed by an "if". */
+ if (i == FORCE_KEYWORD_INDEX)
+ {
+ p += len;
+ p = skip_spaces (p);
+ int nextlen = strlen (linespec_keywords[IF_KEYWORD_INDEX]);
+ if (!(strncmp (p, linespec_keywords[IF_KEYWORD_INDEX], nextlen) == 0
+ && isspace (p[nextlen])))
+ return NULL;
+ }
+
/* Special case: "if" ALWAYS stops the lexer, since it
is not possible to predict what is going to appear in
the condition, which can only be parsed after SaLs have
been found. */
- if (i != IF_KEYWORD_INDEX)
+ else if (i != IF_KEYWORD_INDEX)
{
p += len;
p = skip_spaces (p);
try
{
- set_breakpoint_condition (self_bp->bp, exp, 0);
+ set_breakpoint_condition (self_bp->bp, exp, 0, false);
}
catch (gdb_exception &ex)
{
+2020-10-27 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
+
+ * gdb.base/condbreak-multi-context.exp: Expand to test forcing
+ the condition.
+ * gdb.linespec/cpcompletion.exp: Update to consider the
+ '-force-condition' keyword.
+ * gdb.linespec/explicit.exp: Ditto.
+ * lib/completion-support.exp: Ditto.
+
2020-10-27 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* gdb.base/condbreak-multi-context.cc: New file.
# The second BP's locations are all disabled. No more hits!
gdb_continue_to_end
}
+
+# Scenario 4: Test the '-force'/'-force-condition' flag.
+
+with_test_prefix "force" {
+ clean_restart ${binfile}
+
+ gdb_breakpoint "func"
+ # Pick a condition that is invalid at every location.
+ set bpnum1 [get_integer_valueof "\$bpnum" 0 "get bpnum1"]
+ gdb_test "cond -force $bpnum1 foo" \
+ [multi_line \
+ "${warning} at location ${bpnum1}.1, disabling:" \
+ " No symbol \"foo\" in current context." \
+ "${warning} at location ${bpnum1}.2, disabling:" \
+ " No symbol \"foo\" in current context." \
+ "${warning} at location ${bpnum1}.3, disabling:" \
+ " No symbol \"foo\" in current context."] \
+ "force the condition of bp 1"
+ check_bp_locations $bpnum1 {N* N* N*} "after forcing the condition"
+
+ # Now with the 'break' command.
+ gdb_breakpoint "func -force-condition if baz"
+ set bpnum2 [get_integer_valueof "\$bpnum" 0 "get bpnum2"]
+ check_bp_locations $bpnum2 {N* N* N*} "set using the break command"
+}
}
# Test that completion after a function name offers keyword
-# (if/task/thread) matches in linespec mode, and also the explicit
-# location options in explicit locations mode.
+# (if/task/thread/-force-condition) matches in linespec mode, and also
+# the explicit location options in explicit locations mode.
proc_with_prefix keywords-after-function {} {
set explicit_list \
- [concat $completion::explicit_opts_list $completion::keyword_list]
+ [lsort [concat \
+ $completion::explicit_opts_list \
+ $completion::keyword_list]]
# Test without a source file, with a known source file, and with
# and unknown source file.
proc_with_prefix keywords-after-label {} {
set explicit_list \
- [concat $completion::explicit_opts_list $completion::keyword_list]
+ [lsort [concat \
+ $completion::explicit_opts_list \
+ $completion::keyword_list]]
foreach_location_labels \
{ "" "cpls.cc" } \
# completion matches both the explicit location options and
# the linespec keywords.
set completions_list {
+ "-force-condition"
"-function"
"-label"
"-line"
# List of all quote chars, including no-quote at all.
variable maybe_quoted_list {"" "'" "\""}
- variable keyword_list {"if" "task" "thread"}
+ variable keyword_list {"-force-condition" "if" "task" "thread"}
variable explicit_opts_list \
{"-function" "-label" "-line" "-qualified" "-source"}