aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog21
-rw-r--r--gdb/NEWS22
-rw-r--r--gdb/ada-lang.c2
-rw-r--r--gdb/breakpoint.c51
-rw-r--r--gdb/breakpoint.h6
-rw-r--r--gdb/doc/ChangeLog7
-rw-r--r--gdb/doc/gdb.texinfo30
-rw-r--r--gdb/guile/scm-breakpoint.c2
-rw-r--r--gdb/linespec.c18
-rw-r--r--gdb/python/py-breakpoint.c2
-rw-r--r--gdb/testsuite/ChangeLog9
-rw-r--r--gdb/testsuite/gdb.base/condbreak-multi-context.exp25
-rw-r--r--gdb/testsuite/gdb.linespec/cpcompletion.exp12
-rw-r--r--gdb/testsuite/gdb.linespec/explicit.exp1
-rw-r--r--gdb/testsuite/lib/completion-support.exp2
15 files changed, 189 insertions, 21 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6b0a7c1..7cf96aa 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,26 @@
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.
* breakpoint.c (set_breakpoint_location_condition): New function.
(set_breakpoint_condition): Disable a breakpoint location if parsing
diff --git a/gdb/NEWS b/gdb/NEWS
index 1789cf3..c99d318 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -21,6 +21,28 @@ set debug event-loop
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"
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 0a5b93f..9aba814 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -12684,7 +12684,7 @@ create_ada_exception_catchpoint (struct gdbarch *gdbarch,
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);
}
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 0d3fd0c..152f406 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -882,7 +882,7 @@ set_breakpoint_location_condition (const char *cond_string, bp_location *loc,
void
set_breakpoint_condition (struct breakpoint *b, const char *exp,
- int from_tty)
+ int from_tty, bool force)
{
if (*exp == 0)
{
@@ -950,8 +950,9 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
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;
}
}
@@ -1032,6 +1033,18 @@ condition_command (const char *arg, int from_tty)
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);
@@ -1051,7 +1064,7 @@ condition_command (const char *arg, int from_tty)
" 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);
@@ -9172,6 +9185,7 @@ find_condition_and_thread (const char *tok, CORE_ADDR pc,
*thread = -1;
*task = 0;
*rest = NULL;
+ bool force = false;
while (tok && *tok)
{
@@ -9195,10 +9209,25 @@ find_condition_and_thread (const char *tok, CORE_ADDR pc,
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;
@@ -15252,7 +15281,8 @@ specified name as a complete fully-qualified name instead."
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\
@@ -15265,6 +15295,9 @@ stack frame. This is useful for breaking on return to a stack frame.\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\
@@ -15586,8 +15619,10 @@ then no output is printed when it is hit, except what the commands print."));
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, _("\
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 7d02ced..7845dd7 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -1627,9 +1627,11 @@ extern int breakpoints_should_be_inserted_now (void);
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. */
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 84c173b..b8a4429 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,5 +1,12 @@
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
locations for which the breakpoint condition is invalid.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9da79ed..d779d4a 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -4318,6 +4318,30 @@ undefined variable:
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
@@ -5503,6 +5527,12 @@ not actually evaluate @var{expression} at the time the @code{condition}
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.
diff --git a/gdb/guile/scm-breakpoint.c b/gdb/guile/scm-breakpoint.c
index 96b6ca9..7c97072 100644
--- a/gdb/guile/scm-breakpoint.c
+++ b/gdb/guile/scm-breakpoint.c
@@ -905,7 +905,7 @@ gdbscm_set_breakpoint_condition_x (SCM self, SCM newvalue)
? 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;
});
diff --git a/gdb/linespec.c b/gdb/linespec.c
index a5fd3af..3416193 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -72,7 +72,7 @@ enum class linespec_complete_what
/* 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,
};
@@ -254,8 +254,9 @@ typedef enum ls_token_type linespec_token_type;
/* 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 */
@@ -486,11 +487,22 @@ linespec_lexer_lex_keyword (const char *p)
{
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);
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 7369c91..8099b06 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -461,7 +461,7 @@ bppy_set_condition (PyObject *self, PyObject *newvalue, void *closure)
try
{
- set_breakpoint_condition (self_bp->bp, exp, 0);
+ set_breakpoint_condition (self_bp->bp, exp, 0, false);
}
catch (gdb_exception &ex)
{
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 4e5f5dc..cf646c7 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,14 @@
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.
* gdb.base/condbreak-multi-context.exp: New file.
diff --git a/gdb/testsuite/gdb.base/condbreak-multi-context.exp b/gdb/testsuite/gdb.base/condbreak-multi-context.exp
index 4e56d36..cef4280 100644
--- a/gdb/testsuite/gdb.base/condbreak-multi-context.exp
+++ b/gdb/testsuite/gdb.base/condbreak-multi-context.exp
@@ -228,3 +228,28 @@ with_test_prefix "scenario 3" {
# 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"
+}
diff --git a/gdb/testsuite/gdb.linespec/cpcompletion.exp b/gdb/testsuite/gdb.linespec/cpcompletion.exp
index 2c95e2b..de96556 100644
--- a/gdb/testsuite/gdb.linespec/cpcompletion.exp
+++ b/gdb/testsuite/gdb.linespec/cpcompletion.exp
@@ -836,12 +836,14 @@ proc_with_prefix function-labels {} {
}
# 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.
@@ -865,7 +867,9 @@ proc_with_prefix keywords-after-function {} {
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" } \
diff --git a/gdb/testsuite/gdb.linespec/explicit.exp b/gdb/testsuite/gdb.linespec/explicit.exp
index e9ccbbb..52a1fce 100644
--- a/gdb/testsuite/gdb.linespec/explicit.exp
+++ b/gdb/testsuite/gdb.linespec/explicit.exp
@@ -405,6 +405,7 @@ namespace eval $testfile {
# completion matches both the explicit location options and
# the linespec keywords.
set completions_list {
+ "-force-condition"
"-function"
"-label"
"-line"
diff --git a/gdb/testsuite/lib/completion-support.exp b/gdb/testsuite/lib/completion-support.exp
index 51436cc..dbb9581 100644
--- a/gdb/testsuite/lib/completion-support.exp
+++ b/gdb/testsuite/lib/completion-support.exp
@@ -27,7 +27,7 @@ namespace eval completion {
# 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"}