Automatically use hardware watchpoints

Vladimir Prus
2006-11-01T11:48:00Z

[-- Attachment #1: Type: text/plain, Size: 1296 bytes --]

Hello!

At the moment, gdb is not very good at debugging applications in flash:
- you must remember to use 'hbreak' and not 'break'
- a number of commands (like "next") want to use breakpoints
internally. Since software breakpoints do no work, those commands
do no work either.

This patch makes insert_bp_location automatically decide what breakpoint type
should be used if the target provides a memory map.

Tested by running binary from flash and observing that 'break', 'step', 'next'
and 'finish' all work fine, while they did not work before. OK?

There are couples of other calls to target_set_breakpoint that are not
affected by this patch. On a preliminary look, one call is executed only for
one system (hppa) and the other call seems wrong. I'll look into that more
and will send a separate patch.

- Volodya

gdb/
* breakpoint.c: Include "memattr.h".
(automatic_hardware_breakpoints): New.
(show_automatic_hardware_breakpoints): New.
(insert_bp_location): Automatically use
hardware breakpoints.
(_initialize_breakpoint): Register the "auto-hw"
variable.
* Makefile.in (breakpoint.o): Update dependencies.

gdb/doc
* gdb.texinfo (Setting breakpoints): Document
automatic software/hardware breakpoint usage and
the "set breakpoint auto-hw" command.

[-- Attachment #2: breakpoint.diff --]
[-- Type: text/x-diff, Size: 4221 bytes --]

Index: breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.231
diff -u -r1.231 breakpoint.c
--- breakpoint.c 19 Oct 2006 15:58:25 -0000 1.231
+++ breakpoint.c 1 Nov 2006 11:46:42 -0000
@@ -53,6 +53,7 @@
#include "solist.h"
#include "observer.h"
#include "exceptions.h"
+#include "memattr.h"

#include "gdb-events.h"
#include "mi/mi-common.h"
@@ -231,6 +232,22 @@
value);
}

+/* If 1, gdb will automatically use hardware breakpoints for breakpoints
+ set with "break" but falling in read-only memory.
+ If 0, gdb will warn about such breakpoints, but won't automatically
+ use hardware breakpoints. */
+static int automatic_hardware_breakpoints;
+static void
+show_automatic_hardware_breakpoints (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ fprintf_filtered (file, _("\
+Automatic usage of hardware breakpoints is %s.\n"),
+ value);
+}
+
+
void _initialize_breakpoint (void);

extern int addressprint; /* Print machine addresses? */
@@ -794,6 +811,57 @@
if (bpt->loc_type == bp_loc_software_breakpoint
|| bpt->loc_type == bp_loc_hardware_breakpoint)
{
+ if (bpt->owner->type != bp_hardware_breakpoint)
+ {
+ /* If the explicitly specified breakpoint type
+ is not hardware breakpoint, check the memory map to see
+ if the breakpoint address is in read only memory or not.
+ Two important cases are:
+ - location type is not hardware breakpoint, memory
+ is readonly. We change the type of the location to
+ hardware breakpoint.
+ - location type is hardware breakpoint, memory is read-write.
+ This means we've previously made the location hardware one, but
+ then the memory map changed, so we undo.
+
+ When breakpoints are removed, remove_breakpoints will
+ use location types we've just set here, the only possible
+ problem is that memory map has changed during running program,
+ but it's not going to work anyway with current gdb. */
+ struct mem_region *mr
+ = lookup_mem_region (bpt->target_info.placed_address);
+
+ if (mr)
+ {
+ if (automatic_hardware_breakpoints)
+ {
+ int changed = 0;
+ enum bp_loc_type new_type;
+
+ if (mr->attrib.mode != MEM_RW)
+ new_type = bp_loc_hardware_breakpoint;
+ else
+ new_type = bp_loc_software_breakpoint;
+
+ if (new_type != bpt->loc_type)
+ {
+ static int said = 0;
+ bpt->loc_type = new_type;
+ if (!said)
+ {
+ fprintf_filtered (gdb_stdout,
+ _("Note: automatically using hardware breakpoints for read-only addresses.\n"));
+ said = 1;
+ }
+ }
+ }
+ else if (bpt->loc_type == bp_loc_software_breakpoint
+ && mr->attrib.mode != MEM_RW)
+ warning (_("cannot set software breakpoint at readonly address %s"),
+ paddr (bpt->address));
+ }
+ }
+
/* First check to see if we have to handle an overlay. */
if (overlay_debugging == ovly_off
|| bpt->section == NULL
@@ -1235,6 +1303,9 @@
if (b->inserted)
{
remove_breakpoint (b, mark_inserted);
+ /* Note: since we insert a breakpoint right after removing,
+ any decisions about automatically using hardware breakpoints
+ made in insert_bp_location are preserved. */
if (b->loc_type == bp_loc_hardware_breakpoint)
val = target_insert_hw_breakpoint (&b->target_info);
else
@@ -8127,4 +8198,18 @@
&breakpoint_show_cmdlist);

pending_break_support = AUTO_BOOLEAN_AUTO;
+
+ add_setshow_boolean_cmd ("auto-hw", no_class,
+ &automatic_hardware_breakpoints, _("\
+Set automatic usage of hardware breakpoints."), _("\
+Show automatic usage of hardware breakpoints."), _("\
+If set, the debugger will automatically use hardware breakpoints for\n\
+breakpoints set with \"break\" but falling in read-only memory. If not set,\n\
+a warning will be emitted for such breakpoints."),
+ NULL,
+ show_automatic_hardware_breakpoints,
+ &breakpoint_set_cmdlist,
+ &breakpoint_show_cmdlist);
+
+ automatic_hardware_breakpoints = 1;
}