aboutsummaryrefslogtreecommitdiff
path: root/gdb/breakpoint.h
diff options
context:
space:
mode:
authorTankut Baris Aktemur <tankut.baris.aktemur@intel.com>2020-10-27 10:56:03 +0100
committerTankut Baris Aktemur <tankut.baris.aktemur@intel.com>2020-10-27 10:58:45 +0100
commitb5fa468fef441528147c3a47b085612d5305f181 (patch)
tree8cb19671c8ba66125d06239919fbe935222f5235 /gdb/breakpoint.h
parentafeee87bdc2b786804220949adbda5e331ec9b7a (diff)
downloadgdb-b5fa468fef441528147c3a47b085612d5305f181.zip
gdb-b5fa468fef441528147c3a47b085612d5305f181.tar.gz
gdb-b5fa468fef441528147c3a47b085612d5305f181.tar.bz2
gdb/breakpoint: disable a bp location if condition is invalid at that location
Currently, for a conditional breakpoint, GDB checks if the condition can be evaluated in the context of the first symtab and line (SAL). In case of an error, defining the conditional breakpoint is aborted. This prevents having a conditional breakpoint whose condition may actually be meaningful for some of the location contexts. This patch makes it possible to define conditional BPs by checking all location contexts. If the condition is meaningful for even one context, the breakpoint is defined. The locations for which the condition gives errors are disabled. The bp_location struct is introduced a new field, 'disabled_by_cond'. This field denotes whether the location is disabled automatically because the condition was non-evaluatable. Disabled-by-cond locations cannot be enabled by the user. But locations that are not disabled-by-cond can be enabled/disabled by the user manually as before. For a concrete example, consider 3 contexts of a function 'func'. class Base { public: int b = 20; void func () {} }; class A : public Base { public: int a = 10; void func () {} }; class C : public Base { public: int c = 30; void func () {} }; Note that * the variable 'a' is defined only in the context of A::func. * the variable 'c' is defined only in the context of C::func. * the variable 'b' is defined in all the three contexts. With the existing GDB, it's not possible to define a conditional breakpoint at 'func' if the condition refers to 'a' or 'c': (gdb) break func if a == 10 No symbol "a" in current context. (gdb) break func if c == 30 No symbol "c" in current context. (gdb) info breakpoints No breakpoints or watchpoints. With this patch, it becomes possible: (gdb) break func if a == 10 warning: failed to validate condition at location 1, disabling: No symbol "a" in current context. warning: failed to validate condition at location 3, disabling: No symbol "a" in current context. Breakpoint 1 at 0x11b6: func. (3 locations) (gdb) break func if c == 30 Note: breakpoint 1 also set at pc 0x11ce. Note: breakpoint 1 also set at pc 0x11c2. Note: breakpoint 1 also set at pc 0x11b6. warning: failed to validate condition at location 1, disabling: No symbol "c" in current context. warning: failed to validate condition at location 2, disabling: No symbol "c" in current context. Breakpoint 2 at 0x11b6: func. (3 locations) (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y <MULTIPLE> stop only if a == 10 1.1 N* 0x00000000000011b6 in Base::func() at condbreak-multi-context.cc:23 1.2 y 0x00000000000011c2 in A::func() at condbreak-multi-context.cc:31 1.3 N* 0x00000000000011ce in C::func() at condbreak-multi-context.cc:39 2 breakpoint keep y <MULTIPLE> stop only if c == 30 2.1 N* 0x00000000000011b6 in Base::func() at condbreak-multi-context.cc:23 2.2 N* 0x00000000000011c2 in A::func() at condbreak-multi-context.cc:31 2.3 y 0x00000000000011ce in C::func() at condbreak-multi-context.cc:39 (*): Breakpoint condition is invalid at this location. Here, uppercase 'N' denotes that the location is disabled because of the invalid condition, as mentioned with a footnote in the legend of the table. Locations that are disabled by the user are still denoted with lowercase 'n'. Executing the code hits the breakpoints 1.2 and 2.3 as expected. Defining a condition on an unconditional breakpoint gives the same behavior above: (gdb) break func Breakpoint 1 at 0x11b6: func. (3 locations) (gdb) cond 1 a == 10 warning: failed to validate condition at location 1.1, disabling: No symbol "a" in current context. warning: failed to validate condition at location 1.3, disabling: No symbol "a" in current context. (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y <MULTIPLE> stop only if a == 10 1.1 N* 0x00000000000011b6 in Base::func() at condbreak-multi-context.cc:23 1.2 y 0x00000000000011c2 in A::func() at condbreak-multi-context.cc:31 1.3 N* 0x00000000000011ce in C::func() at condbreak-multi-context.cc:39 (*): Breakpoint condition is invalid at this location. Locations that are disabled because of a condition cannot be enabled by the user: ... (gdb) enable 1.1 Breakpoint 1's condition is invalid at location 1, cannot enable. Resetting the condition enables the locations back: ... (gdb) cond 1 Breakpoint 1's condition is now valid at location 1, enabling. Breakpoint 1's condition is now valid at location 3, enabling. Breakpoint 1 now unconditional. (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y <MULTIPLE> 1.1 y 0x00000000000011b6 in Base::func() at condbreak-multi-context.cc:23 1.2 y 0x00000000000011c2 in A::func() at condbreak-multi-context.cc:31 1.3 y 0x00000000000011ce in C::func() at condbreak-multi-context.cc:39 If a location is disabled by the user, a condition can still be defined but the location will remain disabled even if the condition is meaningful for the disabled location: ... (gdb) disable 1.2 (gdb) cond 1 a == 10 warning: failed to validate condition at location 1.1, disabling: No symbol "a" in current context. warning: failed to validate condition at location 1.3, disabling: No symbol "a" in current context. (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y <MULTIPLE> stop only if a == 10 1.1 N* 0x00000000000011b6 in Base::func() at condbreak-multi-context.cc:23 1.2 n 0x00000000000011c2 in A::func() at condbreak-multi-context.cc:31 1.3 N* 0x00000000000011ce in C::func() at condbreak-multi-context.cc:39 (*): Breakpoint condition is invalid at this location. The condition of a breakpoint can be changed. Locations' enable/disable states are updated accordingly. ... (gdb) cond 1 c == 30 warning: failed to validate condition at location 1.1, disabling: No symbol "c" in current context. Breakpoint 1's condition is now valid at location 3, enabling. (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y <MULTIPLE> stop only if c == 30 1.1 N* 0x00000000000011b6 in Base::func() at condbreak-multi-context.cc:23 1.2 N* 0x00000000000011c2 in A::func() at condbreak-multi-context.cc:31 1.3 y 0x00000000000011ce in C::func() at condbreak-multi-context.cc:39 (*): Breakpoint condition is invalid at this location. (gdb) cond 1 b == 20 Breakpoint 1's condition is now valid at location 1, enabling. (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y <MULTIPLE> stop only if b == 20 1.1 y 0x00000000000011b6 in Base::func() at condbreak-multi-context.cc:23 1.2 n 0x00000000000011c2 in A::func() at condbreak-multi-context.cc:31 1.3 y 0x00000000000011ce in C::func() at condbreak-multi-context.cc:39 # Note that location 1.2 was disabled by the user previously. If the condition expression is bad for all the locations, it will be rejected. (gdb) cond 1 garbage No symbol "garbage" in current context. For conditions that are invalid or valid for all the locations of a breakpoint, the existing behavior is preserved. Regression-tested on X86_64 Linux. gdb/ChangeLog: 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 the condition string gives an error. (should_be_inserted): Update to consider the 'disabled_by_cond' field. (build_target_condition_list): Ditto. (build_target_command_list): Ditto. (build_bpstat_chain): Ditto. (print_one_breakpoint_location): Ditto. (print_one_breakpoint): Ditto. (breakpoint_1): Ditto. (bp_location::bp_location): Ditto. (locations_are_equal): Ditto. (update_breakpoint_locations): Ditto. (enable_disable_bp_num_loc): Ditto. (init_breakpoint_sal): Use set_breakpoint_location_condition. (find_condition_and_thread_for_sals): New static function. (create_breakpoint): Call find_condition_and_thread_for_sals. (location_to_sals): Call find_condition_and_thread_for_sals instead of find_condition_and_thread. gdb/testsuite/ChangeLog: 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. gdb/doc/ChangeLog: 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.
Diffstat (limited to 'gdb/breakpoint.h')
-rw-r--r--gdb/breakpoint.h6
1 files changed, 6 insertions, 0 deletions
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index b9a605e..7d02ced 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -387,6 +387,12 @@ public:
/* Is this particular location enabled. */
bool enabled = false;
+ /* Is this particular location disabled because the condition
+ expression is invalid at this location. For a location to be
+ reported as enabled, the ENABLED field above has to be true *and*
+ the DISABLED_BY_COND field has to be false. */
+ bool disabled_by_cond = false;
+
/* True if this breakpoint is now inserted. */
bool inserted = false;