[RFC] Improve handling of breakpoints with multiple locations.
Philippe Waroquiers
philippe.waroquiers@skynet.be
Sat May 23 21:11:32 GMT 2020
(RFC to get comments on the idea before updating tests and user manual).
Currently, when a breakpoint that has multiple locations is reached,
GDB prints:
Thread 1 "zeoes" hit Breakpoint 1, some_func () at somefunc1.c:5
This patch changes the message so that bkpt_print_id prints the precise
encountered breakpoint:
Thread 1 "zeoes" hit Breakpoint 1.2, some_func () at somefunc1.c:5
Note that bkpt_print_it thus (optionally) prints a new table field "locno":
locno is printed when the breakpoint has more than one location.
According to the GDB user manual node 'GDB/MI Development and Front Ends',
it is ok to add new fields in the output of a command without
changing the MI version.
Also, when a breakpoint is reached, the convenience variables
$bkptno and $locno are set to the reached breakpoint number
and location number.
$bkptno and $locno can a.o. be used in breakpoint commands,
to disable the specific encountered breakpoint.
In case the breakpoint has only one location, $locno is still set to
the value 1, so as to allow a command such as:
disable $bkptno.$locno
even when the breakpoint has only one location.
This also fixes a strange behaviour: when a breakpoint X has only
one location,
enable|disable X.1
is accepted but transforms the breakpoint in a MULTIPLE locations
breakpoint having only one location.
Still to do:
* user manual
* NEWS
* add and update tests to new output.
gdb/ChangeLog
YYYY-MM-DD Philippe Waroquiers <philippe.waroquiers@skynet.be>
* breakpoint.c (has_multiple_locations): New function.
(bpstat_num): Replace comment by 'See Breakpoint.h.'.
(bpstat_locno): New function.
(bkpt_print_it): Print the locno.
(enable_disable_command): Avoid that enable|disable y.1
transforms y into a MULTIPLE locations breakpoint.
* breakpoint.h (bpstat_locno): New function.
* infrun.c (print_stop_location): Initialize convenience vars
$bkptno and $locno.
---
gdb/breakpoint.c | 78 ++++++++++++++++++++++++++++++++++++++++--------
gdb/breakpoint.h | 5 ++++
gdb/infrun.c | 13 +++++++-
3 files changed, 82 insertions(+), 14 deletions(-)
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index aead882acd..b478593fde 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -656,6 +656,21 @@ get_breakpoint (int num)
return NULL;
}
+/* Return TRUE if NUM refer to an existing breakpoint that has
+ multiple locations. */
+
+static bool
+has_multiple_locations (int num)
+{
+ struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->number == num)
+ return b->loc != nullptr && b->loc->next != nullptr;
+
+ return false;
+}
+
/* Mark locations as "conditions have changed" in case the target supports
@@ -4229,15 +4244,7 @@ bpstat_explains_signal (bpstat bsp, enum gdb_signal sig)
return false;
}
-/* Put in *NUM the breakpoint number of the first breakpoint we are
- stopped at. *BSP upon return is a bpstat which points to the
- remaining breakpoints stopped at (but which is not guaranteed to be
- good for anything but further calls to bpstat_num).
-
- Return 0 if passed a bpstat which does not indicate any breakpoints.
- Return -1 if stopped at a breakpoint that has been deleted since
- we set it.
- Return 1 otherwise. */
+/* See breakpoint.h. */
int
bpstat_num (bpstat *bsp, int *num)
@@ -4259,6 +4266,39 @@ bpstat_num (bpstat *bsp, int *num)
return 1;
}
+/* See breakpoint.h */
+
+int
+bpstat_locno (bpstat bs)
+{
+ const struct breakpoint *b = bs->breakpoint_at;
+ const struct bp_location *bl = bs->bp_location_at;
+
+ int locno = 0;
+
+ if (b != nullptr && b->loc->next != nullptr)
+ {
+ const bp_location *bl_i;
+
+ for (bl_i = b->loc;
+ bl_i != bl && bl_i->next != nullptr;
+ bl_i = bl_i->next)
+ locno++;
+
+ if (bl_i == bl)
+ locno++;
+ else
+ {
+ warning (_("location number not found for breakpoint %d address %p."),
+ b->number, paddress (bl->gdbarch, bl->address));
+ locno = 0;
+ }
+ }
+
+ return locno;
+}
+
+
/* See breakpoint.h. */
void
@@ -12455,13 +12495,21 @@ bkpt_print_it (bpstat bs)
async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
uiout->field_string ("disp", bpdisp_text (b->disposition));
}
+
+ int locno = bpstat_locno (bs);
+
if (bp_temp)
- uiout->message ("Temporary breakpoint %pF, ",
+ uiout->message ("Temporary breakpoint %pF",
signed_field ("bkptno", b->number));
else
- uiout->message ("Breakpoint %pF, ",
+ uiout->message ("Breakpoint %pF",
signed_field ("bkptno", b->number));
+ if (locno == 0)
+ uiout->message (", ");
+ else
+ uiout->message (".%pF, ",
+ signed_field ("locno", locno));
return PRINT_SRC_AND_LOC;
}
@@ -14243,9 +14291,13 @@ enable_disable_command (const char *args, int from_tty, bool enable)
extract_bp_number_and_location (num, bp_num_range, bp_loc_range);
if (bp_loc_range.first == bp_loc_range.second
- && bp_loc_range.first == 0)
+ && (bp_loc_range.first == 0
+ || (bp_loc_range.first == 1
+ && bp_num_range.first == bp_num_range.second
+ && !has_multiple_locations (bp_num_range.first))))
{
- /* Handle breakpoint ids with formats 'x' or 'x-z'. */
+ /* Handle breakpoint ids with formats 'x' or 'x-z'
+ or 'y.1' where y has only one location. */
map_breakpoint_number_range (bp_num_range,
enable
? enable_breakpoint
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 347aeb75f3..eaf6d86848 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -1091,6 +1091,11 @@ extern enum print_stop_action bpstat_print (bpstat, int);
Return 1 otherwise. */
extern int bpstat_num (bpstat *, int *);
+/* If BS indicates a breakpoint and this breakpoint has several locations,
+ return the location number of BS, otherwise return 0. */
+
+extern int bpstat_locno (bpstat bs);
+
/* Perform actions associated with the stopped inferior. Actually, we
just use this for breakpoint commands. Perhaps other actions will
go here later, but this is executed at a late time (from the
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 95fc3bfe45..8b84c6e22e 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -8349,7 +8349,18 @@ print_stop_location (struct target_waitstatus *ws)
LOCATION: Print only location
SRC_AND_LOC: Print location and source line. */
if (do_frame_printing)
- print_stack_frame (get_selected_frame (NULL), 0, source_flag, 1);
+ {
+ const struct breakpoint *b = tp->control.stop_bpstat->breakpoint_at;
+
+ if (b != nullptr)
+ {
+ int locno = bpstat_locno (tp->control.stop_bpstat);
+ set_internalvar_integer (lookup_internalvar ("bkptno"), b->number);
+ set_internalvar_integer (lookup_internalvar ("locno"),
+ (locno > 0 ? locno : 1));
+ }
+ print_stack_frame (get_selected_frame (NULL), 0, source_flag, 1);
+ }
}
/* See infrun.h. */
--
2.20.1
More information about the Gdb-patches
mailing list