Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008 Free Software Foundation, Inc.
+ 2008, 2009 Free Software Foundation, Inc.
This file is part of GDB.
#include "ada-lang.h"
#include "top.h"
#include "wrapper.h"
+#include "valprint.h"
#include "mi/mi-common.h"
static void do_enable_breakpoint (struct breakpoint *, enum bpdisp);
-static void create_fork_vfork_event_catchpoint (int tempflag,
- char *cond_string,
- enum bptype bp_kind);
-
static void stop_command (char *arg, int from_tty);
static void stopin_command (char *arg, int from_tty);
static void free_bp_location (struct bp_location *loc);
-static struct bp_location *
-allocate_bp_location (struct breakpoint *bpt, enum bptype bp_type);
+static struct bp_location *allocate_bp_location (struct breakpoint *bpt);
static void update_global_location_list (int);
void _initialize_breakpoint (void);
-extern int addressprint; /* Print machine addresses? */
-
/* Are we executing breakpoint commands? */
static int executing_breakpoint_commands;
int breakpoint_count;
-/* This function returns a pointer to the string representation of the
- pathname of the dynamically-linked library that has just been
- loaded.
-
- This function must be used only when SOLIB_HAVE_LOAD_EVENT is TRUE,
- or undefined results are guaranteed.
-
- This string's contents are only valid immediately after the
- inferior has stopped in the dynamic linker hook, and becomes
- invalid as soon as the inferior is continued. Clients should make
- a copy of this string if they wish to continue the inferior and
- then access the string. */
-
-#ifndef SOLIB_LOADED_LIBRARY_PATHNAME
-#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) ""
-#endif
-
-/* This function returns a pointer to the string representation of the
- pathname of the dynamically-linked library that has just been
- unloaded.
-
- This function must be used only when SOLIB_HAVE_UNLOAD_EVENT is
- TRUE, or undefined results are guaranteed.
-
- This string's contents are only valid immediately after the
- inferior has stopped in the dynamic linker hook, and becomes
- invalid as soon as the inferior is continued. Clients should make
- a copy of this string if they wish to continue the inferior and
- then access the string. */
-
-#ifndef SOLIB_UNLOADED_LIBRARY_PATHNAME
-#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) ""
-#endif
-
-/* This function is called by the "catch load" command. It allows the
- debugger to be notified by the dynamic linker when a specified
- library file (or any library file, if filename is NULL) is loaded. */
-
-#ifndef SOLIB_CREATE_CATCH_LOAD_HOOK
-#define SOLIB_CREATE_CATCH_LOAD_HOOK(pid,tempflag,filename,cond_string) \
- error (_("catch of library loads not yet implemented on this platform"))
-#endif
-
-/* This function is called by the "catch unload" command. It allows
- the debugger to be notified by the dynamic linker when a specified
- library file (or any library file, if filename is NULL) is
- unloaded. */
-
-#ifndef SOLIB_CREATE_CATCH_UNLOAD_HOOK
-#define SOLIB_CREATE_CATCH_UNLOAD_HOOK(pid, tempflag, filename, cond_string) \
- error (_("catch of library unloads not yet implemented on this platform"))
-#endif
-
/* Return whether a breakpoint is an active enabled breakpoint. */
static int
breakpoint_enabled (struct breakpoint *b)
struct breakpoint *b = (struct breakpoint *) args;
int val = -1;
- switch (b->type)
- {
- case bp_catch_fork:
- target_insert_fork_catchpoint (PIDGET (inferior_ptid));
- break;
- case bp_catch_vfork:
- target_insert_vfork_catchpoint (PIDGET (inferior_ptid));
- break;
- case bp_catch_exec:
- target_insert_exec_catchpoint (PIDGET (inferior_ptid));
- break;
- default:
- internal_error (__FILE__, __LINE__, _("unknown breakpoint type"));
- break;
- }
+ gdb_assert (b->type == bp_catchpoint);
+ gdb_assert (b->ops != NULL && b->ops->insert != NULL);
+
+ b->ops->insert (b);
}
static int
in *VAL_CHAIN. RESULTP and VAL_CHAIN may be NULL if the caller does
not need them.
- If an error occurs while evaluating the expression, *RESULTP will
+ If a memory error occurs while evaluating the expression, *RESULTP will
be set to NULL. *RESULTP may be a lazy value, if the result could
not be read from memory. It is used to determine whether a value
is user-specified (we should watch the whole value) or intermediate
struct value **resultp, struct value **val_chain)
{
struct value *mark, *new_mark, *result;
+ volatile struct gdb_exception ex;
*valp = NULL;
if (resultp)
/* Evaluate the expression. */
mark = value_mark ();
result = NULL;
- gdb_evaluate_expression (exp, &result);
+
+ TRY_CATCH (ex, RETURN_MASK_ALL)
+ {
+ result = evaluate_expression (exp);
+ }
+ if (ex.reason < 0)
+ {
+ /* Ignore memory errors, we want watchpoints pointing at
+ inaccessible memory to still be created; otherwise, throw the
+ error to some higher catcher. */
+ switch (ex.error)
+ {
+ case MEMORY_ERROR:
+ break;
+ default:
+ throw_exception (ex);
+ break;
+ }
+ }
+
new_mark = value_mark ();
if (mark == new_mark)
return;
}
}
-/* Assuming that B is a hardware watchpoint:
- - Reparse watchpoint expression, is REPARSE is non-zero
+/* Assuming that B is a watchpoint:
+ - Reparse watchpoint expression, if REPARSE is non-zero
- Evaluate expression and store the result in B->val
+ - Evaluate the condition if there is one, and store the result
+ in b->loc->cond.
- Update the list of values that must be watched in B->loc.
- If the watchpoint is disabled, do nothing. If this is
- local watchpoint that is out of scope, delete it. */
+ If the watchpoint disposition is disp_del_at_next_stop, then do nothing.
+ If this is local watchpoint that is out of scope, delete it. */
static void
update_watchpoint (struct breakpoint *b, int reparse)
{
struct bp_location *loc;
bpstat bs;
- /* We don't free locations. They are stored in
- bp_location_chain and update_global_locations will
- eventually delete them and remove breakpoints if
- needed. */
+ /* We don't free locations. They are stored in bp_location_chain and
+ update_global_locations will eventually delete them and remove
+ breakpoints if needed. */
b->loc = NULL;
if (b->disposition == disp_del_at_next_stop)
b->val_valid = 1;
}
+ /* Change the type of breakpoint between hardware assisted or an
+ ordinary watchpoint depending on the hardware support and free
+ hardware slots. REPARSE is set when the inferior is started. */
+ if ((b->type == bp_watchpoint || b->type == bp_hardware_watchpoint)
+ && reparse)
+ {
+ int i, mem_cnt, other_type_used;
+
+ i = hw_watchpoint_used_count (bp_hardware_watchpoint,
+ &other_type_used);
+ mem_cnt = can_use_hardware_watchpoint (val_chain);
+
+ if (!mem_cnt)
+ b->type = bp_watchpoint;
+ else
+ {
+ int target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT
+ (bp_hardware_watchpoint, i + mem_cnt, other_type_used);
+ if (target_resources_ok <= 0)
+ b->type = bp_watchpoint;
+ else
+ b->type = bp_hardware_watchpoint;
+ }
+ }
+
/* Look at each value on the value chain. */
for (v = val_chain; v; v = next)
{
else if (b->type == bp_access_watchpoint)
type = hw_access;
- loc = allocate_bp_location (b, bp_hardware_watchpoint);
+ loc = allocate_bp_location (b);
for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
;
*tmp = loc;
else if (!within_current_scope)
{
printf_filtered (_("\
-Hardware watchpoint %d deleted because the program has left the block \n\
+Watchpoint %d deleted because the program has left the block \n\
in which its expression is valid.\n"),
b->number);
if (b->related_breakpoint)
/* Insert a low-level "breakpoint" of some type. BPT is the breakpoint.
Any error messages are printed to TMP_ERROR_STREAM; and DISABLED_BREAKS,
- PROCESS_WARNING, and HW_BREAKPOINT_ERROR are used to report problems.
+ and HW_BREAKPOINT_ERROR are used to report problems.
NOTE drow/2003-09-09: This routine could be broken down to an object-style
method for each breakpoint or catchpoint type. */
static int
insert_bp_location (struct bp_location *bpt,
struct ui_file *tmp_error_stream,
- int *disabled_breaks, int *process_warning,
+ int *disabled_breaks,
int *hw_breakpoint_error)
{
int val = 0;
}
else
{
-#ifdef ONE_PROCESS_WRITETEXT
- *process_warning = 1;
-#endif
if (bpt->loc_type == bp_loc_hardware_breakpoint)
{
*hw_breakpoint_error = 1;
bpt->inserted = (val != -1);
}
- else if (bpt->owner->type == bp_catch_fork
- || bpt->owner->type == bp_catch_vfork
- || bpt->owner->type == bp_catch_exec)
+ else if (bpt->owner->type == bp_catchpoint)
{
struct gdb_exception e = catch_exception (uiout, insert_catchpoint,
bpt->owner, RETURN_MASK_ERROR);
update_global_location_list (1);
- if (!breakpoints_always_inserted_mode () && target_has_execution)
+ if (!breakpoints_always_inserted_mode ()
+ && (target_has_execution
+ || (gdbarch_has_global_solist (target_gdbarch)
+ && target_supports_multi_process ())))
/* update_global_location_list does not insert breakpoints
when always_inserted_mode is not enabled. Explicitly
insert them now. */
int val = 0;
int disabled_breaks = 0;
int hw_breakpoint_error = 0;
- int process_warning = 0;
struct ui_file *tmp_error_stream = mem_fileopen ();
- make_cleanup_ui_file_delete (tmp_error_stream);
+ struct cleanup *cleanups = make_cleanup_ui_file_delete (tmp_error_stream);
/* Explicitly mark the warning -- this will only be printed if
there was an error. */
continue;
val = insert_bp_location (b, tmp_error_stream,
- &disabled_breaks, &process_warning,
+ &disabled_breaks,
&hw_breakpoint_error);
if (val)
error = val;
"Could not insert hardware breakpoints:\n\
You may have requested too many hardware breakpoints/watchpoints.\n");
}
-#ifdef ONE_PROCESS_WRITETEXT
- if (process_warning)
- fprintf_unfiltered (tmp_error_stream,
- "The same program may be running in another process.");
-#endif
target_terminal_ours_for_output ();
error_stream (tmp_error_stream);
}
+
+ do_cleanups (cleanups);
}
int
int val;
struct cleanup *old_chain = save_inferior_ptid ();
struct ui_file *tmp_error_stream = mem_fileopen ();
- int dummy1 = 0, dummy2 = 0, dummy3 = 0;
+ int dummy1 = 0, dummy2 = 0;
make_cleanup_ui_file_delete (tmp_error_stream);
{
b->inserted = 0;
val = insert_bp_location (b, tmp_error_stream,
- &dummy1, &dummy2, &dummy3);
+ &dummy1, &dummy2);
if (val != 0)
{
do_cleanups (old_chain);
continue;
}
- /* Don't delete an exec catchpoint, because else the inferior
- won't stop when it ought!
-
- Similarly, we probably ought to keep vfork catchpoints, 'cause
- on this target, we may not be able to stop when the vfork is
- seen, but only when the subsequent exec is seen. (And because
- deleting fork catchpoints here but not vfork catchpoints will
- seem mysterious to users, keep those too.) */
- if ((b->type == bp_catch_exec) ||
- (b->type == bp_catch_vfork) ||
- (b->type == bp_catch_fork))
+ if (b->type == bp_catchpoint)
{
- continue;
+ /* For now, none of the bp_catchpoint breakpoints need to
+ do anything at this point. In the future, if some of
+ the catchpoints need to something, we will need to add
+ a new method, and call this method from here. */
+ continue;
}
/* bp_finish is a special case. The only way we ought to be able
warning (_("Could not remove hardware watchpoint %d."),
b->owner->number);
}
- else if ((b->owner->type == bp_catch_fork ||
- b->owner->type == bp_catch_vfork ||
- b->owner->type == bp_catch_exec)
- && breakpoint_enabled (b->owner)
- && !b->duplicate)
+ else if (b->owner->type == bp_catchpoint
+ && breakpoint_enabled (b->owner)
+ && !b->duplicate)
{
- val = -1;
- switch (b->owner->type)
- {
- case bp_catch_fork:
- val = target_remove_fork_catchpoint (PIDGET (inferior_ptid));
- break;
- case bp_catch_vfork:
- val = target_remove_vfork_catchpoint (PIDGET (inferior_ptid));
- break;
- case bp_catch_exec:
- val = target_remove_exec_catchpoint (PIDGET (inferior_ptid));
- break;
- default:
- warning (_("Internal error, %s line %d."), __FILE__, __LINE__);
- break;
- }
+ gdb_assert (b->owner->ops != NULL && b->owner->ops->remove != NULL);
+
+ val = b->owner->ops->remove (b->owner);
if (val)
return val;
b->inserted = (is == mark_inserted);
struct bp_location *bpt;
int ix;
+ /* If breakpoint locations are shared across processes, then there's
+ nothing to do. */
+ if (gdbarch_has_global_solist (target_gdbarch))
+ return;
+
ALL_BP_LOCATIONS (bpt)
if (bpt->owner->enable_state != bp_permanent)
bpt->inserted = 0;
int
ep_is_catchpoint (struct breakpoint *ep)
{
- return
- (ep->type == bp_catch_load)
- || (ep->type == bp_catch_unload)
- || (ep->type == bp_catch_fork)
- || (ep->type == bp_catch_vfork)
- || (ep->type == bp_catch_exec);
-
- /* ??rehrauer: Add more kinds here, as are implemented... */
-}
-
-int
-ep_is_shlib_catchpoint (struct breakpoint *ep)
-{
- return
- (ep->type == bp_catch_load)
- || (ep->type == bp_catch_unload);
+ return (ep->type == bp_catchpoint);
}
void
if (val == NULL)
fprintf_unfiltered (stream, _("<unreadable>"));
else
- value_print (val, stream, 0, Val_pretty_default);
+ {
+ struct value_print_options opts;
+ get_user_print_options (&opts);
+ value_print (val, stream, &opts);
+ }
}
/* This is the normal print function for a bpstat. In the future,
static enum print_stop_action
print_it_typical (bpstat bs)
{
- struct cleanup *old_chain, *ui_out_chain;
+ struct cleanup *old_chain;
struct breakpoint *b;
const struct bp_location *bl;
struct ui_stream *stb;
- int bp_temp = 0;
- stb = ui_out_stream_new (uiout);
- old_chain = make_cleanup_ui_out_stream_delete (stb);
+ int bp_temp = 0;
+ enum print_stop_action result;
+
/* bs->breakpoint_at can be NULL if it was a momentary breakpoint
which has since been deleted. */
if (bs->breakpoint_at == NULL)
bl = bs->breakpoint_at;
b = bl->owner;
+ stb = ui_out_stream_new (uiout);
+ old_chain = make_cleanup_ui_out_stream_delete (stb);
+
switch (b->type)
{
case bp_breakpoint:
}
ui_out_field_int (uiout, "bkptno", b->number);
ui_out_text (uiout, ", ");
- return PRINT_SRC_AND_LOC;
+ result = PRINT_SRC_AND_LOC;
break;
case bp_shlib_event:
variable? (If so, we report this as a generic, "Stopped due
to shlib event" message.) */
printf_filtered (_("Stopped due to shared library event\n"));
- return PRINT_NOTHING;
+ result = PRINT_NOTHING;
break;
case bp_thread_event:
/* Not sure how we will get here.
GDB should not stop for these breakpoints. */
printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n"));
- return PRINT_NOTHING;
+ result = PRINT_NOTHING;
break;
case bp_overlay_event:
/* By analogy with the thread event, GDB should not stop for these. */
printf_filtered (_("Overlay Event Breakpoint: gdb should not stop!\n"));
- return PRINT_NOTHING;
- break;
-
- case bp_catch_load:
- annotate_catchpoint (b->number);
- printf_filtered (_("\nCatchpoint %d (loaded %s), "),
- b->number,
- b->triggered_dll_pathname);
- return PRINT_SRC_AND_LOC;
- break;
-
- case bp_catch_unload:
- annotate_catchpoint (b->number);
- printf_filtered (_("\nCatchpoint %d (unloaded %s), "),
- b->number,
- b->triggered_dll_pathname);
- return PRINT_SRC_AND_LOC;
- break;
-
- case bp_catch_fork:
- annotate_catchpoint (b->number);
- printf_filtered (_("\nCatchpoint %d (forked process %d), "),
- b->number,
- ptid_get_pid (b->forked_inferior_pid));
- return PRINT_SRC_AND_LOC;
- break;
-
- case bp_catch_vfork:
- annotate_catchpoint (b->number);
- printf_filtered (_("\nCatchpoint %d (vforked process %d), "),
- b->number,
- ptid_get_pid (b->forked_inferior_pid));
- return PRINT_SRC_AND_LOC;
- break;
-
- case bp_catch_exec:
- annotate_catchpoint (b->number);
- printf_filtered (_("\nCatchpoint %d (exec'd %s), "),
- b->number,
- b->exec_pathname);
- return PRINT_SRC_AND_LOC;
+ result = PRINT_NOTHING;
break;
case bp_watchpoint:
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
mention (b);
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+ make_cleanup_ui_out_tuple_begin_end (uiout, "value");
ui_out_text (uiout, "\nOld value = ");
watchpoint_value_print (bs->old_val, stb->stream);
ui_out_field_stream (uiout, "old", stb);
ui_out_text (uiout, "\nNew value = ");
watchpoint_value_print (b->val, stb->stream);
ui_out_field_stream (uiout, "new", stb);
- do_cleanups (ui_out_chain);
ui_out_text (uiout, "\n");
/* More than one watchpoint may have been triggered. */
- return PRINT_UNKNOWN;
+ result = PRINT_UNKNOWN;
break;
case bp_read_watchpoint:
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
mention (b);
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+ make_cleanup_ui_out_tuple_begin_end (uiout, "value");
ui_out_text (uiout, "\nValue = ");
watchpoint_value_print (b->val, stb->stream);
ui_out_field_stream (uiout, "value", stb);
- do_cleanups (ui_out_chain);
ui_out_text (uiout, "\n");
- return PRINT_UNKNOWN;
+ result = PRINT_UNKNOWN;
break;
case bp_access_watchpoint:
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
mention (b);
- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+ make_cleanup_ui_out_tuple_begin_end (uiout, "value");
ui_out_text (uiout, "\nOld value = ");
watchpoint_value_print (bs->old_val, stb->stream);
ui_out_field_stream (uiout, "old", stb);
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");
+ make_cleanup_ui_out_tuple_begin_end (uiout, "value");
ui_out_text (uiout, "\nValue = ");
}
watchpoint_value_print (b->val, stb->stream);
ui_out_field_stream (uiout, "new", stb);
- do_cleanups (ui_out_chain);
ui_out_text (uiout, "\n");
- return PRINT_UNKNOWN;
+ result = PRINT_UNKNOWN;
break;
/* Fall through, we don't deal with these types of breakpoints
ui_out_field_string
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_FUNCTION_FINISHED));
- return PRINT_UNKNOWN;
+ result = PRINT_UNKNOWN;
break;
case bp_until:
ui_out_field_string
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_LOCATION_REACHED));
- return PRINT_UNKNOWN;
+ result = PRINT_UNKNOWN;
break;
case bp_none:
case bp_watchpoint_scope:
case bp_call_dummy:
default:
- return PRINT_UNKNOWN;
+ result = PRINT_UNKNOWN;
+ break;
}
+
+ do_cleanups (old_chain);
+ return result;
}
/* Generic routine for printing messages indicating why we
&& b->type != bp_read_watchpoint
&& b->type != bp_access_watchpoint
&& b->type != bp_hardware_breakpoint
- && b->type != bp_catch_fork
- && b->type != bp_catch_vfork
- && b->type != bp_catch_exec) /* a non-watchpoint bp */
+ && b->type != bp_catchpoint) /* a non-watchpoint bp */
{
if (bl->address != bp_addr) /* address doesn't match */
return 0;
&& !section_is_mapped (bl->section))
return 0;
}
-
- /* Is this a catchpoint of a load or unload? If so, did we
- get a load or unload of the specified library? If not,
- ignore it. */
- if ((b->type == bp_catch_load)
-#if defined(SOLIB_HAVE_LOAD_EVENT)
- && (!SOLIB_HAVE_LOAD_EVENT (PIDGET (inferior_ptid))
- || ((b->dll_pathname != NULL)
- && (strcmp (b->dll_pathname,
- SOLIB_LOADED_LIBRARY_PATHNAME (
- PIDGET (inferior_ptid)))
- != 0)))
-#endif
- )
- return 0;
-
- if ((b->type == bp_catch_unload)
-#if defined(SOLIB_HAVE_UNLOAD_EVENT)
- && (!SOLIB_HAVE_UNLOAD_EVENT (PIDGET (inferior_ptid))
- || ((b->dll_pathname != NULL)
- && (strcmp (b->dll_pathname,
- SOLIB_UNLOADED_LIBRARY_PATHNAME (
- PIDGET (inferior_ptid)))
- != 0)))
-#endif
- )
- return 0;
-
- if ((b->type == bp_catch_fork)
- && !inferior_has_forked (inferior_ptid,
- &b->forked_inferior_pid))
- return 0;
-
- if ((b->type == bp_catch_vfork)
- && !inferior_has_vforked (inferior_ptid,
- &b->forked_inferior_pid))
- return 0;
-
- if ((b->type == bp_catch_exec)
- && !inferior_has_execd (inferior_ptid, &b->exec_pathname))
- return 0;
+ if (b->type == bp_catchpoint)
+ {
+ gdb_assert (b->ops != NULL && b->ops->breakpoint_hit != NULL);
+ if (!b->ops->breakpoint_hit (b))
+ return 0;
+ }
+
return 1;
}
/* We hit the shared library event breakpoint. */
shlib_event,
- /* We caught a shared library event. */
- catch_shlib_event,
-
/* This is just used to count how many enums there are. */
class_last
};
#define clr BPSTAT_WHAT_CLEAR_LONGJMP_RESUME
#define sr BPSTAT_WHAT_STEP_RESUME
#define shl BPSTAT_WHAT_CHECK_SHLIBS
-#define shlr BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK
/* "Can't happen." Might want to print an error message.
abort() is not out of the question, but chances are GDB is just
back and decide something of a lower priority is better. The
ordering is:
- kc < clr sgl shl shlr slr sn sr ss
- sgl < shl shlr slr sn sr ss
- slr < err shl shlr sn sr ss
- clr < err shl shlr sn sr ss
- ss < shl shlr sn sr
- sn < shl shlr sr
- shl < shlr sr
- shlr < sr
+ kc < clr sgl shl slr sn sr ss
+ sgl < shl slr sn sr ss
+ slr < err shl sn sr ss
+ clr < err shl sn sr ss
+ ss < shl sn sr
+ sn < shl sr
+ shl < sr
sr <
What I think this means is that we don't need a damned table
table[(int) class_last][(int) BPSTAT_WHAT_LAST] =
{
/* old action */
- /* kc ss sn sgl slr clr sr shl shlr
+ /* kc ss sn sgl slr clr sr shl
*/
/*no_effect */
- {kc, ss, sn, sgl, slr, clr, sr, shl, shlr},
+ {kc, ss, sn, sgl, slr, clr, sr, shl},
/*wp_silent */
- {ss, ss, sn, ss, ss, ss, sr, shl, shlr},
+ {ss, ss, sn, ss, ss, ss, sr, shl},
/*wp_noisy */
- {sn, sn, sn, sn, sn, sn, sr, shl, shlr},
+ {sn, sn, sn, sn, sn, sn, sr, shl},
/*bp_nostop */
- {sgl, ss, sn, sgl, slr, slr, sr, shl, shlr},
+ {sgl, ss, sn, sgl, slr, slr, sr, shl},
/*bp_silent */
- {ss, ss, sn, ss, ss, ss, sr, shl, shlr},
+ {ss, ss, sn, ss, ss, ss, sr, shl},
/*bp_noisy */
- {sn, sn, sn, sn, sn, sn, sr, shl, shlr},
+ {sn, sn, sn, sn, sn, sn, sr, shl},
/*long_jump */
- {slr, ss, sn, slr, slr, err, sr, shl, shlr},
+ {slr, ss, sn, slr, slr, err, sr, shl},
/*long_resume */
- {clr, ss, sn, err, err, err, sr, shl, shlr},
+ {clr, ss, sn, err, err, err, sr, shl},
/*step_resume */
- {sr, sr, sr, sr, sr, sr, sr, sr, sr},
+ {sr, sr, sr, sr, sr, sr, sr, sr},
/*shlib */
- {shl, shl, shl, shl, shl, shl, sr, shl, shlr},
-/*catch_shlib */
- {shlr, shlr, shlr, shlr, shlr, shlr, sr, shlr, shlr}
+ {shl, shl, shl, shl, shl, shl, sr, shl}
};
#undef kc
#undef sr
#undef ts
#undef shl
-#undef shlr
enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING;
struct bpstat_what retval;
case bp_overlay_event:
bs_class = bp_nostop;
break;
- case bp_catch_load:
- case bp_catch_unload:
- /* Only if this catchpoint triggered should we cause the
- step-out-of-dld behaviour. Otherwise, we ignore this
- catchpoint. */
- if (bs->stop)
- bs_class = catch_shlib_event;
- else
- bs_class = no_effect;
- break;
- case bp_catch_fork:
- case bp_catch_vfork:
- case bp_catch_exec:
+ case bp_catchpoint:
if (bs->stop)
{
if (bs->print)
\f
-/* Given a bpstat that records zero or more triggered eventpoints, this
- function returns another bpstat which contains only the catchpoints
- on that first list, if any. */
-void
-bpstat_get_triggered_catchpoints (bpstat ep_list, bpstat *cp_list)
-{
- struct bpstats root_bs[1];
- bpstat bs = root_bs;
- struct breakpoint *ep;
- char *dll_pathname;
-
- bpstat_clear (cp_list);
- root_bs->next = NULL;
-
- for (; ep_list != NULL; ep_list = ep_list->next)
- {
- /* Is this eventpoint a catchpoint? If not, ignore it. */
- ep = ep_list->breakpoint_at->owner;
- if (ep == NULL)
- break;
- if ((ep->type != bp_catch_load) &&
- (ep->type != bp_catch_unload))
- /* pai: (temp) ADD fork/vfork here!! */
- continue;
-
- /* Yes; add it to the list. */
- bs = bpstat_alloc (ep_list->breakpoint_at, bs);
- *bs = *ep_list;
- bs->next = NULL;
- bs = root_bs->next;
-
-#if defined(SOLIB_ADD)
- /* Also, for each triggered catchpoint, tag it with the name of
- the library that caused this trigger. (We copy the name now,
- because it's only guaranteed to be available NOW, when the
- catchpoint triggers. Clients who may wish to know the name
- later must get it from the catchpoint itself.) */
- if (ep->triggered_dll_pathname != NULL)
- xfree (ep->triggered_dll_pathname);
- if (ep->type == bp_catch_load)
- dll_pathname = SOLIB_LOADED_LIBRARY_PATHNAME (
- PIDGET (inferior_ptid));
- else
- dll_pathname = SOLIB_UNLOADED_LIBRARY_PATHNAME (
- PIDGET (inferior_ptid));
-#else
- dll_pathname = NULL;
-#endif
- if (dll_pathname)
- {
- ep->triggered_dll_pathname = (char *)
- xmalloc (strlen (dll_pathname) + 1);
- strcpy (ep->triggered_dll_pathname, dll_pathname);
- }
- else
- ep->triggered_dll_pathname = NULL;
- }
-
- *cp_list = bs;
-}
-
static void print_breakpoint_location (struct breakpoint *b,
struct bp_location *loc,
char *wrap_indent,
{bp_shlib_event, "shlib events"},
{bp_thread_event, "thread events"},
{bp_overlay_event, "overlay events"},
- {bp_catch_load, "catch load"},
- {bp_catch_unload, "catch unload"},
- {bp_catch_fork, "catch fork"},
- {bp_catch_vfork, "catch vfork"},
- {bp_catch_exec, "catch exec"}
+ {bp_catchpoint, "catchpoint"},
};
static char bpenables[] = "nynny";
int header_of_multiple = 0;
int part_of_multiple = (loc != NULL);
+ struct value_print_options opts;
+
+ get_user_print_options (&opts);
gdb_assert (!loc || loc_number != 0);
/* See comment in print_one_breakpoint concerning
/* 5 and 6 */
strcpy (wrap_indent, " ");
- if (addressprint)
+ if (opts.addressprint)
{
if (gdbarch_addr_bit (current_gdbarch) <= 32)
strcat (wrap_indent, " ");
/* Field 4, the address, is omitted (which makes the columns
not line up too nicely with the headers, but the effect
is relatively readable). */
- if (addressprint)
- ui_out_field_skip (uiout, "addr");
- annotate_field (5);
- print_expression (b->exp, stb->stream);
- ui_out_field_stream (uiout, "what", stb);
- break;
-
- case bp_catch_load:
- case bp_catch_unload:
- /* Field 4, the address, is omitted (which makes the columns
- not line up too nicely with the headers, but the effect
- is relatively readable). */
- if (addressprint)
- ui_out_field_skip (uiout, "addr");
- annotate_field (5);
- if (b->dll_pathname == NULL)
- {
- ui_out_field_string (uiout, "what", "<any library>");
- ui_out_spaces (uiout, 1);
- }
- else
- {
- ui_out_text (uiout, "library \"");
- ui_out_field_string (uiout, "what", b->dll_pathname);
- ui_out_text (uiout, "\" ");
- }
- break;
-
- case bp_catch_fork:
- case bp_catch_vfork:
- /* Field 4, the address, is omitted (which makes the columns
- not line up too nicely with the headers, but the effect
- is relatively readable). */
- if (addressprint)
- ui_out_field_skip (uiout, "addr");
- annotate_field (5);
- if (!ptid_equal (b->forked_inferior_pid, null_ptid))
- {
- ui_out_text (uiout, "process ");
- ui_out_field_int (uiout, "what",
- ptid_get_pid (b->forked_inferior_pid));
- ui_out_spaces (uiout, 1);
- }
- break;
-
- case bp_catch_exec:
- /* Field 4, the address, is omitted (which makes the columns
- not line up too nicely with the headers, but the effect
- is relatively readable). */
- if (addressprint)
+ if (opts.addressprint)
ui_out_field_skip (uiout, "addr");
annotate_field (5);
- if (b->exec_pathname != NULL)
- {
- ui_out_text (uiout, "program \"");
- ui_out_field_string (uiout, "what", b->exec_pathname);
- ui_out_text (uiout, "\" ");
- }
+ ui_out_field_string (uiout, "what", b->exp_string);
break;
case bp_breakpoint:
case bp_shlib_event:
case bp_thread_event:
case bp_overlay_event:
- if (addressprint)
+ if (opts.addressprint)
{
annotate_field (4);
if (header_of_multiple)
user_settable_breakpoint (const struct breakpoint *b)
{
return (b->type == bp_breakpoint
- || b->type == bp_catch_load
- || b->type == bp_catch_unload
- || b->type == bp_catch_fork
- || b->type == bp_catch_vfork
- || b->type == bp_catch_exec
+ || b->type == bp_catchpoint
|| b->type == bp_hardware_breakpoint
|| b->type == bp_watchpoint
|| b->type == bp_read_watchpoint
CORE_ADDR last_addr = (CORE_ADDR) -1;
int nr_printable_breakpoints;
struct cleanup *bkpttbl_chain;
+ struct value_print_options opts;
+ get_user_print_options (&opts);
+
/* Compute the number of rows in the table. */
nr_printable_breakpoints = 0;
ALL_BREAKPOINTS (b)
nr_printable_breakpoints++;
}
- if (addressprint)
+ if (opts.addressprint)
bkpttbl_chain
= make_cleanup_ui_out_table_begin_end (uiout, 6, nr_printable_breakpoints,
"BreakpointTable");
if (nr_printable_breakpoints > 0)
annotate_field (3);
ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb"); /* 4 */
- if (addressprint)
+ if (opts.addressprint)
{
if (nr_printable_breakpoints > 0)
annotate_field (4);
bp_hardware_watchpoint
bp_read_watchpoint
bp_access_watchpoint
- bp_catch_exec
- bp_catch_fork
- bp_catch_vork */
+ bp_catchpoint */
static int
breakpoint_address_is_meaningful (struct breakpoint *bpt)
&& type != bp_hardware_watchpoint
&& type != bp_read_watchpoint
&& type != bp_access_watchpoint
- && type != bp_catch_exec
- && type != bp_catch_fork
- && type != bp_catch_vfork);
+ && type != bp_catchpoint);
}
/* Rescan breakpoints at the same address and section as BPT,
|| bptype == bp_hardware_watchpoint
|| bptype == bp_read_watchpoint
|| bptype == bp_access_watchpoint
- || bptype == bp_catch_fork
- || bptype == bp_catch_vfork
- || bptype == bp_catch_exec)
+ || bptype == bp_catchpoint)
{
/* Watchpoints and the various bp_catch_* eventpoints should not
have their addresses modified. */
/* Allocate a struct bp_location. */
static struct bp_location *
-allocate_bp_location (struct breakpoint *bpt, enum bptype bp_type)
+allocate_bp_location (struct breakpoint *bpt)
{
struct bp_location *loc, *loc_p;
loc->shlib_disabled = 0;
loc->enabled = 1;
- switch (bp_type)
+ switch (bpt->type)
{
case bp_breakpoint:
case bp_until:
case bp_shlib_event:
case bp_thread_event:
case bp_overlay_event:
- case bp_catch_load:
- case bp_catch_unload:
loc->loc_type = bp_loc_software_breakpoint;
break;
case bp_hardware_breakpoint:
loc->loc_type = bp_loc_hardware_watchpoint;
break;
case bp_watchpoint:
- case bp_catch_fork:
- case bp_catch_vfork:
- case bp_catch_exec:
+ case bp_catchpoint:
loc->loc_type = bp_loc_other;
break;
default:
b->ignore_count = 0;
b->commands = NULL;
b->frame_id = null_frame_id;
- b->dll_pathname = NULL;
- b->triggered_dll_pathname = NULL;
b->forked_inferior_pid = null_ptid;
b->exec_pathname = NULL;
b->ops = NULL;
breakpoint may cause target_read_memory() to be called and we do
not want its scan of the location chain to find a breakpoint and
location that's only been partially initialized. */
- adjusted_address = adjust_breakpoint_address (sal.pc, bptype);
+ adjusted_address = adjust_breakpoint_address (sal.pc, b->type);
- b->loc = allocate_bp_location (b, bptype);
+ b->loc = allocate_bp_location (b);
b->loc->requested_address = sal.pc;
b->loc->address = adjusted_address;
}
}
+/* FORK & VFORK catchpoints. */
+
+/* Implement the "insert" breakpoint_ops method for fork catchpoints. */
+
static void
-create_fork_vfork_event_catchpoint (int tempflag, char *cond_string,
- enum bptype bp_kind)
+insert_catch_fork (struct breakpoint *b)
{
- struct symtab_and_line sal;
- struct breakpoint *b;
- int thread = -1; /* All threads. */
+ target_insert_fork_catchpoint (PIDGET (inferior_ptid));
+}
- init_sal (&sal);
- sal.pc = 0;
- sal.symtab = NULL;
- sal.line = 0;
+/* Implement the "remove" breakpoint_ops method for fork catchpoints. */
- b = set_raw_breakpoint (sal, bp_kind);
- set_breakpoint_count (breakpoint_count + 1);
- b->number = breakpoint_count;
- b->cond_string = (cond_string == NULL) ?
- NULL : savestring (cond_string, strlen (cond_string));
- b->thread = thread;
- b->addr_string = NULL;
- b->enable_state = bp_enabled;
- b->disposition = tempflag ? disp_del : disp_donttouch;
- b->forked_inferior_pid = null_ptid;
- update_global_location_list (1);
+static int
+remove_catch_fork (struct breakpoint *b)
+{
+ return target_remove_fork_catchpoint (PIDGET (inferior_ptid));
+}
+/* Implement the "breakpoint_hit" breakpoint_ops method for fork
+ catchpoints. */
- mention (b);
+static int
+breakpoint_hit_catch_fork (struct breakpoint *b)
+{
+ return inferior_has_forked (inferior_ptid, &b->forked_inferior_pid);
}
+/* Implement the "print_it" breakpoint_ops method for fork catchpoints. */
+
+static enum print_stop_action
+print_it_catch_fork (struct breakpoint *b)
+{
+ annotate_catchpoint (b->number);
+ printf_filtered (_("\nCatchpoint %d (forked process %d), "),
+ b->number, ptid_get_pid (b->forked_inferior_pid));
+ return PRINT_SRC_AND_LOC;
+}
+
+/* Implement the "print_one" breakpoint_ops method for fork catchpoints. */
+
static void
-create_fork_event_catchpoint (int tempflag, char *cond_string)
+print_one_catch_fork (struct breakpoint *b, CORE_ADDR *last_addr)
{
- create_fork_vfork_event_catchpoint (tempflag, cond_string, bp_catch_fork);
+ struct value_print_options opts;
+
+ get_user_print_options (&opts);
+
+ /* Field 4, the address, is omitted (which makes the columns
+ not line up too nicely with the headers, but the effect
+ is relatively readable). */
+ if (opts.addressprint)
+ ui_out_field_skip (uiout, "addr");
+ annotate_field (5);
+ ui_out_text (uiout, "fork");
+ if (!ptid_equal (b->forked_inferior_pid, null_ptid))
+ {
+ ui_out_text (uiout, ", process ");
+ ui_out_field_int (uiout, "what",
+ ptid_get_pid (b->forked_inferior_pid));
+ ui_out_spaces (uiout, 1);
+ }
}
+/* Implement the "print_mention" breakpoint_ops method for fork
+ catchpoints. */
+
static void
-create_vfork_event_catchpoint (int tempflag, char *cond_string)
+print_mention_catch_fork (struct breakpoint *b)
{
- create_fork_vfork_event_catchpoint (tempflag, cond_string, bp_catch_vfork);
+ printf_filtered (_("Catchpoint %d (fork)"), b->number);
}
+/* The breakpoint_ops structure to be used in fork catchpoints. */
+
+static struct breakpoint_ops catch_fork_breakpoint_ops =
+{
+ insert_catch_fork,
+ remove_catch_fork,
+ breakpoint_hit_catch_fork,
+ print_it_catch_fork,
+ print_one_catch_fork,
+ print_mention_catch_fork
+};
+
+/* Implement the "insert" breakpoint_ops method for vfork catchpoints. */
+
static void
-create_exec_event_catchpoint (int tempflag, char *cond_string)
+insert_catch_vfork (struct breakpoint *b)
+{
+ target_insert_vfork_catchpoint (PIDGET (inferior_ptid));
+}
+
+/* Implement the "remove" breakpoint_ops method for vfork catchpoints. */
+
+static int
+remove_catch_vfork (struct breakpoint *b)
+{
+ return target_remove_vfork_catchpoint (PIDGET (inferior_ptid));
+}
+
+/* Implement the "breakpoint_hit" breakpoint_ops method for vfork
+ catchpoints. */
+
+static int
+breakpoint_hit_catch_vfork (struct breakpoint *b)
+{
+ return inferior_has_vforked (inferior_ptid, &b->forked_inferior_pid);
+}
+
+/* Implement the "print_it" breakpoint_ops method for vfork catchpoints. */
+
+static enum print_stop_action
+print_it_catch_vfork (struct breakpoint *b)
+{
+ annotate_catchpoint (b->number);
+ printf_filtered (_("\nCatchpoint %d (vforked process %d), "),
+ b->number, ptid_get_pid (b->forked_inferior_pid));
+ return PRINT_SRC_AND_LOC;
+}
+
+/* Implement the "print_one" breakpoint_ops method for vfork catchpoints. */
+
+static void
+print_one_catch_vfork (struct breakpoint *b, CORE_ADDR *last_addr)
+{
+ struct value_print_options opts;
+
+ get_user_print_options (&opts);
+ /* Field 4, the address, is omitted (which makes the columns
+ not line up too nicely with the headers, but the effect
+ is relatively readable). */
+ if (opts.addressprint)
+ ui_out_field_skip (uiout, "addr");
+ annotate_field (5);
+ ui_out_text (uiout, "vfork");
+ if (!ptid_equal (b->forked_inferior_pid, null_ptid))
+ {
+ ui_out_text (uiout, ", process ");
+ ui_out_field_int (uiout, "what",
+ ptid_get_pid (b->forked_inferior_pid));
+ ui_out_spaces (uiout, 1);
+ }
+}
+
+/* Implement the "print_mention" breakpoint_ops method for vfork
+ catchpoints. */
+
+static void
+print_mention_catch_vfork (struct breakpoint *b)
+{
+ printf_filtered (_("Catchpoint %d (vfork)"), b->number);
+}
+
+/* The breakpoint_ops structure to be used in vfork catchpoints. */
+
+static struct breakpoint_ops catch_vfork_breakpoint_ops =
+{
+ insert_catch_vfork,
+ remove_catch_vfork,
+ breakpoint_hit_catch_vfork,
+ print_it_catch_vfork,
+ print_one_catch_vfork,
+ print_mention_catch_vfork
+};
+
+/* Create a new breakpoint of the bp_catchpoint kind and return it.
+
+ If TEMPFLAG is non-zero, then make the breakpoint temporary.
+ If COND_STRING is not NULL, then store it in the breakpoint.
+ OPS, if not NULL, is the breakpoint_ops structure associated
+ to the catchpoint. */
+
+static struct breakpoint *
+create_catchpoint (int tempflag, char *cond_string,
+ struct breakpoint_ops *ops)
{
struct symtab_and_line sal;
struct breakpoint *b;
- int thread = -1; /* All threads. */
init_sal (&sal);
sal.pc = 0;
sal.symtab = NULL;
sal.line = 0;
- b = set_raw_breakpoint (sal, bp_catch_exec);
+ b = set_raw_breakpoint (sal, bp_catchpoint);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
- b->cond_string = (cond_string == NULL) ?
+
+ b->cond_string = (cond_string == NULL) ?
NULL : savestring (cond_string, strlen (cond_string));
- b->thread = thread;
+ b->thread = -1;
b->addr_string = NULL;
b->enable_state = bp_enabled;
b->disposition = tempflag ? disp_del : disp_donttouch;
- update_global_location_list (1);
+ b->ops = ops;
mention (b);
+ update_global_location_list (1);
+
+ return b;
+}
+
+static void
+create_fork_vfork_event_catchpoint (int tempflag, char *cond_string,
+ struct breakpoint_ops *ops)
+{
+ struct breakpoint *b = create_catchpoint (tempflag, cond_string, ops);
+
+ /* FIXME: We should put this information in a breakpoint private data
+ area. */
+ b->forked_inferior_pid = null_ptid;
+}
+
+/* Exec catchpoints. */
+
+static void
+insert_catch_exec (struct breakpoint *b)
+{
+ target_insert_exec_catchpoint (PIDGET (inferior_ptid));
}
+static int
+remove_catch_exec (struct breakpoint *b)
+{
+ return target_remove_exec_catchpoint (PIDGET (inferior_ptid));
+}
+
+static int
+breakpoint_hit_catch_exec (struct breakpoint *b)
+{
+ return inferior_has_execd (inferior_ptid, &b->exec_pathname);
+}
+
+static enum print_stop_action
+print_it_catch_exec (struct breakpoint *b)
+{
+ annotate_catchpoint (b->number);
+ printf_filtered (_("\nCatchpoint %d (exec'd %s), "), b->number,
+ b->exec_pathname);
+ return PRINT_SRC_AND_LOC;
+}
+
+static void
+print_one_catch_exec (struct breakpoint *b, CORE_ADDR *last_addr)
+{
+ struct value_print_options opts;
+
+ get_user_print_options (&opts);
+
+ /* Field 4, the address, is omitted (which makes the columns
+ not line up too nicely with the headers, but the effect
+ is relatively readable). */
+ if (opts.addressprint)
+ ui_out_field_skip (uiout, "addr");
+ annotate_field (5);
+ ui_out_text (uiout, "exec");
+ if (b->exec_pathname != NULL)
+ {
+ ui_out_text (uiout, ", program \"");
+ ui_out_field_string (uiout, "what", b->exec_pathname);
+ ui_out_text (uiout, "\" ");
+ }
+}
+
+static void
+print_mention_catch_exec (struct breakpoint *b)
+{
+ printf_filtered (_("Catchpoint %d (exec)"), b->number);
+}
+
+static struct breakpoint_ops catch_exec_breakpoint_ops =
+{
+ insert_catch_exec,
+ remove_catch_exec,
+ breakpoint_hit_catch_exec,
+ print_it_catch_exec,
+ print_one_catch_exec,
+ print_mention_catch_exec
+};
+
static int
hw_breakpoint_used_count (void)
{
mention (struct breakpoint *b)
{
int say_where = 0;
- struct cleanup *old_chain, *ui_out_chain;
- struct ui_stream *stb;
+ struct cleanup *ui_out_chain;
+ struct value_print_options opts;
- stb = ui_out_stream_new (uiout);
- old_chain = make_cleanup_ui_out_stream_delete (stb);
+ get_user_print_options (&opts);
/* FIXME: This is misplaced; mention() is called by things (like
hitting a watchpoint) other than breakpoint creation. It should
ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
ui_out_field_int (uiout, "number", b->number);
ui_out_text (uiout, ": ");
- print_expression (b->exp, stb->stream);
- ui_out_field_stream (uiout, "exp", stb);
+ ui_out_field_string (uiout, "exp", b->exp_string);
do_cleanups (ui_out_chain);
break;
case bp_hardware_watchpoint:
ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
ui_out_field_int (uiout, "number", b->number);
ui_out_text (uiout, ": ");
- print_expression (b->exp, stb->stream);
- ui_out_field_stream (uiout, "exp", stb);
+ ui_out_field_string (uiout, "exp", b->exp_string);
do_cleanups (ui_out_chain);
break;
case bp_read_watchpoint:
ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-rwpt");
ui_out_field_int (uiout, "number", b->number);
ui_out_text (uiout, ": ");
- print_expression (b->exp, stb->stream);
- ui_out_field_stream (uiout, "exp", stb);
+ ui_out_field_string (uiout, "exp", b->exp_string);
do_cleanups (ui_out_chain);
break;
case bp_access_watchpoint:
ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-awpt");
ui_out_field_int (uiout, "number", b->number);
ui_out_text (uiout, ": ");
- print_expression (b->exp, stb->stream);
- ui_out_field_stream (uiout, "exp", stb);
+ ui_out_field_string (uiout, "exp", b->exp_string);
do_cleanups (ui_out_chain);
break;
case bp_breakpoint:
printf_filtered (_("Hardware assisted breakpoint %d"), b->number);
say_where = 1;
break;
- case bp_catch_load:
- case bp_catch_unload:
- printf_filtered (_("Catchpoint %d (%s %s)"),
- b->number,
- (b->type == bp_catch_load) ? "load" : "unload",
- (b->dll_pathname != NULL) ?
- b->dll_pathname : "<any library>");
- break;
- case bp_catch_fork:
- case bp_catch_vfork:
- printf_filtered (_("Catchpoint %d (%s)"),
- b->number,
- (b->type == bp_catch_fork) ? "fork" : "vfork");
- break;
- case bp_catch_exec:
- printf_filtered (_("Catchpoint %d (exec)"),
- b->number);
- break;
case bp_until:
case bp_finish:
}
else
{
- if (addressprint || b->source_file == NULL)
+ if (opts.addressprint || b->source_file == NULL)
{
printf_filtered (" at ");
fputs_filtered (paddress (b->loc->address), gdb_stdout);
}
}
- do_cleanups (old_chain);
if (ui_out_is_mi_like_p (uiout))
return;
printf_filtered ("\n");
\f
static struct bp_location *
-add_location_to_breakpoint (struct breakpoint *b, enum bptype bptype,
+add_location_to_breakpoint (struct breakpoint *b,
const struct symtab_and_line *sal)
{
struct bp_location *loc, **tmp;
- loc = allocate_bp_location (b, bptype);
+ loc = allocate_bp_location (b);
for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
;
*tmp = loc;
loc->requested_address = sal->pc;
- loc->address = adjust_breakpoint_address (loc->requested_address,
- bptype);
+ loc->address = adjust_breakpoint_address (loc->requested_address, b->type);
loc->section = sal->section;
set_breakpoint_location_function (loc);
CORE_ADDR addr;
const gdb_byte *brk;
gdb_byte *target_mem;
+ struct cleanup *cleanup;
+ int retval = 0;
gdb_assert (loc != NULL);
addr = loc->address;
brk = gdbarch_breakpoint_from_pc (current_gdbarch, &addr, &len);
+ /* Software breakpoints unsupported? */
+ if (brk == NULL)
+ return 0;
+
target_mem = alloca (len);
+ /* Enable the automatic memory restoration from breakpoints while
+ we read the memory. Otherwise we could say about our temporary
+ breakpoints they are permanent. */
+ cleanup = make_show_memory_breakpoints_cleanup (0);
+
if (target_read_memory (loc->address, target_mem, len) == 0
&& memcmp (target_mem, brk, len) == 0)
- return 1;
+ retval = 1;
- return 0;
+ do_cleanups (cleanup);
+
+ return retval;
}
char *cond_string,
enum bptype type, enum bpdisp disposition,
int thread, int ignore_count,
- struct breakpoint_ops *ops, int from_tty)
+ struct breakpoint_ops *ops, int from_tty, int enabled)
{
struct breakpoint *b = NULL;
int i;
b->cond_string = cond_string;
b->ignore_count = ignore_count;
- b->enable_state = bp_enabled;
+ b->enable_state = enabled ? bp_enabled : bp_disabled;
b->disposition = disposition;
loc = b->loc;
}
else
{
- loc = add_location_to_breakpoint (b, type, &sal);
+ loc = add_location_to_breakpoint (b, &sal);
}
if (bp_loc_is_permanent (loc))
char *cond_string,
enum bptype type, enum bpdisp disposition,
int thread, int ignore_count,
- struct breakpoint_ops *ops, int from_tty)
+ struct breakpoint_ops *ops, int from_tty,
+ int enabled)
{
int i;
for (i = 0; i < sals.nelts; ++i)
create_breakpoint (expanded, addr_string[i],
cond_string, type, disposition,
- thread, ignore_count, ops, from_tty);
+ thread, ignore_count, ops, from_tty, enabled);
}
update_global_location_list (1);
if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
{
+ struct expression *expr;
+
tok = cond_start = end_tok + 1;
- parse_exp_1 (&tok, block_for_pc (pc), 0);
+ expr = parse_exp_1 (&tok, block_for_pc (pc), 0);
+ xfree (expr);
cond_end = tok;
*cond_string = savestring (cond_start,
cond_end - cond_start);
int ignore_count,
enum auto_boolean pending_break_support,
struct breakpoint_ops *ops,
- int from_tty)
+ int from_tty,
+ int enabled)
{
struct gdb_exception e;
struct symtabs_and_lines sals;
hardwareflag ? bp_hardware_breakpoint
: bp_breakpoint,
tempflag ? disp_del : disp_donttouch,
- thread, ignore_count, ops, from_tty);
+ thread, ignore_count, ops, from_tty, enabled);
}
else
{
b->disposition = tempflag ? disp_del : disp_donttouch;
b->condition_not_parsed = 1;
b->ops = ops;
+ b->enable_state = enabled ? bp_enabled : bp_disabled;
update_global_location_list (1);
mention (b);
0 /* Ignore count */,
pending_break_support,
NULL /* breakpoint_ops */,
- from_tty);
+ from_tty,
+ 1 /* enabled */);
}
set_breakpoint (char *address, char *condition,
int hardwareflag, int tempflag,
int thread, int ignore_count,
- int pending)
+ int pending, int enabled)
{
break_command_really (address, condition, thread,
0 /* condition and thread are valid. */,
ignore_count,
pending
? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
- NULL, 0);
+ NULL, 0, enabled);
}
/* Adjust SAL to the first instruction past the function prologue.
exp_start = arg;
exp = parse_exp_1 (&arg, 0, 0);
exp_end = arg;
+ /* Remove trailing whitespace from the expression before saving it.
+ This makes the eventual display of the expression string a bit
+ prettier. */
+ while (exp_end > exp_start && (exp_end[-1] == ' ' || exp_end[-1] == '\t'))
+ --exp_end;
+
exp_valid_block = innermost_block;
mark = value_mark ();
fetch_watchpoint_value (exp, &val, NULL, NULL);
{
case catch_fork_temporary:
case catch_fork_permanent:
- create_fork_event_catchpoint (tempflag, cond_string);
+ create_fork_vfork_event_catchpoint (tempflag, cond_string,
+ &catch_fork_breakpoint_ops);
break;
case catch_vfork_temporary:
case catch_vfork_permanent:
- create_vfork_event_catchpoint (tempflag, cond_string);
+ create_fork_vfork_event_catchpoint (tempflag, cond_string,
+ &catch_vfork_breakpoint_ops);
break;
default:
error (_("unsupported or unknown fork kind; cannot catch it"));
/* If this target supports it, create an exec catchpoint
and enable reporting of such events. */
- create_exec_event_catchpoint (tempflag, cond_string);
-}
-
-static void
-catch_load_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
-{
- int tempflag;
- char *dll_pathname = NULL;
- char *cond_string = NULL;
-
- tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
-
- if (!arg)
- arg = "";
- ep_skip_leading_whitespace (&arg);
-
- /* The allowed syntax is:
- catch load
- catch load if <cond>
- catch load <filename>
- catch load <filename> if <cond>
-
- The user is not allowed to specify the <filename> after an
- if clause.
-
- We'll ignore the pathological case of a file named "if".
-
- First, check if there's an if clause. If so, then there
- cannot be a filename. */
- cond_string = ep_parse_optional_if_clause (&arg);
-
- /* If there was an if clause, then there cannot be a filename.
- Else, there might be a filename and an if clause. */
- if (cond_string == NULL)
- {
- dll_pathname = ep_parse_optional_filename (&arg);
- ep_skip_leading_whitespace (&arg);
- cond_string = ep_parse_optional_if_clause (&arg);
- }
-
- if ((*arg != '\0') && !isspace (*arg))
- error (_("Junk at end of arguments."));
-
- /* Create a load breakpoint that only triggers when a load of
- the specified dll (or any dll, if no pathname was specified)
- occurs. */
- SOLIB_CREATE_CATCH_LOAD_HOOK (PIDGET (inferior_ptid), tempflag,
- dll_pathname, cond_string);
-}
-
-static void
-catch_unload_command_1 (char *arg, int from_tty,
- struct cmd_list_element *command)
-{
- int tempflag;
- char *dll_pathname = NULL;
- char *cond_string = NULL;
-
- tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
-
- if (!arg)
- arg = "";
- ep_skip_leading_whitespace (&arg);
-
- /* The allowed syntax is:
- catch unload
- catch unload if <cond>
- catch unload <filename>
- catch unload <filename> if <cond>
-
- The user is not allowed to specify the <filename> after an
- if clause.
-
- We'll ignore the pathological case of a file named "if".
-
- First, check if there's an if clause. If so, then there
- cannot be a filename. */
- cond_string = ep_parse_optional_if_clause (&arg);
-
- /* If there was an if clause, then there cannot be a filename.
- Else, there might be a filename and an if clause. */
- if (cond_string == NULL)
- {
- dll_pathname = ep_parse_optional_filename (&arg);
- ep_skip_leading_whitespace (&arg);
- cond_string = ep_parse_optional_if_clause (&arg);
- }
-
- if ((*arg != '\0') && !isspace (*arg))
- error (_("Junk at end of arguments."));
-
- /* Create an unload breakpoint that only triggers when an unload of
- the specified dll (or any dll, if no pathname was specified)
- occurs. */
- SOLIB_CREATE_CATCH_UNLOAD_HOOK (PIDGET (inferior_ptid), tempflag,
- dll_pathname, cond_string);
+ create_catchpoint (tempflag, cond_string, &catch_exec_breakpoint_ops);
}
static enum print_stop_action
static void
print_one_exception_catchpoint (struct breakpoint *b, CORE_ADDR *last_addr)
{
- if (addressprint)
+ struct value_print_options opts;
+ get_user_print_options (&opts);
+ if (opts.addressprint)
{
annotate_field (4);
if (b->loc == NULL || b->loc->shlib_disabled)
}
static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = {
+ NULL, /* insert */
+ NULL, /* remove */
+ NULL, /* breakpoint_hit */
print_exception_catchpoint,
print_one_exception_catchpoint,
print_mention_exception_catchpoint
tempflag, 0,
0,
AUTO_BOOLEAN_TRUE /* pending */,
- &gnu_v3_exception_catchpoint_ops, from_tty);
+ &gnu_v3_exception_catchpoint_ops, from_tty,
+ 1 /* enabled */);
return 1;
}
}
}
-/* If SHOULD_INSERT is true, do not insert any breakpoint locations
+/* A cleanup function which destroys a vector. */
+
+static void
+do_vec_free (void *p)
+{
+ VEC(bp_location_p) **vec = p;
+ if (*vec)
+ VEC_free (bp_location_p, *vec);
+}
+
+/* If SHOULD_INSERT is false, do not insert any breakpoint locations
into the inferior, only remove already-inserted locations that no
longer should be inserted. Functions that delete a breakpoint or
breakpoints should pass false, so that deleting a breakpoint
struct bp_location **next = &bp_location_chain;
struct bp_location *loc;
struct bp_location *loc2;
- struct gdb_exception e;
VEC(bp_location_p) *old_locations = NULL;
int ret;
int ix;
-
+ struct cleanup *cleanups;
+
+ cleanups = make_cleanup (do_vec_free, &old_locations);
/* Store old locations for future reference. */
for (loc = bp_location_chain; loc; loc = loc->global_next)
VEC_safe_push (bp_location_p, old_locations, loc);
check_duplicates (b);
}
- if (breakpoints_always_inserted_mode ()
- && should_insert
- && target_has_execution)
+ if (breakpoints_always_inserted_mode () && should_insert
+ && (target_has_execution
+ || (gdbarch_has_global_solist (target_gdbarch)
+ && target_supports_multi_process ())))
insert_breakpoint_locations ();
+
+ do_cleanups (cleanups);
}
void
value_free (bpt->val);
if (bpt->source_file != NULL)
xfree (bpt->source_file);
- if (bpt->dll_pathname != NULL)
- xfree (bpt->dll_pathname);
- if (bpt->triggered_dll_pathname != NULL)
- xfree (bpt->triggered_dll_pathname);
if (bpt->exec_pathname != NULL)
xfree (bpt->exec_pathname);
for (i = 0; i < sals.nelts; ++i)
{
struct bp_location *new_loc =
- add_location_to_breakpoint (b, b->type, &(sals.sals[i]));
+ add_location_to_breakpoint (b, &(sals.sals[i]));
/* Reparse conditions, they might contain references to the
old symtab. */
char *s;
enum enable_state save_enable;
struct gdb_exception e;
-
+ struct cleanup *cleanups;
switch (b->type)
{
return 0;
case bp_breakpoint:
case bp_hardware_breakpoint:
- case bp_catch_load:
- case bp_catch_unload:
if (b->addr_string == NULL)
{
/* Anything without a string can't be re-set. */
b->condition_not_parsed = 0;
}
expanded = expand_line_sal_maybe (sals.sals[0]);
+ cleanups = make_cleanup (xfree, sals.sals);
update_breakpoint_locations (b, expanded);
-
- xfree (sals.sals);
+ do_cleanups (cleanups);
break;
case bp_watchpoint:
/* We needn't really do anything to reset these, since the mask
that requests them is unaffected by e.g., new libraries being
loaded. */
- case bp_catch_fork:
- case bp_catch_vfork:
- case bp_catch_exec:
+ case bp_catchpoint:
break;
default:
error (_("No breakpoint number %d."), bptnum);
}
+void
+make_breakpoint_silent (struct breakpoint *b)
+{
+ /* Silence the breakpoint. */
+ b->silent = 1;
+}
+
/* Command to set ignore-count of breakpoint N to COUNT. */
static void
bpt->number);
continue;
case bp_breakpoint:
- case bp_catch_load:
- case bp_catch_unload:
- case bp_catch_fork:
- case bp_catch_vfork:
- case bp_catch_exec:
+ case bp_catchpoint:
case bp_hardware_breakpoint:
case bp_watchpoint:
case bp_hardware_watchpoint:
bpt->type == bp_read_watchpoint ||
bpt->type == bp_access_watchpoint)
{
- struct frame_id saved_frame_id;
-
- saved_frame_id = get_frame_id (get_selected_frame (NULL));
- if (bpt->exp_valid_block != NULL)
+ struct gdb_exception e;
+
+ TRY_CATCH (e, RETURN_MASK_ALL)
{
- struct frame_info *fr =
- fr = frame_find_by_id (bpt->watchpoint_frame);
- if (fr == NULL)
- {
- printf_filtered (_("\
-Cannot enable watchpoint %d because the block in which its expression\n\
-is valid is not currently in scope.\n"), bpt->number);
- return;
- }
- select_frame (fr);
+ update_watchpoint (bpt, 1 /* reparse */);
}
-
- if (bpt->val)
- value_free (bpt->val);
- mark = value_mark ();
- fetch_watchpoint_value (bpt->exp, &bpt->val, NULL, NULL);
- if (bpt->val)
- release_value (bpt->val);
- bpt->val_valid = 1;
-
- if (bpt->type == bp_hardware_watchpoint ||
- bpt->type == bp_read_watchpoint ||
- bpt->type == bp_access_watchpoint)
+ if (e.reason < 0)
{
- int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
- int mem_cnt = can_use_hardware_watchpoint (bpt->val);
-
- /* Hack around 'unused var' error for some targets here */
- (void) mem_cnt, (void) i;
- target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (
- bpt->type, i + mem_cnt, other_type_used);
- /* we can consider of type is bp_hardware_watchpoint, convert to
- bp_watchpoint in the following condition */
- if (target_resources_ok < 0)
- {
- printf_filtered (_("\
-Cannot enable watchpoint %d because target watch resources\n\
-have been allocated for other watchpoints.\n"), bpt->number);
- value_free_to_mark (mark);
- return;
- }
+ exception_fprintf (gdb_stderr, e, _("Cannot enable watchpoint %d: "),
+ bpt->number);
+ return;
}
-
- select_frame (frame_find_by_id (saved_frame_id));
- value_free_to_mark (mark);
}
if (bpt->enable_state != bp_permanent)
bpt->number);
continue;
case bp_breakpoint:
- case bp_catch_load:
- case bp_catch_unload:
- case bp_catch_fork:
- case bp_catch_vfork:
- case bp_catch_exec:
+ case bp_catchpoint:
case bp_hardware_breakpoint:
case bp_watchpoint:
case bp_hardware_watchpoint:
catch_exec_command_1,
CATCH_PERMANENT,
CATCH_TEMPORARY);
- add_catch_command ("load", _("\
-Catch library loads.\n\
-With an argument, catch only loads of that library."),
- catch_load_command_1,
- CATCH_PERMANENT,
- CATCH_TEMPORARY);
- add_catch_command ("unload", _("\
-Catch library unloads.\n\
-With an argument, catch only unloads of that library."),
- catch_unload_command_1,
- CATCH_PERMANENT,
- CATCH_TEMPORARY);
add_catch_command ("exception", _("\
Catch Ada exceptions, when raised.\n\
With an argument, catch only exceptions with the given name."),