/* Everything about breakpoints, for GDB.
- Copyright (C) 1986-2014 Free Software Foundation, Inc.
+ Copyright (C) 1986-2015 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 "skip.h"
#include "ax-gdb.h"
#include "dummy-frame.h"
-
+#include "interps.h"
#include "format.h"
/* readline include files */
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);
static int strace_marker_p (struct breakpoint *b);
-/* The abstract base class all breakpoint_ops structures inherit
- from. */
-struct breakpoint_ops base_breakpoint_ops;
-
/* The breakpoint_ops structure to be inherited by all breakpoint_ops
that are implemented on top of software or hardware breakpoints
(user breakpoints, internal and momentary breakpoints, etc.). */
/* Dynamic printf class type. */
struct breakpoint_ops dprintf_breakpoint_ops;
-/* One (or perhaps two) breakpoints used for software single
- stepping. */
-
-static struct breakpoint *single_step_breakpoints;
-
/* The style in which to perform a dynamic printf. This is a user
option because different output options have different tradeoffs;
if GDB does the printing, there is better error handling if there
static struct cmd_list_element *breakpoint_show_cmdlist;
struct cmd_list_element *save_cmdlist;
+/* See declaration at breakpoint.h. */
+
+struct breakpoint *
+breakpoint_find_if (int (*func) (struct breakpoint *b, void *d),
+ void *user_data)
+{
+ struct breakpoint *b = NULL;
+
+ ALL_BREAKPOINTS (b)
+ {
+ if (func (b, user_data) != 0)
+ break;
+ }
+
+ return b;
+}
+
/* Return whether a breakpoint is an active enabled breakpoint. */
static int
breakpoint_enabled (struct breakpoint *b)
}
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);
parse_cond_to_aexpr (CORE_ADDR scope, struct expression *cond)
{
struct agent_expr *aexpr = NULL;
- volatile struct gdb_exception ex;
if (!cond)
return NULL;
/* We don't want to stop processing, so catch any errors
that may show up. */
- TRY_CATCH (ex, RETURN_MASK_ERROR)
+ TRY
{
aexpr = gen_eval_for_expr (scope, cond);
}
- if (ex.reason < 0)
+ CATCH (ex, RETURN_MASK_ERROR)
{
/* If we got here, it means the condition could not be parsed to a valid
bytecode expression and thus can't be evaluated on the target's side.
It's no use iterating through the conditions. */
return NULL;
}
+ END_CATCH
/* We have a valid agent expression. */
return aexpr;
struct cleanup *old_cleanups = 0;
struct expression *expr, **argvec;
struct agent_expr *aexpr = NULL;
- volatile struct gdb_exception ex;
const char *cmdrest;
const char *format_start, *format_end;
struct format_piece *fpieces;
/* We don't want to stop processing, so catch any errors
that may show up. */
- TRY_CATCH (ex, RETURN_MASK_ERROR)
+ TRY
{
aexpr = gen_printf (scope, gdbarch, 0, 0,
format_start, format_end - format_start,
fpieces, nargs, argvec);
}
-
- do_cleanups (old_cleanups);
-
- if (ex.reason < 0)
+ CATCH (ex, RETURN_MASK_ERROR)
{
/* If we got here, it means the command could not be parsed to a valid
bytecode expression and thus can't be evaluated on the target's side.
It's no use iterating through the other commands. */
- return NULL;
+ aexpr = NULL;
}
+ END_CATCH
+
+ do_cleanups (old_cleanups);
/* We have a valid agent expression, return it. */
return aexpr;
{
enum errors bp_err = GDB_NO_ERROR;
const char *bp_err_message = NULL;
- volatile struct gdb_exception e;
if (!should_be_inserted (bl) || (bl->inserted && !bl->needs_update))
return 0;
|| !(section_is_overlay (bl->section)))
{
/* No overlay handling: just set the breakpoint. */
- TRY_CATCH (e, RETURN_MASK_ALL)
+ TRY
{
int val;
if (val)
bp_err = GENERIC_ERROR;
}
- if (e.reason < 0)
+ CATCH (e, RETURN_MASK_ALL)
{
bp_err = e.error;
bp_err_message = e.message;
}
+ END_CATCH
}
else
{
bl->overlay_target_info.reqstd_address = addr;
/* No overlay handling: just set the breakpoint. */
- TRY_CATCH (e, RETURN_MASK_ALL)
+ TRY
{
int val;
if (val)
bp_err = GENERIC_ERROR;
}
- if (e.reason < 0)
+ CATCH (e, RETURN_MASK_ALL)
{
bp_err = e.error;
bp_err_message = e.message;
}
+ END_CATCH
if (bp_err != GDB_NO_ERROR)
fprintf_unfiltered (tmp_error_stream,
if (section_is_mapped (bl->section))
{
/* Yes. This overlay section is mapped into memory. */
- TRY_CATCH (e, RETURN_MASK_ALL)
+ TRY
{
int val;
if (val)
bp_err = GENERIC_ERROR;
}
- if (e.reason < 0)
+ CATCH (e, RETURN_MASK_ALL)
{
bp_err = e.error;
bp_err_message = e.message;
}
+ END_CATCH
}
else
{
if (bl->pspace != inf->pspace)
continue;
- if (bl->owner->type == bp_dprintf)
- continue;
-
- if (bl->inserted)
+ if (bl->inserted && !bl->target_info.persist)
{
val = remove_breakpoint (bl, mark_uninserted);
if (val != 0)
/* BL is never in moribund_locations by our callers. */
gdb_assert (bl->owner != NULL);
- if (bl->owner->enable_state == bp_permanent)
+ if (bl->permanent)
/* Permanent breakpoints cannot be inserted or removed. */
return 0;
/* BL is never in moribund_locations by our callers. */
gdb_assert (bl->owner != NULL);
- if (bl->owner->enable_state == bp_permanent)
+ if (bl->permanent)
/* Permanent breakpoints cannot be inserted or removed. */
return 0;
struct bp_location *bl, **blp_tmp;
ALL_BP_LOCATIONS (bl, blp_tmp)
- if (bl->pspace == current_program_space)
+ if (bl->pspace == current_program_space
+ && !bl->permanent)
bl->inserted = 0;
}
if (gdbarch_has_global_breakpoints (target_gdbarch ()))
return;
- ALL_BP_LOCATIONS (bl, blp_tmp)
- {
- /* ALL_BP_LOCATIONS bp_location has BL->OWNER always non-NULL. */
- if (bl->pspace == pspace
- && bl->owner->enable_state != bp_permanent)
- bl->inserted = 0;
- }
+ mark_breakpoints_out ();
ALL_BREAKPOINTS_SAFE (b, b_tmp)
{
/* ALL_BP_LOCATIONS bp_location has BL->OWNER always non-NULL. */
if ((breakpoint_enabled (bl->owner)
- || bl->owner->enable_state == bp_permanent)
+ || bl->permanent)
&& breakpoint_location_address_match (bl, aspace, pc))
{
if (overlay_debugging
&& section_is_overlay (bl->section)
&& !section_is_mapped (bl->section))
continue; /* unmapped overlay -- can't be a match */
- else if (bl->owner->enable_state == bp_permanent)
+ else if (bl->permanent)
return permanent_breakpoint_here;
else
any_breakpoint_here = 1;
return 0;
}
+/* Returns non-zero iff BL is inserted at PC, in address space
+ ASPACE. */
+
+static int
+bp_location_inserted_here_p (struct bp_location *bl,
+ struct address_space *aspace, CORE_ADDR pc)
+{
+ if (bl->inserted
+ && breakpoint_address_match (bl->pspace->aspace, bl->address,
+ aspace, pc))
+ {
+ if (overlay_debugging
+ && section_is_overlay (bl->section)
+ && !section_is_mapped (bl->section))
+ return 0; /* unmapped overlay -- can't be a match */
+ else
+ return 1;
+ }
+ return 0;
+}
+
/* Returns non-zero iff there's a breakpoint inserted at PC. */
int
breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc)
{
- struct bp_location *bl, **blp_tmp;
+ struct bp_location **blp, **blp_tmp = NULL;
+ struct bp_location *bl;
- ALL_BP_LOCATIONS (bl, blp_tmp)
+ ALL_BP_LOCATIONS_AT_ADDR (blp, blp_tmp, pc)
{
+ struct bp_location *bl = *blp;
+
if (bl->loc_type != bp_loc_software_breakpoint
&& bl->loc_type != bp_loc_hardware_breakpoint)
continue;
- if (bl->inserted
- && breakpoint_location_address_match (bl, aspace, pc))
- {
- if (overlay_debugging
- && section_is_overlay (bl->section)
- && !section_is_mapped (bl->section))
- continue; /* unmapped overlay -- can't be a match */
- else
- return 1;
- }
+ if (bp_location_inserted_here_p (bl, aspace, pc))
+ return 1;
}
return 0;
}
software_breakpoint_inserted_here_p (struct address_space *aspace,
CORE_ADDR pc)
{
- struct bp_location *bl, **blp_tmp;
+ struct bp_location **blp, **blp_tmp = NULL;
+ struct bp_location *bl;
- ALL_BP_LOCATIONS (bl, blp_tmp)
+ ALL_BP_LOCATIONS_AT_ADDR (blp, blp_tmp, pc)
{
+ struct bp_location *bl = *blp;
+
if (bl->loc_type != bp_loc_software_breakpoint)
continue;
- if (bl->inserted
- && breakpoint_address_match (bl->pspace->aspace, bl->address,
- aspace, pc))
- {
- if (overlay_debugging
- && section_is_overlay (bl->section)
- && !section_is_mapped (bl->section))
- continue; /* unmapped overlay -- can't be a match */
- else
- return 1;
- }
+ if (bp_location_inserted_here_p (bl, aspace, pc))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* See breakpoint.h. */
+
+int
+hardware_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)
+ {
+ struct bp_location *bl = *blp;
+
+ if (bl->loc_type != bp_loc_hardware_breakpoint)
+ continue;
+
+ if (bp_location_inserted_here_p (bl, aspace, pc))
+ return 1;
}
return 0;
}
return 0;
}
-
-/* breakpoint_thread_match (PC, PTID) returns true if the breakpoint at
- PC is valid for process/thread PTID. */
-
-int
-breakpoint_thread_match (struct address_space *aspace, CORE_ADDR pc,
- ptid_t ptid)
-{
- struct bp_location *bl, **blp_tmp;
- /* The thread and task IDs associated to PTID, computed lazily. */
- int thread = -1;
- int task = 0;
-
- ALL_BP_LOCATIONS (bl, blp_tmp)
- {
- if (bl->loc_type != bp_loc_software_breakpoint
- && bl->loc_type != bp_loc_hardware_breakpoint)
- continue;
-
- /* ALL_BP_LOCATIONS bp_location has bl->OWNER always non-NULL. */
- if (!breakpoint_enabled (bl->owner)
- && bl->owner->enable_state != bp_permanent)
- continue;
-
- if (!breakpoint_location_address_match (bl, aspace, pc))
- continue;
-
- if (bl->owner->thread != -1)
- {
- /* This is a thread-specific breakpoint. Check that ptid
- matches that thread. If thread hasn't been computed yet,
- it is now time to do so. */
- if (thread == -1)
- thread = pid_to_thread_id (ptid);
- if (bl->owner->thread != thread)
- continue;
- }
-
- if (bl->owner->task != 0)
- {
- /* This is a task-specific breakpoint. Check that ptid
- matches that task. If task hasn't been computed yet,
- it is now time to do so. */
- if (task == 0)
- task = ada_get_task_number (ptid);
- if (bl->owner->task != task)
- continue;
- }
-
- if (overlay_debugging
- && section_is_overlay (bl->section)
- && !section_is_mapped (bl->section))
- continue; /* unmapped overlay -- can't be a match */
-
- return 1;
- }
-
- return 0;
-}
\f
/* bpstat stuff. External routines' interfaces are documented
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 (target_can_async_p ())
+ if (interpreter_async && target_can_async_p ())
/* 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. */
}
}
+/* Returns true if we need to track moribund locations of LOC's type
+ on the current target. */
+
+static int
+need_moribund_for_location_type (struct bp_location *loc)
+{
+ return ((loc->loc_type == bp_loc_software_breakpoint
+ && !target_supports_stopped_by_sw_breakpoint ())
+ || (loc->loc_type == bp_loc_hardware_breakpoint
+ && !target_supports_stopped_by_hw_breakpoint ()));
+}
+
/* Get a bpstat associated with having just stopped at address
BP_ADDR in thread PTID.
ALL_BREAKPOINTS (b)
{
- if (!breakpoint_enabled (b) && b->enable_state != bp_permanent)
+ if (!breakpoint_enabled (b))
continue;
for (bl = b->loc; bl != NULL; bl = bl->next)
}
/* Check if a moribund breakpoint explains the stop. */
- for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix)
+ if (!target_supports_stopped_by_sw_breakpoint ()
+ || !target_supports_stopped_by_hw_breakpoint ())
{
- if (breakpoint_location_address_match (loc, aspace, bp_addr))
+ for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix)
{
- bs = bpstat_alloc (loc, &bs_link);
- /* For hits of moribund locations, we should just proceed. */
- bs->stop = 0;
- bs->print = 0;
- bs->print_it = print_it_noop;
+ if (breakpoint_location_address_match (loc, aspace, bp_addr)
+ && need_moribund_for_location_type (loc))
+ {
+ bs = bpstat_alloc (loc, &bs_link);
+ /* For hits of moribund locations, we should just proceed. */
+ bs->stop = 0;
+ bs->print = 0;
+ bs->print_it = print_it_noop;
+ }
}
}
if (b->disposition == disp_disable)
{
--(b->enable_count);
- if (b->enable_count <= 0
- && b->enable_state != bp_permanent)
+ if (b->enable_count <= 0)
b->enable_state = bp_disabled;
removed_any = 1;
}
((b->enable_state == bp_disabled
|| b->enable_state == bp_call_disabled)
? " (disabled)"
- : b->enable_state == bp_permanent
- ? " (permanent)"
: ""),
(others > 1) ? ","
: ((others == 1) ? " and" : ""));
if (sal.section)
return get_objfile_arch (sal.section->objfile);
if (sal.symtab)
- return get_objfile_arch (sal.symtab->objfile);
+ return get_objfile_arch (SYMTAB_OBJFILE (sal.symtab));
return NULL;
}
{
struct bp_location *bl;
- b->enable_state = bp_permanent;
-
/* 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->inserted = 1;
+ {
+ bl->permanent = 1;
+ bl->inserted = 1;
+ }
}
/* Call this routine when stepping and nexting to enable a breakpoint
catch_load_or_unload (arg, from_tty, 0, command);
}
-/* An instance of this type is used to represent a syscall catchpoint.
+/* 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);
+
+ c->forked_inferior_pid = null_ptid;
+
+ install_breakpoint (0, &c->base, 1);
+}
+
+/* Exec catchpoints. */
+
+/* An instance of this type is used to represent an exec 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. */
+ CATCH_EXEC_BREAKPOINT_OPS. */
-struct syscall_catchpoint
+struct exec_catchpoint
{
/* 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;
+ /* Filename of a program whose exec triggered this catchpoint.
+ This field is only valid immediately after this catchpoint has
+ triggered. */
+ char *exec_pathname;
};
-/* Implement the "dtor" breakpoint_ops method for syscall
+/* Implement the "dtor" breakpoint_ops method for exec
catchpoints. */
static void
-dtor_catch_syscall (struct breakpoint *b)
+dtor_catch_exec (struct breakpoint *b)
{
- struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
+ struct exec_catchpoint *c = (struct exec_catchpoint *) b;
- VEC_free (int, c->syscalls_to_be_caught);
+ xfree (c->exec_pathname);
base_breakpoint_ops.dtor (b);
}
-static const struct inferior_data *catch_syscall_inferior_data = NULL;
-
-struct catch_syscall_inferior_data
+static int
+insert_catch_exec (struct bp_location *bl)
{
- /* 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;
-};
+ return target_insert_exec_catchpoint (ptid_get_pid (inferior_ptid));
+}
-static struct catch_syscall_inferior_data*
-get_catch_syscall_inferior_data (struct inferior *inf)
+static int
+remove_catch_exec (struct bp_location *bl)
{
- 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);
- }
-
- return inf_data;
+ return target_remove_exec_catchpoint (ptid_get_pid (inferior_ptid));
}
-static void
-catch_syscall_inferior_data_cleanup (struct inferior *inf, void *arg)
+static int
+breakpoint_hit_catch_exec (const struct bp_location *bl,
+ struct address_space *aspace, CORE_ADDR bp_addr,
+ const struct target_waitstatus *ws)
{
- xfree (arg);
-}
+ struct exec_catchpoint *c = (struct exec_catchpoint *) bl->owner;
+ if (ws->kind != TARGET_WAITKIND_EXECD)
+ return 0;
-/* Implement the "insert" breakpoint_ops method for syscall
- catchpoints. */
+ c->exec_pathname = xstrdup (ws->value.execd_pathname);
+ return 1;
+}
-static int
-insert_catch_syscall (struct bp_location *bl)
+static enum print_stop_action
+print_it_catch_exec (bpstat bs)
{
- 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);
+ struct ui_out *uiout = current_uiout;
+ struct breakpoint *b = bs->breakpoint_at;
+ struct exec_catchpoint *c = (struct exec_catchpoint *) b;
- ++inf_data->total_syscalls_count;
- if (!c->syscalls_to_be_caught)
- ++inf_data->any_syscall_count;
+ 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))
{
- 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);
- }
+ ui_out_field_string (uiout, "reason",
+ async_reason_lookup (EXEC_ASYNC_EXEC));
+ ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
}
+ ui_out_field_int (uiout, "bkptno", b->number);
+ ui_out_text (uiout, " (exec'd ");
+ ui_out_field_string (uiout, "new-exec", c->exec_pathname);
+ ui_out_text (uiout, "), ");
- 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;
-
- get_last_target_status (&ptid, &last);
-
- get_syscall_by_number (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;
-
- 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 (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;
-
- 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 (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;
-
- 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 (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);
-
- c->forked_inferior_pid = null_ptid;
-
- install_breakpoint (0, &c->base, 1);
-}
-
-/* Exec catchpoints. */
-
-/* An instance of this type is used to represent an exec 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_EXEC_BREAKPOINT_OPS. */
-
-struct exec_catchpoint
-{
- /* The base class. */
- struct breakpoint base;
-
- /* Filename of a program whose exec triggered this catchpoint.
- This field is only valid immediately after this catchpoint has
- triggered. */
- char *exec_pathname;
-};
-
-/* Implement the "dtor" breakpoint_ops method for exec
- catchpoints. */
-
-static void
-dtor_catch_exec (struct breakpoint *b)
-{
- struct exec_catchpoint *c = (struct exec_catchpoint *) b;
-
- xfree (c->exec_pathname);
-
- base_breakpoint_ops.dtor (b);
-}
-
-static int
-insert_catch_exec (struct bp_location *bl)
-{
- return target_insert_exec_catchpoint (ptid_get_pid (inferior_ptid));
-}
-
-static int
-remove_catch_exec (struct bp_location *bl)
-{
- return target_remove_exec_catchpoint (ptid_get_pid (inferior_ptid));
-}
-
-static int
-breakpoint_hit_catch_exec (const struct bp_location *bl,
- struct address_space *aspace, CORE_ADDR bp_addr,
- const struct target_waitstatus *ws)
-{
- struct exec_catchpoint *c = (struct exec_catchpoint *) bl->owner;
-
- if (ws->kind != TARGET_WAITKIND_EXECD)
- return 0;
-
- c->exec_pathname = xstrdup (ws->value.execd_pathname);
- return 1;
-}
-
-static enum print_stop_action
-print_it_catch_exec (bpstat bs)
-{
- struct ui_out *uiout = current_uiout;
- struct breakpoint *b = bs->breakpoint_at;
- struct exec_catchpoint *c = (struct exec_catchpoint *) b;
-
- 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 (EXEC_ASYNC_EXEC));
- ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
- }
- ui_out_field_int (uiout, "bkptno", b->number);
- ui_out_text (uiout, " (exec'd ");
- ui_out_field_string (uiout, "new-exec", c->exec_pathname);
- ui_out_text (uiout, "), ");
-
- return PRINT_SRC_AND_LOC;
+ return PRINT_SRC_AND_LOC;
}
static void
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)
{
}
\f
+static int bp_loc_is_permanent (struct bp_location *loc);
+
static struct bp_location *
add_location_to_breakpoint (struct breakpoint *b,
const struct symtab_and_line *sal)
set_breakpoint_location_function (loc,
sal->explicit_pc || sal->explicit_line);
+
+ if (bp_loc_is_permanent (loc))
+ {
+ loc->inserted = 1;
+ loc->permanent = 1;
+ }
+
return loc;
}
\f
-/* Return 1 if LOC is pointing to a permanent breakpoint,
- return 0 otherwise. */
+/* See breakpoint.h. */
-static int
-bp_loc_is_permanent (struct bp_location *loc)
+int
+program_breakpoint_here_p (struct gdbarch *gdbarch, CORE_ADDR address)
{
int len;
CORE_ADDR addr;
struct cleanup *cleanup;
int retval = 0;
- gdb_assert (loc != NULL);
-
- addr = loc->address;
- bpoint = gdbarch_breakpoint_from_pc (loc->gdbarch, &addr, &len);
+ addr = address;
+ bpoint = gdbarch_breakpoint_from_pc (gdbarch, &addr, &len);
/* Software breakpoints unsupported? */
if (bpoint == NULL)
/* Enable the automatic memory restoration from breakpoints while
we read the memory. Otherwise we could say about our temporary
breakpoints they are permanent. */
- cleanup = save_current_space_and_thread ();
-
- switch_to_program_space_and_thread (loc->pspace);
- make_show_memory_breakpoints_cleanup (0);
+ cleanup = make_show_memory_breakpoints_cleanup (0);
- if (target_read_memory (loc->address, target_mem, len) == 0
+ if (target_read_memory (address, target_mem, len) == 0
&& memcmp (target_mem, bpoint, len) == 0)
retval = 1;
return retval;
}
+/* Return 1 if LOC is pointing to a permanent breakpoint,
+ return 0 otherwise. */
+
+static int
+bp_loc_is_permanent (struct bp_location *loc)
+{
+ struct cleanup *cleanup;
+ int retval;
+
+ 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)
+ return 0;
+
+ cleanup = save_current_space_and_thread ();
+ switch_to_program_space_and_thread (loc->pspace);
+
+ retval = program_breakpoint_here_p (loc->gdbarch, loc->address);
+
+ do_cleanups (cleanup);
+
+ return retval;
+}
+
/* Build a command list for the dprintf corresponding to the current
settings of the dprintf style options. */
struct command_line *printf_cmd_line
= xmalloc (sizeof (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;
loc->inserted = 1;
}
- if (bp_loc_is_permanent (loc))
- make_breakpoint_permanent (b);
-
if (b->cond_string)
{
const char *arg = b->cond_string;
{
/* If no arg given, or if first arg is 'if ', use the default
breakpoint. */
- if ((*address) == NULL
- || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2])))
+ if ((*address) == NULL || linespec_lexer_lex_keyword (*address))
{
/* The last displayed codepoint, if it's valid, is our default breakpoint
address. */
int from_tty, int enabled, int internal,
unsigned flags)
{
- volatile struct gdb_exception e;
char *copy_arg = NULL;
char *addr_start = arg;
struct linespec_result canonical;
init_linespec_result (&canonical);
- TRY_CATCH (e, RETURN_MASK_ALL)
+ TRY
{
ops->create_sals_from_address (&arg, &canonical, type_wanted,
addr_start, ©_arg);
}
-
- /* If caller is interested in rc value from parse, set value. */
- switch (e.reason)
+ CATCH (e, RETURN_MASK_ERROR)
{
- case GDB_NO_ERROR:
- if (VEC_empty (linespec_sals, canonical.sals))
- return 0;
- break;
- case RETURN_ERROR:
- switch (e.error)
+ /* If caller is interested in rc value from parse, set
+ value. */
+ if (e.error == NOT_FOUND_ERROR)
{
- case NOT_FOUND_ERROR:
-
/* If pending breakpoint support is turned off, throw
error. */
pending = 1;
VEC_safe_push (linespec_sals, canonical.sals, &lsal);
}
- break;
- default:
- throw_exception (e);
}
- break;
- default:
- throw_exception (e);
+ else
+ throw_exception (e);
}
+ END_CATCH
+
+ if (VEC_empty (linespec_sals, canonical.sals))
+ return 0;
/* Create a chain of things that always need to be cleaned up. */
old_chain = make_cleanup_destroy_linespec_result (&canonical);
make_cleanup (xfree, cond_string);
}
b->cond_string = cond_string;
+ b->thread = thread;
}
b->extra_string = NULL;
b->ignore_count = ignore_count;
const struct block *b;
struct symbol *sym;
- bv = blockvector_for_pc_sect (sal->pc, 0, &b, sal->symtab);
+ bv = blockvector_for_pc_sect (sal->pc, 0, &b,
+ SYMTAB_COMPUNIT (sal->symtab));
if (bv != NULL)
{
sym = block_linkage_function (b);
if (sym != NULL)
{
- fixup_symbol_section (sym, sal->symtab->objfile);
- sal->section = SYMBOL_OBJ_SECTION (sal->symtab->objfile, sym);
+ fixup_symbol_section (sym, SYMTAB_OBJFILE (sal->symtab));
+ sal->section = SYMBOL_OBJ_SECTION (SYMTAB_OBJFILE (sal->symtab),
+ sym);
}
else
{
watch_command_1 (const char *arg, int accessflag, int from_tty,
int just_location, int internal)
{
- volatile struct gdb_exception e;
struct breakpoint *b, *scope_breakpoint = NULL;
struct expression *exp;
const struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL;
tok++;
toklen = end_tok - tok + 1;
- if (toklen == 6 && !strncmp (tok, "thread", 6))
+ if (toklen == 6 && startswith (tok, "thread"))
{
/* At this point we've found a "thread" token, which means
the user is trying to set a watchpoint that triggers
if (!valid_thread_id (thread))
invalid_thread_id_error (thread);
}
- else if (toklen == 4 && !strncmp (tok, "mask", 4))
+ else if (toklen == 4 && startswith (tok, "mask"))
{
/* We've found a "mask" token, which means the user wants to
create a hardware watchpoint that is going to have the mask
if (!just_location)
value_free_to_mark (mark);
- TRY_CATCH (e, RETURN_MASK_ALL)
+ TRY
{
/* Finally update the new watchpoint. This creates the locations
that should be inserted. */
update_watchpoint (w, 1);
}
- if (e.reason < 0)
+ CATCH (e, RETURN_MASK_ALL)
{
delete_breakpoint (b);
throw_exception (e);
}
+ END_CATCH
install_breakpoint (internal, b, 1);
do_cleanups (back_to);
stack_frame_id, bp_until);
make_cleanup_delete_breakpoint (breakpoint);
- proceed (-1, GDB_SIGNAL_DEFAULT, 0);
+ proceed (-1, GDB_SIGNAL_DEFAULT);
/* If we are running asynchronously, and proceed call above has
actually managed to start the target, arrange for breakpoints to
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);
-
- 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 (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 (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 (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)
{
/* A comparison function for bp_location AP and BP being interfaced to
qsort. Sort elements primarily by their ADDRESS (no matter what
does breakpoint_address_is_meaningful say for its OWNER),
- secondarily by ordering first bp_permanent OWNERed elements and
+ secondarily by ordering first permanent elements and
terciarily just ensuring the array is sorted stable way despite
qsort being an unstable algorithm. */
{
struct bp_location *a = *(void **) ap;
struct bp_location *b = *(void **) bp;
- /* A and B come from existing breakpoints having non-NULL OWNER. */
- int a_perm = a->owner->enable_state == bp_permanent;
- int b_perm = b->owner->enable_state == bp_permanent;
if (a->address != b->address)
return (a->address > b->address) - (a->address < b->address);
- (a->pspace->num < b->pspace->num));
/* Sort permanent breakpoints first. */
- if (a_perm != b_perm)
- return (a_perm < b_perm) - (a_perm > b_perm);
+ if (a->permanent != b->permanent)
+ return (a->permanent < b->permanent) - (a->permanent > b->permanent);
/* Make the internal GDB representation stable across GDB runs
where A and B memory inside GDB can differ. Breakpoint locations of
if (!found_object)
{
if (removed && non_stop
- && breakpoint_address_is_meaningful (old_loc->owner)
- && !is_hardware_watchpoint (old_loc->owner))
+ && need_moribund_for_location_type (old_loc))
{
/* This location was removed from the target. In
non-stop mode, a race condition is possible where
}
/* Permanent breakpoint should always be inserted. */
- if (b->enable_state == bp_permanent && ! loc->inserted)
+ if (loc->permanent && ! loc->inserted)
internal_error (__FILE__, __LINE__,
_("allegedly permanent breakpoint is not "
"actually inserted"));
/* Clear the condition modification flag. */
loc->condition_changed = condition_unchanged;
- if ((*loc_first_p)->owner->enable_state == bp_permanent && loc->inserted
- && b->enable_state != bp_permanent)
+ if (loc->inserted && !loc->permanent
+ && (*loc_first_p)->permanent)
internal_error (__FILE__, __LINE__,
_("another breakpoint was inserted on top of "
"a permanent breakpoint"));
static void
update_global_location_list_nothrow (enum ugll_insert_mode insert_mode)
{
- volatile struct gdb_exception e;
- TRY_CATCH (e, RETURN_MASK_ERROR)
- update_global_location_list (insert_mode);
+ TRY
+ {
+ update_global_location_list (insert_mode);
+ }
+ CATCH (e, RETURN_MASK_ERROR)
+ {
+ }
+ END_CATCH
}
/* Clear BKP from a BPS. */
if (b->cond_string != NULL)
{
const char *s;
- volatile struct gdb_exception e;
s = b->cond_string;
- TRY_CATCH (e, RETURN_MASK_ERROR)
+ TRY
{
new_loc->cond = parse_exp_1 (&s, sals.sals[i].pc,
block_for_pc (sals.sals[i].pc),
0);
}
- if (e.reason < 0)
+ CATCH (e, RETURN_MASK_ERROR)
{
warning (_("failed to reevaluate condition "
"for breakpoint %d: %s"),
b->number, e.message);
new_loc->enabled = 0;
}
+ END_CATCH
}
if (sals_end.nelts)
}
}
- /* Update locations of permanent breakpoints. */
- if (b->enable_state == bp_permanent)
- make_breakpoint_permanent (b);
-
/* If possible, carry over 'disable' status from existing
breakpoints. */
{
{
char *s;
struct symtabs_and_lines sals = {0};
- volatile struct gdb_exception e;
+ struct gdb_exception exception = exception_none;
gdb_assert (b->ops != NULL);
s = addr_string;
- TRY_CATCH (e, RETURN_MASK_ERROR)
+ TRY
{
b->ops->decode_linespec (b, &s, &sals);
}
- if (e.reason < 0)
+ CATCH (e, RETURN_MASK_ERROR)
{
int not_found_and_ok = 0;
+
+ exception = e;
+
/* For pending breakpoints, it's expected that parsing will
fail until the right shared library is loaded. User has
already told to create pending breakpoints and don't need
throw_exception (e);
}
}
+ END_CATCH
- if (e.reason == 0 || e.error != NOT_FOUND_ERROR)
+ if (exception.reason == 0 || exception.error != NOT_FOUND_ERROR)
{
int i;
int match;
struct get_number_or_range_state state;
- if (args == 0)
+ if (args == 0 || *args == '\0')
error_no_arg (_("one or more breakpoint numbers"));
init_number_or_range (&state, args);
if (bpt->type == bp_watchpoint_scope)
return;
- /* You can't disable permanent breakpoints. */
- if (bpt->enable_state == bp_permanent)
- return;
-
bpt->enable_state = bp_disabled;
/* Mark breakpoint locations modified. */
{
/* Initialize it just to avoid a GCC false warning. */
enum enable_state orig_enable_state = 0;
- volatile struct gdb_exception e;
- TRY_CATCH (e, RETURN_MASK_ALL)
+ TRY
{
struct watchpoint *w = (struct watchpoint *) bpt;
bpt->enable_state = bp_enabled;
update_watchpoint (w, 1 /* reparse */);
}
- if (e.reason < 0)
+ CATCH (e, RETURN_MASK_ALL)
{
bpt->enable_state = orig_enable_state;
exception_fprintf (gdb_stderr, e, _("Cannot enable watchpoint %d: "),
bpt->number);
return;
}
+ END_CATCH
}
- if (bpt->enable_state != bp_permanent)
- bpt->enable_state = bp_enabled;
-
bpt->enable_state = bp_enabled;
/* Mark breakpoint locations modified. */
static void
enable_count_command (char *args, int from_tty)
{
- int count = get_number (&args);
+ int count;
+
+ if (args == NULL)
+ error_no_arg (_("hit count"));
+
+ count = get_number (&args);
map_breakpoint_numbers (args, do_map_enable_count_breakpoint, &count);
}
struct symtab_and_line sal;
CORE_ADDR pc = next_pc;
- if (single_step_breakpoints == NULL)
- single_step_breakpoints = new_single_step_breakpoint (tp->num, gdbarch);
+ if (tp->control.single_step_breakpoints == NULL)
+ {
+ tp->control.single_step_breakpoints
+ = new_single_step_breakpoint (tp->num, gdbarch);
+ }
sal = find_pc_line (pc, 0);
sal.pc = pc;
sal.section = find_pc_overlay (pc);
sal.explicit_pc = 1;
- add_location_to_breakpoint (single_step_breakpoints, &sal);
+ add_location_to_breakpoint (tp->control.single_step_breakpoints, &sal);
update_global_location_list (UGLL_INSERT);
}
-/* Check if the breakpoints used for software single stepping
- were inserted or not. */
+/* See breakpoint.h. */
int
-single_step_breakpoints_inserted (void)
-{
- return (single_step_breakpoints != NULL);
-}
-
-/* Remove and delete any breakpoints used for software single step. */
-
-void
-remove_single_step_breakpoints (void)
-{
- gdb_assert (single_step_breakpoints != NULL);
-
- delete_breakpoint (single_step_breakpoints);
-
- single_step_breakpoints = NULL;
-}
-
-/* Delete software single step breakpoints without removing them from
- the inferior. This is intended to be used if the inferior's address
- space where they were inserted is already gone, e.g. after exit or
- exec. */
-
-void
-cancel_single_step_breakpoints (void)
-{
- /* We don't really need to (or should) delete them here. After an
- exit, breakpoint_init_inferior deletes it. After an exec,
- update_breakpoints_after_exec does it. Just clear our
- reference. */
- single_step_breakpoints = NULL;
-}
-
-/* Check whether any location of BP is inserted at PC. */
-
-static int
breakpoint_has_location_inserted_here (struct breakpoint *bp,
struct address_space *aspace,
CORE_ADDR pc)
single_step_breakpoint_inserted_here_p (struct address_space *aspace,
CORE_ADDR pc)
{
- return (single_step_breakpoints != NULL
- && breakpoint_has_location_inserted_here (single_step_breakpoints,
- aspace, pc));
-}
-
-/* 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;
- }
+ struct breakpoint *bpt;
+ ALL_BREAKPOINTS (bpt)
+ {
+ if (bpt->type == bp_single_step
+ && breakpoint_has_location_inserted_here (bpt, aspace, pc))
+ 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 ();
- 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. */
/* Decide if we are dealing with a static tracepoint marker (`-m'),
or with a normal static tracepoint. */
- if (arg && strncmp (arg, "-m", 2) == 0 && isspace (arg[2]))
+ if (arg && startswith (arg, "-m") && isspace (arg[2]))
ops = &strace_marker_breakpoint_ops;
else
ops = &tracepoint_breakpoint_ops;
if (tp->type != bp_dprintf && tp->commands)
{
- volatile struct gdb_exception ex;
+ struct gdb_exception exception;
fprintf_unfiltered (fp, " commands\n");
ui_out_redirect (current_uiout, fp);
- TRY_CATCH (ex, RETURN_MASK_ALL)
+ TRY
{
print_command_lines (current_uiout, tp->commands->commands, 2);
}
- ui_out_redirect (current_uiout, NULL);
-
- if (ex.reason < 0)
- throw_exception (ex);
+ CATCH (ex, RETURN_MASK_ALL)
+ {
+ ui_out_redirect (current_uiout, NULL);
+ throw_exception (ex);
+ }
+ END_CATCH
+ ui_out_redirect (current_uiout, NULL);
fprintf_unfiltered (fp, " end\n");
}
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) or `-probe-stap' (for a SystemTap probe).\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\
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)
{
struct bp_location **locp, *loc;
ALL_BP_LOCATIONS (loc, locp)
- if (loc->symtab != NULL && loc->symtab->objfile == objfile)
+ if (loc->symtab != NULL && SYMTAB_OBJFILE (loc->symtab) == objfile)
loc->symtab = NULL;
}
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\
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\