#include "top.h"
#include "valprint.h"
#include "jit.h"
-#include "xml-syscall.h"
#include "parser-defs.h"
#include "gdb_regex.h"
#include "probe.h"
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 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);
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
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
{
/* 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);
/* 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);
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;
}
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
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);
}
}
+/* 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.
}
/* 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;
+ }
}
}
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. */
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. */
-
-struct syscall_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;
-};
-
-/* Implement the "dtor" breakpoint_ops method for syscall
- catchpoints. */
-
-static void
-dtor_catch_syscall (struct breakpoint *b)
-{
- struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
-
- VEC_free (int, c->syscalls_to_be_caught);
-
- base_breakpoint_ops.dtor (b);
-}
-
-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)
-{
- 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;
-}
-
-static void
-catch_syscall_inferior_data_cleanup (struct inferior *inf, void *arg)
-{
- xfree (arg);
-}
-
-
-/* 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
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)
{
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;
}
\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);
-
- /* 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;
-
- 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);
+
+ 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;
{
/* 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. */
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)
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);
b->addr_string = copy_arg;
if (parse_arg)
- b->cond_string = NULL;
+ {
+ b->cond_string = NULL;
+ b->extra_string = NULL;
+ }
else
{
/* Create a private copy of condition string. */
cond_string = xstrdup (cond_string);
make_cleanup (xfree, cond_string);
}
+ /* Create a private copy of any extra string. */
+ if (extra_string != NULL)
+ {
+ extra_string = xstrdup (extra_string);
+ make_cleanup (xfree, extra_string);
+ }
b->cond_string = cond_string;
+ b->extra_string = extra_string;
+ b->thread = thread;
}
- b->extra_string = NULL;
b->ignore_count = ignore_count;
b->disposition = tempflag ? disp_del : disp_donttouch;
b->condition_not_parsed = 1;
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);
- 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)
{
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
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 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)
{
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;
{
/* 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
}
bpt->enable_state = bp_enabled;
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. */
/* 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");
}
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->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\