/* Everything about breakpoints, for GDB.
- Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
- 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
+ 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
#include <ctype.h>
#include "cli/cli-script.h"
#include "gdb_assert.h"
#include "block.h"
+#include "solib.h"
#include "solist.h"
#include "observer.h"
#include "exceptions.h"
+#include "memattr.h"
#include "gdb-events.h"
+#include "mi/mi-common.h"
/* Prototypes for local functions. */
static CORE_ADDR adjust_breakpoint_address (CORE_ADDR bpaddr,
enum bptype bptype);
-static void describe_other_breakpoints (CORE_ADDR, asection *);
+static void describe_other_breakpoints (CORE_ADDR, asection *, int);
static void breakpoints_info (char *, int);
if such is available. */
static int can_use_hw_watchpoints;
+static void
+show_can_use_hw_watchpoints (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ fprintf_filtered (file, _("\
+Debugger's willingness to use watchpoint hardware is %s.\n"),
+ value);
+}
+
/* If AUTO_BOOLEAN_FALSE, gdb will not attempt to create pending breakpoints.
If AUTO_BOOLEAN_TRUE, gdb will automatically create pending breakpoints
for unrecognized breakpoint locations.
If AUTO_BOOLEAN_AUTO, gdb will query when breakpoints are unrecognized. */
static enum auto_boolean pending_break_support;
+static void
+show_pending_break_support (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ fprintf_filtered (file, _("\
+Debugger's behavior regarding pending breakpoints is %s.\n"),
+ 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);
shadow contents, not the breakpoints themselves. From breakpoint.c. */
int
-deprecated_read_memory_nobpt (CORE_ADDR memaddr, char *myaddr, unsigned len)
+read_memory_nobpt (CORE_ADDR memaddr, gdb_byte *myaddr, unsigned len)
{
int status;
struct bp_location *b;
continue;
/* Addresses and length of the part of the breakpoint that
we need to copy. */
- /* XXXX The m68k, sh and h8300 have different local and remote
- breakpoint values. BREAKPOINT_FROM_PC still manages to
- correctly determine the breakpoints memory address and size
- for these targets. */
- bp_addr = b->address;
- bp_size = 0;
- if (BREAKPOINT_FROM_PC (&bp_addr, &bp_size) == NULL)
- continue;
+ bp_addr = b->target_info.placed_address;
+ bp_size = b->target_info.shadow_len;
if (bp_size == 0)
- /* bp isn't valid */
+ /* bp isn't valid, or doesn't shadow memory. */
continue;
if (bp_addr + bp_size <= memaddr)
/* The breakpoint is entirely before the chunk of memory we
}
memcpy (myaddr + bp_addr - memaddr,
- b->shadow_contents + bptoffset, bp_size);
+ b->target_info.shadow_contents + bptoffset, bp_size);
if (bp_addr > memaddr)
{
/* Copy the section of memory before the breakpoint. */
- status = deprecated_read_memory_nobpt (memaddr, myaddr, bp_addr - memaddr);
+ status = read_memory_nobpt (memaddr, myaddr, bp_addr - memaddr);
if (status != 0)
return status;
}
if (bp_addr + bp_size < memaddr + len)
{
/* Copy the section of memory after the breakpoint. */
- status = deprecated_read_memory_nobpt (bp_addr + bp_size,
+ status = read_memory_nobpt (bp_addr + bp_size,
myaddr + bp_addr + bp_size - memaddr,
memaddr + len - (bp_addr + bp_size));
if (status != 0)
/* Helper routine: free the value chain for a breakpoint (watchpoint). */
-static void free_valchain (struct bp_location *b)
+static void
+free_valchain (struct bp_location *b)
{
struct value *v;
struct value *n;
if (bpt->inserted || bpt->duplicate)
return 0;
+ /* Initialize the target-specific information. */
+ memset (&bpt->target_info, 0, sizeof (bpt->target_info));
+ bpt->target_info.placed_address = bpt->address;
+
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
/* No overlay handling: just set the breakpoint. */
if (bpt->loc_type == bp_loc_hardware_breakpoint)
- val = target_insert_hw_breakpoint (bpt->address,
- bpt->shadow_contents);
+ val = target_insert_hw_breakpoint (&bpt->target_info);
else
- val = target_insert_breakpoint (bpt->address,
- bpt->shadow_contents);
+ val = target_insert_breakpoint (&bpt->target_info);
}
else
{
CORE_ADDR addr = overlay_unmapped_address (bpt->address,
bpt->section);
/* Set a software (trap) breakpoint at the LMA. */
- val = target_insert_breakpoint (addr, bpt->shadow_contents);
+ bpt->overlay_target_info = bpt->target_info;
+ bpt->overlay_target_info.placed_address = addr;
+ val = target_insert_breakpoint (&bpt->overlay_target_info);
if (val != 0)
fprintf_unfiltered (tmp_error_stream,
"Overlay breakpoint %d failed: in ROM?",
{
/* Yes. This overlay section is mapped into memory. */
if (bpt->loc_type == bp_loc_hardware_breakpoint)
- val = target_insert_hw_breakpoint (bpt->address,
- bpt->shadow_contents);
+ val = target_insert_hw_breakpoint (&bpt->target_info);
else
- val = target_insert_breakpoint (bpt->address,
- bpt->shadow_contents);
+ val = target_insert_breakpoint (&bpt->target_info);
}
else
{
if (val)
{
/* Can't set the breakpoint. */
+ if (
#if defined (DISABLE_UNSETTABLE_BREAK)
- if (DISABLE_UNSETTABLE_BREAK (bpt->address))
+ DISABLE_UNSETTABLE_BREAK (bpt->address)
+#else
+ solib_address (bpt->address)
+#endif
+ )
{
/* See also: disable_breakpoints_in_shlibs. */
val = 0;
"breakpoint #%d\n", bpt->owner->number);
}
else
-#endif
{
#ifdef ONE_PROCESS_WRITETEXT
*process_warning = 1;
/* If we get here, we must have a callback mechanism for exception
events -- with g++ style embedded label support, we insert
ordinary breakpoints and not catchpoints. */
- val = target_insert_breakpoint (bpt->address, bpt->shadow_contents);
+ val = target_insert_breakpoint (&bpt->target_info);
if (val)
{
/* Couldn't set breakpoint for some reason */
|| bpt->owner->type == bp_catch_vfork
|| bpt->owner->type == bp_catch_exec)
{
- struct exception e = catch_exception (uiout, insert_catchpoint,
- bpt->owner, RETURN_MASK_ERROR);
+ struct gdb_exception e = catch_exception (uiout, insert_catchpoint,
+ bpt->owner, RETURN_MASK_ERROR);
exception_fprintf (gdb_stderr, e, "warning: inserting catchpoint %d: ",
bpt->owner->number);
if (e.reason < 0)
if (!breakpoint_enabled (b->owner))
continue;
+ /* There is no point inserting thread-specific breakpoints if the
+ thread no longer exists. */
+ if (b->owner->thread != -1
+ && !valid_thread_id (b->owner->thread))
+ continue;
+
/* FIXME drow/2003-10-07: This code should be pushed elsewhere when
hardware watchpoints are split into multiple loc breakpoints. */
if ((b->loc_type == bp_loc_hardware_watchpoint
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->address, b->shadow_contents);
+ val = target_insert_hw_breakpoint (&b->target_info);
else
- val = target_insert_breakpoint (b->address, b->shadow_contents);
+ val = target_insert_breakpoint (&b->target_info);
/* FIXME drow/2003-10-07: This doesn't handle any other kinds of
breakpoints. It's wrong for watchpoints, for example. */
if (val != 0)
(b->type == bp_catch_vfork) ||
(b->type == bp_catch_fork))
{
- b->loc->address = (CORE_ADDR) NULL;
+ b->loc->address = (CORE_ADDR) 0;
continue;
}
unnecessary. A call to breakpoint_re_set_one always recomputes
the breakpoint's address from scratch, or deletes it if it can't.
So I think this assignment could be deleted without effect. */
- b->loc->address = (CORE_ADDR) NULL;
+ b->loc->address = (CORE_ADDR) 0;
}
/* FIXME what about longjmp breakpoints? Re-create them here? */
create_overlay_event_breakpoint ("_ovly_debug_event");
/* No overlay handling: just remove the breakpoint. */
if (b->loc_type == bp_loc_hardware_breakpoint)
- val = target_remove_hw_breakpoint (b->address,
- b->shadow_contents);
+ val = target_remove_hw_breakpoint (&b->target_info);
else
- val = target_remove_breakpoint (b->address, b->shadow_contents);
+ val = target_remove_breakpoint (&b->target_info);
}
else
{
/* Yes -- overlay event support is not active, so we
should have set a breakpoint at the LMA. Remove it.
*/
- CORE_ADDR addr = overlay_unmapped_address (b->address,
- b->section);
/* Ignore any failures: if the LMA is in ROM, we will
have already warned when we failed to insert it. */
if (b->loc_type == bp_loc_hardware_breakpoint)
- target_remove_hw_breakpoint (addr, b->shadow_contents);
+ target_remove_hw_breakpoint (&b->overlay_target_info);
else
- target_remove_breakpoint (addr, b->shadow_contents);
+ target_remove_breakpoint (&b->overlay_target_info);
}
/* Did we set a breakpoint at the VMA?
If so, we will have marked the breakpoint 'inserted'. */
unmapped, but let's not rely on that being safe. We
don't know what the overlay manager might do. */
if (b->loc_type == bp_loc_hardware_breakpoint)
- val = target_remove_hw_breakpoint (b->address,
- b->shadow_contents);
+ val = target_remove_hw_breakpoint (&b->target_info);
else
- val = target_remove_breakpoint (b->address,
- b->shadow_contents);
+ val = target_remove_breakpoint (&b->target_info);
}
else
{
&& breakpoint_enabled (b->owner)
&& !b->duplicate)
{
-
- val = target_remove_breakpoint (b->address, b->shadow_contents);
+ val = target_remove_breakpoint (&b->target_info);
if (val)
return val;
b->inserted = (is == mark_inserted);
&& breakpoint_enabled (b->owner)
&& !b->duplicate)
{
-
- val = target_remove_breakpoint (b->address, b->shadow_contents);
+ val = target_remove_breakpoint (&b->target_info);
if (val)
return val;
annotate_breakpoint (bs->breakpoint_at->number);
ui_out_text (uiout, "\nBreakpoint ");
if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "reason", "breakpoint-hit");
+ ui_out_field_string (uiout, "reason",
+ async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
ui_out_field_int (uiout, "bkptno", bs->breakpoint_at->number);
ui_out_text (uiout, ", ");
return PRINT_SRC_AND_LOC;
{
annotate_watchpoint (bs->breakpoint_at->number);
if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "reason", "watchpoint-trigger");
+ ui_out_field_string
+ (uiout, "reason",
+ async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
mention (bs->breakpoint_at);
ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
ui_out_text (uiout, "\nOld value = ");
case bp_read_watchpoint:
if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "reason", "read-watchpoint-trigger");
+ ui_out_field_string
+ (uiout, "reason",
+ async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
mention (bs->breakpoint_at);
ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
ui_out_text (uiout, "\nValue = ");
{
annotate_watchpoint (bs->breakpoint_at->number);
if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "reason", "access-watchpoint-trigger");
+ ui_out_field_string
+ (uiout, "reason",
+ async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
mention (bs->breakpoint_at);
ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
ui_out_text (uiout, "\nOld value = ");
{
mention (bs->breakpoint_at);
if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "reason", "access-watchpoint-trigger");
+ ui_out_field_string
+ (uiout, "reason",
+ async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
ui_out_text (uiout, "\nValue = ");
}
case bp_finish:
if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "reason", "function-finished");
+ ui_out_field_string
+ (uiout, "reason",
+ async_reason_lookup (EXEC_ASYNC_FUNCTION_FINISHED));
return PRINT_UNKNOWN;
break;
case bp_until:
if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "reason", "location-reached");
+ ui_out_field_string
+ (uiout, "reason",
+ async_reason_lookup (EXEC_ASYNC_LOCATION_REACHED));
return PRINT_UNKNOWN;
break;
reinit_frame_cache ();
fr = frame_find_by_id (b->watchpoint_frame);
within_current_scope = (fr != NULL);
+
+ /* If we've gotten confused in the unwinder, we might have
+ returned a frame that can't describe this variable. */
+ if (within_current_scope
+ && block_function (b->exp_valid_block) != get_frame_function (fr))
+ within_current_scope = 0;
+
/* in_function_epilogue_p() returns a non-zero value if we're still
in the function but the stack frame has already been invalidated.
Since we can't rely on the values of local variables after the
will be deleted already. So we have no choice but print the
information here. */
if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "reason", "watchpoint-scope");
+ ui_out_field_string
+ (uiout, "reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE));
ui_out_text (uiout, "\nWatchpoint ");
ui_out_field_int (uiout, "wpnum", bs->breakpoint_at->number);
ui_out_text (uiout, " deleted because the program has left the block in\n\
ui_out_field_int (uiout, "what", b->forked_inferior_pid);
ui_out_spaces (uiout, 1);
}
+ break;
case bp_catch_exec:
/* Field 4, the address, is omitted (which makes the columns
}
ui_out_field_string (uiout, "file", b->source_file);
ui_out_text (uiout, ":");
+
+ if (ui_out_is_mi_like_p (uiout))
+ {
+ struct symtab_and_line sal = find_pc_line (b->loc->address, 0);
+ char *fullname = symtab_to_fullname (sal.symtab);
+
+ if (fullname)
+ ui_out_field_string (uiout, "fullname", fullname);
+ }
+
ui_out_field_int (uiout, "line", b->line_number);
}
else if (b->pending)
/* Print a message describing any breakpoints set at PC. */
static void
-describe_other_breakpoints (CORE_ADDR pc, asection *section)
+describe_other_breakpoints (CORE_ADDR pc, asection *section, int thread)
{
int others = 0;
struct breakpoint *b;
if (!b->pending && (!overlay_debugging || b->loc->section == section))
{
others--;
- printf_filtered ("%d%s%s ",
- b->number,
+ printf_filtered ("%d", b->number);
+ if (b->thread == -1 && thread != -1)
+ printf_filtered (" (all threads)");
+ else if (b->thread != -1)
+ printf_filtered (" (thread %d)", b->thread);
+ printf_filtered ("%s%s ",
((b->enable_state == bp_disabled ||
b->enable_state == bp_shlib_disabled ||
b->enable_state == bp_call_disabled)
- ? " (disabled)"
+ ? " (disabled)"
: b->enable_state == bp_permanent
? " (permanent)"
: ""),
return rc;
}
-#ifdef SOLIB_ADD
void
remove_solib_event_breakpoints (void)
{
/* See also: insert_breakpoints, under DISABLE_UNSETTABLE_BREAK. */
ALL_BREAKPOINTS (b)
{
-#if defined (PC_SOLIB)
- if (((b->type == bp_breakpoint) ||
- (b->type == bp_hardware_breakpoint)) &&
- breakpoint_enabled (b) &&
- !b->loc->duplicate &&
- PC_SOLIB (b->loc->address))
+ if (((b->type == bp_breakpoint) || (b->type == bp_hardware_breakpoint))
+ && breakpoint_enabled (b) && !b->loc->duplicate
+#ifdef PC_SOLIB
+ && PC_SOLIB (b->loc->address)
+#else
+ && solib_address (b->loc->address)
+#endif
+ )
{
b->enable_state = bp_shlib_disabled;
if (!silent)
warning (_("breakpoint #%d "), b->number);
}
}
-#endif
}
}
struct breakpoint *b;
int disabled_shlib_breaks = 0;
-#if defined (PC_SOLIB)
/* See also: insert_breakpoints, under DISABLE_UNSETTABLE_BREAK. */
ALL_BREAKPOINTS (b)
{
if ((b->loc->loc_type == bp_loc_hardware_breakpoint
|| b->loc->loc_type == bp_loc_software_breakpoint)
- && breakpoint_enabled (b)
- && !b->loc->duplicate)
+ && breakpoint_enabled (b) && !b->loc->duplicate)
{
+#ifdef PC_SOLIB
char *so_name = PC_SOLIB (b->loc->address);
- if (so_name
- && !strcmp (so_name, solib->so_name))
+#else
+ char *so_name = solib_address (b->loc->address);
+#endif
+ if (so_name && !strcmp (so_name, solib->so_name))
{
b->enable_state = bp_shlib_disabled;
/* At this point, we cannot rely on remove_breakpoint
}
}
}
-#endif
}
/* Try to reenable any breakpoints in shared libraries. */
{
if (b->enable_state == bp_shlib_disabled)
{
- char buf[1], *lib;
+ gdb_byte buf[1];
+ char *lib;
- /* Do not reenable the breakpoint if the shared library
- is still not mapped in. */
+ /* Do not reenable the breakpoint if the shared library is
+ still not mapped in. */
+#ifdef PC_SOLIB
lib = PC_SOLIB (b->loc->address);
+#else
+ lib = solib_address (b->loc->address);
+#endif
if (lib != NULL && target_read_memory (b->loc->address, buf, 1) == 0)
b->enable_state = bp_enabled;
}
}
}
-#endif
-
static void
solib_load_unload_1 (char *hookname, int tempflag, char *dll_pathname,
char *cond_string, enum bptype bp_kind)
struct symtab_and_line sal = sals.sals[i];
if (from_tty)
- describe_other_breakpoints (sal.pc, sal.section);
+ describe_other_breakpoints (sal.pc, sal.section, thread);
b = set_raw_breakpoint (sal, type);
set_breakpoint_count (breakpoint_count + 1);
static int
break_command_1 (char *arg, int flag, int from_tty, struct breakpoint *pending_bp)
{
- struct exception e;
+ struct gdb_exception e;
int tempflag, hardwareflag;
struct symtabs_and_lines sals;
struct expression **cond = 0;
in hardware. If the watchpoint can not be handled
in hardware return zero. */
-#if !defined(TARGET_REGION_OK_FOR_HW_WATCHPOINT)
-#define TARGET_REGION_OK_FOR_HW_WATCHPOINT(ADDR,LEN) \
- (TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(LEN))
-#endif
-
static int
can_use_hardware_watchpoint (struct value *v)
{
_("another breakpoint was inserted on top of "
"a permanent breakpoint"));
+ memset (&b->loc->target_info, 0, sizeof (b->loc->target_info));
+ b->loc->target_info.placed_address = b->loc->address;
if (b->type == bp_hardware_breakpoint)
- val = target_insert_hw_breakpoint (b->loc->address, b->loc->shadow_contents);
+ val = target_insert_hw_breakpoint (&b->loc->target_info);
else
- val = target_insert_breakpoint (b->loc->address, b->loc->shadow_contents);
+ val = target_insert_breakpoint (&b->loc->target_info);
/* If there was an error in the insert, print a message, then stop execution. */
if (val != 0)
error (_("Junk at end of line specification: %s"), string);
return sals;
}
+
+/* Create and insert a raw software breakpoint at PC. Return an
+ identifier, which should be used to remove the breakpoint later.
+ In general, places which call this should be using something on the
+ breakpoint chain instead; this function should be eliminated
+ someday. */
+
+void *
+deprecated_insert_raw_breakpoint (CORE_ADDR pc)
+{
+ struct bp_target_info *bp_tgt;
+
+ bp_tgt = xmalloc (sizeof (struct bp_target_info));
+ memset (bp_tgt, 0, sizeof (struct bp_target_info));
+
+ bp_tgt->placed_address = pc;
+ if (target_insert_breakpoint (bp_tgt) != 0)
+ {
+ /* Could not insert the breakpoint. */
+ xfree (bp_tgt);
+ return NULL;
+ }
+
+ return bp_tgt;
+}
+
+/* Remove a breakpoint BP inserted by deprecated_insert_raw_breakpoint. */
+
+int
+deprecated_remove_raw_breakpoint (void *bp)
+{
+ struct bp_target_info *bp_tgt = bp;
+ int ret;
+
+ ret = target_remove_breakpoint (bp_tgt);
+ xfree (bp_tgt);
+
+ return ret;
+}
+
+/* One (or perhaps two) breakpoints used for software single stepping. */
+
+static void *single_step_breakpoints[2];
+
+/* Create and insert a breakpoint for software single step. */
+
+void
+insert_single_step_breakpoint (CORE_ADDR next_pc)
+{
+ void **bpt_p;
+
+ if (single_step_breakpoints[0] == NULL)
+ bpt_p = &single_step_breakpoints[0];
+ else
+ {
+ gdb_assert (single_step_breakpoints[1] == NULL);
+ bpt_p = &single_step_breakpoints[1];
+ }
+
+ /* NOTE drow/2006-04-11: A future improvement to this function would be
+ to only create the breakpoints once, and actually put them on the
+ breakpoint chain. That would let us use set_raw_breakpoint. We could
+ adjust the addresses each time they were needed. Doing this requires
+ corresponding changes elsewhere where single step breakpoints are
+ handled, however. So, for now, we use this. */
+
+ *bpt_p = deprecated_insert_raw_breakpoint (next_pc);
+ if (*bpt_p == NULL)
+ error (_("Could not insert single-step breakpoint at 0x%s"),
+ paddr_nz (next_pc));
+}
+
+/* Remove and delete any breakpoints used for software single step. */
+
+void
+remove_single_step_breakpoints (void)
+{
+ gdb_assert (single_step_breakpoints[0] != NULL);
+
+ /* See insert_single_step_breakpoint for more about this deprecated
+ call. */
+ deprecated_remove_raw_breakpoint (single_step_breakpoints[0]);
+ single_step_breakpoints[0] = NULL;
+
+ if (single_step_breakpoints[1] != NULL)
+ {
+ deprecated_remove_raw_breakpoint (single_step_breakpoints[1]);
+ single_step_breakpoints[1] = NULL;
+ }
+}
+
\f
+/* This help string is used for the break, hbreak, tbreak and thbreak commands.
+ It is defined as a macro to prevent duplication.
+ COMMAND should be a string constant containing the name of the command. */
+#define BREAK_ARGS_HELP(command) \
+command" [LOCATION] [thread THREADNUM] [if CONDITION]\n\
+LOCATION may be a line number, function name, or \"*\" and an address.\n\
+If a line number is specified, break at start of code for that line.\n\
+If a function is specified, break at start of code for that function.\n\
+If an address is specified, break at that exact address.\n\
+With no LOCATION, uses current execution address of selected stack frame.\n\
+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\
+Multiple breakpoints at one place are permitted, and useful if conditional.\n\
+\n\
+Do \"help breakpoints\" for info on other commands dealing with breakpoints."
+
void
_initialize_breakpoint (void)
{
static struct cmd_list_element *breakpoint_show_cmdlist;
struct cmd_list_element *c;
-#ifdef SOLIB_ADD
observer_attach_solib_unloaded (disable_breakpoints_in_unloaded_shlib);
-#endif
breakpoint_chain = 0;
/* Don't bother to call set_breakpoint_count. $bpnum isn't useful
expression to be evaluated whenever breakpoint N is reached."));
c = add_com ("tbreak", class_breakpoint, tbreak_command, _("\
-Set a temporary breakpoint. Args like \"break\" command.\n\
+Set a temporary breakpoint.\n\
Like \"break\" except the breakpoint is only temporary,\n\
so it will be deleted when hit. Equivalent to \"break\" followed\n\
-by using \"enable delete\" on the breakpoint number."));
+by using \"enable delete\" on the breakpoint number.\n\
+\n"
+BREAK_ARGS_HELP ("tbreak")));
set_cmd_completer (c, location_completer);
c = add_com ("hbreak", class_breakpoint, hbreak_command, _("\
-Set a hardware assisted breakpoint. Args like \"break\" command.\n\
+Set a hardware assisted breakpoint.\n\
Like \"break\" except the breakpoint requires hardware support,\n\
-some target hardware may not have this support."));
+some target hardware may not have this support.\n\
+\n"
+BREAK_ARGS_HELP ("hbreak")));
set_cmd_completer (c, location_completer);
c = add_com ("thbreak", class_breakpoint, thbreak_command, _("\
-Set a temporary hardware assisted breakpoint. Args like \"break\" command.\n\
+Set a temporary hardware assisted breakpoint.\n\
Like \"hbreak\" except the breakpoint is only temporary,\n\
-so it will be deleted when hit."));
+so it will be deleted when hit.\n\
+\n"
+BREAK_ARGS_HELP ("thbreak")));
set_cmd_completer (c, location_completer);
add_prefix_cmd ("enable", class_breakpoint, enable_command, _("\
The \"unset\" command is also an alias for \"delete\"."),
&deletelist, "delete ", 1, &cmdlist);
add_com_alias ("d", "delete", class_breakpoint, 1);
+ add_com_alias ("del", "delete", class_breakpoint, 1);
if (xdb_commands)
add_com ("db", class_breakpoint, delete_command, _("\
Delete some breakpoints.\n\
See also the \"delete\" command which clears breakpoints by number."));
c = add_com ("break", class_breakpoint, break_command, _("\
-Set breakpoint at specified line or function.\n\
-Argument may be line number, function name, or \"*\" and an address.\n\
-If line number is specified, break at start of code for that line.\n\
-If function is specified, break at start of code for that function.\n\
-If an address is specified, break at that exact address.\n\
-With no arg, uses current execution address of selected stack frame.\n\
-This is useful for breaking on return to a stack frame.\n\
-\n\
-Multiple breakpoints at one place are permitted, and useful if conditional.\n\
-\n\
-Do \"help breakpoints\" for info on other commands dealing with breakpoints."));
+Set breakpoint at specified line or function.\n"
+BREAK_ARGS_HELP ("break")));
set_cmd_completer (c, location_completer);
add_com_alias ("b", "break", class_run, 1);
_("Synonym for ``info breakpoints''."));
+ /* XXX: cagney/2005-02-23: This should be a boolean, and should
+ respond to changes - contrary to the description. */
add_setshow_zinteger_cmd ("can-use-hw-watchpoints", class_support,
&can_use_hw_watchpoints, _("\
Set debugger's willingness to use watchpoint hardware."), _("\
created before setting this to nonzero, will continue to use watchpoint\n\
hardware.)"),
NULL,
- NULL, /* FIXME: i18n: */
+ show_can_use_hw_watchpoints,
&setlist, &showlist);
can_use_hw_watchpoints = 1;
an error. If auto, an unrecognized breakpoint location results in a\n\
user-query to see if a pending breakpoint should be created."),
NULL,
- NULL, /* FIXME: i18n: Debugger's behavior regarding pending breakpoints is %s. */
+ show_pending_break_support,
&breakpoint_set_cmdlist,
&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;
}