/* Memory breakpoint operations for the remote server for GDB.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2018 Free Software Foundation, Inc.
Contributed by MontaVista Software.
/* A GDB access watchpoint, requested with a Z4 packet. */
gdb_breakpoint_Z4,
- /* A basic-software-single-step breakpoint. */
- reinsert_breakpoint,
+ /* A software single-step breakpoint. */
+ single_step_breakpoint,
/* Any other breakpoint type that doesn't require specific
treatment goes here. E.g., an event breakpoint. */
int (*handler) (CORE_ADDR);
};
-/* Reinsert breakpoint. */
+/* Breakpoint for single step. */
-struct reinsert_breakpoint
+struct single_step_breakpoint
{
struct breakpoint base;
+
+ /* Thread the reinsert breakpoint belongs to. */
+ ptid_t ptid;
};
/* Return the breakpoint size from its kind. */
{
struct process_info *proc = current_process ();
struct raw_breakpoint *bp;
- struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
if (type == raw_bkpt_type_sw || type == raw_bkpt_type_hw)
{
else
bp = find_raw_breakpoint_at (where, type, kind);
+ gdb::unique_xmalloc_ptr<struct raw_breakpoint> bp_holder;
if (bp == NULL)
{
- bp = XCNEW (struct raw_breakpoint);
+ bp_holder.reset (XCNEW (struct raw_breakpoint));
+ bp = bp_holder.get ();
bp->pc = where;
bp->kind = kind;
bp->raw_type = type;
- make_cleanup (xfree, bp);
}
if (!bp->inserted)
debug_printf ("Failed to insert breakpoint at 0x%s (%d).\n",
paddress (where), *err);
- do_cleanups (old_chain);
return NULL;
}
bp->inserted = 1;
}
- discard_cleanups (old_chain);
+ /* If the breakpoint was allocated above, we know we want to keep it
+ now. */
+ bp_holder.release ();
/* Link the breakpoint in, if this is the first reference. */
if (++bp->refcount == 1)
other_bp->handler = handler;
bp = (struct breakpoint *) other_bp;
}
- else if (type == reinsert_breakpoint)
+ else if (type == single_step_breakpoint)
{
- struct reinsert_breakpoint *reinsert_bp
- = XCNEW (struct reinsert_breakpoint);
+ struct single_step_breakpoint *ss_bp
+ = XCNEW (struct single_step_breakpoint);
- bp = (struct breakpoint *) reinsert_bp;
+ bp = (struct breakpoint *) ss_bp;
}
else
gdb_assert_not_reached ("unhandled breakpoint type");
for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
if (bp->type == type && bp->raw->pc == addr
&& (kind == -1 || bp->raw->kind == kind))
- return (gdb_breakpoint *) bp;
+ return (struct gdb_breakpoint *) bp;
return NULL;
}
/* Add a target-side condition CONDITION to a breakpoint. */
int
-add_breakpoint_condition (struct gdb_breakpoint *bp, char **condition)
+add_breakpoint_condition (struct gdb_breakpoint *bp, const char **condition)
{
- char *actparm = *condition;
+ const char *actparm = *condition;
struct agent_expr *cond;
if (condition == NULL)
if (cond == NULL)
{
- fprintf (stderr, "Condition evaluation failed. "
- "Assuming unconditional.\n");
+ warning ("Condition evaluation failed. Assuming unconditional.");
return 0;
}
/* Add a target-side command COMMAND to the breakpoint at ADDR. */
int
-add_breakpoint_commands (struct gdb_breakpoint *bp, char **command,
+add_breakpoint_commands (struct gdb_breakpoint *bp, const char **command,
int persist)
{
- char *actparm = *command;
+ const char *actparm = *command;
struct agent_expr *cmd;
if (command == NULL)
if (cmd == NULL)
{
- fprintf (stderr, "Command evaluation failed. "
- "Disabling.\n");
+ warning ("Command evaluation failed. Disabling.");
return 0;
}
}
void
-set_reinsert_breakpoint (CORE_ADDR stop_at)
+set_single_step_breakpoint (CORE_ADDR stop_at, ptid_t ptid)
{
- struct breakpoint *bp;
+ struct single_step_breakpoint *bp;
+
+ gdb_assert (ptid_get_pid (current_ptid) == ptid_get_pid (ptid));
- bp = set_breakpoint_type_at (reinsert_breakpoint, stop_at, NULL);
+ bp = (struct single_step_breakpoint *) set_breakpoint_type_at (single_step_breakpoint,
+ stop_at, NULL);
+ bp->ptid = ptid;
}
void
-delete_reinsert_breakpoints (void)
+delete_single_step_breakpoints (struct thread_info *thread)
{
- struct process_info *proc = current_process ();
+ struct process_info *proc = get_thread_process (thread);
struct breakpoint *bp, **bp_link;
bp = proc->breakpoints;
while (bp)
{
- if (bp->type == reinsert_breakpoint)
+ if (bp->type == single_step_breakpoint
+ && ptid_equal (((struct single_step_breakpoint *) bp)->ptid,
+ ptid_of (thread)))
{
+ struct thread_info *saved_thread = current_thread;
+
+ current_thread = thread;
*bp_link = bp->next;
release_breakpoint (proc, bp);
bp = *bp_link;
+ current_thread = saved_thread;
}
else
{
}
void
-uninsert_reinsert_breakpoints (void)
+uninsert_single_step_breakpoints (struct thread_info *thread)
{
- struct process_info *proc = current_process ();
+ struct process_info *proc = get_thread_process (thread);
struct breakpoint *bp;
for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
{
- if (bp->type == reinsert_breakpoint)
+ if (bp->type == single_step_breakpoint
+ && ptid_equal (((struct single_step_breakpoint *) bp)->ptid,
+ ptid_of (thread)))
{
gdb_assert (bp->raw->inserted > 0);
/* Only uninsert the raw breakpoint if it only belongs to a
reinsert breakpoint. */
if (bp->raw->refcount == 1)
- uninsert_raw_breakpoint (bp->raw);
+ {
+ struct thread_info *saved_thread = current_thread;
+
+ current_thread = thread;
+ uninsert_raw_breakpoint (bp->raw);
+ current_thread = saved_thread;
+ }
}
}
}
}
int
-has_reinsert_breakpoints (struct process_info *proc)
+has_single_step_breakpoints (struct thread_info *thread)
{
+ struct process_info *proc = get_thread_process (thread);
struct breakpoint *bp, **bp_link;
bp = proc->breakpoints;
while (bp)
{
- if (bp->type == reinsert_breakpoint)
+ if (bp->type == single_step_breakpoint
+ && ptid_equal (((struct single_step_breakpoint *) bp)->ptid,
+ ptid_of (thread)))
return 1;
else
{
}
void
-reinsert_reinsert_breakpoints (void)
+reinsert_single_step_breakpoints (struct thread_info *thread)
{
- struct process_info *proc = current_process ();
+ struct process_info *proc = get_thread_process (thread);
struct breakpoint *bp;
for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
{
- if (bp->type == reinsert_breakpoint)
+ if (bp->type == single_step_breakpoint
+ && ptid_equal (((struct single_step_breakpoint *) bp)->ptid,
+ ptid_of (thread)))
{
gdb_assert (bp->raw->inserted > 0);
if (bp->raw->refcount == 1)
- reinsert_raw_breakpoint (bp->raw);
+ {
+ struct thread_info *saved_thread = current_thread;
+
+ current_thread = thread;
+ reinsert_raw_breakpoint (bp->raw);
+ current_thread = saved_thread;
+ }
}
}
}
/* See mem-break.h. */
int
-reinsert_breakpoint_inserted_here (CORE_ADDR addr)
+single_step_breakpoint_inserted_here (CORE_ADDR addr)
{
struct process_info *proc = current_process ();
struct breakpoint *bp;
for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
- if (bp->type == reinsert_breakpoint
+ if (bp->type == single_step_breakpoint
&& bp->raw->pc == addr
&& bp->raw->inserted)
return 1;
next = bp->next;
if (bp->raw->inserted < 0)
{
- /* If reinsert_breakpoints become disabled, that means the
+ /* If single_step_breakpoints become disabled, that means the
manipulations (insertion and removal) of them are wrong. */
- gdb_assert (bp->type != reinsert_breakpoint);
+ gdb_assert (bp->type != single_step_breakpoint);
delete_breakpoint_1 (proc, bp);
}
}
/* Deep-copy the contents of one breakpoint to another. */
static struct breakpoint *
-clone_one_breakpoint (const struct breakpoint *src)
+clone_one_breakpoint (const struct breakpoint *src, ptid_t ptid)
{
struct breakpoint *dest;
struct raw_breakpoint *dest_raw;
other_dest->handler = ((struct other_breakpoint *) src)->handler;
dest = (struct breakpoint *) other_dest;
}
- else if (src->type == reinsert_breakpoint)
+ else if (src->type == single_step_breakpoint)
{
- struct reinsert_breakpoint *reinsert_dest
- = XCNEW (struct reinsert_breakpoint);
+ struct single_step_breakpoint *ss_dest
+ = XCNEW (struct single_step_breakpoint);
- dest = (struct breakpoint *) reinsert_dest;
+ dest = (struct breakpoint *) ss_dest;
+ /* Since single-step breakpoint is thread specific, don't copy
+ thread id from SRC, use ID instead. */
+ ss_dest->ptid = ptid;
}
else
gdb_assert_not_reached ("unhandled breakpoint type");
return dest;
}
-/* Create a new breakpoint list NEW_LIST that is a copy of the
- list starting at SRC_LIST. Create the corresponding new
- raw_breakpoint list NEW_RAW_LIST as well. */
+/* See mem-break.h. */
void
-clone_all_breakpoints (struct breakpoint **new_list,
- struct raw_breakpoint **new_raw_list,
- const struct breakpoint *src_list)
+clone_all_breakpoints (struct thread_info *child_thread,
+ const struct thread_info *parent_thread)
{
const struct breakpoint *bp;
struct breakpoint *new_bkpt;
struct breakpoint *bkpt_tail = NULL;
struct raw_breakpoint *raw_bkpt_tail = NULL;
+ struct process_info *child_proc = get_thread_process (child_thread);
+ struct process_info *parent_proc = get_thread_process (parent_thread);
+ struct breakpoint **new_list = &child_proc->breakpoints;
+ struct raw_breakpoint **new_raw_list = &child_proc->raw_breakpoints;
- for (bp = src_list; bp != NULL; bp = bp->next)
+ for (bp = parent_proc->breakpoints; bp != NULL; bp = bp->next)
{
- new_bkpt = clone_one_breakpoint (bp);
+ new_bkpt = clone_one_breakpoint (bp, ptid_of (child_thread));
APPEND_TO_LIST (new_list, new_bkpt, bkpt_tail);
APPEND_TO_LIST (new_raw_list, new_bkpt->raw, raw_bkpt_tail);
}