/* Everything about breakpoints, for GDB.
- Copyright (C) 1986-2015 Free Software Foundation, Inc.
+ Copyright (C) 1986-2016 Free Software Foundation, Inc.
This file is part of GDB.
#include "top.h"
#include "valprint.h"
#include "jit.h"
-#include "xml-syscall.h"
#include "parser-defs.h"
#include "gdb_regex.h"
#include "probe.h"
#include "dummy-frame.h"
#include "interps.h"
#include "format.h"
+#include "location.h"
+#include "thread-fsm.h"
+#include "tid-parse.h"
/* readline include files */
#include "readline/readline.h"
#include "mi/mi-common.h"
#include "extension.h"
+#include <algorithm>
/* Enums for exception-handling support. */
enum exception_event_kind
static void breakpoint_re_set_default (struct breakpoint *);
-static void create_sals_from_address_default (char **,
- struct linespec_result *,
- enum bptype, char *,
- char **);
+static void
+ create_sals_from_location_default (const struct event_location *location,
+ struct linespec_result *canonical,
+ enum bptype type_wanted);
static void create_breakpoints_sal_default (struct gdbarch *,
struct linespec_result *,
const struct breakpoint_ops *,
int, int, int, unsigned);
-static void decode_linespec_default (struct breakpoint *, char **,
- struct symtabs_and_lines *);
+static void decode_location_default (struct breakpoint *b,
+ const struct event_location *location,
+ struct program_space *search_pspace,
+ struct symtabs_and_lines *sals);
static void clear_command (char *, int);
struct address_space *aspace,
CORE_ADDR addr);
+static int breakpoint_location_address_range_overlap (struct bp_location *,
+ struct address_space *,
+ CORE_ADDR, int);
+
static void breakpoints_info (char *, int);
static void watchpoints_info (char *, int);
static void condition_command (char *, int);
-typedef enum
- {
- mark_inserted,
- mark_uninserted
- }
-insertion_state_t;
-
-static int remove_breakpoint (struct bp_location *, insertion_state_t);
-static int remove_breakpoint_1 (struct bp_location *, insertion_state_t);
+static int remove_breakpoint (struct bp_location *);
+static int remove_breakpoint_1 (struct bp_location *, enum remove_bp_reason);
static enum print_stop_action print_bp_stop_message (bpstat bs);
static void insert_breakpoint_locations (void);
-static int syscall_catchpoint_p (struct breakpoint *b);
-
static void tracepoints_info (char *, int);
static void delete_trace_command (char *, int);
}
else if (target_has_execution)
{
+ struct thread_info *tp;
+
if (always_inserted_mode)
{
/* The user wants breakpoints inserted even if all threads
if (threads_are_executing ())
return 1;
+
+ /* Don't remove breakpoints yet if, even though all threads are
+ stopped, we still have events to process. */
+ ALL_NON_EXITED_THREADS (tp)
+ if (tp->resumed
+ && tp->suspend.waitstatus_pending_p)
+ return 1;
}
return 0;
}
static struct counted_command_line *
alloc_counted_command_line (struct command_line *commands)
{
- struct counted_command_line *result
- = xmalloc (sizeof (struct counted_command_line));
+ struct counted_command_line *result = XNEW (struct counted_command_line);
result->refc = 1;
result->commands = commands;
+
return result;
}
static void
do_cleanup_counted_command_line (void *arg)
{
- decref_counted_command_line (arg);
+ decref_counted_command_line ((struct counted_command_line **) arg);
}
/* Create a cleanup that calls decref_counted_command_line on the
static int
bp_location_compare_addrs (const void *ap, const void *bp)
{
- struct bp_location *a = *(void **) ap;
- struct bp_location *b = *(void **) bp;
+ const struct bp_location *a = *(const struct bp_location **) ap;
+ const struct bp_location *b = *(const struct bp_location **) bp;
if (a->address == b->address)
return 0;
dummy_loc.address = address;
/* Find a close match to the first location at ADDRESS. */
- locp_found = bsearch (&dummy_locp, bp_location, bp_location_count,
- sizeof (struct bp_location **),
- bp_location_compare_addrs);
+ locp_found = ((struct bp_location **)
+ bsearch (&dummy_locp, bp_location, bp_location_count,
+ sizeof (struct bp_location **),
+ bp_location_compare_addrs));
/* Nothing was found, nothing left to do. */
if (locp_found == NULL)
}
void
-set_breakpoint_condition (struct breakpoint *b, char *exp,
+set_breakpoint_condition (struct breakpoint *b, const char *exp,
int from_tty)
{
xfree (b->cond_string);
void
check_tracepoint_command (char *line, void *closure)
{
- struct breakpoint *b = closure;
+ struct breakpoint *b = (struct breakpoint *) closure;
validate_actionline (line, b);
}
static void
do_map_commands_command (struct breakpoint *b, void *data)
{
- struct commands_info *info = data;
+ struct commands_info *info = (struct commands_info *) data;
if (info->cmd == NULL)
{
/* Left boundary, right boundary and median element of our binary
search. */
unsigned bc_l, bc_r, bc;
- size_t i;
/* Find BC_L which is a leftmost element which may affect BUF
content. It is safe to report lower value but a failure to
for (bc = bc_l; bc < bp_location_count; bc++)
{
struct bp_location *bl = bp_location[bc];
- CORE_ADDR bp_addr = 0;
- int bp_size = 0;
- int bptoffset = 0;
/* bp_location array has BL->OWNER always non-NULL. */
if (bl->owner->type == bp_none)
return bit_val;
}
+/* Allocate a dummy location and add it to B, which must be a software
+ watchpoint. This is required because even if a software watchpoint
+ is not watching any memory, bpstat_stop_status requires a location
+ to be able to report stops. */
+
+static void
+software_watchpoint_add_no_memory_location (struct breakpoint *b,
+ struct program_space *pspace)
+{
+ gdb_assert (b->type == bp_watchpoint && b->loc == NULL);
+
+ b->loc = allocate_bp_location (b);
+ b->loc->pspace = pspace;
+ b->loc->address = -1;
+ b->loc->length = -1;
+}
+
+/* Returns true if B is a software watchpoint that is not watching any
+ memory (e.g., "watch $pc"). */
+
+static int
+is_no_memory_software_watchpoint (struct breakpoint *b)
+{
+ return (b->type == bp_watchpoint
+ && b->loc != NULL
+ && b->loc->next == NULL
+ && b->loc->address == -1
+ && b->loc->length == -1);
+}
+
/* Assuming that B is a watchpoint:
- Reparse watchpoint expression, if REPARSE is non-zero
- Evaluate expression and store the result in B->val
struct gdbarch *frame_arch = get_frame_arch (fi);
CORE_ADDR frame_pc = get_frame_pc (fi);
- /* If we're in a function epilogue, unwinding may not work
- properly, so do not attempt to recreate locations at this
+ /* If we're at a point where the stack has been destroyed
+ (e.g. in a function epilogue), unwinding may not work
+ properly. Do not attempt to recreate locations at this
point. See similar comments in watchpoint_check. */
- if (gdbarch_in_function_epilogue_p (frame_arch, frame_pc))
+ if (gdbarch_stack_frame_destroyed_p (frame_arch, frame_pc))
return;
/* Save the current frame's ID so we can restore it after
&& TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
{
CORE_ADDR addr;
- int type;
+ enum target_hw_bp_type type;
struct bp_location *loc, **tmp;
int bitpos = 0, bitsize = 0;
bpstat_stop_status requires a location to be able to report
stops, so make sure there's at least a dummy one. */
if (b->base.type == bp_watchpoint && b->base.loc == NULL)
- {
- struct breakpoint *base = &b->base;
- base->loc = allocate_bp_location (base);
- base->loc->pspace = frame_pspace;
- base->loc->address = -1;
- base->loc->length = -1;
- base->loc->watchpoint_type = -1;
- }
+ software_watchpoint_add_no_memory_location (&b->base, frame_pspace);
}
else if (!within_current_scope)
{
return 0;
/* Don't insert a breakpoint if we're trying to step past its
- location. */
+ location, except if the breakpoint is a single-step breakpoint,
+ and the breakpoint's thread is the thread which is stepping past
+ a breakpoint. */
if ((bl->loc_type == bp_loc_software_breakpoint
|| bl->loc_type == bp_loc_hardware_breakpoint)
&& stepping_past_instruction_at (bl->pspace->aspace,
- bl->address))
+ bl->address)
+ /* The single-step breakpoint may be inserted at the location
+ we're trying to step if the instruction branches to itself.
+ However, the instruction won't be executed at all and it may
+ break the semantics of the instruction, for example, the
+ instruction is a conditional branch or updates some flags.
+ We can't fix it unless GDB is able to emulate the instruction
+ or switch to displaced stepping. */
+ && !(bl->owner->type == bp_single_step
+ && thread_is_stepping_over_breakpoint (bl->owner->thread)))
{
if (debug_infrun)
{
need to parse the condition to bytecodes again. */
aexpr = parse_cond_to_aexpr (bl->address, loc->cond);
loc->cond_bytecode = aexpr;
-
- /* Check if we managed to parse the conditional expression
- correctly. If not, we will not send this condition
- to the target. */
- if (aexpr)
- continue;
}
/* If we have a NULL bytecode expression, it means something
aexpr = parse_cmd_to_aexpr (bl->address,
loc->owner->extra_string);
loc->cmd_bytecode = aexpr;
-
- if (!aexpr)
- continue;
}
/* If we have a NULL bytecode expression, it means something
bl->target_info.persist = 1;
}
+/* Return the kind of breakpoint on address *ADDR. Get the kind
+ of breakpoint according to ADDR except single-step breakpoint.
+ Get the kind of single-step breakpoint according to the current
+ registers state. */
+
+static int
+breakpoint_kind (struct bp_location *bl, CORE_ADDR *addr)
+{
+ if (bl->owner->type == bp_single_step)
+ {
+ struct thread_info *thr = find_thread_global_id (bl->owner->thread);
+ struct regcache *regcache;
+
+ regcache = get_thread_regcache (thr->ptid);
+
+ return gdbarch_breakpoint_kind_from_current_state (bl->gdbarch,
+ regcache, addr);
+ }
+ else
+ return gdbarch_breakpoint_kind_from_pc (bl->gdbarch, addr);
+}
+
/* Insert a low-level "breakpoint" of some type. BL is the breakpoint
location. Any error messages are printed to TMP_ERROR_STREAM; and
DISABLED_BREAKS, and HW_BREAKPOINT_ERROR are used to report problems.
{
int val;
+ bl->overlay_target_info.kind
+ = breakpoint_kind (bl, &addr);
+ bl->overlay_target_info.placed_address = addr;
val = target_insert_breakpoint (bl->gdbarch,
&bl->overlay_target_info);
if (val)
the thread no longer exists. ALL_BP_LOCATIONS bp_location
has BL->OWNER always non-NULL. */
if (bl->owner->thread != -1
- && !valid_thread_id (bl->owner->thread))
+ && !valid_global_thread_id (bl->owner->thread))
continue;
switch_to_program_space_and_thread (bl->pspace);
{
for (loc = bpt->loc; loc; loc = loc->next)
if (loc->inserted)
- remove_breakpoint (loc, mark_uninserted);
+ remove_breakpoint (loc);
hw_breakpoint_error = 1;
fprintf_unfiltered (tmp_error_stream,
ALL_BP_LOCATIONS (bl, blp_tmp)
{
if (bl->inserted && !is_tracepoint (bl->owner))
- val |= remove_breakpoint (bl, mark_uninserted);
+ val |= remove_breakpoint (bl);
}
return val;
}
ALL_BREAKPOINTS_SAFE (b, b_tmp)
{
- if (b->thread == tp->num && user_breakpoint_p (b))
+ if (b->thread == tp->global_num && user_breakpoint_p (b))
{
b->disposition = disp_del_at_next_stop;
printf_filtered (_("\
-Thread-specific breakpoint %d deleted - thread %d no longer in the thread list.\n"),
- b->number, tp->num);
+Thread-specific breakpoint %d deleted - thread %s no longer in the thread list.\n"),
+ b->number, print_thread_id (tp));
/* Hide it from the user. */
b->number = 0;
if (bl->inserted && !bl->target_info.persist)
{
- val = remove_breakpoint (bl, mark_uninserted);
+ val = remove_breakpoint (bl);
if (val != 0)
return val;
}
{
struct breakpoint_objfile_data *bp_objfile_data;
- bp_objfile_data = objfile_data (objfile, breakpoint_objfile_key);
+ bp_objfile_data = ((struct breakpoint_objfile_data *)
+ objfile_data (objfile, breakpoint_objfile_key));
if (bp_objfile_data == NULL)
{
- bp_objfile_data = obstack_alloc (&objfile->objfile_obstack,
- sizeof (*bp_objfile_data));
+ bp_objfile_data =
+ XOBNEW (&objfile->objfile_obstack, struct breakpoint_objfile_data);
memset (bp_objfile_data, 0, sizeof (*bp_objfile_data));
set_objfile_data (objfile, breakpoint_objfile_key, bp_objfile_data);
static void
free_breakpoint_probes (struct objfile *obj, void *data)
{
- struct breakpoint_objfile_data *bp_objfile_data = data;
+ struct breakpoint_objfile_data *bp_objfile_data
+ = (struct breakpoint_objfile_data *) data;
VEC_free (probe_p, bp_objfile_data->longjmp_probes);
VEC_free (probe_p, bp_objfile_data->exception_probes);
struct breakpoint *b;
struct breakpoint_objfile_data *bp_objfile_data;
CORE_ADDR addr;
+ struct explicit_location explicit_loc;
bp_objfile_data = get_breakpoint_objfile_data (objfile);
b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
bp_overlay_event,
&internal_breakpoint_ops);
- b->addr_string = xstrdup (func_name);
+ initialize_explicit_location (&explicit_loc);
+ explicit_loc.function_name = ASTRDUP (func_name);
+ b->location = new_explicit_location (&explicit_loc);
if (overlay_debugging == ovly_auto)
{
overlay_events_enabled = 0;
}
}
- update_global_location_list (UGLL_MAY_INSERT);
}
static void
objfile),
bp_longjmp_master,
&internal_breakpoint_ops);
- b->addr_string = xstrdup ("-probe-stap libc:longjmp");
+ b->location
+ = new_probe_location ("-probe-stap libc:longjmp");
b->enable_state = bp_disabled;
}
struct breakpoint *b;
const char *func_name;
CORE_ADDR addr;
+ struct explicit_location explicit_loc;
if (msym_not_found_p (bp_objfile_data->longjmp_msym[i].minsym))
continue;
addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master,
&internal_breakpoint_ops);
- b->addr_string = xstrdup (func_name);
+ initialize_explicit_location (&explicit_loc);
+ explicit_loc.function_name = ASTRDUP (func_name);
+ b->location = new_explicit_location (&explicit_loc);
b->enable_state = bp_disabled;
}
}
}
- update_global_location_list (UGLL_MAY_INSERT);
do_cleanups (old_chain);
}
{
struct breakpoint *b;
struct breakpoint_objfile_data *bp_objfile_data;
+ struct explicit_location explicit_loc;
bp_objfile_data = get_breakpoint_objfile_data (objfile);
b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
bp_std_terminate_master,
&internal_breakpoint_ops);
- b->addr_string = xstrdup (func_name);
+ initialize_explicit_location (&explicit_loc);
+ explicit_loc.function_name = ASTRDUP (func_name);
+ b->location = new_explicit_location (&explicit_loc);
b->enable_state = bp_disabled;
}
}
- update_global_location_list (UGLL_MAY_INSERT);
-
do_cleanups (old_chain);
}
struct gdbarch *gdbarch;
struct breakpoint_objfile_data *bp_objfile_data;
CORE_ADDR addr;
+ struct explicit_location explicit_loc;
bp_objfile_data = get_breakpoint_objfile_data (objfile);
objfile),
bp_exception_master,
&internal_breakpoint_ops);
- b->addr_string = xstrdup ("-probe-stap libgcc:unwind");
+ b->location
+ = new_probe_location ("-probe-stap libgcc:unwind");
b->enable_state = bp_disabled;
}
¤t_target);
b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
&internal_breakpoint_ops);
- b->addr_string = xstrdup (func_name);
+ initialize_explicit_location (&explicit_loc);
+ explicit_loc.function_name = ASTRDUP (func_name);
+ b->location = new_explicit_location (&explicit_loc);
b->enable_state = bp_disabled;
}
+}
- update_global_location_list (UGLL_MAY_INSERT);
+/* Does B have a location spec? */
+
+static int
+breakpoint_event_location_empty_p (const struct breakpoint *b)
+{
+ return b->location != NULL && event_location_empty_p (b->location);
}
void
/* Without a symbolic address, we have little hope of the
pre-exec() address meaning the same thing in the post-exec()
a.out. */
- if (b->addr_string == NULL)
+ if (breakpoint_event_location_empty_p (b))
{
delete_breakpoint (b);
continue;
continue;
if (bl->inserted)
- val |= remove_breakpoint_1 (bl, mark_inserted);
+ val |= remove_breakpoint_1 (bl, DETACH_BREAKPOINT);
}
do_cleanups (old_chain);
*not* look at bl->pspace->aspace here. */
static int
-remove_breakpoint_1 (struct bp_location *bl, insertion_state_t is)
+remove_breakpoint_1 (struct bp_location *bl, enum remove_bp_reason reason)
{
int val;
/* BL is never in moribund_locations by our callers. */
gdb_assert (bl->owner != NULL);
- if (bl->permanent)
- /* Permanent breakpoints cannot be inserted or removed. */
- return 0;
-
/* The type of none suggests that owner is actually deleted.
This should not ever happen. */
gdb_assert (bl->owner->type != bp_none);
&& !memory_validate_breakpoint (bl->gdbarch, &bl->target_info))
val = 0;
else
- val = bl->owner->ops->remove_location (bl);
+ val = bl->owner->ops->remove_location (bl, reason);
}
else
{
&bl->overlay_target_info);
else
target_remove_breakpoint (bl->gdbarch,
- &bl->overlay_target_info);
+ &bl->overlay_target_info,
+ reason);
}
/* Did we set a breakpoint at the VMA?
If so, we will have marked the breakpoint 'inserted'. */
wrong code with the saved shadow contents. */
if (bl->loc_type == bp_loc_hardware_breakpoint
|| section_is_mapped (bl->section))
- val = bl->owner->ops->remove_location (bl);
+ val = bl->owner->ops->remove_location (bl, reason);
else
val = 0;
}
if (val)
return val;
- bl->inserted = (is == mark_inserted);
+ bl->inserted = (reason == DETACH_BREAKPOINT);
}
else if (bl->loc_type == bp_loc_hardware_watchpoint)
{
gdb_assert (bl->owner->ops != NULL
&& bl->owner->ops->remove_location != NULL);
- bl->inserted = (is == mark_inserted);
- bl->owner->ops->remove_location (bl);
+ bl->inserted = (reason == DETACH_BREAKPOINT);
+ bl->owner->ops->remove_location (bl, reason);
/* Failure to remove any of the hardware watchpoints comes here. */
- if ((is == mark_uninserted) && (bl->inserted))
+ if (reason == REMOVE_BREAKPOINT && bl->inserted)
warning (_("Could not remove hardware watchpoint %d."),
bl->owner->number);
}
gdb_assert (bl->owner->ops != NULL
&& bl->owner->ops->remove_location != NULL);
- val = bl->owner->ops->remove_location (bl);
+ val = bl->owner->ops->remove_location (bl, reason);
if (val)
return val;
- bl->inserted = (is == mark_inserted);
+ bl->inserted = (reason == DETACH_BREAKPOINT);
}
return 0;
}
static int
-remove_breakpoint (struct bp_location *bl, insertion_state_t is)
+remove_breakpoint (struct bp_location *bl)
{
int ret;
struct cleanup *old_chain;
/* BL is never in moribund_locations by our callers. */
gdb_assert (bl->owner != NULL);
- if (bl->permanent)
- /* Permanent breakpoints cannot be inserted or removed. */
- return 0;
-
/* The type of none suggests that owner is actually deleted.
This should not ever happen. */
gdb_assert (bl->owner->type != bp_none);
switch_to_program_space_and_thread (bl->pspace);
- ret = remove_breakpoint_1 (bl, is);
+ ret = remove_breakpoint_1 (bl, REMOVE_BREAKPOINT);
do_cleanups (old_chain);
return ret;
struct bp_location *bl, **blp_tmp;
ALL_BP_LOCATIONS (bl, blp_tmp)
- if (bl->pspace == current_program_space
- && !bl->permanent)
+ if (bl->pspace == current_program_space)
bl->inserted = 0;
}
breakpoint_init_inferior (enum inf_context context)
{
struct breakpoint *b, *b_tmp;
- struct bp_location *bl, **blp_tmp;
+ struct bp_location *bl;
int ix;
struct program_space *pspace = current_program_space;
/* Likewise for watchpoints on local expressions. */
if (w->exp_valid_block != NULL)
delete_breakpoint (b);
- else if (context == inf_starting)
+ else
{
- /* Reset val field to force reread of starting value in
- insert_breakpoints. */
- if (w->val)
- value_free (w->val);
- w->val = NULL;
- w->val_valid = 0;
- }
+ /* Get rid of existing locations, which are no longer
+ valid. New ones will be created in
+ update_watchpoint, when the inferior is restarted.
+ The next update_global_location_list call will
+ garbage collect them. */
+ b->loc = NULL;
+
+ if (context == inf_starting)
+ {
+ /* Reset val field to force reread of starting value in
+ insert_breakpoints. */
+ if (w->val)
+ value_free (w->val);
+ w->val = NULL;
+ w->val_valid = 0;
+ }
+ }
}
break;
default:
}
}
- return any_breakpoint_here ? ordinary_breakpoint_here : 0;
+ return any_breakpoint_here ? ordinary_breakpoint_here : no_breakpoint_here;
+}
+
+/* See breakpoint.h. */
+
+int
+breakpoint_in_range_p (struct address_space *aspace,
+ CORE_ADDR addr, ULONGEST len)
+{
+ struct bp_location *bl, **blp_tmp;
+
+ ALL_BP_LOCATIONS (bl, blp_tmp)
+ {
+ if (bl->loc_type != bp_loc_software_breakpoint
+ && bl->loc_type != bp_loc_hardware_breakpoint)
+ continue;
+
+ if ((breakpoint_enabled (bl->owner)
+ || bl->permanent)
+ && breakpoint_location_address_range_overlap (bl, aspace,
+ addr, len))
+ {
+ if (overlay_debugging
+ && section_is_overlay (bl->section)
+ && !section_is_mapped (bl->section))
+ {
+ /* Unmapped overlay -- can't be a match. */
+ continue;
+ }
+
+ return 1;
+ }
+ }
+
+ return 0;
}
/* Return true if there's a moribund breakpoint at PC. */
breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc)
{
struct bp_location **blp, **blp_tmp = NULL;
- struct bp_location *bl;
ALL_BP_LOCATIONS_AT_ADDR (blp, blp_tmp, pc)
{
CORE_ADDR pc)
{
struct bp_location **blp, **blp_tmp = NULL;
- struct bp_location *bl;
ALL_BP_LOCATIONS_AT_ADDR (blp, blp_tmp, pc)
{
CORE_ADDR pc)
{
struct bp_location **blp, **blp_tmp = NULL;
- struct bp_location *bl;
ALL_BP_LOCATIONS_AT_ADDR (blp, blp_tmp, pc)
{
CORE_ADDR l, h;
/* Check for intersection. */
- l = max (loc->address, addr);
- h = min (loc->address + loc->length, addr + len);
+ l = std::max<CORE_ADDR> (loc->address, addr);
+ h = std::min<CORE_ADDR> (loc->address + loc->length, addr + len);
if (l < h)
return 1;
}
static int
command_line_is_silent (struct command_line *cmd)
{
- return cmd && (strcmp ("silent", cmd->line) == 0
- || (xdb_commands && strcmp ("Q", cmd->line) == 0));
+ return cmd && (strcmp ("silent", cmd->line) == 0);
}
/* Execute all the commands associated with all the breakpoints at
if (breakpoint_proceeded)
{
- if (interpreter_async && target_can_async_p ())
+ if (current_ui->async)
/* If we are in async mode, then the target might be still
running, not stopped at any breakpoint, so nothing for
us to do here -- just return to the event loop. */
}
}
+/* Print the "Thread ID hit" part of "Thread ID hit Breakpoint N" if
+ debugging multiple threads. */
+
+void
+maybe_print_thread_hit_breakpoint (struct ui_out *uiout)
+{
+ if (ui_out_is_mi_like_p (uiout))
+ return;
+
+ ui_out_text (uiout, "\n");
+
+ if (show_thread_that_caused_stop ())
+ {
+ const char *name;
+ struct thread_info *thr = inferior_thread ();
+
+ ui_out_text (uiout, "Thread ");
+ ui_out_field_fmt (uiout, "thread-id", "%s", print_thread_id (thr));
+
+ name = thr->name != NULL ? thr->name : target_thread_name (thr);
+ if (name != NULL)
+ {
+ ui_out_text (uiout, " \"");
+ ui_out_field_fmt (uiout, "name", "%s", name);
+ ui_out_text (uiout, "\"");
+ }
+
+ ui_out_text (uiout, " hit ");
+ }
+}
+
/* Generic routine for printing messages indicating why we
stopped. The behavior of this function depends on the value
'print_it' in the bpstat structure. Under some circumstances we
enum print_stop_action
bpstat_print (bpstat bs, int kind)
{
- int val;
+ enum print_stop_action val;
/* Maybe another breakpoint in the chain caused us to stop.
(Currently all watchpoints go on the bpstat whether hit or not.
struct gdbarch *frame_arch = get_frame_arch (frame);
CORE_ADDR frame_pc = get_frame_pc (frame);
- /* in_function_epilogue_p() returns a non-zero value if we're
+ /* stack_frame_destroyed_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 stack has been destroyed, we are treating
frame is in an epilogue - even if they are in some other
frame, our view of the stack is likely to be wrong and
frame_find_by_id could error out. */
- if (gdbarch_in_function_epilogue_p (frame_arch, frame_pc))
+ if (gdbarch_stack_frame_destroyed_p (frame_arch, frame_pc))
return WP_IGNORE;
fr = frame_find_by_id (b->watchpoint_frame);
}
else
{
- struct ui_out *uiout = current_uiout;
-
/* This seems like the only logical thing to do because
if we temporarily ignored the watchpoint, then when
we reenter the block in which it is valid it contains
call breakpoint_ops->print_it this bp 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", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE));
- ui_out_text (uiout, "\nWatchpoint ");
- ui_out_field_int (uiout, "wpnum", b->base.number);
- ui_out_text (uiout,
- " deleted because the program has left the block in\n\
-which its expression is valid.\n");
+
+ SWITCH_THRU_ALL_UIS ()
+ {
+ struct ui_out *uiout = current_uiout;
+
+ if (ui_out_is_mi_like_p (uiout))
+ ui_out_field_string
+ (uiout, "reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE));
+ ui_out_text (uiout, "\nWatchpoint ");
+ ui_out_field_int (uiout, "wpnum", b->base.number);
+ ui_out_text (uiout,
+ " deleted because the program has left the block in\n"
+ "which its expression is valid.\n");
+ }
/* Make sure the watchpoint's commands aren't executed. */
decref_counted_command_line (&b->base.commands);
/* Can't happen. */
case 0:
/* Error from catch_errors. */
- printf_filtered (_("Watchpoint %d deleted.\n"), b->base.number);
- watchpoint_del_at_next_stop (b);
- /* We've already printed what needs to be printed. */
- bs->print_it = print_it_done;
+ {
+ SWITCH_THRU_ALL_UIS ()
+ {
+ printf_filtered (_("Watchpoint %d deleted.\n"),
+ b->base.number);
+ }
+ watchpoint_del_at_next_stop (b);
+ /* We've already printed what needs to be printed. */
+ bs->print_it = print_it_done;
+ }
break;
}
}
/* If this is a thread/task-specific breakpoint, don't waste cpu
evaluating the condition if this isn't the specified
thread/task. */
- if ((b->thread != -1 && b->thread != pid_to_thread_id (ptid))
+ if ((b->thread != -1 && b->thread != ptid_to_global_thread_id (ptid))
|| (b->task != 0 && b->task != ada_get_task_number (ptid)))
{
struct frame_info *frame;
struct gdbarch *gdbarch;
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "handling bp_jit_event\n");
+
/* Switch terminal for any messages produced by
breakpoint_re_set. */
target_terminal_ours_for_output ();
bpstat_what (bpstat bs_head)
{
struct bpstat_what retval;
- int jit_event = 0;
bpstat bs;
retval.main_action = BPSTAT_WHAT_KEEP_CHECKING;
case bp_longjmp:
case bp_longjmp_call_dummy:
case bp_exception:
- this_action = BPSTAT_WHAT_SET_LONGJMP_RESUME;
- retval.is_longjmp = bptype != bp_exception;
+ if (bs->stop)
+ {
+ this_action = BPSTAT_WHAT_SET_LONGJMP_RESUME;
+ retval.is_longjmp = bptype != bp_exception;
+ }
+ else
+ this_action = BPSTAT_WHAT_SINGLE;
break;
case bp_longjmp_resume:
case bp_exception_resume:
- this_action = BPSTAT_WHAT_CLEAR_LONGJMP_RESUME;
- retval.is_longjmp = bptype == bp_longjmp_resume;
+ if (bs->stop)
+ {
+ this_action = BPSTAT_WHAT_CLEAR_LONGJMP_RESUME;
+ retval.is_longjmp = bptype == bp_longjmp_resume;
+ }
+ else
+ this_action = BPSTAT_WHAT_SINGLE;
break;
case bp_step_resume:
if (bs->stop)
}
break;
case bp_jit_event:
- jit_event = 1;
this_action = BPSTAT_WHAT_SINGLE;
break;
case bp_call_dummy:
_("bpstat_what: unhandled bptype %d"), (int) bptype);
}
- retval.main_action = max (retval.main_action, this_action);
+ retval.main_action = std::max (retval.main_action, this_action);
}
- /* These operations may affect the bs->breakpoint_at state so they are
- delayed after MAIN_ACTION is decided above. */
-
- if (jit_event)
- {
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "bpstat_what: bp_jit_event\n");
+ return retval;
+}
- handle_jit_event ();
- }
+void
+bpstat_run_callbacks (bpstat bs_head)
+{
+ bpstat bs;
for (bs = bs_head; bs != NULL; bs = bs->next)
{
continue;
switch (b->type)
{
+ case bp_jit_event:
+ handle_jit_event ();
+ break;
case bp_gnu_ifunc_resolver:
gnu_ifunc_resolver_stop (b);
break;
break;
}
}
-
- return retval;
}
/* Nonzero if we should step constantly (e.g. watchpoints on machines
set_current_program_space (loc->pspace);
if (b->display_canonical)
- ui_out_field_string (uiout, "what", b->addr_string);
+ ui_out_field_string (uiout, "what",
+ event_location_to_string (b->location));
else if (loc && loc->symtab)
{
struct symbol *sym
do_cleanups (stb_chain);
}
else
- ui_out_field_string (uiout, "pending", b->addr_string);
+ {
+ ui_out_field_string (uiout, "pending",
+ event_location_to_string (b->location));
+ /* If extra_string is available, it could be holding a condition
+ or dprintf arguments. In either case, make sure it is printed,
+ too, but only for non-MI streams. */
+ if (!ui_out_is_mi_like_p (uiout) && b->extra_string != NULL)
+ {
+ if (b->type == bp_dprintf)
+ ui_out_text (uiout, ",");
+ else
+ ui_out_text (uiout, " ");
+ ui_out_text (uiout, b->extra_string);
+ }
+ }
if (loc && is_breakpoint (b)
&& breakpoint_condition_evaluation_mode () == condition_evaluation_target
{
/* FIXME should make an annotation for this. */
ui_out_text (uiout, "\tstop only in thread ");
- ui_out_field_int (uiout, "thread", b->thread);
+ if (ui_out_is_mi_like_p (uiout))
+ ui_out_field_int (uiout, "thread", b->thread);
+ else
+ {
+ struct thread_info *thr = find_thread_global_id (b->thread);
+
+ ui_out_field_string (uiout, "thread", print_thread_id (thr));
+ }
ui_out_text (uiout, "\n");
}
ui_out_field_string (uiout, "original-location", w->exp_string);
}
- else if (b->addr_string)
- ui_out_field_string (uiout, "original-location", b->addr_string);
+ else if (b->location != NULL
+ && event_location_to_string (b->location) != NULL)
+ ui_out_field_string (uiout, "original-location",
+ event_location_to_string (b->location));
}
}
int print_address_bits = 0;
struct bp_location *loc;
+ /* Software watchpoints that aren't watching memory don't have an
+ address to print. */
+ if (is_no_memory_software_watchpoint (b))
+ return 0;
+
for (loc = b->loc; loc; loc = loc->next)
{
int addr_bit;
- /* Software watchpoints that aren't watching memory don't have
- an address to print. */
- if (b->type == bp_watchpoint && loc->watchpoint_type == -1)
- continue;
-
addr_bit = gdbarch_addr_bit (loc->gdbarch);
if (addr_bit > print_address_bits)
print_address_bits = addr_bit;
static int
do_captured_breakpoint_query (struct ui_out *uiout, void *data)
{
- struct captured_breakpoint_query_args *args = data;
+ struct captured_breakpoint_query_args *args
+ = (struct captured_breakpoint_query_args *) data;
struct breakpoint *b;
struct bp_location *dummy_loc = NULL;
return b->number > 0;
}
+/* See breakpoint.h. */
+
+int
+pending_breakpoint_p (struct breakpoint *b)
+{
+ return b->loc == NULL;
+}
+
/* Print information on user settable breakpoint (watchpoint, etc)
number BNUM. If BNUM is -1 print all user-settable breakpoints.
If ALLFLAG is non-zero, include non-user-settable breakpoints. If
\f
/* Return true iff it is meaningful to use the address member of
- BPT. For some breakpoint types, the address member is irrelevant
- and it makes no sense to attempt to compare it to other addresses
- (or use it for any other purpose either).
+ BPT locations. For some breakpoint types, the locations' address members
+ are irrelevant and it makes no sense to attempt to compare them to other
+ addresses (or use them for any other purpose either).
More specifically, each of the following breakpoint types will
- always have a zero valued address and we don't want to mark
+ always have a zero valued location address and we don't want to mark
breakpoints of any of these types to be a duplicate of an actual
- breakpoint at address zero:
+ breakpoint location at address zero:
bp_watchpoint
bp_catchpoint
aspace, addr)));
}
+/* Returns true if the [ADDR,ADDR+LEN) range in ASPACE overlaps
+ breakpoint BL. BL may be a ranged breakpoint. In most targets, a
+ match happens only if ASPACE matches the breakpoint's address
+ space. On targets that have global breakpoints, the address space
+ doesn't really matter. */
+
+static int
+breakpoint_location_address_range_overlap (struct bp_location *bl,
+ struct address_space *aspace,
+ CORE_ADDR addr, int len)
+{
+ if (gdbarch_has_global_breakpoints (target_gdbarch ())
+ || bl->pspace->aspace == aspace)
+ {
+ int bl_len = bl->length != 0 ? bl->length : 1;
+
+ if (mem_ranges_overlap (addr, len, bl->address, bl_len))
+ return 1;
+ }
+ return 0;
+}
+
/* If LOC1 and LOC2's owners are not tracepoints, returns false directly.
Then, if LOC1 and LOC2 represent the same tracepoint location, returns
true, otherwise returns false. */
b->condition_not_parsed = 0;
b->py_bp_object = NULL;
b->related_breakpoint = b;
+ b->location = NULL;
}
/* Helper to set_raw_breakpoint below. Creates a breakpoint
return b;
}
-
-/* Note that the breakpoint object B describes a permanent breakpoint
- instruction, hard-wired into the inferior's code. */
-void
-make_breakpoint_permanent (struct breakpoint *b)
-{
- struct bp_location *bl;
-
- /* By definition, permanent breakpoints are already present in the
- code. Mark all locations as inserted. For now,
- make_breakpoint_permanent is called in just one place, so it's
- hard to say if it's reasonable to have permanent breakpoint with
- multiple locations or not, but it's easy to implement. */
- for (bl = b->loc; bl; bl = bl->next)
- {
- bl->permanent = 1;
- bl->inserted = 1;
- }
-}
-
/* Call this routine when stepping and nexting to enable a breakpoint
if we do a longjmp() or 'throw' in TP. FRAME is the frame which
initiated the operation. */
set_longjmp_breakpoint (struct thread_info *tp, struct frame_id frame)
{
struct breakpoint *b, *b_tmp;
- int thread = tp->num;
+ int thread = tp->global_num;
/* To avoid having to rescan all objfile symbols at every step,
we maintain a list of continually-inserted but always disabled
new_b = momentary_breakpoint_from_master (b, bp_longjmp_call_dummy,
&momentary_breakpoint_ops,
1);
- new_b->thread = pid_to_thread_id (inferior_ptid);
+ new_b->thread = ptid_to_global_thread_id (inferior_ptid);
/* Link NEW_B into the chain of RETVAL breakpoints. */
struct breakpoint *b, *b_tmp;
ALL_BREAKPOINTS_SAFE (b, b_tmp)
- if (b->type == bp_longjmp_call_dummy && b->thread == tp->num)
+ if (b->type == bp_longjmp_call_dummy && b->thread == tp->global_num)
{
struct breakpoint *dummy_b = b->related_breakpoint;
&internal_breakpoint_ops);
b->enable_state = bp_enabled;
- /* addr_string has to be used or breakpoint_re_set will delete me. */
- b->addr_string
- = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
+ /* location has to be used or breakpoint_re_set will delete me. */
+ b->location = new_address_location (b->loc->address, NULL, 0);
update_global_location_list_nothrow (UGLL_MAY_INSERT);
return b;
}
-void
-remove_thread_event_breakpoints (void)
-{
- struct breakpoint *b, *b_tmp;
-
- ALL_BREAKPOINTS_SAFE (b, b_tmp)
- if (b->type == bp_thread_event
- && b->loc->pspace == current_program_space)
- delete_breakpoint (b);
-}
-
struct lang_and_radix
{
enum language lang;
struct breakpoint *
create_jit_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
{
- struct breakpoint *b;
-
- b = create_internal_breakpoint (gdbarch, address, bp_jit_event,
- &internal_breakpoint_ops);
- update_global_location_list_nothrow (UGLL_MAY_INSERT);
- return b;
+ return create_internal_breakpoint (gdbarch, address, bp_jit_event,
+ &internal_breakpoint_ops);
}
/* Remove JIT code registration and unregistration breakpoint(s). */
catchpoints. */
static int
-remove_catch_fork (struct bp_location *bl)
+remove_catch_fork (struct bp_location *bl, enum remove_bp_reason reason)
{
return target_remove_fork_catchpoint (ptid_get_pid (inferior_ptid));
}
struct fork_catchpoint *c = (struct fork_catchpoint *) bs->breakpoint_at;
annotate_catchpoint (b->number);
+ maybe_print_thread_hit_breakpoint (uiout);
if (b->disposition == disp_del)
- ui_out_text (uiout, "\nTemporary catchpoint ");
+ ui_out_text (uiout, "Temporary catchpoint ");
else
- ui_out_text (uiout, "\nCatchpoint ");
+ ui_out_text (uiout, "Catchpoint ");
if (ui_out_is_mi_like_p (uiout))
{
ui_out_field_string (uiout, "reason",
catchpoints. */
static int
-remove_catch_vfork (struct bp_location *bl)
+remove_catch_vfork (struct bp_location *bl, enum remove_bp_reason reason)
{
return target_remove_vfork_catchpoint (ptid_get_pid (inferior_ptid));
}
struct fork_catchpoint *c = (struct fork_catchpoint *) b;
annotate_catchpoint (b->number);
+ maybe_print_thread_hit_breakpoint (uiout);
if (b->disposition == disp_del)
- ui_out_text (uiout, "\nTemporary catchpoint ");
+ ui_out_text (uiout, "Temporary catchpoint ");
else
- ui_out_text (uiout, "\nCatchpoint ");
+ ui_out_text (uiout, "Catchpoint ");
if (ui_out_is_mi_like_p (uiout))
{
ui_out_field_string (uiout, "reason",
}
static int
-remove_catch_solib (struct bp_location *ignore)
+remove_catch_solib (struct bp_location *ignore, enum remove_bp_reason reason)
{
return 0;
}
struct ui_out *uiout = current_uiout;
annotate_catchpoint (b->number);
+ maybe_print_thread_hit_breakpoint (uiout);
if (b->disposition == disp_del)
- ui_out_text (uiout, "\nTemporary catchpoint ");
+ ui_out_text (uiout, "Temporary catchpoint ");
else
- ui_out_text (uiout, "\nCatchpoint ");
+ ui_out_text (uiout, "Catchpoint ");
ui_out_field_int (uiout, "bkptno", b->number);
ui_out_text (uiout, "\n");
if (ui_out_is_mi_like_p (uiout))
catch_load_or_unload (arg, from_tty, 0, command);
}
-/* An instance of this type is used to represent a syscall catchpoint.
- It includes a "struct breakpoint" as a kind of base class; users
- downcast to "struct breakpoint *" when needed. A breakpoint is
- really of this type iff its ops pointer points to
- CATCH_SYSCALL_BREAKPOINT_OPS. */
+/* Initialize a new breakpoint of the bp_catchpoint kind. 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. */
-struct syscall_catchpoint
+void
+init_catchpoint (struct breakpoint *b,
+ struct gdbarch *gdbarch, int tempflag,
+ char *cond_string,
+ const struct breakpoint_ops *ops)
{
- /* The base class. */
- struct breakpoint base;
-
- /* Syscall numbers used for the 'catch syscall' feature. If no
- syscall has been specified for filtering, its value is NULL.
- Otherwise, it holds a list of all syscalls to be caught. The
- list elements are allocated with xmalloc. */
- VEC(int) *syscalls_to_be_caught;
-};
-
-/* Implement the "dtor" breakpoint_ops method for syscall
- catchpoints. */
+ struct symtab_and_line sal;
-static void
-dtor_catch_syscall (struct breakpoint *b)
-{
- struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
+ init_sal (&sal);
+ sal.pspace = current_program_space;
- VEC_free (int, c->syscalls_to_be_caught);
+ init_raw_breakpoint (b, gdbarch, sal, bp_catchpoint, ops);
- base_breakpoint_ops.dtor (b);
+ b->cond_string = (cond_string == NULL) ? NULL : xstrdup (cond_string);
+ b->disposition = tempflag ? disp_del : disp_donttouch;
}
-static const struct inferior_data *catch_syscall_inferior_data = NULL;
-
-struct catch_syscall_inferior_data
-{
- /* We keep a count of the number of times the user has requested a
- particular syscall to be tracked, and pass this information to the
- target. This lets capable targets implement filtering directly. */
-
- /* Number of times that "any" syscall is requested. */
- int any_syscall_count;
-
- /* Count of each system call. */
- VEC(int) *syscalls_counts;
-
- /* This counts all syscall catch requests, so we can readily determine
- if any catching is necessary. */
- int total_syscalls_count;
-};
-
-static struct catch_syscall_inferior_data*
-get_catch_syscall_inferior_data (struct inferior *inf)
+void
+install_breakpoint (int internal, struct breakpoint *b, int update_gll)
{
- struct catch_syscall_inferior_data *inf_data;
-
- inf_data = inferior_data (inf, catch_syscall_inferior_data);
- if (inf_data == NULL)
- {
- inf_data = XCNEW (struct catch_syscall_inferior_data);
- set_inferior_data (inf, catch_syscall_inferior_data, inf_data);
- }
+ add_to_breakpoint_chain (b);
+ set_breakpoint_number (internal, b);
+ if (is_tracepoint (b))
+ set_tracepoint_count (breakpoint_count);
+ if (!internal)
+ mention (b);
+ observer_notify_breakpoint_created (b);
- return inf_data;
+ if (update_gll)
+ update_global_location_list (UGLL_MAY_INSERT);
}
static void
-catch_syscall_inferior_data_cleanup (struct inferior *inf, void *arg)
+create_fork_vfork_event_catchpoint (struct gdbarch *gdbarch,
+ int tempflag, char *cond_string,
+ const struct breakpoint_ops *ops)
{
- xfree (arg);
-}
+ struct fork_catchpoint *c = XNEW (struct fork_catchpoint);
-
-/* Implement the "insert" breakpoint_ops method for syscall
- catchpoints. */
-
-static int
-insert_catch_syscall (struct bp_location *bl)
-{
- struct syscall_catchpoint *c = (struct syscall_catchpoint *) bl->owner;
- struct inferior *inf = current_inferior ();
- struct catch_syscall_inferior_data *inf_data
- = get_catch_syscall_inferior_data (inf);
-
- ++inf_data->total_syscalls_count;
- if (!c->syscalls_to_be_caught)
- ++inf_data->any_syscall_count;
- else
- {
- int i, iter;
-
- for (i = 0;
- VEC_iterate (int, c->syscalls_to_be_caught, i, iter);
- i++)
- {
- int elem;
-
- if (iter >= VEC_length (int, inf_data->syscalls_counts))
- {
- int old_size = VEC_length (int, inf_data->syscalls_counts);
- uintptr_t vec_addr_offset
- = old_size * ((uintptr_t) sizeof (int));
- uintptr_t vec_addr;
- VEC_safe_grow (int, inf_data->syscalls_counts, iter + 1);
- vec_addr = ((uintptr_t) VEC_address (int,
- inf_data->syscalls_counts)
- + vec_addr_offset);
- memset ((void *) vec_addr, 0,
- (iter + 1 - old_size) * sizeof (int));
- }
- elem = VEC_index (int, inf_data->syscalls_counts, iter);
- VEC_replace (int, inf_data->syscalls_counts, iter, ++elem);
- }
- }
-
- return target_set_syscall_catchpoint (ptid_get_pid (inferior_ptid),
- inf_data->total_syscalls_count != 0,
- inf_data->any_syscall_count,
- VEC_length (int,
- inf_data->syscalls_counts),
- VEC_address (int,
- inf_data->syscalls_counts));
-}
-
-/* Implement the "remove" breakpoint_ops method for syscall
- catchpoints. */
-
-static int
-remove_catch_syscall (struct bp_location *bl)
-{
- struct syscall_catchpoint *c = (struct syscall_catchpoint *) bl->owner;
- struct inferior *inf = current_inferior ();
- struct catch_syscall_inferior_data *inf_data
- = get_catch_syscall_inferior_data (inf);
-
- --inf_data->total_syscalls_count;
- if (!c->syscalls_to_be_caught)
- --inf_data->any_syscall_count;
- else
- {
- int i, iter;
-
- for (i = 0;
- VEC_iterate (int, c->syscalls_to_be_caught, i, iter);
- i++)
- {
- int elem;
- if (iter >= VEC_length (int, inf_data->syscalls_counts))
- /* Shouldn't happen. */
- continue;
- elem = VEC_index (int, inf_data->syscalls_counts, iter);
- VEC_replace (int, inf_data->syscalls_counts, iter, --elem);
- }
- }
-
- return target_set_syscall_catchpoint (ptid_get_pid (inferior_ptid),
- inf_data->total_syscalls_count != 0,
- inf_data->any_syscall_count,
- VEC_length (int,
- inf_data->syscalls_counts),
- VEC_address (int,
- inf_data->syscalls_counts));
-}
-
-/* Implement the "breakpoint_hit" breakpoint_ops method for syscall
- catchpoints. */
-
-static int
-breakpoint_hit_catch_syscall (const struct bp_location *bl,
- struct address_space *aspace, CORE_ADDR bp_addr,
- const struct target_waitstatus *ws)
-{
- /* We must check if we are catching specific syscalls in this
- breakpoint. If we are, then we must guarantee that the called
- syscall is the same syscall we are catching. */
- int syscall_number = 0;
- const struct syscall_catchpoint *c
- = (const struct syscall_catchpoint *) bl->owner;
-
- if (ws->kind != TARGET_WAITKIND_SYSCALL_ENTRY
- && ws->kind != TARGET_WAITKIND_SYSCALL_RETURN)
- return 0;
-
- syscall_number = ws->value.syscall_number;
-
- /* Now, checking if the syscall is the same. */
- if (c->syscalls_to_be_caught)
- {
- int i, iter;
-
- for (i = 0;
- VEC_iterate (int, c->syscalls_to_be_caught, i, iter);
- i++)
- if (syscall_number == iter)
- return 1;
-
- return 0;
- }
-
- return 1;
-}
-
-/* Implement the "print_it" breakpoint_ops method for syscall
- catchpoints. */
-
-static enum print_stop_action
-print_it_catch_syscall (bpstat bs)
-{
- struct ui_out *uiout = current_uiout;
- struct breakpoint *b = bs->breakpoint_at;
- /* These are needed because we want to know in which state a
- syscall is. It can be in the TARGET_WAITKIND_SYSCALL_ENTRY
- or TARGET_WAITKIND_SYSCALL_RETURN, and depending on it we
- must print "called syscall" or "returned from syscall". */
- ptid_t ptid;
- struct target_waitstatus last;
- struct syscall s;
- struct gdbarch *gdbarch = bs->bp_location_at->gdbarch;
-
- get_last_target_status (&ptid, &last);
-
- get_syscall_by_number (gdbarch, last.value.syscall_number, &s);
-
- annotate_catchpoint (b->number);
-
- if (b->disposition == disp_del)
- ui_out_text (uiout, "\nTemporary catchpoint ");
- else
- ui_out_text (uiout, "\nCatchpoint ");
- if (ui_out_is_mi_like_p (uiout))
- {
- ui_out_field_string (uiout, "reason",
- async_reason_lookup (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY
- ? EXEC_ASYNC_SYSCALL_ENTRY
- : EXEC_ASYNC_SYSCALL_RETURN));
- ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
- }
- ui_out_field_int (uiout, "bkptno", b->number);
-
- if (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY)
- ui_out_text (uiout, " (call to syscall ");
- else
- ui_out_text (uiout, " (returned from syscall ");
-
- if (s.name == NULL || ui_out_is_mi_like_p (uiout))
- ui_out_field_int (uiout, "syscall-number", last.value.syscall_number);
- if (s.name != NULL)
- ui_out_field_string (uiout, "syscall-name", s.name);
-
- ui_out_text (uiout, "), ");
-
- return PRINT_SRC_AND_LOC;
-}
-
-/* Implement the "print_one" breakpoint_ops method for syscall
- catchpoints. */
-
-static void
-print_one_catch_syscall (struct breakpoint *b,
- struct bp_location **last_loc)
-{
- struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
- struct value_print_options opts;
- struct ui_out *uiout = current_uiout;
- struct gdbarch *gdbarch = b->loc->gdbarch;
-
- 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);
-
- if (c->syscalls_to_be_caught
- && VEC_length (int, c->syscalls_to_be_caught) > 1)
- ui_out_text (uiout, "syscalls \"");
- else
- ui_out_text (uiout, "syscall \"");
-
- if (c->syscalls_to_be_caught)
- {
- int i, iter;
- char *text = xstrprintf ("%s", "");
-
- for (i = 0;
- VEC_iterate (int, c->syscalls_to_be_caught, i, iter);
- i++)
- {
- char *x = text;
- struct syscall s;
- get_syscall_by_number (gdbarch, iter, &s);
-
- if (s.name != NULL)
- text = xstrprintf ("%s%s, ", text, s.name);
- else
- text = xstrprintf ("%s%d, ", text, iter);
-
- /* We have to xfree the last 'text' (now stored at 'x')
- because xstrprintf dynamically allocates new space for it
- on every call. */
- xfree (x);
- }
- /* Remove the last comma. */
- text[strlen (text) - 2] = '\0';
- ui_out_field_string (uiout, "what", text);
- }
- else
- ui_out_field_string (uiout, "what", "<any syscall>");
- ui_out_text (uiout, "\" ");
-
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "catch-type", "syscall");
-}
-
-/* Implement the "print_mention" breakpoint_ops method for syscall
- catchpoints. */
-
-static void
-print_mention_catch_syscall (struct breakpoint *b)
-{
- struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
- struct gdbarch *gdbarch = b->loc->gdbarch;
-
- if (c->syscalls_to_be_caught)
- {
- int i, iter;
-
- if (VEC_length (int, c->syscalls_to_be_caught) > 1)
- printf_filtered (_("Catchpoint %d (syscalls"), b->number);
- else
- printf_filtered (_("Catchpoint %d (syscall"), b->number);
-
- for (i = 0;
- VEC_iterate (int, c->syscalls_to_be_caught, i, iter);
- i++)
- {
- struct syscall s;
- get_syscall_by_number (gdbarch, iter, &s);
-
- if (s.name)
- printf_filtered (" '%s' [%d]", s.name, s.number);
- else
- printf_filtered (" %d", s.number);
- }
- printf_filtered (")");
- }
- else
- printf_filtered (_("Catchpoint %d (any syscall)"),
- b->number);
-}
-
-/* Implement the "print_recreate" breakpoint_ops method for syscall
- catchpoints. */
-
-static void
-print_recreate_catch_syscall (struct breakpoint *b, struct ui_file *fp)
-{
- struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
- struct gdbarch *gdbarch = b->loc->gdbarch;
-
- fprintf_unfiltered (fp, "catch syscall");
-
- if (c->syscalls_to_be_caught)
- {
- int i, iter;
-
- for (i = 0;
- VEC_iterate (int, c->syscalls_to_be_caught, i, iter);
- i++)
- {
- struct syscall s;
-
- get_syscall_by_number (gdbarch, iter, &s);
- if (s.name)
- fprintf_unfiltered (fp, " %s", s.name);
- else
- fprintf_unfiltered (fp, " %d", s.number);
- }
- }
- print_recreate_thread (b, fp);
-}
-
-/* The breakpoint_ops structure to be used in syscall catchpoints. */
-
-static struct breakpoint_ops catch_syscall_breakpoint_ops;
-
-/* Returns non-zero if 'b' is a syscall catchpoint. */
-
-static int
-syscall_catchpoint_p (struct breakpoint *b)
-{
- return (b->ops == &catch_syscall_breakpoint_ops);
-}
-
-/* Initialize a new breakpoint of the bp_catchpoint kind. 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. */
-
-void
-init_catchpoint (struct breakpoint *b,
- struct gdbarch *gdbarch, int tempflag,
- char *cond_string,
- const struct breakpoint_ops *ops)
-{
- struct symtab_and_line sal;
-
- init_sal (&sal);
- sal.pspace = current_program_space;
-
- init_raw_breakpoint (b, gdbarch, sal, bp_catchpoint, ops);
-
- b->cond_string = (cond_string == NULL) ? NULL : xstrdup (cond_string);
- b->disposition = tempflag ? disp_del : disp_donttouch;
-}
-
-void
-install_breakpoint (int internal, struct breakpoint *b, int update_gll)
-{
- add_to_breakpoint_chain (b);
- set_breakpoint_number (internal, b);
- if (is_tracepoint (b))
- set_tracepoint_count (breakpoint_count);
- if (!internal)
- mention (b);
- observer_notify_breakpoint_created (b);
-
- if (update_gll)
- update_global_location_list (UGLL_MAY_INSERT);
-}
-
-static void
-create_fork_vfork_event_catchpoint (struct gdbarch *gdbarch,
- int tempflag, char *cond_string,
- const struct breakpoint_ops *ops)
-{
- struct fork_catchpoint *c = XNEW (struct fork_catchpoint);
-
- init_catchpoint (&c->base, gdbarch, tempflag, cond_string, ops);
+ init_catchpoint (&c->base, gdbarch, tempflag, cond_string, ops);
c->forked_inferior_pid = null_ptid;
}
static int
-remove_catch_exec (struct bp_location *bl)
+remove_catch_exec (struct bp_location *bl, enum remove_bp_reason reason)
{
return target_remove_exec_catchpoint (ptid_get_pid (inferior_ptid));
}
struct exec_catchpoint *c = (struct exec_catchpoint *) b;
annotate_catchpoint (b->number);
+ maybe_print_thread_hit_breakpoint (uiout);
if (b->disposition == disp_del)
- ui_out_text (uiout, "\nTemporary catchpoint ");
+ ui_out_text (uiout, "Temporary catchpoint ");
else
- ui_out_text (uiout, "\nCatchpoint ");
+ ui_out_text (uiout, "Catchpoint ");
if (ui_out_is_mi_like_p (uiout))
{
ui_out_field_string (uiout, "reason",
static struct breakpoint_ops catch_exec_breakpoint_ops;
-static void
-create_syscall_event_catchpoint (int tempflag, VEC(int) *filter,
- const struct breakpoint_ops *ops)
-{
- struct syscall_catchpoint *c;
- struct gdbarch *gdbarch = get_current_arch ();
-
- c = XNEW (struct syscall_catchpoint);
- init_catchpoint (&c->base, gdbarch, tempflag, NULL, ops);
- c->syscalls_to_be_caught = filter;
-
- install_breakpoint (0, &c->base, 1);
-}
-
static int
hw_breakpoint_used_count (void)
{
momentary breakpoints to be active in only a single thread of
control. */
if (in_thread_list (inferior_ptid))
- b->thread = pid_to_thread_id (inferior_ptid);
+ b->thread = ptid_to_global_thread_id (inferior_ptid);
update_global_location_list_nothrow (UGLL_MAY_INSERT);
set_breakpoint_location_function (loc,
sal->explicit_pc || sal->explicit_line);
+ /* While by definition, permanent breakpoints are already present in the
+ code, we don't mark the location as inserted. Normally one would expect
+ that GDB could rely on that breakpoint instruction to stop the program,
+ thus removing the need to insert its own breakpoint, except that executing
+ the breakpoint instruction can kill the target instead of reporting a
+ SIGTRAP. E.g., on SPARC, when interrupts are disabled, executing the
+ instruction resets the CPU, so QEMU 2.0.0 for SPARC correspondingly dies
+ with "Trap 0x02 while interrupts disabled, Error state". Letting the
+ breakpoint be inserted normally results in QEMU knowing about the GDB
+ breakpoint, and thus trap before the breakpoint instruction is executed.
+ (If GDB later needs to continue execution past the permanent breakpoint,
+ it manually increments the PC, thus avoiding executing the breakpoint
+ instruction.) */
if (bp_loc_is_permanent (loc))
- {
- loc->inserted = 1;
- loc->permanent = 1;
- }
+ loc->permanent = 1;
return loc;
}
if (bpoint == NULL)
return 0;
- target_mem = alloca (len);
+ target_mem = (gdb_byte *) alloca (len);
/* Enable the automatic memory restoration from breakpoints while
we read the memory. Otherwise we could say about our temporary
gdb_assert (loc != NULL);
- /* bp_call_dummy breakpoint locations are usually memory locations
- where GDB just wrote a breakpoint instruction, making it look
- as if there is a permanent breakpoint at that location. Considering
- it permanent makes GDB rely on that breakpoint instruction to stop
- the program, thus removing the need to insert its own breakpoint
- there. This is normally expected to work, except that some versions
- of QEMU (Eg: QEMU 2.0.0 for SPARC) just report a fatal problem (Trap
- 0x02 while interrupts disabled, Error state) instead of reporting
- a SIGTRAP. QEMU should probably be fixed, but in the interest of
- compatibility with versions that behave this way, we always consider
- bp_call_dummy breakpoint locations as non-permanent. */
- if (loc->owner->type == bp_call_dummy)
+ /* If we have a catchpoint or a watchpoint, just return 0. We should not
+ attempt to read from the addresses the locations of these breakpoint types
+ point to. program_breakpoint_here_p, below, will attempt to read
+ memory. */
+ if (!breakpoint_address_is_meaningful (loc->owner))
return 0;
cleanup = save_current_space_and_thread ();
gdb_assert (printf_line != NULL);
/* Manufacture a printf sequence. */
{
- struct command_line *printf_cmd_line
- = xmalloc (sizeof (struct command_line));
+ struct command_line *printf_cmd_line = XNEW (struct command_line);
- printf_cmd_line = xmalloc (sizeof (struct command_line));
printf_cmd_line->control_type = simple_control;
printf_cmd_line->body_count = 0;
printf_cmd_line->body_list = NULL;
}
}
-/* Create a breakpoint with SAL as location. Use ADDR_STRING
- as textual description of the location, and COND_STRING
- as condition expression. */
+/* Create a breakpoint with SAL as location. Use LOCATION
+ as a description of the location, and COND_STRING
+ as condition expression. If LOCATION is NULL then create an
+ "address location" from the address in the SAL. */
static void
init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
- struct symtabs_and_lines sals, char *addr_string,
+ struct symtabs_and_lines sals,
+ struct event_location *location,
char *filter, char *cond_string,
char *extra_string,
enum bptype type, enum bpdisp disposition,
{
/* We already know the marker exists, otherwise, we
wouldn't see a sal for it. */
- char *p = &addr_string[3];
- char *endp;
+ const char *p = &event_location_to_string (b->location)[3];
+ const char *endp;
char *marker_str;
- p = skip_spaces (p);
+ p = skip_spaces_const (p);
- endp = skip_to_space (p);
+ endp = skip_to_space_const (p);
marker_str = savestring (p, endp - p);
t->static_trace_marker_id = marker_str;
}
b->display_canonical = display_canonical;
- if (addr_string)
- b->addr_string = addr_string;
+ if (location != NULL)
+ b->location = location;
else
- /* addr_string has to be used or breakpoint_re_set will delete
- me. */
- b->addr_string
- = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
+ {
+ const char *addr_string = NULL;
+ int addr_string_len = 0;
+
+ if (location != NULL)
+ addr_string = event_location_to_string (location);
+ if (addr_string != NULL)
+ addr_string_len = strlen (addr_string);
+
+ b->location = new_address_location (b->loc->address,
+ addr_string, addr_string_len);
+ }
b->filter = filter;
}
static void
create_breakpoint_sal (struct gdbarch *gdbarch,
- struct symtabs_and_lines sals, char *addr_string,
+ struct symtabs_and_lines sals,
+ struct event_location *location,
char *filter, char *cond_string,
char *extra_string,
enum bptype type, enum bpdisp disposition,
old_chain = make_cleanup (xfree, b);
init_breakpoint_sal (b, gdbarch,
- sals, addr_string,
+ sals, location,
filter, cond_string, extra_string,
type, disposition,
thread, task, ignore_count,
for (i = 0; VEC_iterate (linespec_sals, canonical->sals, i, lsal); ++i)
{
- /* Note that 'addr_string' can be NULL in the case of a plain
+ /* Note that 'location' can be NULL in the case of a plain
'break', without arguments. */
- char *addr_string = (canonical->addr_string
- ? xstrdup (canonical->addr_string)
- : NULL);
+ struct event_location *location
+ = (canonical->location != NULL
+ ? copy_event_location (canonical->location) : NULL);
char *filter_string = lsal->canonical ? xstrdup (lsal->canonical) : NULL;
- struct cleanup *inner = make_cleanup (xfree, addr_string);
+ struct cleanup *inner = make_cleanup_delete_event_location (location);
make_cleanup (xfree, filter_string);
create_breakpoint_sal (gdbarch, lsal->sals,
- addr_string,
+ location,
filter_string,
cond_string, extra_string,
type, disposition,
}
}
-/* Parse ADDRESS which is assumed to be a SAL specification possibly
+/* Parse LOCATION which is assumed to be a SAL specification possibly
followed by conditionals. On return, SALS contains an array of SAL
- addresses found. ADDR_STRING contains a vector of (canonical)
- address strings. ADDRESS points to the end of the SAL.
+ addresses found. LOCATION points to the end of the SAL (for
+ linespec locations).
The array and the line spec strings are allocated on the heap, it is
the caller's responsibility to free them. */
static void
-parse_breakpoint_sals (char **address,
+parse_breakpoint_sals (const struct event_location *location,
struct linespec_result *canonical)
{
- /* If no arg given, or if first arg is 'if ', use the default
- breakpoint. */
- if ((*address) == NULL
- || (startswith ((*address), "if") && isspace ((*address)[2])))
+ struct symtab_and_line cursal;
+
+ if (event_location_type (location) == LINESPEC_LOCATION)
{
- /* The last displayed codepoint, if it's valid, is our default breakpoint
- address. */
- if (last_displayed_sal_is_valid ())
+ const char *address = get_linespec_location (location);
+
+ if (address == NULL)
{
- struct linespec_sals lsal;
- struct symtab_and_line sal;
- CORE_ADDR pc;
-
- init_sal (&sal); /* Initialize to zeroes. */
- lsal.sals.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
-
- /* Set sal's pspace, pc, symtab, and line to the values
- corresponding to the last call to print_frame_info.
- Be sure to reinitialize LINE with NOTCURRENT == 0
- as the breakpoint line number is inappropriate otherwise.
- find_pc_line would adjust PC, re-set it back. */
- get_last_displayed_sal (&sal);
- pc = sal.pc;
- sal = find_pc_line (pc, 0);
-
- /* "break" without arguments is equivalent to "break *PC"
- where PC is the last displayed codepoint's address. So
- make sure to set sal.explicit_pc to prevent GDB from
- trying to expand the list of sals to include all other
- instances with the same symtab and line. */
- sal.pc = pc;
- sal.explicit_pc = 1;
-
- lsal.sals.sals[0] = sal;
- lsal.sals.nelts = 1;
- lsal.canonical = NULL;
-
- VEC_safe_push (linespec_sals, canonical->sals, &lsal);
+ /* The last displayed codepoint, if it's valid, is our default
+ breakpoint address. */
+ if (last_displayed_sal_is_valid ())
+ {
+ struct linespec_sals lsal;
+ struct symtab_and_line sal;
+ CORE_ADDR pc;
+
+ init_sal (&sal); /* Initialize to zeroes. */
+ lsal.sals.sals = XNEW (struct symtab_and_line);
+
+ /* Set sal's pspace, pc, symtab, and line to the values
+ corresponding to the last call to print_frame_info.
+ Be sure to reinitialize LINE with NOTCURRENT == 0
+ as the breakpoint line number is inappropriate otherwise.
+ find_pc_line would adjust PC, re-set it back. */
+ get_last_displayed_sal (&sal);
+ pc = sal.pc;
+ sal = find_pc_line (pc, 0);
+
+ /* "break" without arguments is equivalent to "break *PC"
+ where PC is the last displayed codepoint's address. So
+ make sure to set sal.explicit_pc to prevent GDB from
+ trying to expand the list of sals to include all other
+ instances with the same symtab and line. */
+ sal.pc = pc;
+ sal.explicit_pc = 1;
+
+ lsal.sals.sals[0] = sal;
+ lsal.sals.nelts = 1;
+ lsal.canonical = NULL;
+
+ VEC_safe_push (linespec_sals, canonical->sals, &lsal);
+ return;
+ }
+ else
+ error (_("No default breakpoint address now."));
}
- else
- error (_("No default breakpoint address now."));
}
- else
+
+ /* Force almost all breakpoints to be in terms of the
+ current_source_symtab (which is decode_line_1's default).
+ This should produce the results we want almost all of the
+ time while leaving default_breakpoint_* alone.
+
+ ObjC: However, don't match an Objective-C method name which
+ may have a '+' or '-' succeeded by a '['. */
+ cursal = get_current_source_symtab_and_line ();
+ if (last_displayed_sal_is_valid ())
{
- struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+ const char *address = NULL;
- /* Force almost all breakpoints to be in terms of the
- current_source_symtab (which is decode_line_1's default).
- This should produce the results we want almost all of the
- time while leaving default_breakpoint_* alone.
+ if (event_location_type (location) == LINESPEC_LOCATION)
+ address = get_linespec_location (location);
- ObjC: However, don't match an Objective-C method name which
- may have a '+' or '-' succeeded by a '['. */
- if (last_displayed_sal_is_valid ()
- && (!cursal.symtab
- || ((strchr ("+-", (*address)[0]) != NULL)
- && ((*address)[1] != '['))))
- decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
- get_last_displayed_symtab (),
- get_last_displayed_line (),
- canonical, NULL, NULL);
- else
- decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
- cursal.symtab, cursal.line, canonical, NULL, NULL);
+ if (!cursal.symtab
+ || (address != NULL
+ && strchr ("+-", address[0]) != NULL
+ && address[1] != '['))
+ {
+ decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, NULL,
+ get_last_displayed_symtab (),
+ get_last_displayed_line (),
+ canonical, NULL, NULL);
+ return;
+ }
}
+
+ decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, NULL,
+ cursal.symtab, cursal.line, canonical, NULL, NULL);
}
associated with SAL. */
if (sarch == NULL)
sarch = gdbarch;
- rslt = gdbarch_fast_tracepoint_valid_at (sarch, sal->pc,
- NULL, &msg);
+ rslt = gdbarch_fast_tracepoint_valid_at (sarch, sal->pc, &msg);
old_chain = make_cleanup (xfree, msg);
if (!rslt)
- error (_("May not have a fast tracepoint at 0x%s%s"),
+ error (_("May not have a fast tracepoint at %s%s"),
paddress (sarch, sal->pc), (msg ? msg : ""));
do_cleanups (old_chain);
}
}
-/* Issue an invalid thread ID error. */
-
-static void ATTRIBUTE_NORETURN
-invalid_thread_id_error (int id)
-{
- error (_("Unknown thread %d."), id);
-}
-
/* Given TOK, a string specification of condition and thread, as
accepted by the 'break' command, extract the condition
string and thread number and set *COND_STRING and *THREAD.
}
else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
{
- char *tmptok;
+ const char *tmptok;
+ struct thread_info *thr;
tok = end_tok + 1;
- *thread = strtol (tok, &tmptok, 0);
+ thr = parse_thread_id (tok, &tmptok);
if (tok == tmptok)
error (_("Junk after thread keyword."));
- if (!valid_thread_id (*thread))
- invalid_thread_id_error (*thread);
+ *thread = thr->global_num;
tok = tmptok;
}
else if (toklen >= 1 && strncmp (tok, "task", toklen) == 0)
/* Decode a static tracepoint marker spec. */
static struct symtabs_and_lines
-decode_static_tracepoint_spec (char **arg_p)
+decode_static_tracepoint_spec (const char **arg_p)
{
VEC(static_tracepoint_marker_p) *markers = NULL;
struct symtabs_and_lines sals;
struct cleanup *old_chain;
- char *p = &(*arg_p)[3];
- char *endp;
+ const char *p = &(*arg_p)[3];
+ const char *endp;
char *marker_str;
int i;
- p = skip_spaces (p);
+ p = skip_spaces_const (p);
- endp = skip_to_space (p);
+ endp = skip_to_space_const (p);
marker_str = savestring (p, endp - p);
old_chain = make_cleanup (xfree, marker_str);
error (_("No known static tracepoint marker named %s"), marker_str);
sals.nelts = VEC_length(static_tracepoint_marker_p, markers);
- sals.sals = xmalloc (sizeof *sals.sals * sals.nelts);
+ sals.sals = XNEWVEC (struct symtab_and_line, sals.nelts);
for (i = 0; i < sals.nelts; i++)
{
return sals;
}
-/* Set a breakpoint. This function is shared between CLI and MI
- functions for setting a breakpoint. This function has two major
- modes of operations, selected by the PARSE_ARG parameter. If
- non-zero, the function will parse ARG, extracting location,
- condition, thread and extra string. Otherwise, ARG is just the
- breakpoint's location, with condition, thread, and extra string
- specified by the COND_STRING, THREAD and EXTRA_STRING parameters.
- If INTERNAL is non-zero, the breakpoint number will be allocated
- from the internal breakpoint count. Returns true if any breakpoint
- was created; false otherwise. */
+/* See breakpoint.h. */
int
create_breakpoint (struct gdbarch *gdbarch,
- char *arg, char *cond_string,
+ const struct event_location *location, char *cond_string,
int thread, char *extra_string,
- int parse_arg,
+ int parse_extra,
int tempflag, enum bptype type_wanted,
int ignore_count,
enum auto_boolean pending_break_support,
int from_tty, int enabled, int internal,
unsigned flags)
{
- char *copy_arg = NULL;
- char *addr_start = arg;
struct linespec_result canonical;
struct cleanup *old_chain;
struct cleanup *bkpt_chain = NULL;
gdb_assert (ops != NULL);
+ /* If extra_string isn't useful, set it to NULL. */
+ if (extra_string != NULL && *extra_string == '\0')
+ extra_string = NULL;
+
init_linespec_result (&canonical);
TRY
{
- ops->create_sals_from_address (&arg, &canonical, type_wanted,
- addr_start, ©_arg);
+ ops->create_sals_from_location (location, &canonical, type_wanted);
}
CATCH (e, RETURN_MASK_ERROR)
{
a pending breakpoint and selected yes, or pending
breakpoint behavior is on and thus a pending breakpoint
is defaulted on behalf of the user. */
- {
- struct linespec_sals lsal;
-
- copy_arg = xstrdup (addr_start);
- lsal.canonical = xstrdup (copy_arg);
- lsal.sals.nelts = 1;
- lsal.sals.sals = XNEW (struct symtab_and_line);
- init_sal (&lsal.sals.sals[0]);
- pending = 1;
- VEC_safe_push (linespec_sals, canonical.sals, &lsal);
- }
+ pending = 1;
}
else
throw_exception (e);
}
END_CATCH
- if (VEC_empty (linespec_sals, canonical.sals))
+ if (!pending && VEC_empty (linespec_sals, canonical.sals))
return 0;
/* Create a chain of things that always need to be cleaned up. */
breakpoint. */
if (!pending)
{
- if (parse_arg)
+ if (parse_extra)
{
char *rest;
struct linespec_sals *lsal;
sal is OK. When setting the breakpoint we'll
re-parse it in context of each sal. */
- find_condition_and_thread (arg, lsal->sals.sals[0].pc, &cond_string,
- &thread, &task, &rest);
+ find_condition_and_thread (extra_string, lsal->sals.sals[0].pc,
+ &cond_string, &thread, &task, &rest);
if (cond_string)
make_cleanup (xfree, cond_string);
if (rest)
make_cleanup (xfree, rest);
if (rest)
extra_string = rest;
+ else
+ extra_string = NULL;
}
else
{
- if (*arg != '\0')
- error (_("Garbage '%s' at end of location"), arg);
+ if (type_wanted != bp_dprintf
+ && extra_string != NULL && *extra_string != '\0')
+ error (_("Garbage '%s' at end of location"), extra_string);
/* Create a private copy of condition string. */
if (cond_string)
{
struct breakpoint *b;
- make_cleanup (xfree, copy_arg);
-
if (is_tracepoint_type (type_wanted))
{
struct tracepoint *t;
b = XNEW (struct breakpoint);
init_raw_breakpoint_without_location (b, gdbarch, type_wanted, ops);
+ b->location = copy_event_location (location);
- b->addr_string = copy_arg;
- if (parse_arg)
+ if (parse_extra)
b->cond_string = NULL;
else
{
make_cleanup (xfree, cond_string);
}
b->cond_string = cond_string;
+ b->thread = thread;
+ }
+
+ /* Create a private copy of any extra string. */
+ if (extra_string != NULL)
+ {
+ extra_string = xstrdup (extra_string);
+ make_cleanup (xfree, extra_string);
}
- b->extra_string = NULL;
+ b->extra_string = extra_string;
b->ignore_count = ignore_count;
b->disposition = tempflag ? disp_del : disp_donttouch;
b->condition_not_parsed = 1;
? bp_hardware_breakpoint
: bp_breakpoint);
struct breakpoint_ops *ops;
- const char *arg_cp = arg;
+ struct event_location *location;
+ struct cleanup *cleanup;
+
+ location = string_to_event_location (&arg, current_language);
+ cleanup = make_cleanup_delete_event_location (location);
/* Matching breakpoints on probes. */
- if (arg && probe_linespec_to_ops (&arg_cp) != NULL)
+ if (location != NULL
+ && event_location_type (location) == PROBE_LOCATION)
ops = &bkpt_probe_breakpoint_ops;
else
ops = &bkpt_breakpoint_ops;
create_breakpoint (get_current_arch (),
- arg,
- NULL, 0, NULL, 1 /* parse arg */,
+ location,
+ NULL, 0, arg, 1 /* parse arg */,
tempflag, type_wanted,
0 /* Ignore count */,
pending_break_support,
1 /* enabled */,
0 /* internal */,
0);
+ do_cleanups (cleanup);
}
/* Helper function for break_command_1 and disassemble_command. */
static void
dprintf_command (char *arg, int from_tty)
{
+ struct event_location *location;
+ struct cleanup *cleanup;
+
+ location = string_to_event_location (&arg, current_language);
+ cleanup = make_cleanup_delete_event_location (location);
+
+ /* If non-NULL, ARG should have been advanced past the location;
+ the next character must be ','. */
+ if (arg != NULL)
+ {
+ if (arg[0] != ',' || arg[1] == '\0')
+ error (_("Format string required"));
+ else
+ {
+ /* Skip the comma. */
+ ++arg;
+ }
+ }
+
create_breakpoint (get_current_arch (),
- arg,
- NULL, 0, NULL, 1 /* parse arg */,
+ location,
+ NULL, 0, arg, 1 /* parse arg */,
0, bp_dprintf,
0 /* Ignore count */,
pending_break_support,
1 /* enabled */,
0 /* internal */,
0);
+ do_cleanups (cleanup);
}
static void
gdb_assert (bl && bl->next == NULL);
annotate_breakpoint (b->number);
+
+ maybe_print_thread_hit_breakpoint (uiout);
+
if (b->disposition == disp_del)
- ui_out_text (uiout, "\nTemporary ranged breakpoint ");
+ ui_out_text (uiout, "Temporary ranged breakpoint ");
else
- ui_out_text (uiout, "\nRanged breakpoint ");
+ ui_out_text (uiout, "Ranged breakpoint ");
if (ui_out_is_mi_like_p (uiout))
{
ui_out_field_string (uiout, "reason",
static void
print_recreate_ranged_breakpoint (struct breakpoint *b, struct ui_file *fp)
{
- fprintf_unfiltered (fp, "break-range %s, %s", b->addr_string,
- b->addr_string_range_end);
+ fprintf_unfiltered (fp, "break-range %s, %s",
+ event_location_to_string (b->location),
+ event_location_to_string (b->location_range_end));
print_recreate_thread (b, fp);
}
static void
break_range_command (char *arg, int from_tty)
{
- char *arg_start, *addr_string_start, *addr_string_end;
+ char *arg_start, *addr_string_start;
struct linespec_result canonical_start, canonical_end;
int bp_count, can_use_bp, length;
CORE_ADDR end;
struct symtab_and_line sal_start, sal_end;
struct cleanup *cleanup_bkpt;
struct linespec_sals *lsal_start, *lsal_end;
+ struct event_location *start_location, *end_location;
/* We don't support software ranged breakpoints. */
if (target_ranged_break_num_registers () < 0)
init_linespec_result (&canonical_start);
arg_start = arg;
- parse_breakpoint_sals (&arg, &canonical_start);
-
- cleanup_bkpt = make_cleanup_destroy_linespec_result (&canonical_start);
+ start_location = string_to_event_location (&arg, current_language);
+ cleanup_bkpt = make_cleanup_delete_event_location (start_location);
+ parse_breakpoint_sals (start_location, &canonical_start);
+ make_cleanup_destroy_linespec_result (&canonical_start);
if (arg[0] != ',')
error (_("Too few arguments."));
symtab and line as the default symtab and line for the end of the
range. This makes it possible to have ranges like "foo.c:27, +14",
where +14 means 14 lines from the start location. */
- decode_line_full (&arg, DECODE_LINE_FUNFIRSTLINE,
+ end_location = string_to_event_location (&arg, current_language);
+ make_cleanup_delete_event_location (end_location);
+ decode_line_full (end_location, DECODE_LINE_FUNFIRSTLINE, NULL,
sal_start.symtab, sal_start.line,
&canonical_end, NULL, NULL);
error (_("Cannot create a ranged breakpoint with multiple locations."));
sal_end = lsal_end->sals.sals[0];
- addr_string_end = savestring (arg_start, arg - arg_start);
- make_cleanup (xfree, addr_string_end);
end = find_breakpoint_range_end (sal_end);
if (sal_start.pc > end)
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
b->disposition = disp_donttouch;
- b->addr_string = xstrdup (addr_string_start);
- b->addr_string_range_end = xstrdup (addr_string_end);
+ b->location = copy_event_location (start_location);
+ b->location_range_end = copy_event_location (end_location);
b->loc->length = length;
do_cleanups (cleanup_bkpt);
/* Implement the "remove" breakpoint_ops method for hardware watchpoints. */
static int
-remove_watchpoint (struct bp_location *bl)
+remove_watchpoint (struct bp_location *bl, enum remove_bp_reason reason)
{
struct watchpoint *w = (struct watchpoint *) bl->owner;
int length = w->exact ? 1 : bl->length;
stb = mem_fileopen ();
old_chain = make_cleanup_ui_file_delete (stb);
+ annotate_watchpoint (b->number);
+ maybe_print_thread_hit_breakpoint (uiout);
+
switch (b->type)
{
case bp_watchpoint:
case bp_hardware_watchpoint:
- annotate_watchpoint (b->number);
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string
(uiout, "reason",
case bp_access_watchpoint:
if (bs->old_val != NULL)
{
- annotate_watchpoint (b->number);
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string
(uiout, "reason",
masked hardware watchpoints. */
static int
-remove_masked_watchpoint (struct bp_location *bl)
+remove_masked_watchpoint (struct bp_location *bl, enum remove_bp_reason reason)
{
struct watchpoint *w = (struct watchpoint *) bl->owner;
/* Masked watchpoints have only one location. */
gdb_assert (b->loc && b->loc->next == NULL);
+ annotate_watchpoint (b->number);
+ maybe_print_thread_hit_breakpoint (uiout);
+
switch (b->type)
{
case bp_hardware_watchpoint:
- annotate_watchpoint (b->number);
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string
(uiout, "reason",
if (toklen == 6 && startswith (tok, "thread"))
{
+ struct thread_info *thr;
/* At this point we've found a "thread" token, which means
the user is trying to set a watchpoint that triggers
only in a specific thread. */
- char *endp;
+ const char *endp;
if (thread != -1)
error(_("You can specify only one thread."));
/* Extract the thread ID from the next token. */
- thread = strtol (value_start, &endp, 0);
+ thr = parse_thread_id (value_start, &endp);
- /* Check if the user provided a valid numeric value for the
- thread ID. */
+ /* Check if the user provided a valid thread ID. */
if (*endp != ' ' && *endp != '\t' && *endp != '\0')
- error (_("Invalid thread ID specification %s."), value_start);
+ invalid_thread_id_error (value_start);
- /* Check if the thread actually exists. */
- if (!valid_thread_id (thread))
- invalid_thread_id_error (thread);
+ thread = thr->global_num;
}
else if (toklen == 4 && startswith (tok, "mask"))
{
}
\f
-/* Helper routines for the until_command routine in infcmd.c. Here
- because it uses the mechanisms of breakpoints. */
+/* Data for the FSM that manages the until(location)/advance commands
+ in infcmd.c. Here because it uses the mechanisms of
+ breakpoints. */
+
+struct until_break_fsm
+{
+ /* The base class. */
+ struct thread_fsm thread_fsm;
+
+ /* The thread that as current when the command was executed. */
+ int thread;
+
+ /* The breakpoint set at the destination location. */
+ struct breakpoint *location_breakpoint;
+
+ /* Breakpoint set at the return address in the caller frame. May be
+ NULL. */
+ struct breakpoint *caller_breakpoint;
+};
+
+static void until_break_fsm_clean_up (struct thread_fsm *self,
+ struct thread_info *thread);
+static int until_break_fsm_should_stop (struct thread_fsm *self,
+ struct thread_info *thread);
+static enum async_reply_reason
+ until_break_fsm_async_reply_reason (struct thread_fsm *self);
+
+/* until_break_fsm's vtable. */
+
+static struct thread_fsm_ops until_break_fsm_ops =
+{
+ NULL, /* dtor */
+ until_break_fsm_clean_up,
+ until_break_fsm_should_stop,
+ NULL, /* return_value */
+ until_break_fsm_async_reply_reason,
+};
+
+/* Allocate a new until_break_command_fsm. */
+
+static struct until_break_fsm *
+new_until_break_fsm (struct interp *cmd_interp, int thread,
+ struct breakpoint *location_breakpoint,
+ struct breakpoint *caller_breakpoint)
+{
+ struct until_break_fsm *sm;
+
+ sm = XCNEW (struct until_break_fsm);
+ thread_fsm_ctor (&sm->thread_fsm, &until_break_fsm_ops, cmd_interp);
+
+ sm->thread = thread;
+ sm->location_breakpoint = location_breakpoint;
+ sm->caller_breakpoint = caller_breakpoint;
+
+ return sm;
+}
+
+/* Implementation of the 'should_stop' FSM method for the
+ until(location)/advance commands. */
+
+static int
+until_break_fsm_should_stop (struct thread_fsm *self,
+ struct thread_info *tp)
+{
+ struct until_break_fsm *sm = (struct until_break_fsm *) self;
+
+ if (bpstat_find_breakpoint (tp->control.stop_bpstat,
+ sm->location_breakpoint) != NULL
+ || (sm->caller_breakpoint != NULL
+ && bpstat_find_breakpoint (tp->control.stop_bpstat,
+ sm->caller_breakpoint) != NULL))
+ thread_fsm_set_finished (self);
+
+ return 1;
+}
-struct until_break_command_continuation_args
-{
- struct breakpoint *breakpoint;
- struct breakpoint *breakpoint2;
- int thread_num;
-};
+/* Implementation of the 'clean_up' FSM method for the
+ until(location)/advance commands. */
-/* This function is called by fetch_inferior_event via the
- cmd_continuation pointer, to complete the until command. It takes
- care of cleaning up the temporary breakpoints set up by the until
- command. */
static void
-until_break_command_continuation (void *arg, int err)
+until_break_fsm_clean_up (struct thread_fsm *self,
+ struct thread_info *thread)
{
- struct until_break_command_continuation_args *a = arg;
+ struct until_break_fsm *sm = (struct until_break_fsm *) self;
+
+ /* Clean up our temporary breakpoints. */
+ if (sm->location_breakpoint != NULL)
+ {
+ delete_breakpoint (sm->location_breakpoint);
+ sm->location_breakpoint = NULL;
+ }
+ if (sm->caller_breakpoint != NULL)
+ {
+ delete_breakpoint (sm->caller_breakpoint);
+ sm->caller_breakpoint = NULL;
+ }
+ delete_longjmp_breakpoint (sm->thread);
+}
- delete_breakpoint (a->breakpoint);
- if (a->breakpoint2)
- delete_breakpoint (a->breakpoint2);
- delete_longjmp_breakpoint (a->thread_num);
+/* Implementation of the 'async_reply_reason' FSM method for the
+ until(location)/advance commands. */
+
+static enum async_reply_reason
+until_break_fsm_async_reply_reason (struct thread_fsm *self)
+{
+ return EXEC_ASYNC_LOCATION_REACHED;
}
void
struct gdbarch *frame_gdbarch;
struct frame_id stack_frame_id;
struct frame_id caller_frame_id;
- struct breakpoint *breakpoint;
- struct breakpoint *breakpoint2 = NULL;
- struct cleanup *old_chain;
+ struct breakpoint *location_breakpoint;
+ struct breakpoint *caller_breakpoint = NULL;
+ struct cleanup *old_chain, *cleanup;
int thread;
struct thread_info *tp;
+ struct event_location *location;
+ struct until_break_fsm *sm;
clear_proceed_status (0);
/* Set a breakpoint where the user wants it and at return from
this function. */
+ location = string_to_event_location (&arg, current_language);
+ cleanup = make_cleanup_delete_event_location (location);
+
if (last_displayed_sal_is_valid ())
- sals = decode_line_1 (&arg, DECODE_LINE_FUNFIRSTLINE,
+ sals = decode_line_1 (location, DECODE_LINE_FUNFIRSTLINE, NULL,
get_last_displayed_symtab (),
get_last_displayed_line ());
else
- sals = decode_line_1 (&arg, DECODE_LINE_FUNFIRSTLINE,
- (struct symtab *) NULL, 0);
+ sals = decode_line_1 (location, DECODE_LINE_FUNFIRSTLINE,
+ NULL, (struct symtab *) NULL, 0);
if (sals.nelts != 1)
error (_("Couldn't get information on specified line."));
resolve_sal_pc (&sal);
tp = inferior_thread ();
- thread = tp->num;
+ thread = tp->global_num;
old_chain = make_cleanup (null_cleanup, NULL);
if (frame_id_p (caller_frame_id))
{
struct symtab_and_line sal2;
+ struct gdbarch *caller_gdbarch;
sal2 = find_pc_line (frame_unwind_caller_pc (frame), 0);
sal2.pc = frame_unwind_caller_pc (frame);
- breakpoint2 = set_momentary_breakpoint (frame_unwind_caller_arch (frame),
- sal2,
- caller_frame_id,
- bp_until);
- make_cleanup_delete_breakpoint (breakpoint2);
+ caller_gdbarch = frame_unwind_caller_arch (frame);
+ caller_breakpoint = set_momentary_breakpoint (caller_gdbarch,
+ sal2,
+ caller_frame_id,
+ bp_until);
+ make_cleanup_delete_breakpoint (caller_breakpoint);
set_longjmp_breakpoint (tp, caller_frame_id);
make_cleanup (delete_longjmp_breakpoint_cleanup, &thread);
if (anywhere)
/* If the user told us to continue until a specified location,
we don't specify a frame at which we need to stop. */
- breakpoint = set_momentary_breakpoint (frame_gdbarch, sal,
- null_frame_id, bp_until);
+ location_breakpoint = set_momentary_breakpoint (frame_gdbarch, sal,
+ null_frame_id, bp_until);
else
/* Otherwise, specify the selected frame, because we want to stop
only at the very same frame. */
- breakpoint = set_momentary_breakpoint (frame_gdbarch, sal,
- stack_frame_id, bp_until);
- make_cleanup_delete_breakpoint (breakpoint);
+ location_breakpoint = set_momentary_breakpoint (frame_gdbarch, sal,
+ stack_frame_id, bp_until);
+ make_cleanup_delete_breakpoint (location_breakpoint);
- proceed (-1, GDB_SIGNAL_DEFAULT, 0);
+ sm = new_until_break_fsm (command_interp (), tp->global_num,
+ location_breakpoint, caller_breakpoint);
+ tp->thread_fsm = &sm->thread_fsm;
- /* If we are running asynchronously, and proceed call above has
- actually managed to start the target, arrange for breakpoints to
- be deleted when the target stops. Otherwise, we're already
- stopped and delete breakpoints via cleanup chain. */
-
- if (target_can_async_p () && is_running (inferior_ptid))
- {
- struct until_break_command_continuation_args *args;
- args = xmalloc (sizeof (*args));
+ discard_cleanups (old_chain);
- args->breakpoint = breakpoint;
- args->breakpoint2 = breakpoint2;
- args->thread_num = thread;
+ proceed (-1, GDB_SIGNAL_DEFAULT);
- discard_cleanups (old_chain);
- add_continuation (inferior_thread (),
- until_break_command_continuation, args,
- xfree);
- }
- else
- do_cleanups (old_chain);
+ do_cleanups (cleanup);
}
/* This function attempts to parse an optional "if <cond>" clause
b->enable_state = enabled ? bp_enabled : bp_disabled;
b->disposition = tempflag ? disp_del : disp_donttouch;
- b->addr_string = addr_string;
+ b->location = string_to_event_location (&addr_string,
+ language_def (language_ada));
b->language = language_ada;
}
-/* Splits the argument using space as delimiter. Returns an xmalloc'd
- filter list, or NULL if no filtering is required. */
-static VEC(int) *
-catch_syscall_split_args (char *arg)
-{
- VEC(int) *result = NULL;
- struct cleanup *cleanup = make_cleanup (VEC_cleanup (int), &result);
- struct gdbarch *gdbarch = target_gdbarch ();
-
- while (*arg != '\0')
- {
- int i, syscall_number;
- char *endptr;
- char cur_name[128];
- struct syscall s;
-
- /* Skip whitespace. */
- arg = skip_spaces (arg);
-
- for (i = 0; i < 127 && arg[i] && !isspace (arg[i]); ++i)
- cur_name[i] = arg[i];
- cur_name[i] = '\0';
- arg += i;
-
- /* Check if the user provided a syscall name or a number. */
- syscall_number = (int) strtol (cur_name, &endptr, 0);
- if (*endptr == '\0')
- get_syscall_by_number (gdbarch, syscall_number, &s);
- else
- {
- /* We have a name. Let's check if it's valid and convert it
- to a number. */
- get_syscall_by_name (gdbarch, cur_name, &s);
-
- if (s.number == UNKNOWN_SYSCALL)
- /* Here we have to issue an error instead of a warning,
- because GDB cannot do anything useful if there's no
- syscall number to be caught. */
- error (_("Unknown syscall name '%s'."), cur_name);
- }
-
- /* Ok, it's valid. */
- VEC_safe_push (int, result, s.number);
- }
-
- discard_cleanups (cleanup);
- return result;
-}
-
-/* Implement the "catch syscall" command. */
-
-static void
-catch_syscall_command_1 (char *arg, int from_tty,
- struct cmd_list_element *command)
-{
- int tempflag;
- VEC(int) *filter;
- struct syscall s;
- struct gdbarch *gdbarch = get_current_arch ();
-
- /* Checking if the feature if supported. */
- if (gdbarch_get_syscall_number_p (gdbarch) == 0)
- error (_("The feature 'catch syscall' is not supported on \
-this architecture yet."));
-
- tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
-
- arg = skip_spaces (arg);
-
- /* We need to do this first "dummy" translation in order
- to get the syscall XML file loaded or, most important,
- to display a warning to the user if there's no XML file
- for his/her architecture. */
- get_syscall_by_number (gdbarch, 0, &s);
-
- /* The allowed syntax is:
- catch syscall
- catch syscall <name | number> [<name | number> ... <name | number>]
-
- Let's check if there's a syscall name. */
-
- if (arg != NULL)
- filter = catch_syscall_split_args (arg);
- else
- filter = NULL;
-
- create_syscall_event_catchpoint (tempflag, filter,
- &catch_syscall_breakpoint_ops);
-}
-
static void
catch_command (char *arg, int from_tty)
{
static int
compare_breakpoints (const void *a, const void *b)
{
- const breakpoint_p *ba = a;
+ const breakpoint_p *ba = (const breakpoint_p *) a;
uintptr_t ua = (uintptr_t) *ba;
- const breakpoint_p *bb = b;
+ const breakpoint_p *bb = (const breakpoint_p *) b;
uintptr_t ub = (uintptr_t) *bb;
if ((*ba)->number < (*bb)->number)
}
else
{
- sals.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
+ sals.sals = XNEW (struct symtab_and_line);
make_cleanup (xfree, sals.sals);
init_sal (&sal); /* Initialize to zeroes. */
static int
bp_location_compare (const void *ap, const void *bp)
{
- struct bp_location *a = *(void **) ap;
- struct bp_location *b = *(void **) bp;
+ const struct bp_location *a = *(const struct bp_location **) ap;
+ const struct bp_location *b = *(const struct bp_location **) bp;
if (a->address != b->address)
return (a->address > b->address) - (a->address < b->address);
{
struct breakpoint *b;
struct cleanup *old_chain;
-
- if (!target_can_download_tracepoint ())
- return;
+ enum tribool can_download_tracepoint = TRIBOOL_UNKNOWN;
old_chain = save_current_space_and_thread ();
: !may_insert_tracepoints))
continue;
+ if (can_download_tracepoint == TRIBOOL_UNKNOWN)
+ {
+ if (target_can_download_tracepoint ())
+ can_download_tracepoint = TRIBOOL_TRUE;
+ else
+ can_download_tracepoint = TRIBOOL_FALSE;
+ }
+
+ if (can_download_tracepoint == TRIBOOL_FALSE)
+ break;
+
for (bl = b->loc; bl; bl = bl->next)
{
/* In tracepoint, locations are _never_ duplicated, so
for (loc = b->loc; loc; loc = loc->next)
bp_location_count++;
- bp_location = xmalloc (sizeof (*bp_location) * bp_location_count);
+ bp_location = XNEWVEC (struct bp_location *, bp_location_count);
locp = bp_location;
ALL_BREAKPOINTS (b)
for (loc = b->loc; loc; loc = loc->next)
if (!keep_in_target)
{
- if (remove_breakpoint (old_loc, mark_uninserted))
+ if (remove_breakpoint (old_loc))
{
/* This is just about all we can do. We could keep
this location on the global list, and try to
if (!found_object)
{
- if (removed && non_stop
+ if (removed && target_is_non_stop_p ()
&& need_moribund_for_location_type (old_loc))
{
/* This location was removed from the target. In
continue;
}
- /* Permanent breakpoint should always be inserted. */
- if (loc->permanent && ! loc->inserted)
- internal_error (__FILE__, __LINE__,
- _("allegedly permanent breakpoint is not "
- "actually inserted"));
-
if (b->type == bp_hardware_watchpoint)
loc_first_p = &wp_loc_first;
else if (b->type == bp_read_watchpoint)
/* Clear the condition modification flag. */
loc->condition_changed = condition_unchanged;
-
- if (loc->inserted && !loc->permanent
- && (*loc_first_p)->permanent)
- internal_error (__FILE__, __LINE__,
- _("another breakpoint was inserted on top of "
- "a permanent breakpoint"));
}
if (insert_mode == UGLL_INSERT || breakpoints_should_be_inserted_now ())
static int
bpstat_remove_breakpoint_callback (struct thread_info *th, void *data)
{
- struct breakpoint *bpt = data;
+ struct breakpoint *bpt = (struct breakpoint *) data;
bpstat_remove_bp_location (th->control.stop_bpstat, bpt);
return 0;
single string. */
if (b->loc == NULL)
{
- printf_filtered (_(" (%s) pending."), b->addr_string);
+ /* For pending locations, the output differs slightly based
+ on b->extra_string. If this is non-NULL, it contains either
+ a condition or dprintf arguments. */
+ if (b->extra_string == NULL)
+ {
+ printf_filtered (_(" (%s) pending."),
+ event_location_to_string (b->location));
+ }
+ else if (b->type == bp_dprintf)
+ {
+ printf_filtered (_(" (%s,%s) pending."),
+ event_location_to_string (b->location),
+ b->extra_string);
+ }
+ else
+ {
+ printf_filtered (_(" (%s %s) pending."),
+ event_location_to_string (b->location),
+ b->extra_string);
+ }
}
else
{
/* This is not ideal, but each location may have a
different file name, and this at least reflects the
real situation somewhat. */
- printf_filtered (": %s.", b->addr_string);
+ printf_filtered (": %s.",
+ event_location_to_string (b->location));
}
if (b->loc->next)
decref_counted_command_line (&self->commands);
xfree (self->cond_string);
xfree (self->extra_string);
- xfree (self->addr_string);
xfree (self->filter);
- xfree (self->addr_string_range_end);
+ delete_event_location (self->location);
+ delete_event_location (self->location_range_end);
}
static struct bp_location *
}
static int
-base_breakpoint_remove_location (struct bp_location *bl)
+base_breakpoint_remove_location (struct bp_location *bl,
+ enum remove_bp_reason reason)
{
internal_error_pure_virtual_called ();
}
}
static void
-base_breakpoint_create_sals_from_address (char **arg,
- struct linespec_result *canonical,
- enum bptype type_wanted,
- char *addr_start,
- char **copy_arg)
+base_breakpoint_create_sals_from_location
+ (const struct event_location *location,
+ struct linespec_result *canonical,
+ enum bptype type_wanted)
{
internal_error_pure_virtual_called ();
}
}
static void
-base_breakpoint_decode_linespec (struct breakpoint *b, char **s,
+base_breakpoint_decode_location (struct breakpoint *b,
+ const struct event_location *location,
+ struct program_space *search_pspace,
struct symtabs_and_lines *sals)
{
internal_error_pure_virtual_called ();
base_breakpoint_print_one_detail,
base_breakpoint_print_mention,
base_breakpoint_print_recreate,
- base_breakpoint_create_sals_from_address,
+ base_breakpoint_create_sals_from_location,
base_breakpoint_create_breakpoints_sal,
- base_breakpoint_decode_linespec,
+ base_breakpoint_decode_location,
base_breakpoint_explains_signal,
base_breakpoint_after_condition_true,
};
bkpt_re_set (struct breakpoint *b)
{
/* FIXME: is this still reachable? */
- if (b->addr_string == NULL)
+ if (breakpoint_event_location_empty_p (b))
{
- /* Anything without a string can't be re-set. */
+ /* Anything without a location can't be re-set. */
delete_breakpoint (b);
return;
}
static int
bkpt_insert_location (struct bp_location *bl)
{
+ CORE_ADDR addr = bl->target_info.reqstd_address;
+
+ bl->target_info.kind = breakpoint_kind (bl, &addr);
+ bl->target_info.placed_address = addr;
+
if (bl->loc_type == bp_loc_hardware_breakpoint)
return target_insert_hw_breakpoint (bl->gdbarch, &bl->target_info);
else
}
static int
-bkpt_remove_location (struct bp_location *bl)
+bkpt_remove_location (struct bp_location *bl, enum remove_bp_reason reason)
{
if (bl->loc_type == bp_loc_hardware_breakpoint)
return target_remove_hw_breakpoint (bl->gdbarch, &bl->target_info);
else
- return target_remove_breakpoint (bl->gdbarch, &bl->target_info);
+ return target_remove_breakpoint (bl->gdbarch, &bl->target_info, reason);
}
static int
bl->address,
b->number, 1);
annotate_breakpoint (b->number);
+ maybe_print_thread_hit_breakpoint (uiout);
+
if (bp_temp)
- ui_out_text (uiout, "\nTemporary breakpoint ");
+ ui_out_text (uiout, "Temporary breakpoint ");
else
- ui_out_text (uiout, "\nBreakpoint ");
+ ui_out_text (uiout, "Breakpoint ");
if (ui_out_is_mi_like_p (uiout))
{
ui_out_field_string (uiout, "reason",
internal_error (__FILE__, __LINE__,
_("unhandled breakpoint type %d"), (int) tp->type);
- fprintf_unfiltered (fp, " %s", tp->addr_string);
+ fprintf_unfiltered (fp, " %s",
+ event_location_to_string (tp->location));
+
+ /* Print out extra_string if this breakpoint is pending. It might
+ contain, for example, conditions that were set by the user. */
+ if (tp->loc == NULL && tp->extra_string != NULL)
+ fprintf_unfiltered (fp, " %s", tp->extra_string);
+
print_recreate_thread (tp, fp);
}
static void
-bkpt_create_sals_from_address (char **arg,
- struct linespec_result *canonical,
- enum bptype type_wanted,
- char *addr_start, char **copy_arg)
+bkpt_create_sals_from_location (const struct event_location *location,
+ struct linespec_result *canonical,
+ enum bptype type_wanted)
{
- create_sals_from_address_default (arg, canonical, type_wanted,
- addr_start, copy_arg);
+ create_sals_from_location_default (location, canonical, type_wanted);
}
static void
}
static void
-bkpt_decode_linespec (struct breakpoint *b, char **s,
+bkpt_decode_location (struct breakpoint *b,
+ const struct event_location *location,
+ struct program_space *search_pspace,
struct symtabs_and_lines *sals)
{
- decode_linespec_default (b, s, sals);
+ decode_location_default (b, location, search_pspace, sals);
}
/* Virtual table for internal breakpoints. */
static enum print_stop_action
momentary_bkpt_print_it (bpstat bs)
{
- struct ui_out *uiout = current_uiout;
-
- if (ui_out_is_mi_like_p (uiout))
- {
- struct breakpoint *b = bs->breakpoint_at;
-
- switch (b->type)
- {
- case bp_finish:
- ui_out_field_string
- (uiout, "reason",
- async_reason_lookup (EXEC_ASYNC_FUNCTION_FINISHED));
- break;
-
- case bp_until:
- ui_out_field_string
- (uiout, "reason",
- async_reason_lookup (EXEC_ASYNC_LOCATION_REACHED));
- break;
- }
- }
-
return PRINT_UNKNOWN;
}
static void
longjmp_bkpt_dtor (struct breakpoint *self)
{
- struct thread_info *tp = find_thread_id (self->thread);
+ struct thread_info *tp = find_thread_global_id (self->thread);
if (tp)
tp->initiating_frame = null_frame_id;
}
static int
-bkpt_probe_remove_location (struct bp_location *bl)
+bkpt_probe_remove_location (struct bp_location *bl,
+ enum remove_bp_reason reason)
{
/* Let's clear the semaphore before removing the location. */
if (bl->probe.probe->pops->clear_semaphore != NULL)
bl->probe.objfile,
bl->gdbarch);
- return bkpt_remove_location (bl);
+ return bkpt_remove_location (bl, reason);
}
static void
-bkpt_probe_create_sals_from_address (char **arg,
- struct linespec_result *canonical,
- enum bptype type_wanted,
- char *addr_start, char **copy_arg)
+bkpt_probe_create_sals_from_location (const struct event_location *location,
+ struct linespec_result *canonical,
+ enum bptype type_wanted)
{
struct linespec_sals lsal;
- lsal.sals = parse_probes (arg, canonical);
-
- *copy_arg = xstrdup (canonical->addr_string);
- lsal.canonical = xstrdup (*copy_arg);
-
+ lsal.sals = parse_probes (location, NULL, canonical);
+ lsal.canonical = xstrdup (event_location_to_string (canonical->location));
VEC_safe_push (linespec_sals, canonical->sals, &lsal);
}
static void
-bkpt_probe_decode_linespec (struct breakpoint *b, char **s,
+bkpt_probe_decode_location (struct breakpoint *b,
+ const struct event_location *location,
+ struct program_space *search_pspace,
struct symtabs_and_lines *sals)
{
- *sals = parse_probes (s, NULL);
+ *sals = parse_probes (location, search_pspace, NULL);
if (!sals->sals)
error (_("probe not found"));
}
if (self->type == bp_fast_tracepoint)
fprintf_unfiltered (fp, "ftrace");
- if (self->type == bp_static_tracepoint)
+ else if (self->type == bp_static_tracepoint)
fprintf_unfiltered (fp, "strace");
else if (self->type == bp_tracepoint)
fprintf_unfiltered (fp, "trace");
internal_error (__FILE__, __LINE__,
_("unhandled tracepoint type %d"), (int) self->type);
- fprintf_unfiltered (fp, " %s", self->addr_string);
+ fprintf_unfiltered (fp, " %s",
+ event_location_to_string (self->location));
print_recreate_thread (self, fp);
if (tp->pass_count)
}
static void
-tracepoint_create_sals_from_address (char **arg,
- struct linespec_result *canonical,
- enum bptype type_wanted,
- char *addr_start, char **copy_arg)
+tracepoint_create_sals_from_location (const struct event_location *location,
+ struct linespec_result *canonical,
+ enum bptype type_wanted)
{
- create_sals_from_address_default (arg, canonical, type_wanted,
- addr_start, copy_arg);
+ create_sals_from_location_default (location, canonical, type_wanted);
}
static void
}
static void
-tracepoint_decode_linespec (struct breakpoint *b, char **s,
+tracepoint_decode_location (struct breakpoint *b,
+ const struct event_location *location,
+ struct program_space *search_pspace,
struct symtabs_and_lines *sals)
{
- decode_linespec_default (b, s, sals);
+ decode_location_default (b, location, search_pspace, sals);
}
struct breakpoint_ops tracepoint_breakpoint_ops;
static probe. */
static void
-tracepoint_probe_create_sals_from_address (char **arg,
- struct linespec_result *canonical,
- enum bptype type_wanted,
- char *addr_start, char **copy_arg)
+tracepoint_probe_create_sals_from_location
+ (const struct event_location *location,
+ struct linespec_result *canonical,
+ enum bptype type_wanted)
{
/* We use the same method for breakpoint on probes. */
- bkpt_probe_create_sals_from_address (arg, canonical, type_wanted,
- addr_start, copy_arg);
+ bkpt_probe_create_sals_from_location (location, canonical, type_wanted);
}
static void
-tracepoint_probe_decode_linespec (struct breakpoint *b, char **s,
+tracepoint_probe_decode_location (struct breakpoint *b,
+ const struct event_location *location,
+ struct program_space *search_pspace,
struct symtabs_and_lines *sals)
{
/* We use the same method for breakpoint on probes. */
- bkpt_probe_decode_linespec (b, s, sals);
+ bkpt_probe_decode_location (b, location, search_pspace, sals);
}
static struct breakpoint_ops tracepoint_probe_breakpoint_ops;
{
breakpoint_re_set_default (b);
- /* This breakpoint could have been pending, and be resolved now, and
- if so, we should now have the extra string. If we don't, the
- dprintf was malformed when created, but we couldn't tell because
- we can't extract the extra string until the location is
- resolved. */
- if (b->loc != NULL && b->extra_string == NULL)
- error (_("Format string required"));
+ /* extra_string should never be non-NULL for dprintf. */
+ gdb_assert (b->extra_string != NULL);
/* 1 - connect to target 1, that can run breakpoint commands.
2 - create a dprintf, which resolves fine.
static void
dprintf_print_recreate (struct breakpoint *tp, struct ui_file *fp)
{
- fprintf_unfiltered (fp, "dprintf %s%s", tp->addr_string,
+ fprintf_unfiltered (fp, "dprintf %s,%s",
+ event_location_to_string (tp->location),
tp->extra_string);
print_recreate_thread (tp, fp);
}
markers (`-m'). */
static void
-strace_marker_create_sals_from_address (char **arg,
- struct linespec_result *canonical,
- enum bptype type_wanted,
- char *addr_start, char **copy_arg)
+strace_marker_create_sals_from_location (const struct event_location *location,
+ struct linespec_result *canonical,
+ enum bptype type_wanted)
{
struct linespec_sals lsal;
+ const char *arg_start, *arg;
+ char *str;
+ struct cleanup *cleanup;
- lsal.sals = decode_static_tracepoint_spec (arg);
+ arg = arg_start = get_linespec_location (location);
+ lsal.sals = decode_static_tracepoint_spec (&arg);
- *copy_arg = savestring (addr_start, *arg - addr_start);
+ str = savestring (arg_start, arg - arg_start);
+ cleanup = make_cleanup (xfree, str);
+ canonical->location = new_linespec_location (&str);
+ do_cleanups (cleanup);
- canonical->addr_string = xstrdup (*copy_arg);
- lsal.canonical = xstrdup (*copy_arg);
+ lsal.canonical = xstrdup (event_location_to_string (canonical->location));
VEC_safe_push (linespec_sals, canonical->sals, &lsal);
}
struct symtabs_and_lines expanded;
struct tracepoint *tp;
struct cleanup *old_chain;
- char *addr_string;
+ struct event_location *location;
expanded.nelts = 1;
expanded.sals = &lsal->sals.sals[i];
- addr_string = xstrdup (canonical->addr_string);
- old_chain = make_cleanup (xfree, addr_string);
+ location = copy_event_location (canonical->location);
+ old_chain = make_cleanup_delete_event_location (location);
tp = XCNEW (struct tracepoint);
init_breakpoint_sal (&tp->base, gdbarch, expanded,
- addr_string, NULL,
+ location, NULL,
cond_string, extra_string,
type_wanted, disposition,
thread, task, ignore_count, ops,
}
static void
-strace_marker_decode_linespec (struct breakpoint *b, char **s,
+strace_marker_decode_location (struct breakpoint *b,
+ const struct event_location *location,
+ struct program_space *search_pspace,
struct symtabs_and_lines *sals)
{
struct tracepoint *tp = (struct tracepoint *) b;
+ const char *s = get_linespec_location (location);
- *sals = decode_static_tracepoint_spec (s);
+ *sals = decode_static_tracepoint_spec (&s);
if (sals->nelts > tp->static_trace_marker_id_idx)
{
sals->sals[0] = sals->sals[tp->static_trace_marker_id_idx];
static void
do_delete_breakpoint_cleanup (void *b)
{
- delete_breakpoint (b);
+ delete_breakpoint ((struct breakpoint *) b);
}
struct cleanup *
map_breakpoint_numbers (arg, do_map_delete_breakpoint, NULL);
}
+/* Return true if all locations of B bound to PSPACE are pending. If
+ PSPACE is NULL, all locations of all program spaces are
+ considered. */
+
static int
-all_locations_are_pending (struct bp_location *loc)
+all_locations_are_pending (struct breakpoint *b, struct program_space *pspace)
{
- for (; loc; loc = loc->next)
- if (!loc->shlib_disabled
+ struct bp_location *loc;
+
+ for (loc = b->loc; loc != NULL; loc = loc->next)
+ if ((pspace == NULL
+ || loc->pspace == pspace)
+ && !loc->shlib_disabled
&& !loc->pspace->executing_startup)
return 0;
return 1;
struct symbol *sym;
struct static_tracepoint_marker *tpmarker;
struct ui_out *uiout = current_uiout;
+ struct explicit_location explicit_loc;
tpmarker = VEC_index (static_tracepoint_marker_p, markers, 0);
b->loc->line_number = sal2.line;
b->loc->symtab = sym != NULL ? sal2.symtab : NULL;
- xfree (b->addr_string);
- b->addr_string = xstrprintf ("%s:%d",
- symtab_to_filename_for_display (sal2.symtab),
- b->loc->line_number);
+ delete_event_location (b->location);
+ initialize_explicit_location (&explicit_loc);
+ explicit_loc.source_filename
+ = ASTRDUP (symtab_to_filename_for_display (sal2.symtab));
+ explicit_loc.line_offset.offset = b->loc->line_number;
+ explicit_loc.line_offset.sign = LINE_OFFSET_NONE;
+ b->location = new_explicit_location (&explicit_loc);
/* Might be nice to check if function changed, and warn if
so. */
return 1;
}
-/* Create new breakpoint locations for B (a hardware or software breakpoint)
- based on SALS and SALS_END. If SALS_END.NELTS is not zero, then B is
- a ranged breakpoint. */
+/* Split all locations of B that are bound to PSPACE out of B's
+ location list to a separate list and return that list's head. If
+ PSPACE is NULL, hoist out all locations of B. */
+
+static struct bp_location *
+hoist_existing_locations (struct breakpoint *b, struct program_space *pspace)
+{
+ struct bp_location head;
+ struct bp_location *i = b->loc;
+ struct bp_location **i_link = &b->loc;
+ struct bp_location *hoisted = &head;
+
+ if (pspace == NULL)
+ {
+ i = b->loc;
+ b->loc = NULL;
+ return i;
+ }
+
+ head.next = NULL;
+
+ while (i != NULL)
+ {
+ if (i->pspace == pspace)
+ {
+ *i_link = i->next;
+ i->next = NULL;
+ hoisted->next = i;
+ hoisted = i;
+ }
+ else
+ i_link = &i->next;
+ i = *i_link;
+ }
+
+ return head.next;
+}
+
+/* Create new breakpoint locations for B (a hardware or software
+ breakpoint) based on SALS and SALS_END. If SALS_END.NELTS is not
+ zero, then B is a ranged breakpoint. Only recreates locations for
+ FILTER_PSPACE. Locations of other program spaces are left
+ untouched. */
void
update_breakpoint_locations (struct breakpoint *b,
+ struct program_space *filter_pspace,
struct symtabs_and_lines sals,
struct symtabs_and_lines sals_end)
{
int i;
- struct bp_location *existing_locations = b->loc;
+ struct bp_location *existing_locations;
if (sals_end.nelts != 0 && (sals.nelts != 1 || sals_end.nelts != 1))
{
/* Ranged breakpoints have only one start location and one end
location. */
b->enable_state = bp_disabled;
- update_global_location_list (UGLL_MAY_INSERT);
printf_unfiltered (_("Could not reset ranged breakpoint %d: "
"multiple locations found\n"),
b->number);
We'd like to retain the location, so that when the library is
loaded again, we don't loose the enabled/disabled status of the
individual locations. */
- if (all_locations_are_pending (existing_locations) && sals.nelts == 0)
+ if (all_locations_are_pending (b, filter_pspace) && sals.nelts == 0)
return;
- b->loc = NULL;
+ existing_locations = hoist_existing_locations (b, filter_pspace);
for (i = 0; i < sals.nelts; ++i)
{
if (!locations_are_equal (existing_locations, b->loc))
observer_notify_breakpoint_modified (b);
-
- update_global_location_list (UGLL_MAY_INSERT);
}
-/* Find the SaL locations corresponding to the given ADDR_STRING.
+/* Find the SaL locations corresponding to the given LOCATION.
On return, FOUND will be 1 if any SaL was found, zero otherwise. */
static struct symtabs_and_lines
-addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found)
+location_to_sals (struct breakpoint *b, struct event_location *location,
+ struct program_space *search_pspace, int *found)
{
- char *s;
struct symtabs_and_lines sals = {0};
struct gdb_exception exception = exception_none;
gdb_assert (b->ops != NULL);
- s = addr_string;
TRY
{
- b->ops->decode_linespec (b, &s, &sals);
+ b->ops->decode_location (b, location, search_pspace, &sals);
}
CATCH (e, RETURN_MASK_ERROR)
{
breakpoint being disabled, and don't want to see more
errors. */
if (e.error == NOT_FOUND_ERROR
- && (b->condition_not_parsed
+ && (b->condition_not_parsed
+ || (b->loc != NULL
+ && search_pspace != NULL
+ && b->loc->pspace != search_pspace)
|| (b->loc && b->loc->shlib_disabled)
|| (b->loc && b->loc->pspace->executing_startup)
|| b->enable_state == bp_disabled))
for (i = 0; i < sals.nelts; ++i)
resolve_sal_pc (&sals.sals[i]);
- if (b->condition_not_parsed && s && s[0])
+ if (b->condition_not_parsed && b->extra_string != NULL)
{
char *cond_string, *extra_string;
int thread, task;
- find_condition_and_thread (s, sals.sals[0].pc,
+ find_condition_and_thread (b->extra_string, sals.sals[0].pc,
&cond_string, &thread, &task,
&extra_string);
+ gdb_assert (b->cond_string == NULL);
if (cond_string)
b->cond_string = cond_string;
b->thread = thread;
b->task = task;
if (extra_string)
- b->extra_string = extra_string;
+ {
+ xfree (b->extra_string);
+ b->extra_string = extra_string;
+ }
b->condition_not_parsed = 0;
}
struct symtabs_and_lines sals, sals_end;
struct symtabs_and_lines expanded = {0};
struct symtabs_and_lines expanded_end = {0};
+ struct program_space *filter_pspace = current_program_space;
- sals = addr_string_to_sals (b, b->addr_string, &found);
+ sals = location_to_sals (b, b->location, filter_pspace, &found);
if (found)
{
make_cleanup (xfree, sals.sals);
expanded = sals;
}
- if (b->addr_string_range_end)
+ if (b->location_range_end != NULL)
{
- sals_end = addr_string_to_sals (b, b->addr_string_range_end, &found);
+ sals_end = location_to_sals (b, b->location_range_end,
+ filter_pspace, &found);
if (found)
{
make_cleanup (xfree, sals_end.sals);
}
}
- update_breakpoint_locations (b, expanded, expanded_end);
+ update_breakpoint_locations (b, filter_pspace, expanded, expanded_end);
}
/* Default method for creating SALs from an address string. It basically
calls parse_breakpoint_sals. Return 1 for success, zero for failure. */
static void
-create_sals_from_address_default (char **arg,
- struct linespec_result *canonical,
- enum bptype type_wanted,
- char *addr_start, char **copy_arg)
+create_sals_from_location_default (const struct event_location *location,
+ struct linespec_result *canonical,
+ enum bptype type_wanted)
{
- parse_breakpoint_sals (arg, canonical);
+ parse_breakpoint_sals (location, canonical);
}
/* Call create_breakpoints_sal for the given arguments. This is the default
}
/* Decode the line represented by S by calling decode_line_full. This is the
- default function for the `decode_linespec' method of breakpoint_ops. */
+ default function for the `decode_location' method of breakpoint_ops. */
static void
-decode_linespec_default (struct breakpoint *b, char **s,
+decode_location_default (struct breakpoint *b,
+ const struct event_location *location,
+ struct program_space *search_pspace,
struct symtabs_and_lines *sals)
{
struct linespec_result canonical;
init_linespec_result (&canonical);
- decode_line_full (s, DECODE_LINE_FUNFIRSTLINE,
+ decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, search_pspace,
(struct symtab *) NULL, 0,
&canonical, multiple_symbols_all,
b->filter);
static struct cleanup *
prepare_re_set_context (struct breakpoint *b)
{
- struct cleanup *cleanups;
-
input_radix = b->input_radix;
- cleanups = save_current_space_and_thread ();
- if (b->pspace != NULL)
- switch_to_program_space_and_thread (b->pspace);
set_language (b->language);
- return cleanups;
+ return make_cleanup (null_cleanup, NULL);
}
/* Reset a breakpoint given it's struct breakpoint * BINT.
return 0;
}
-/* Re-set all breakpoints after symbols have been re-loaded. */
+/* Re-set breakpoint locations for the current program space.
+ Locations bound to other program spaces are left untouched. */
+
void
breakpoint_re_set (void)
{
save_language = current_language->la_language;
save_input_radix = input_radix;
- old_chain = save_current_program_space ();
+ old_chain = save_current_space_and_thread ();
+
+ /* Note: we must not try to insert locations until after all
+ breakpoints have been re-set. Otherwise, e.g., when re-setting
+ breakpoint 1, we'd insert the locations of breakpoint 2, which
+ hadn't been re-set yet, and thus may have stale locations. */
ALL_BREAKPOINTS_SAFE (b, b_tmp)
{
create_longjmp_master_breakpoint ();
create_std_terminate_master_breakpoint ();
create_exception_master_breakpoint ();
+
+ /* Now we can insert. */
+ update_global_location_list (UGLL_MAY_INSERT);
}
\f
/* Reset the thread number of this breakpoint:
if (b->thread != -1)
{
if (in_thread_list (inferior_ptid))
- b->thread = pid_to_thread_id (inferior_ptid);
+ b->thread = ptid_to_global_thread_id (inferior_ptid);
/* We're being called after following a fork. The new fork is
selected as current, and unless this was a vfork will have a
{
int num;
struct breakpoint *b, *tmp;
- int match;
- struct get_number_or_range_state state;
if (args == 0 || *args == '\0')
error_no_arg (_("one or more breakpoint numbers"));
- init_number_or_range (&state, args);
+ number_or_range_parser parser (args);
- while (!state.finished)
+ while (!parser.finished ())
{
- const char *p = state.string;
-
- match = 0;
+ const char *p = parser.cur_tok ();
+ bool match = false;
- num = get_number_or_range (&state);
+ num = parser.get_number ();
if (num == 0)
{
warning (_("bad breakpoint number at or near '%s'"), p);
ALL_BREAKPOINTS_SAFE (b, tmp)
if (b->number == num)
{
- match = 1;
+ match = true;
function (b, data);
break;
}
- if (match == 0)
+ if (!match)
printf_unfiltered (_("No breakpoint number %d.\n"), num);
}
}
if (is_watchpoint (bpt))
{
/* Initialize it just to avoid a GCC false warning. */
- enum enable_state orig_enable_state = 0;
+ enum enable_state orig_enable_state = bp_disabled;
TRY
{
if (tp->control.single_step_breakpoints == NULL)
{
tp->control.single_step_breakpoints
- = new_single_step_breakpoint (tp->num, gdbarch);
+ = new_single_step_breakpoint (tp->global_num, gdbarch);
}
sal = find_pc_line (pc, 0);
update_global_location_list (UGLL_INSERT);
}
+/* Insert single step breakpoints according to the current state. */
+
+int
+insert_single_step_breakpoints (struct gdbarch *gdbarch)
+{
+ struct frame_info *frame = get_current_frame ();
+ VEC (CORE_ADDR) * next_pcs;
+
+ next_pcs = gdbarch_software_single_step (gdbarch, frame);
+
+ if (next_pcs != NULL)
+ {
+ int i;
+ CORE_ADDR pc;
+ struct address_space *aspace = get_frame_address_space (frame);
+
+ for (i = 0; VEC_iterate (CORE_ADDR, next_pcs, i, pc); i++)
+ insert_single_step_breakpoint (gdbarch, aspace, pc);
+
+ VEC_free (CORE_ADDR, next_pcs);
+
+ return 1;
+ }
+ else
+ return 0;
+}
+
/* See breakpoint.h. */
int
return 0;
}
-/* Returns 0 if 'bp' is NOT a syscall catchpoint,
- non-zero otherwise. */
-static int
-is_syscall_catchpoint_enabled (struct breakpoint *bp)
-{
- if (syscall_catchpoint_p (bp)
- && bp->enable_state != bp_disabled
- && bp->enable_state != bp_call_disabled)
- return 1;
- else
- return 0;
-}
-
-int
-catch_syscall_enabled (void)
-{
- struct catch_syscall_inferior_data *inf_data
- = get_catch_syscall_inferior_data (current_inferior ());
-
- return inf_data->total_syscalls_count != 0;
-}
-
-int
-catching_syscall_number (int syscall_number)
-{
- struct breakpoint *bp;
-
- ALL_BREAKPOINTS (bp)
- if (is_syscall_catchpoint_enabled (bp))
- {
- struct syscall_catchpoint *c = (struct syscall_catchpoint *) bp;
-
- if (c->syscalls_to_be_caught)
- {
- int i, iter;
- for (i = 0;
- VEC_iterate (int, c->syscalls_to_be_caught, i, iter);
- i++)
- if (syscall_number == iter)
- return 1;
- }
- else
- return 1;
- }
-
- return 0;
-}
-
-/* Complete syscall names. Used by "catch syscall". */
-static VEC (char_ptr) *
-catch_syscall_completer (struct cmd_list_element *cmd,
- const char *text, const char *word)
-{
- const char **list = get_syscall_names (get_current_arch ());
- VEC (char_ptr) *retlist
- = (list == NULL) ? NULL : complete_on_enum (list, word, word);
-
- xfree (list);
- return retlist;
-}
-
/* Tracepoint-specific operations. */
/* Set tracepoint count to NUM. */
trace_command (char *arg, int from_tty)
{
struct breakpoint_ops *ops;
- const char *arg_cp = arg;
+ struct event_location *location;
+ struct cleanup *back_to;
- if (arg && probe_linespec_to_ops (&arg_cp))
+ location = string_to_event_location (&arg, current_language);
+ back_to = make_cleanup_delete_event_location (location);
+ if (location != NULL
+ && event_location_type (location) == PROBE_LOCATION)
ops = &tracepoint_probe_breakpoint_ops;
else
ops = &tracepoint_breakpoint_ops;
create_breakpoint (get_current_arch (),
- arg,
- NULL, 0, NULL, 1 /* parse arg */,
+ location,
+ NULL, 0, arg, 1 /* parse arg */,
0 /* tempflag */,
bp_tracepoint /* type_wanted */,
0 /* Ignore count */,
from_tty,
1 /* enabled */,
0 /* internal */, 0);
+ do_cleanups (back_to);
}
static void
ftrace_command (char *arg, int from_tty)
{
+ struct event_location *location;
+ struct cleanup *back_to;
+
+ location = string_to_event_location (&arg, current_language);
+ back_to = make_cleanup_delete_event_location (location);
create_breakpoint (get_current_arch (),
- arg,
- NULL, 0, NULL, 1 /* parse arg */,
+ location,
+ NULL, 0, arg, 1 /* parse arg */,
0 /* tempflag */,
bp_fast_tracepoint /* type_wanted */,
0 /* Ignore count */,
from_tty,
1 /* enabled */,
0 /* internal */, 0);
+ do_cleanups (back_to);
}
/* strace command implementation. Creates a static tracepoint. */
strace_command (char *arg, int from_tty)
{
struct breakpoint_ops *ops;
+ struct event_location *location;
+ struct cleanup *back_to;
/* Decide if we are dealing with a static tracepoint marker (`-m'),
or with a normal static tracepoint. */
if (arg && startswith (arg, "-m") && isspace (arg[2]))
- ops = &strace_marker_breakpoint_ops;
+ {
+ ops = &strace_marker_breakpoint_ops;
+ location = new_linespec_location (&arg);
+ }
else
- ops = &tracepoint_breakpoint_ops;
+ {
+ ops = &tracepoint_breakpoint_ops;
+ location = string_to_event_location (&arg, current_language);
+ }
+ back_to = make_cleanup_delete_event_location (location);
create_breakpoint (get_current_arch (),
- arg,
- NULL, 0, NULL, 1 /* parse arg */,
+ location,
+ NULL, 0, arg, 1 /* parse arg */,
0 /* tempflag */,
bp_static_tracepoint /* type_wanted */,
0 /* Ignore count */,
from_tty,
1 /* enabled */,
0 /* internal */, 0);
+ do_cleanups (back_to);
}
/* Set up a fake reader function that gets command lines from a linked
{
char *addr_str, small_buf[100];
struct tracepoint *tp;
+ struct event_location *location;
+ struct cleanup *cleanup;
if (utp->at_string)
addr_str = utp->at_string;
"has no source form, ignoring it"),
utp->number);
+ location = string_to_event_location (&addr_str, current_language);
+ cleanup = make_cleanup_delete_event_location (location);
if (!create_breakpoint (get_current_arch (),
- addr_str,
- utp->cond_string, -1, NULL,
+ location,
+ utp->cond_string, -1, addr_str,
0 /* parse cond/thread */,
0 /* tempflag */,
utp->type /* type_wanted */,
utp->enabled /* enabled */,
0 /* internal */,
CREATE_BREAKPOINT_FLAGS_INSERTED))
- return NULL;
+ {
+ do_cleanups (cleanup);
+ return NULL;
+ }
+
+ do_cleanups (cleanup);
/* Get the tracepoint we just created. */
tp = get_tracepoint (tracepoint_count);
}
else
{
- struct get_number_or_range_state state;
-
- init_number_or_range (&state, args);
- while (!state.finished)
+ number_or_range_parser parser (args);
+ while (!parser.finished ())
{
- t1 = get_tracepoint_by_number (&args, &state);
+ t1 = get_tracepoint_by_number (&args, &parser);
if (t1)
trace_pass_set_count (t1, count, from_tty);
}
struct tracepoint *
get_tracepoint_by_number (char **arg,
- struct get_number_or_range_state *state)
+ number_or_range_parser *parser)
{
struct breakpoint *t;
int tpnum;
char *instring = arg == NULL ? NULL : *arg;
- if (state)
+ if (parser != NULL)
{
- gdb_assert (!state->finished);
- tpnum = get_number_or_range (state);
+ gdb_assert (!parser->finished ());
+ tpnum = parser->get_number ();
}
else if (arg == NULL || *arg == NULL || ! **arg)
tpnum = tracepoint_count;
if (tp->type != bp_dprintf && tp->commands)
{
- struct gdb_exception exception;
-
fprintf_unfiltered (fp, " commands\n");
ui_out_redirect (current_uiout, fp);
}
\f
+/* This help string is used to consolidate all the help string for specifying
+ locations used by several commands. */
+
+#define LOCATION_HELP_STRING \
+"Linespecs are colon-separated lists of location parameters, such as\n\
+source filename, function name, label name, and line number.\n\
+Example: To specify the start of a label named \"the_top\" in the\n\
+function \"fact\" in the file \"factorial.c\", use\n\
+\"factorial.c:fact:the_top\".\n\
+\n\
+Address locations begin with \"*\" and specify an exact address in the\n\
+program. Example: To specify the fourth byte past the start function\n\
+\"main\", use \"*main + 4\".\n\
+\n\
+Explicit locations are similar to linespecs but use an option/argument\n\
+syntax to specify location parameters.\n\
+Example: To specify the start of the label named \"the_top\" in the\n\
+function \"fact\" in the file \"factorial.c\", use \"-source factorial.c\n\
+-function fact -label the_top\".\n"
+
/* 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" [PROBE_MODIFIER] [LOCATION] [thread THREADNUM] [if CONDITION]\n\
PROBE_MODIFIER shall be present if the command is to be placed in a\n\
probe point. Accepted values are `-probe' (for a generic, automatically\n\
guessed probe type), `-probe-stap' (for a SystemTap probe) or \n\
`-probe-dtrace' (for a DTrace probe).\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\
+LOCATION may be a linespec, address, or explicit location as described\n\
+below.\n\
+\n\
With no LOCATION, uses current execution address of the selected\n\
stack frame. 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\
+\n" LOCATION_HELP_STRING "\n\
Multiple breakpoints at one place are permitted, and useful if their\n\
conditions are different.\n\
\n\
set_cmd_completer (command, completer);
}
-static void
-clear_syscall_counts (struct inferior *inf)
-{
- struct catch_syscall_inferior_data *inf_data
- = get_catch_syscall_inferior_data (inf);
-
- inf_data->total_syscalls_count = 0;
- inf_data->any_syscall_count = 0;
- VEC_free (int, inf_data->syscalls_counts);
-}
-
static void
save_command (char *arg, int from_tty)
{
ops->insert_location = bkpt_insert_location;
ops->remove_location = bkpt_remove_location;
ops->breakpoint_hit = bkpt_breakpoint_hit;
- ops->create_sals_from_address = bkpt_create_sals_from_address;
+ ops->create_sals_from_location = bkpt_create_sals_from_location;
ops->create_breakpoints_sal = bkpt_create_breakpoints_sal;
- ops->decode_linespec = bkpt_decode_linespec;
+ ops->decode_location = bkpt_decode_location;
/* The breakpoint_ops structure to be used in regular breakpoints. */
ops = &bkpt_breakpoint_ops;
*ops = bkpt_breakpoint_ops;
ops->insert_location = bkpt_probe_insert_location;
ops->remove_location = bkpt_probe_remove_location;
- ops->create_sals_from_address = bkpt_probe_create_sals_from_address;
- ops->decode_linespec = bkpt_probe_decode_linespec;
+ ops->create_sals_from_location = bkpt_probe_create_sals_from_location;
+ ops->decode_location = bkpt_probe_decode_location;
/* Watchpoints. */
ops = &watchpoint_breakpoint_ops;
ops->print_one_detail = tracepoint_print_one_detail;
ops->print_mention = tracepoint_print_mention;
ops->print_recreate = tracepoint_print_recreate;
- ops->create_sals_from_address = tracepoint_create_sals_from_address;
+ ops->create_sals_from_location = tracepoint_create_sals_from_location;
ops->create_breakpoints_sal = tracepoint_create_breakpoints_sal;
- ops->decode_linespec = tracepoint_decode_linespec;
+ ops->decode_location = tracepoint_decode_location;
/* Probe tracepoints. */
ops = &tracepoint_probe_breakpoint_ops;
*ops = tracepoint_breakpoint_ops;
- ops->create_sals_from_address = tracepoint_probe_create_sals_from_address;
- ops->decode_linespec = tracepoint_probe_decode_linespec;
+ ops->create_sals_from_location = tracepoint_probe_create_sals_from_location;
+ ops->decode_location = tracepoint_probe_decode_location;
/* Static tracepoints with marker (`-m'). */
ops = &strace_marker_breakpoint_ops;
*ops = tracepoint_breakpoint_ops;
- ops->create_sals_from_address = strace_marker_create_sals_from_address;
+ ops->create_sals_from_location = strace_marker_create_sals_from_location;
ops->create_breakpoints_sal = strace_marker_create_breakpoints_sal;
- ops->decode_linespec = strace_marker_decode_linespec;
+ ops->decode_location = strace_marker_decode_location;
/* Fork catchpoints. */
ops = &catch_fork_breakpoint_ops;
ops->print_mention = print_mention_catch_exec;
ops->print_recreate = print_recreate_catch_exec;
- /* Syscall catchpoints. */
- ops = &catch_syscall_breakpoint_ops;
- *ops = base_breakpoint_ops;
- ops->dtor = dtor_catch_syscall;
- ops->insert_location = insert_catch_syscall;
- ops->remove_location = remove_catch_syscall;
- ops->breakpoint_hit = breakpoint_hit_catch_syscall;
- ops->print_it = print_it_catch_syscall;
- ops->print_one = print_one_catch_syscall;
- ops->print_mention = print_mention_catch_syscall;
- ops->print_recreate = print_recreate_catch_syscall;
-
/* Solib-related catchpoints. */
ops = &catch_solib_breakpoint_ops;
*ops = base_breakpoint_ops;
observer_attach_solib_unloaded (disable_breakpoints_in_unloaded_shlib);
observer_attach_free_objfile (disable_breakpoints_in_freed_objfile);
- observer_attach_inferior_exit (clear_syscall_counts);
observer_attach_memory_changed (invalidate_bp_value_on_memory_change);
breakpoint_objfile_key
= register_objfile_data_with_cleanup (NULL, free_breakpoint_probes);
- catch_syscall_inferior_data
- = register_inferior_data_with_cleanup (NULL,
- catch_syscall_inferior_data_cleanup);
-
breakpoint_chain = 0;
/* Don't bother to call set_breakpoint_count. $bpnum isn't useful
before a breakpoint is set. */
add_com ("ignore", class_breakpoint, ignore_command, _("\
Set ignore-count of breakpoint number N to COUNT.\n\
Usage is `ignore N COUNT'."));
- if (xdb_commands)
- add_com_alias ("bc", "ignore", class_breakpoint, 1);
add_com ("commands", class_breakpoint, commands_command, _("\
Set commands to be executed when a breakpoint is hit.\n\
This is used to cancel the effect of the \"disable\" command.\n\
With a subcommand you can enable temporarily."),
&enablelist, "enable ", 1, &cmdlist);
- if (xdb_commands)
- add_com ("ab", class_breakpoint, enable_command, _("\
-Enable some breakpoints.\n\
-Give breakpoint numbers (separated by spaces) as arguments.\n\
-With no subcommand, breakpoints are enabled until you command otherwise.\n\
-This is used to cancel the effect of the \"disable\" command.\n\
-With a subcommand you can enable temporarily."));
add_com_alias ("en", "enable", class_breakpoint, 1);
&disablelist, "disable ", 1, &cmdlist);
add_com_alias ("dis", "disable", class_breakpoint, 1);
add_com_alias ("disa", "disable", class_breakpoint, 1);
- if (xdb_commands)
- add_com ("sb", class_breakpoint, disable_command, _("\
-Disable some breakpoints.\n\
-Arguments are breakpoint numbers with spaces in between.\n\
-To disable all breakpoints, give no argument.\n\
-A disabled breakpoint is not forgotten, but has no effect until re-enabled."));
add_cmd ("breakpoints", class_alias, disable_command, _("\
Disable some breakpoints.\n\
&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\
-Arguments are breakpoint numbers with spaces in between.\n\
-To delete all breakpoints, give no argument.\n"));
add_cmd ("breakpoints", class_alias, delete_command, _("\
Delete some breakpoints or auto-display expressions.\n\
&deletelist);
add_com ("clear", class_breakpoint, clear_command, _("\
-Clear breakpoint at specified line or function.\n\
-Argument may be line number, function name, or \"*\" and an address.\n\
-If line number is specified, all breakpoints in that line are cleared.\n\
-If function is specified, breakpoints at beginning of function are cleared.\n\
-If an address is specified, breakpoints at that address are cleared.\n\
+Clear breakpoint at specified location.\n\
+Argument may be a linespec, explicit, or address location as described below.\n\
\n\
With no argument, clears all breakpoints in the line that the selected frame\n\
-is executing in.\n\
-\n\
+is executing in.\n"
+"\n" LOCATION_HELP_STRING "\n\
See also the \"delete\" command which clears breakpoints by number."));
add_com_alias ("cl", "clear", class_breakpoint, 1);
c = add_com ("break", class_breakpoint, break_command, _("\
-Set breakpoint at specified line or function.\n"
+Set breakpoint at specified location.\n"
BREAK_ARGS_HELP ("break")));
set_cmd_completer (c, location_completer);
add_com_alias ("bre", "break", class_run, 1);
add_com_alias ("brea", "break", class_run, 1);
- if (xdb_commands)
- add_com_alias ("ba", "break", class_breakpoint, 1);
-
if (dbx_commands)
{
add_abbrev_prefix_cmd ("stop", class_breakpoint, stop_command, _("\
add_info_alias ("b", "breakpoints", 1);
- if (xdb_commands)
- add_com ("lb", class_breakpoint, breakpoints_info, _("\
-Status of user-settable breakpoints, or breakpoint number NUMBER.\n\
-The \"Type\" column indicates one of:\n\
-\tbreakpoint - normal breakpoint\n\
-\twatchpoint - watchpoint\n\
-The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\n\
-the disposition of the breakpoint after it gets hit. \"dis\" means that the\n\
-breakpoint will be disabled. The \"Address\" and \"What\" columns indicate the\n\
-address and file/line number respectively.\n\
-\n\
-Convenience variable \"$_\" and default examine address for \"x\"\n\
-are set to the address of the last breakpoint listed unless the command\n\
-is prefixed with \"server \".\n\n\
-Convenience variable \"$bpnum\" contains the number of the last\n\
-breakpoint set."));
-
add_cmd ("breakpoints", class_maintenance, maintenance_info_breakpoints, _("\
Status of all breakpoints, or breakpoint number NUMBER.\n\
The \"Type\" column indicates one of:\n\
NULL,
CATCH_PERMANENT,
CATCH_TEMPORARY);
- add_catch_command ("syscall", _("\
-Catch system calls by their names and/or numbers.\n\
-Arguments say which system calls to catch. If no arguments\n\
-are given, every system call will be caught.\n\
-Arguments, if given, should be one or more system call names\n\
-(if your system supports that), or system call numbers."),
- catch_syscall_command_1,
- catch_syscall_completer,
- CATCH_PERMANENT,
- CATCH_TEMPORARY);
c = add_com ("watch", class_breakpoint, watch_command, _("\
Set a watchpoint for an expression.\n\
/* Tracepoint manipulation commands. */
c = add_com ("trace", class_breakpoint, trace_command, _("\
-Set a tracepoint at specified line or function.\n\
+Set a tracepoint at specified location.\n\
\n"
BREAK_ARGS_HELP ("trace") "\n\
Do \"help tracepoints\" for info on other tracepoint commands."));
add_com_alias ("trac", "trace", class_alias, 1);
c = add_com ("ftrace", class_breakpoint, ftrace_command, _("\
-Set a fast tracepoint at specified line or function.\n\
+Set a fast tracepoint at specified location.\n\
\n"
BREAK_ARGS_HELP ("ftrace") "\n\
Do \"help tracepoints\" for info on other tracepoint commands."));
set_cmd_completer (c, location_completer);
c = add_com ("strace", class_breakpoint, strace_command, _("\
-Set a static tracepoint at specified line, function or marker.\n\
+Set a static tracepoint at location or marker.\n\
\n\
strace [LOCATION] [if CONDITION]\n\
-LOCATION may be a line number, function name, \"*\" and an address,\n\
-or -m MARKER_ID.\n\
-If a line number is specified, probe the marker at start of code\n\
-for that line. If a function is specified, probe the marker at start\n\
-of code for that function. If an address is specified, probe the marker\n\
-at that exact address. If a marker id is specified, probe the marker\n\
-with that name. With no LOCATION, uses current execution address of\n\
-the selected stack frame.\n\
+LOCATION may be a linespec, explicit, or address location (described below) \n\
+or -m MARKER_ID.\n\n\
+If a marker id is specified, probe the marker with that name. With\n\
+no LOCATION, uses current execution address of the selected stack frame.\n\
Static tracepoints accept an extra collect action -- ``collect $_sdata''.\n\
This collects arbitrary user data passed in the probe point call to the\n\
tracing library. You can inspect it when analyzing the trace buffer,\n\
by printing the $_sdata variable like any other convenience variable.\n\
\n\
CONDITION is a boolean expression.\n\
-\n\
+\n" LOCATION_HELP_STRING "\n\
Multiple tracepoints at one place are permitted, and useful if their\n\
conditions are different.\n\
\n\
range (including START-LOCATION and END-LOCATION)."));
c = add_com ("dprintf", class_breakpoint, dprintf_command, _("\
-Set a dynamic printf at specified line or function.\n\
+Set a dynamic printf at specified location.\n\
dprintf location,format string,arg1,arg2,...\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."));
+location may be a linespec, explicit, or address location.\n"
+"\n" LOCATION_HELP_STRING));
set_cmd_completer (c, location_completer);
add_setshow_enum_cmd ("dprintf-style", class_support,