mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-25 11:04:18 +08:00
Teach linux gdbserver to step-over-breakpoints.
* linux-low.c (can_hardware_single_step): New. (supports_breakpoints): New. (handle_extended_wait): If stopping threads, read the stop pc of the new cloned LWP. (get_pc): New. (get_stop_pc): Add `lwp' parameter. Handle it. Bail out if the low target doesn't support retrieving the PC. (add_lwp): Set last_resume_kind to resume_continue. (linux_attach_lwp_1): Adjust comments. Always set stop_expected. (linux_attach): Don't clear stop_expected. Set the lwp's last_resume_kind to resume_stop. (linux_detach_one_lwp): Don't check for removed breakpoints. (check_removed_breakpoint): Delete. (status_pending_p): Rename to ... (status_pending_p_callback): ... this. Don't check for removed breakpoints. Don't consider threads that are stopped from GDB's perspective. (linux_wait_for_lwp): Always read the stop_pc here. (cancel_breakpoint): New. (step_over_bkpt): New global. (linux_wait_for_event_1): Implement stepping over breakpoints. (gdb_wants_lwp_stopped): New. (gdb_wants_all_stopped): New. (linux_wait_1): Tag threads as gdb-wants-stopped. Cancel finished single-step traps here. Store the thread's last reported target wait status. (send_sigstop): Don't clear stop_expected. Always set it, instead. (mark_lwp_dead): Remove reference to pending_is_breakpoint. (cancel_finished_single_step): New. (cancel_finished_single_steps): New. (wait_for_sigstop): Don't cancel finished single-step traps here. (linux_resume_one_lwp): Don't check for removed breakpoints. Don't set `step' on non-hardware step archs. (linux_set_resume_request): Ignore resume_stop requests if already stopping or stopped. Set the lwp's last_resume_kind. (resume_status_pending_p): Don't check for removed breakpoints. (need_step_over_p): New. (start_step_over): New. (finish_step_over): New. (linux_resume_one_thread): Always queue a sigstop for resume_stop requests. Clear the thread's last reported target waitstatus. Don't use the `suspended' flag. Don't consider pending breakpoints. (linux_resume): Start a step-over if necessary. (proceed_one_lwp): New. (proceed_all_lwps): New. (unstop_all_lwps): New. * linux-low.h (struct lwp_info): Rewrite comment for the `suspended' flag. Add the `stop_pc' field. Delete the `pending_stop_pc' field. Tweak the `stepping' flag's comment. Add `'last_resume_kind' and `need_step_over' fields. * inferiors.c (struct thread_info): Delete, moved elsewhere. * mem-break.c (struct breakpoint): Delete `reinserting' flag. Delete `breakpoint_to_reinsert' field. New flag `inserted'. (set_raw_breakpoint_at): New. (set_breakpoint_at): Rewrite to use it. (reinsert_breakpoint_handler): Delete. (set_reinsert_breakpoint): New. (reinsert_breakpoint_by_bp): Delete. (delete_reinsert_breakpoints): New. (uninsert_breakpoint): Rewrite. (uninsert_breakpoints_at): New. (reinsert_breakpoint): Rewrite. (reinsert_breakpoints_at): New. (check_breakpoints): Rewrite. (breakpoint_here): New. (breakpoint_inserted_here): New. (check_mem_read): Adjust. * mem-break.h (breakpoints_supported, breakpoint_here) (breakpoint_inserted_here, set_reinsert_breakpoint): Declare. (reinsert_breakpoint_by_bp): Delete declaration. (delete_reinsert_breakpoints): Declare. (reinsert_breakpoint): Delete declaration. (reinsert_breakpoints_at): Declare. (uninsert_breakpoint): Delete declaration. (uninsert_breakpoints_at): Declare. (check_breakpoints): Adjust prototype. * server.h: Adjust include order. (struct thread_info): Declare here. Add a `last_status' field.
This commit is contained in:
parent
8541339168
commit
d50171e439
@ -1,3 +1,87 @@
|
||||
2010-03-24 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
Teach linux gdbserver to step-over-breakpoints.
|
||||
|
||||
* linux-low.c (can_hardware_single_step): New.
|
||||
(supports_breakpoints): New.
|
||||
(handle_extended_wait): If stopping threads, read the stop pc of
|
||||
the new cloned LWP.
|
||||
(get_pc): New.
|
||||
(get_stop_pc): Add `lwp' parameter. Handle it. Bail out if the
|
||||
low target doesn't support retrieving the PC.
|
||||
(add_lwp): Set last_resume_kind to resume_continue.
|
||||
(linux_attach_lwp_1): Adjust comments. Always set stop_expected.
|
||||
(linux_attach): Don't clear stop_expected. Set the lwp's
|
||||
last_resume_kind to resume_stop.
|
||||
(linux_detach_one_lwp): Don't check for removed breakpoints.
|
||||
(check_removed_breakpoint): Delete.
|
||||
(status_pending_p): Rename to ...
|
||||
(status_pending_p_callback): ... this. Don't check for removed
|
||||
breakpoints. Don't consider threads that are stopped from GDB's
|
||||
perspective.
|
||||
(linux_wait_for_lwp): Always read the stop_pc here.
|
||||
(cancel_breakpoint): New.
|
||||
(step_over_bkpt): New global.
|
||||
(linux_wait_for_event_1): Implement stepping over breakpoints.
|
||||
(gdb_wants_lwp_stopped): New.
|
||||
(gdb_wants_all_stopped): New.
|
||||
(linux_wait_1): Tag threads as gdb-wants-stopped. Cancel finished
|
||||
single-step traps here. Store the thread's last reported target
|
||||
wait status.
|
||||
(send_sigstop): Don't clear stop_expected. Always set it,
|
||||
instead.
|
||||
(mark_lwp_dead): Remove reference to pending_is_breakpoint.
|
||||
(cancel_finished_single_step): New.
|
||||
(cancel_finished_single_steps): New.
|
||||
(wait_for_sigstop): Don't cancel finished single-step traps here.
|
||||
(linux_resume_one_lwp): Don't check for removed breakpoints.
|
||||
Don't set `step' on non-hardware step archs.
|
||||
(linux_set_resume_request): Ignore resume_stop requests if already
|
||||
stopping or stopped. Set the lwp's last_resume_kind.
|
||||
(resume_status_pending_p): Don't check for removed breakpoints.
|
||||
(need_step_over_p): New.
|
||||
(start_step_over): New.
|
||||
(finish_step_over): New.
|
||||
(linux_resume_one_thread): Always queue a sigstop for resume_stop
|
||||
requests. Clear the thread's last reported target waitstatus.
|
||||
Don't use the `suspended' flag. Don't consider pending breakpoints.
|
||||
(linux_resume): Start a step-over if necessary.
|
||||
(proceed_one_lwp): New.
|
||||
(proceed_all_lwps): New.
|
||||
(unstop_all_lwps): New.
|
||||
* linux-low.h (struct lwp_info): Rewrite comment for the
|
||||
`suspended' flag. Add the `stop_pc' field. Delete the
|
||||
`pending_stop_pc' field. Tweak the `stepping' flag's comment.
|
||||
Add `'last_resume_kind' and `need_step_over' fields.
|
||||
* inferiors.c (struct thread_info): Delete, moved elsewhere.
|
||||
* mem-break.c (struct breakpoint): Delete `reinserting' flag.
|
||||
Delete `breakpoint_to_reinsert' field. New flag `inserted'.
|
||||
(set_raw_breakpoint_at): New.
|
||||
(set_breakpoint_at): Rewrite to use it.
|
||||
(reinsert_breakpoint_handler): Delete.
|
||||
(set_reinsert_breakpoint): New.
|
||||
(reinsert_breakpoint_by_bp): Delete.
|
||||
(delete_reinsert_breakpoints): New.
|
||||
(uninsert_breakpoint): Rewrite.
|
||||
(uninsert_breakpoints_at): New.
|
||||
(reinsert_breakpoint): Rewrite.
|
||||
(reinsert_breakpoints_at): New.
|
||||
(check_breakpoints): Rewrite.
|
||||
(breakpoint_here): New.
|
||||
(breakpoint_inserted_here): New.
|
||||
(check_mem_read): Adjust.
|
||||
* mem-break.h (breakpoints_supported, breakpoint_here)
|
||||
(breakpoint_inserted_here, set_reinsert_breakpoint): Declare.
|
||||
(reinsert_breakpoint_by_bp): Delete declaration.
|
||||
(delete_reinsert_breakpoints): Declare.
|
||||
(reinsert_breakpoint): Delete declaration.
|
||||
(reinsert_breakpoints_at): Declare.
|
||||
(uninsert_breakpoint): Delete declaration.
|
||||
(uninsert_breakpoints_at): Declare.
|
||||
(check_breakpoints): Adjust prototype.
|
||||
* server.h: Adjust include order.
|
||||
(struct thread_info): Declare here. Add a `last_status' field.
|
||||
|
||||
2010-03-23 Michael Snyder <msnyder@vmware.com>
|
||||
|
||||
* server.c (crc32): New function.
|
||||
|
@ -23,14 +23,6 @@
|
||||
|
||||
#include "server.h"
|
||||
|
||||
struct thread_info
|
||||
{
|
||||
struct inferior_list_entry entry;
|
||||
void *target_data;
|
||||
void *regcache_data;
|
||||
unsigned int gdb_id;
|
||||
};
|
||||
|
||||
struct inferior_list all_processes;
|
||||
struct inferior_list all_threads;
|
||||
struct inferior_list all_dlls;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -137,7 +137,8 @@ struct lwp_info
|
||||
yet. */
|
||||
int stop_expected;
|
||||
|
||||
/* True if this thread was suspended (with vCont;t). */
|
||||
/* When this is true, we shall not try to resume this thread, even
|
||||
if last_resume_kind isn't resume_stop. */
|
||||
int suspended;
|
||||
|
||||
/* If this flag is set, the lwp is known to be stopped right now (stop
|
||||
@ -152,15 +153,15 @@ struct lwp_info
|
||||
/* When stopped is set, the last wait status recorded for this lwp. */
|
||||
int last_status;
|
||||
|
||||
/* When stopped is set, this is where the lwp stopped, with
|
||||
decr_pc_after_break already accounted for. */
|
||||
CORE_ADDR stop_pc;
|
||||
|
||||
/* If this flag is set, STATUS_PENDING is a waitstatus that has not yet
|
||||
been reported. */
|
||||
int status_pending_p;
|
||||
int status_pending;
|
||||
|
||||
/* If this flag is set, the pending status is a (GDB-placed) breakpoint. */
|
||||
int pending_is_breakpoint;
|
||||
CORE_ADDR pending_stop_pc;
|
||||
|
||||
/* STOPPED_BY_WATCHPOINT is non-zero if this LWP stopped with a data
|
||||
watchpoint trap. */
|
||||
int stopped_by_watchpoint;
|
||||
@ -175,8 +176,8 @@ struct lwp_info
|
||||
stop (SIGTRAP stops only). */
|
||||
CORE_ADDR bp_reinsert;
|
||||
|
||||
/* If this flag is set, the last continue operation on this process
|
||||
was a single-step. */
|
||||
/* If this flag is set, the last continue operation at the ptrace
|
||||
level on this process was a single-step. */
|
||||
int stepping;
|
||||
|
||||
/* If this flag is set, we need to set the event request flags the
|
||||
@ -189,9 +190,15 @@ struct lwp_info
|
||||
|
||||
/* A link used when resuming. It is initialized from the resume request,
|
||||
and then processed and cleared in linux_resume_one_lwp. */
|
||||
|
||||
struct thread_resume *resume;
|
||||
|
||||
/* The last resume GDB requested on this thread. */
|
||||
enum resume_kind last_resume_kind;
|
||||
|
||||
/* True if the LWP was seen stop at an internal breakpoint and needs
|
||||
stepping over later when it is resumed. */
|
||||
int need_step_over;
|
||||
|
||||
int thread_known;
|
||||
#ifdef HAVE_THREAD_DB_H
|
||||
/* The thread handle, used for e.g. TLS access. Only valid if
|
||||
|
@ -32,38 +32,75 @@ struct breakpoint
|
||||
CORE_ADDR pc;
|
||||
unsigned char old_data[MAX_BREAKPOINT_LEN];
|
||||
|
||||
/* Non-zero iff we are stepping over this breakpoint. */
|
||||
int reinserting;
|
||||
|
||||
/* Non-NULL iff this breakpoint was inserted to step over
|
||||
another one. Points to the other breakpoint (which is also
|
||||
in the *next chain somewhere). */
|
||||
struct breakpoint *breakpoint_to_reinsert;
|
||||
/* Non-zero if this breakpoint is currently inserted in the
|
||||
inferior. */
|
||||
int inserted;
|
||||
|
||||
/* Function to call when we hit this breakpoint. If it returns 1,
|
||||
the breakpoint will be deleted; 0, it will be reinserted for
|
||||
another round. */
|
||||
the breakpoint shall be deleted; 0, it will be left inserted. */
|
||||
int (*handler) (CORE_ADDR);
|
||||
};
|
||||
|
||||
static struct breakpoint *
|
||||
set_raw_breakpoint_at (CORE_ADDR where)
|
||||
{
|
||||
struct process_info *proc = current_process ();
|
||||
struct breakpoint *bp;
|
||||
int err;
|
||||
|
||||
if (breakpoint_data == NULL)
|
||||
error ("Target does not support breakpoints.");
|
||||
|
||||
bp = xcalloc (1, sizeof (*bp));
|
||||
bp->pc = where;
|
||||
|
||||
err = (*the_target->read_memory) (where, bp->old_data,
|
||||
breakpoint_len);
|
||||
if (err != 0)
|
||||
{
|
||||
if (debug_threads)
|
||||
fprintf (stderr,
|
||||
"Failed to read shadow memory of"
|
||||
" breakpoint at 0x%s (%s).\n",
|
||||
paddress (where), strerror (err));
|
||||
free (bp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = (*the_target->write_memory) (where, breakpoint_data,
|
||||
breakpoint_len);
|
||||
if (err != 0)
|
||||
{
|
||||
if (debug_threads)
|
||||
fprintf (stderr,
|
||||
"Failed to insert breakpoint at 0x%s (%s).\n",
|
||||
paddress (where), strerror (err));
|
||||
free (bp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Link the breakpoint in. */
|
||||
bp->inserted = 1;
|
||||
bp->next = proc->breakpoints;
|
||||
proc->breakpoints = bp;
|
||||
return bp;
|
||||
}
|
||||
|
||||
void
|
||||
set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
|
||||
{
|
||||
struct process_info *proc = current_process ();
|
||||
struct breakpoint *bp;
|
||||
|
||||
if (breakpoint_data == NULL)
|
||||
error ("Target does not support breakpoints.");
|
||||
bp = set_raw_breakpoint_at (where);
|
||||
|
||||
bp = xmalloc (sizeof (struct breakpoint));
|
||||
memset (bp, 0, sizeof (struct breakpoint));
|
||||
if (bp == NULL)
|
||||
{
|
||||
/* warn? */
|
||||
return;
|
||||
}
|
||||
|
||||
(*the_target->read_memory) (where, bp->old_data,
|
||||
breakpoint_len);
|
||||
(*the_target->write_memory) (where, breakpoint_data,
|
||||
breakpoint_len);
|
||||
|
||||
bp->pc = where;
|
||||
bp = xcalloc (1, sizeof (struct breakpoint));
|
||||
bp->handler = handler;
|
||||
|
||||
bp->next = proc->breakpoints;
|
||||
@ -123,97 +160,145 @@ delete_breakpoint_at (CORE_ADDR addr)
|
||||
delete_breakpoint (bp);
|
||||
}
|
||||
|
||||
static int
|
||||
reinsert_breakpoint_handler (CORE_ADDR stop_pc)
|
||||
void
|
||||
set_reinsert_breakpoint (CORE_ADDR stop_at)
|
||||
{
|
||||
struct breakpoint *stop_bp, *orig_bp;
|
||||
|
||||
stop_bp = find_breakpoint_at (stop_pc);
|
||||
if (stop_bp == NULL)
|
||||
error ("lost the stopping breakpoint.");
|
||||
|
||||
orig_bp = stop_bp->breakpoint_to_reinsert;
|
||||
if (orig_bp == NULL)
|
||||
error ("no breakpoint to reinsert");
|
||||
|
||||
(*the_target->write_memory) (orig_bp->pc, breakpoint_data,
|
||||
breakpoint_len);
|
||||
orig_bp->reinserting = 0;
|
||||
return 1;
|
||||
set_breakpoint_at (stop_at, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
reinsert_breakpoint_by_bp (CORE_ADDR stop_pc, CORE_ADDR stop_at)
|
||||
delete_reinsert_breakpoints (void)
|
||||
{
|
||||
struct breakpoint *bp, *orig_bp;
|
||||
struct process_info *proc = current_process ();
|
||||
struct breakpoint *bp, **bp_link;
|
||||
|
||||
orig_bp = find_breakpoint_at (stop_pc);
|
||||
if (orig_bp == NULL)
|
||||
error ("Could not find original breakpoint in list.");
|
||||
bp = proc->breakpoints;
|
||||
bp_link = &proc->breakpoints;
|
||||
|
||||
set_breakpoint_at (stop_at, reinsert_breakpoint_handler);
|
||||
while (bp)
|
||||
{
|
||||
*bp_link = bp->next;
|
||||
delete_breakpoint (bp);
|
||||
bp = *bp_link;
|
||||
}
|
||||
}
|
||||
|
||||
bp = find_breakpoint_at (stop_at);
|
||||
if (bp == NULL)
|
||||
error ("Could not find breakpoint in list (reinserting by breakpoint).");
|
||||
bp->breakpoint_to_reinsert = orig_bp;
|
||||
static void
|
||||
uninsert_breakpoint (struct breakpoint *bp)
|
||||
{
|
||||
if (bp->inserted)
|
||||
{
|
||||
int err;
|
||||
|
||||
(*the_target->write_memory) (orig_bp->pc, orig_bp->old_data,
|
||||
breakpoint_len);
|
||||
orig_bp->reinserting = 1;
|
||||
bp->inserted = 0;
|
||||
err = (*the_target->write_memory) (bp->pc, bp->old_data,
|
||||
breakpoint_len);
|
||||
if (err != 0)
|
||||
{
|
||||
bp->inserted = 1;
|
||||
|
||||
if (debug_threads)
|
||||
fprintf (stderr,
|
||||
"Failed to uninsert raw breakpoint at 0x%s (%s).\n",
|
||||
paddress (bp->pc), strerror (err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
uninsert_breakpoint (CORE_ADDR stopped_at)
|
||||
uninsert_breakpoints_at (CORE_ADDR pc)
|
||||
{
|
||||
struct breakpoint *bp;
|
||||
|
||||
bp = find_breakpoint_at (stopped_at);
|
||||
bp = find_breakpoint_at (pc);
|
||||
if (bp == NULL)
|
||||
error ("Could not find breakpoint in list (uninserting).");
|
||||
{
|
||||
/* This can happen when we remove all breakpoints while handling
|
||||
a step-over. */
|
||||
if (debug_threads)
|
||||
fprintf (stderr,
|
||||
"Could not find breakpoint at 0x%s "
|
||||
"in list (uninserting).\n",
|
||||
paddress (pc));
|
||||
return;
|
||||
}
|
||||
|
||||
(*the_target->write_memory) (bp->pc, bp->old_data,
|
||||
breakpoint_len);
|
||||
bp->reinserting = 1;
|
||||
if (bp->inserted)
|
||||
uninsert_breakpoint (bp);
|
||||
}
|
||||
|
||||
void
|
||||
reinsert_breakpoint (CORE_ADDR stopped_at)
|
||||
static void
|
||||
reinsert_breakpoint (struct breakpoint *bp)
|
||||
{
|
||||
struct breakpoint *bp;
|
||||
int err;
|
||||
|
||||
bp = find_breakpoint_at (stopped_at);
|
||||
if (bp == NULL)
|
||||
error ("Could not find breakpoint in list (uninserting).");
|
||||
if (! bp->reinserting)
|
||||
if (bp->inserted)
|
||||
error ("Breakpoint already inserted at reinsert time.");
|
||||
|
||||
(*the_target->write_memory) (bp->pc, breakpoint_data,
|
||||
breakpoint_len);
|
||||
bp->reinserting = 0;
|
||||
err = (*the_target->write_memory) (bp->pc, breakpoint_data,
|
||||
breakpoint_len);
|
||||
if (err == 0)
|
||||
bp->inserted = 1;
|
||||
else if (debug_threads)
|
||||
fprintf (stderr,
|
||||
"Failed to reinsert breakpoint at 0x%s (%s).\n",
|
||||
paddress (bp->pc), strerror (err));
|
||||
}
|
||||
|
||||
int
|
||||
check_breakpoints (CORE_ADDR stop_pc)
|
||||
void
|
||||
reinsert_breakpoints_at (CORE_ADDR pc)
|
||||
{
|
||||
struct breakpoint *bp;
|
||||
|
||||
bp = find_breakpoint_at (stop_pc);
|
||||
bp = find_breakpoint_at (pc);
|
||||
if (bp == NULL)
|
||||
return 0;
|
||||
if (bp->reinserting)
|
||||
{
|
||||
warning ("Hit a removed breakpoint?");
|
||||
return 0;
|
||||
/* This can happen when we remove all breakpoints while handling
|
||||
a step-over. */
|
||||
if (debug_threads)
|
||||
fprintf (stderr,
|
||||
"Could not find breakpoint at 0x%s "
|
||||
"in list (reinserting).\n",
|
||||
paddress (pc));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((*bp->handler) (bp->pc))
|
||||
reinsert_breakpoint (bp);
|
||||
}
|
||||
|
||||
void
|
||||
check_breakpoints (CORE_ADDR stop_pc)
|
||||
{
|
||||
struct process_info *proc = current_process ();
|
||||
struct breakpoint *bp, **bp_link;
|
||||
|
||||
bp = proc->breakpoints;
|
||||
bp_link = &proc->breakpoints;
|
||||
|
||||
while (bp)
|
||||
{
|
||||
delete_breakpoint (bp);
|
||||
return 2;
|
||||
if (bp->pc == stop_pc)
|
||||
{
|
||||
if (!bp->inserted)
|
||||
{
|
||||
warning ("Hit a removed breakpoint?");
|
||||
return;
|
||||
}
|
||||
|
||||
if (bp->handler != NULL && (*bp->handler) (stop_pc))
|
||||
{
|
||||
*bp_link = bp->next;
|
||||
|
||||
delete_breakpoint (bp);
|
||||
|
||||
bp = *bp_link;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bp_link = &bp->next;
|
||||
bp = *bp_link;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
@ -223,6 +308,32 @@ set_breakpoint_data (const unsigned char *bp_data, int bp_len)
|
||||
breakpoint_len = bp_len;
|
||||
}
|
||||
|
||||
int
|
||||
breakpoint_here (CORE_ADDR addr)
|
||||
{
|
||||
struct process_info *proc = current_process ();
|
||||
struct breakpoint *bp;
|
||||
|
||||
for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
|
||||
if (bp->pc == addr)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
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->pc == addr && bp->inserted)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
|
||||
{
|
||||
@ -288,7 +399,7 @@ check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
|
||||
buf_offset = start - mem_addr;
|
||||
|
||||
memcpy (bp->old_data + copy_offset, buf + buf_offset, copy_len);
|
||||
if (bp->reinserting == 0)
|
||||
if (bp->inserted)
|
||||
memcpy (buf + buf_offset, breakpoint_data + copy_offset, copy_len);
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,19 @@
|
||||
|
||||
/* Breakpoints are opaque. */
|
||||
|
||||
/* Returns TRUE if breakpoints are supported on this target. */
|
||||
|
||||
int breakpoints_supported (void);
|
||||
|
||||
/* Returns TRUE if there's any breakpoint at ADDR in our tables,
|
||||
inserted, or not. */
|
||||
|
||||
int breakpoint_here (CORE_ADDR addr);
|
||||
|
||||
/* Returns TRUE if there's any inserted breakpoint set at ADDR. */
|
||||
|
||||
int breakpoint_inserted_here (CORE_ADDR addr);
|
||||
|
||||
/* Create a new breakpoint at WHERE, and call HANDLER when
|
||||
it is hit. HANDLER should return 1 if the breakpoint
|
||||
should be deleted, 0 otherwise. */
|
||||
@ -36,24 +49,28 @@ void set_breakpoint_at (CORE_ADDR where,
|
||||
|
||||
void delete_breakpoint_at (CORE_ADDR addr);
|
||||
|
||||
/* Create a reinsertion breakpoint at STOP_AT for the breakpoint
|
||||
currently at STOP_PC (and temporarily remove the breakpoint at
|
||||
STOP_PC). */
|
||||
/* Set a reinsert breakpoint at STOP_AT. */
|
||||
|
||||
void reinsert_breakpoint_by_bp (CORE_ADDR stop_pc, CORE_ADDR stop_at);
|
||||
void set_reinsert_breakpoint (CORE_ADDR stop_at);
|
||||
|
||||
/* Change the status of the breakpoint at WHERE to inserted. */
|
||||
/* Delete all reinsert breakpoints. */
|
||||
|
||||
void reinsert_breakpoint (CORE_ADDR where);
|
||||
void delete_reinsert_breakpoints (void);
|
||||
|
||||
/* Change the status of the breakpoint at WHERE to uninserted. */
|
||||
/* Reinsert breakpoints at WHERE (and change their status to
|
||||
inserted). */
|
||||
|
||||
void uninsert_breakpoint (CORE_ADDR where);
|
||||
void reinsert_breakpoints_at (CORE_ADDR where);
|
||||
|
||||
/* Uninsert breakpoints at WHERE (and change their status to
|
||||
uninserted). This still leaves the breakpoints in the table. */
|
||||
|
||||
void uninsert_breakpoints_at (CORE_ADDR where);
|
||||
|
||||
/* See if any breakpoint claims ownership of STOP_PC. Call the handler for
|
||||
the breakpoint, if found. */
|
||||
|
||||
int check_breakpoints (CORE_ADDR stop_pc);
|
||||
void check_breakpoints (CORE_ADDR stop_pc);
|
||||
|
||||
/* See if any breakpoints shadow the target memory area from MEM_ADDR
|
||||
to MEM_ADDR + MEM_LEN. Update the data already read from the target
|
||||
|
@ -162,8 +162,25 @@ struct inferior_list_entry
|
||||
struct inferior_list_entry *next;
|
||||
};
|
||||
|
||||
/* Opaque type for user-visible threads. */
|
||||
struct thread_info;
|
||||
struct process_info;
|
||||
struct regcache;
|
||||
|
||||
#include "regcache.h"
|
||||
#include "gdb/signals.h"
|
||||
#include "gdb_signals.h"
|
||||
#include "target.h"
|
||||
#include "mem-break.h"
|
||||
|
||||
struct thread_info
|
||||
{
|
||||
struct inferior_list_entry entry;
|
||||
void *target_data;
|
||||
void *regcache_data;
|
||||
|
||||
/* The last wait status reported for this thread. */
|
||||
struct target_waitstatus last_status;
|
||||
};
|
||||
|
||||
struct dll_info
|
||||
{
|
||||
@ -203,12 +220,6 @@ struct process_info
|
||||
struct process_info *current_process (void);
|
||||
struct process_info *get_thread_process (struct thread_info *);
|
||||
|
||||
#include "regcache.h"
|
||||
#include "gdb/signals.h"
|
||||
#include "gdb_signals.h"
|
||||
#include "target.h"
|
||||
#include "mem-break.h"
|
||||
|
||||
/* Target-specific functions */
|
||||
|
||||
void initialize_low ();
|
||||
|
Loading…
Reference in New Issue
Block a user