mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-21 02:24:17 +08:00
* linux-low.c (linux_wait_1): Avoid setting need_step_over is
there's a GDB breakpoint at stop_pc. Always report a trap to GDB if we could tell there's a GDB breakpoint at stop_pc. (need_step_over_p): Don't do a step over if we find a GDB breakpoint at the resume PC. * mem-break.c (struct raw_breakpoint): New. (enum bkpt_type): New type `gdb_breakpoint'. (struct breakpoint): Delete the `PC', `old_data' and `inserted' fields. New field `raw'. (find_raw_breakpoint_at): New. (set_raw_breakpoint_at): Handle refcounting. Create a raw breakpoint instead. (set_breakpoint_at): Adjust. (delete_raw_breakpoint): New. (release_breakpoint): New. (delete_breakpoint): Rename to... (delete_breakpoint_1): ... this. Add proc parameter. Use release_breakpoint. Return ENOENT. (delete_breakpoint): Reimplement. (find_breakpoint_at): Delete. (find_gdb_breakpoint_at): New. (delete_breakpoint_at): Delete. (set_gdb_breakpoint_at): New. (delete_gdb_breakpoint_at): New. (gdb_breakpoint_here): New. (set_reinsert_breakpoint): Use release_breakpoint. (uninsert_breakpoint): Rename to ... (uninsert_raw_breakpoint): ... this. (uninsert_breakpoints_at): Adjust to handle raw breakpoints. (reinsert_raw_breakpoint): Change parameter type to raw_breakpoint. (reinsert_breakpoints_at): Adjust to handle raw breakpoints instead. (check_breakpoints): Adjust. Use release_breakpoint. (breakpoint_here): Rewrite using find_raw_breakpoint_at. (breakpoint_inserted_here): Ditto. (check_mem_read): Adjust to iterate over raw breakpoints instead. Don't trust the breakpoint's shadow if it is not inserted. (check_mem_write): Adjust to iterate over raw breakpoints instead. (delete_all_breakpoints): Adjust. (free_all_breakpoints): Mark all breakpoints as uninserted, and use delete_breakpoint_1. * mem-break.h (breakpoints_supported): Delete declaration. (set_gdb_breakpoint_at): Declare. (gdb_breakpoint_here): Declare. (delete_breakpoint_at): Delete. (delete_gdb_breakpoint_at): Declare. * server.h (struct raw_breakpoint): Forward declare. (struct process_info): New field `raw_breakpoints'. * linux-x86-low.c (x86_insert_point, x86_remote_point): Handle Z0 breakpoints.
This commit is contained in:
@ -1,3 +1,61 @@
|
|||||||
|
2010-04-01 Pedro Alves <pedro@codesourcery.com>
|
||||||
|
|
||||||
|
* linux-low.c (linux_wait_1): Avoid setting need_step_over is
|
||||||
|
there's a GDB breakpoint at stop_pc. Always report a trap to GDB
|
||||||
|
if we could tell there's a GDB breakpoint at stop_pc.
|
||||||
|
(need_step_over_p): Don't do a step over if we find a GDB
|
||||||
|
breakpoint at the resume PC.
|
||||||
|
|
||||||
|
* mem-break.c (struct raw_breakpoint): New.
|
||||||
|
(enum bkpt_type): New type `gdb_breakpoint'.
|
||||||
|
(struct breakpoint): Delete the `PC', `old_data' and `inserted'
|
||||||
|
fields. New field `raw'.
|
||||||
|
(find_raw_breakpoint_at): New.
|
||||||
|
(set_raw_breakpoint_at): Handle refcounting. Create a raw
|
||||||
|
breakpoint instead.
|
||||||
|
(set_breakpoint_at): Adjust.
|
||||||
|
(delete_raw_breakpoint): New.
|
||||||
|
(release_breakpoint): New.
|
||||||
|
(delete_breakpoint): Rename to...
|
||||||
|
(delete_breakpoint_1): ... this. Add proc parameter. Use
|
||||||
|
release_breakpoint. Return ENOENT.
|
||||||
|
(delete_breakpoint): Reimplement.
|
||||||
|
(find_breakpoint_at): Delete.
|
||||||
|
(find_gdb_breakpoint_at): New.
|
||||||
|
(delete_breakpoint_at): Delete.
|
||||||
|
(set_gdb_breakpoint_at): New.
|
||||||
|
(delete_gdb_breakpoint_at): New.
|
||||||
|
(gdb_breakpoint_here): New.
|
||||||
|
(set_reinsert_breakpoint): Use release_breakpoint.
|
||||||
|
(uninsert_breakpoint): Rename to ...
|
||||||
|
(uninsert_raw_breakpoint): ... this.
|
||||||
|
(uninsert_breakpoints_at): Adjust to handle raw breakpoints.
|
||||||
|
(reinsert_raw_breakpoint): Change parameter type to
|
||||||
|
raw_breakpoint.
|
||||||
|
(reinsert_breakpoints_at): Adjust to handle raw breakpoints
|
||||||
|
instead.
|
||||||
|
(check_breakpoints): Adjust. Use release_breakpoint.
|
||||||
|
(breakpoint_here): Rewrite using find_raw_breakpoint_at.
|
||||||
|
(breakpoint_inserted_here): Ditto.
|
||||||
|
(check_mem_read): Adjust to iterate over raw breakpoints instead.
|
||||||
|
Don't trust the breakpoint's shadow if it is not inserted.
|
||||||
|
(check_mem_write): Adjust to iterate over raw breakpoints instead.
|
||||||
|
(delete_all_breakpoints): Adjust.
|
||||||
|
(free_all_breakpoints): Mark all breakpoints as uninserted, and
|
||||||
|
use delete_breakpoint_1.
|
||||||
|
|
||||||
|
* mem-break.h (breakpoints_supported): Delete declaration.
|
||||||
|
(set_gdb_breakpoint_at): Declare.
|
||||||
|
(gdb_breakpoint_here): Declare.
|
||||||
|
(delete_breakpoint_at): Delete.
|
||||||
|
(delete_gdb_breakpoint_at): Declare.
|
||||||
|
|
||||||
|
* server.h (struct raw_breakpoint): Forward declare.
|
||||||
|
(struct process_info): New field `raw_breakpoints'.
|
||||||
|
|
||||||
|
* linux-x86-low.c (x86_insert_point, x86_remote_point): Handle Z0
|
||||||
|
breakpoints.
|
||||||
|
|
||||||
2010-03-24 Pedro Alves <pedro@codesourcery.com>
|
2010-03-24 Pedro Alves <pedro@codesourcery.com>
|
||||||
|
|
||||||
* linux-low.c (status_pending_p_callback): Fix comment.
|
* linux-low.c (status_pending_p_callback): Fix comment.
|
||||||
|
@ -1740,7 +1740,8 @@ retry:
|
|||||||
if (debug_threads)
|
if (debug_threads)
|
||||||
fprintf (stderr, "Hit a gdbserver breakpoint.\n");
|
fprintf (stderr, "Hit a gdbserver breakpoint.\n");
|
||||||
|
|
||||||
event_child->need_step_over = 1;
|
if (breakpoint_here (event_child->stop_pc))
|
||||||
|
event_child->need_step_over = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1755,11 +1756,18 @@ retry:
|
|||||||
|
|
||||||
/* Check If GDB would be interested in this event. If GDB wanted
|
/* Check If GDB would be interested in this event. If GDB wanted
|
||||||
this thread to single step, we always want to report the SIGTRAP,
|
this thread to single step, we always want to report the SIGTRAP,
|
||||||
and let GDB handle it. */
|
and let GDB handle it. Watchpoints should always be reported.
|
||||||
|
So should signals we can't explain. A SIGTRAP we can't explain
|
||||||
|
could be a GDB breakpoint --- we may or not support Z0
|
||||||
|
breakpoints. If we do, we're be able to handle GDB breakpoints
|
||||||
|
on top of internal breakpoints, by handling the internal
|
||||||
|
breakpoint and still reporting the event to GDB. If we don't,
|
||||||
|
we're out of luck, GDB won't see the breakpoint hit. */
|
||||||
report_to_gdb = (!maybe_internal_trap
|
report_to_gdb = (!maybe_internal_trap
|
||||||
|| event_child->last_resume_kind == resume_step
|
|| event_child->last_resume_kind == resume_step
|
||||||
|| event_child->stopped_by_watchpoint
|
|| event_child->stopped_by_watchpoint
|
||||||
|| (!step_over_finished && !bp_explains_trap));
|
|| (!step_over_finished && !bp_explains_trap)
|
||||||
|
|| gdb_breakpoint_here (event_child->stop_pc));
|
||||||
|
|
||||||
/* We found no reason GDB would want us to stop. We either hit one
|
/* We found no reason GDB would want us to stop. We either hit one
|
||||||
of our own breakpoints, or finished an internal step GDB
|
of our own breakpoints, or finished an internal step GDB
|
||||||
@ -1801,6 +1809,8 @@ retry:
|
|||||||
fprintf (stderr, "GDB wanted to single-step, reporting event.\n");
|
fprintf (stderr, "GDB wanted to single-step, reporting event.\n");
|
||||||
if (event_child->stopped_by_watchpoint)
|
if (event_child->stopped_by_watchpoint)
|
||||||
fprintf (stderr, "Stopped by watchpoint.\n");
|
fprintf (stderr, "Stopped by watchpoint.\n");
|
||||||
|
if (gdb_breakpoint_here (event_child->stop_pc))
|
||||||
|
fprintf (stderr, "Stopped by GDB breakpoint.\n");
|
||||||
if (debug_threads)
|
if (debug_threads)
|
||||||
fprintf (stderr, "Hit a non-gdbserver trap event.\n");
|
fprintf (stderr, "Hit a non-gdbserver trap event.\n");
|
||||||
}
|
}
|
||||||
@ -2401,21 +2411,37 @@ need_step_over_p (struct inferior_list_entry *entry, void *dummy)
|
|||||||
saved_inferior = current_inferior;
|
saved_inferior = current_inferior;
|
||||||
current_inferior = get_lwp_thread (lwp);
|
current_inferior = get_lwp_thread (lwp);
|
||||||
|
|
||||||
/* We only step over our breakpoints. */
|
/* We can only step over breakpoints we know about. */
|
||||||
if (breakpoint_here (pc))
|
if (breakpoint_here (pc))
|
||||||
{
|
{
|
||||||
if (debug_threads)
|
/* Don't step over a breakpoint that GDB expects to hit
|
||||||
fprintf (stderr,
|
though. */
|
||||||
"Need step over [LWP %ld]? yes, found breakpoint at 0x%s\n",
|
if (gdb_breakpoint_here (pc))
|
||||||
lwpid_of (lwp), paddress (pc));
|
{
|
||||||
|
if (debug_threads)
|
||||||
|
fprintf (stderr,
|
||||||
|
"Need step over [LWP %ld]? yes, but found"
|
||||||
|
" GDB breakpoint at 0x%s; skipping step over\n",
|
||||||
|
lwpid_of (lwp), paddress (pc));
|
||||||
|
|
||||||
/* We've found an lwp that needs stepping over --- return 1 so
|
current_inferior = saved_inferior;
|
||||||
that find_inferior stops looking. */
|
return 0;
|
||||||
current_inferior = saved_inferior;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (debug_threads)
|
||||||
|
fprintf (stderr,
|
||||||
|
"Need step over [LWP %ld]? yes, found breakpoint at 0x%s\n",
|
||||||
|
lwpid_of (lwp), paddress (pc));
|
||||||
|
|
||||||
/* If the step over is cancelled, this is set again. */
|
/* We've found an lwp that needs stepping over --- return 1 so
|
||||||
lwp->need_step_over = 0;
|
that find_inferior stops looking. */
|
||||||
return 1;
|
current_inferior = saved_inferior;
|
||||||
|
|
||||||
|
/* If the step over is cancelled, this is set again. */
|
||||||
|
lwp->need_step_over = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
current_inferior = saved_inferior;
|
current_inferior = saved_inferior;
|
||||||
|
@ -431,6 +431,8 @@ x86_insert_point (char type, CORE_ADDR addr, int len)
|
|||||||
struct process_info *proc = current_process ();
|
struct process_info *proc = current_process ();
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
case '0':
|
||||||
|
return set_gdb_breakpoint_at (addr);
|
||||||
case '2':
|
case '2':
|
||||||
case '3':
|
case '3':
|
||||||
case '4':
|
case '4':
|
||||||
@ -448,6 +450,8 @@ x86_remove_point (char type, CORE_ADDR addr, int len)
|
|||||||
struct process_info *proc = current_process ();
|
struct process_info *proc = current_process ();
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
case '0':
|
||||||
|
return delete_gdb_breakpoint_at (addr);
|
||||||
case '2':
|
case '2':
|
||||||
case '3':
|
case '3':
|
||||||
case '4':
|
case '4':
|
||||||
|
@ -26,9 +26,53 @@ int breakpoint_len;
|
|||||||
|
|
||||||
#define MAX_BREAKPOINT_LEN 8
|
#define MAX_BREAKPOINT_LEN 8
|
||||||
|
|
||||||
|
/* GDB will never try to install multiple breakpoints at the same
|
||||||
|
address. But, we need to keep track of internal breakpoints too,
|
||||||
|
and so we do need to be able to install multiple breakpoints at the
|
||||||
|
same address transparently. We keep track of two different, and
|
||||||
|
closely related structures. A raw breakpoint, which manages the
|
||||||
|
low level, close to the metal aspect of a breakpoint. It holds the
|
||||||
|
breakpoint address, and a buffer holding a copy of the instructions
|
||||||
|
that would be in memory had not been a breakpoint there (we call
|
||||||
|
that the shadow memory of the breakpoint). We occasionally need to
|
||||||
|
temporarilly uninsert a breakpoint without the client knowing about
|
||||||
|
it (e.g., to step over an internal breakpoint), so we keep an
|
||||||
|
`inserted' state associated with this low level breakpoint
|
||||||
|
structure. There can only be one such object for a given address.
|
||||||
|
Then, we have (a bit higher level) breakpoints. This structure
|
||||||
|
holds a callback to be called whenever a breakpoint is hit, a
|
||||||
|
high-level type, and a link to a low level raw breakpoint. There
|
||||||
|
can be many high-level breakpoints at the same address, and all of
|
||||||
|
them will point to the same raw breakpoint, which is reference
|
||||||
|
counted. */
|
||||||
|
|
||||||
|
/* The low level, physical, raw breakpoint. */
|
||||||
|
struct raw_breakpoint
|
||||||
|
{
|
||||||
|
struct raw_breakpoint *next;
|
||||||
|
|
||||||
|
/* A reference count. Each high level breakpoint referencing this
|
||||||
|
raw breakpoint accounts for one reference. */
|
||||||
|
int refcount;
|
||||||
|
|
||||||
|
/* The breakpoint's insertion address. There can only be one raw
|
||||||
|
breakpoint for a given PC. */
|
||||||
|
CORE_ADDR pc;
|
||||||
|
|
||||||
|
/* The breakpoint's shadow memory. */
|
||||||
|
unsigned char old_data[MAX_BREAKPOINT_LEN];
|
||||||
|
|
||||||
|
/* Non-zero if this breakpoint is currently inserted in the
|
||||||
|
inferior. */
|
||||||
|
int inserted;
|
||||||
|
};
|
||||||
|
|
||||||
/* The type of a breakpoint. */
|
/* The type of a breakpoint. */
|
||||||
enum bkpt_type
|
enum bkpt_type
|
||||||
{
|
{
|
||||||
|
/* A GDB breakpoint, requested with a Z0 packet. */
|
||||||
|
gdb_breakpoint,
|
||||||
|
|
||||||
/* A basic-software-single-step breakpoint. */
|
/* A basic-software-single-step breakpoint. */
|
||||||
reinsert_breakpoint,
|
reinsert_breakpoint,
|
||||||
|
|
||||||
@ -37,38 +81,57 @@ enum bkpt_type
|
|||||||
other_breakpoint,
|
other_breakpoint,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* A high level (in gdbserver's perspective) breakpoint. */
|
||||||
struct breakpoint
|
struct breakpoint
|
||||||
{
|
{
|
||||||
struct breakpoint *next;
|
struct breakpoint *next;
|
||||||
CORE_ADDR pc;
|
|
||||||
unsigned char old_data[MAX_BREAKPOINT_LEN];
|
|
||||||
|
|
||||||
/* Non-zero if this breakpoint is currently inserted in the
|
|
||||||
inferior. */
|
|
||||||
int inserted;
|
|
||||||
|
|
||||||
/* The breakpoint's type. */
|
/* The breakpoint's type. */
|
||||||
enum bkpt_type type;
|
enum bkpt_type type;
|
||||||
|
|
||||||
|
/* Link to this breakpoint's raw breakpoint. This is always
|
||||||
|
non-NULL. */
|
||||||
|
struct raw_breakpoint *raw;
|
||||||
|
|
||||||
/* Function to call when we hit this breakpoint. If it returns 1,
|
/* Function to call when we hit this breakpoint. If it returns 1,
|
||||||
the breakpoint shall be deleted; 0, it will be left inserted. */
|
the breakpoint shall be deleted; 0 or if this callback is NULL,
|
||||||
|
it will be left inserted. */
|
||||||
int (*handler) (CORE_ADDR);
|
int (*handler) (CORE_ADDR);
|
||||||
};
|
};
|
||||||
|
|
||||||
static void uninsert_breakpoint (struct breakpoint *bp);
|
static struct raw_breakpoint *
|
||||||
|
find_raw_breakpoint_at (CORE_ADDR where)
|
||||||
|
{
|
||||||
|
struct process_info *proc = current_process ();
|
||||||
|
struct raw_breakpoint *bp;
|
||||||
|
|
||||||
static struct breakpoint *
|
for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
|
||||||
|
if (bp->pc == where)
|
||||||
|
return bp;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct raw_breakpoint *
|
||||||
set_raw_breakpoint_at (CORE_ADDR where)
|
set_raw_breakpoint_at (CORE_ADDR where)
|
||||||
{
|
{
|
||||||
struct process_info *proc = current_process ();
|
struct process_info *proc = current_process ();
|
||||||
struct breakpoint *bp;
|
struct raw_breakpoint *bp;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (breakpoint_data == NULL)
|
if (breakpoint_data == NULL)
|
||||||
error ("Target does not support breakpoints.");
|
error ("Target does not support breakpoints.");
|
||||||
|
|
||||||
|
bp = find_raw_breakpoint_at (where);
|
||||||
|
if (bp != NULL)
|
||||||
|
{
|
||||||
|
bp->refcount++;
|
||||||
|
return bp;
|
||||||
|
}
|
||||||
|
|
||||||
bp = xcalloc (1, sizeof (*bp));
|
bp = xcalloc (1, sizeof (*bp));
|
||||||
bp->pc = where;
|
bp->pc = where;
|
||||||
|
bp->refcount = 1;
|
||||||
|
|
||||||
err = (*the_target->read_memory) (where, bp->old_data,
|
err = (*the_target->read_memory) (where, bp->old_data,
|
||||||
breakpoint_len);
|
breakpoint_len);
|
||||||
@ -97,8 +160,8 @@ set_raw_breakpoint_at (CORE_ADDR where)
|
|||||||
|
|
||||||
/* Link the breakpoint in. */
|
/* Link the breakpoint in. */
|
||||||
bp->inserted = 1;
|
bp->inserted = 1;
|
||||||
bp->next = proc->breakpoints;
|
bp->next = proc->raw_breakpoints;
|
||||||
proc->breakpoints = bp;
|
proc->raw_breakpoints = bp;
|
||||||
return bp;
|
return bp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,10 +170,11 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
|
|||||||
{
|
{
|
||||||
struct process_info *proc = current_process ();
|
struct process_info *proc = current_process ();
|
||||||
struct breakpoint *bp;
|
struct breakpoint *bp;
|
||||||
|
struct raw_breakpoint *raw;
|
||||||
|
|
||||||
bp = set_raw_breakpoint_at (where);
|
raw = set_raw_breakpoint_at (where);
|
||||||
|
|
||||||
if (bp == NULL)
|
if (raw == NULL)
|
||||||
{
|
{
|
||||||
/* warn? */
|
/* warn? */
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -118,6 +182,8 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
|
|||||||
|
|
||||||
bp = xcalloc (1, sizeof (struct breakpoint));
|
bp = xcalloc (1, sizeof (struct breakpoint));
|
||||||
bp->type = other_breakpoint;
|
bp->type = other_breakpoint;
|
||||||
|
|
||||||
|
bp->raw = raw;
|
||||||
bp->handler = handler;
|
bp->handler = handler;
|
||||||
|
|
||||||
bp->next = proc->breakpoints;
|
bp->next = proc->breakpoints;
|
||||||
@ -126,11 +192,84 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
|
|||||||
return bp;
|
return bp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
delete_breakpoint (struct breakpoint *todel)
|
delete_raw_breakpoint (struct process_info *proc, struct raw_breakpoint *todel)
|
||||||
|
{
|
||||||
|
struct raw_breakpoint *bp, **bp_link;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
bp = proc->raw_breakpoints;
|
||||||
|
bp_link = &proc->raw_breakpoints;
|
||||||
|
|
||||||
|
while (bp)
|
||||||
|
{
|
||||||
|
if (bp == todel)
|
||||||
|
{
|
||||||
|
if (bp->inserted)
|
||||||
|
{
|
||||||
|
struct raw_breakpoint *prev_bp_link = *bp_link;
|
||||||
|
|
||||||
|
*bp_link = bp->next;
|
||||||
|
|
||||||
|
ret = (*the_target->write_memory) (bp->pc, bp->old_data,
|
||||||
|
breakpoint_len);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
/* Something went wrong, relink the breakpoint. */
|
||||||
|
*bp_link = prev_bp_link;
|
||||||
|
|
||||||
|
if (debug_threads)
|
||||||
|
fprintf (stderr,
|
||||||
|
"Failed to uninsert raw breakpoint "
|
||||||
|
"at 0x%s (%s) while deleting it.\n",
|
||||||
|
paddress (bp->pc), strerror (ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*bp_link = bp->next;
|
||||||
|
|
||||||
|
free (bp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bp_link = &bp->next;
|
||||||
|
bp = *bp_link;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
warning ("Could not find raw breakpoint in list.");
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
release_breakpoint (struct process_info *proc, struct breakpoint *bp)
|
||||||
|
{
|
||||||
|
int newrefcount;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
newrefcount = bp->raw->refcount - 1;
|
||||||
|
if (newrefcount == 0)
|
||||||
|
{
|
||||||
|
ret = delete_raw_breakpoint (proc, bp->raw);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
bp->raw->refcount = newrefcount;
|
||||||
|
|
||||||
|
free (bp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
delete_breakpoint_1 (struct process_info *proc, struct breakpoint *todel)
|
||||||
{
|
{
|
||||||
struct process_info *proc = current_process ();
|
|
||||||
struct breakpoint *bp, **bp_link;
|
struct breakpoint *bp, **bp_link;
|
||||||
|
int err;
|
||||||
|
|
||||||
bp = proc->breakpoints;
|
bp = proc->breakpoints;
|
||||||
bp_link = &proc->breakpoints;
|
bp_link = &proc->breakpoints;
|
||||||
@ -141,9 +280,12 @@ delete_breakpoint (struct breakpoint *todel)
|
|||||||
{
|
{
|
||||||
*bp_link = bp->next;
|
*bp_link = bp->next;
|
||||||
|
|
||||||
uninsert_breakpoint (bp);
|
err = release_breakpoint (proc, bp);
|
||||||
free (bp);
|
if (err != 0)
|
||||||
return;
|
return err;
|
||||||
|
|
||||||
|
bp = *bp_link;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -153,30 +295,71 @@ delete_breakpoint (struct breakpoint *todel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
warning ("Could not find breakpoint in list.");
|
warning ("Could not find breakpoint in list.");
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
delete_breakpoint (struct breakpoint *todel)
|
||||||
|
{
|
||||||
|
struct process_info *proc = current_process ();
|
||||||
|
return delete_breakpoint_1 (proc, todel);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct breakpoint *
|
static struct breakpoint *
|
||||||
find_breakpoint_at (CORE_ADDR where)
|
find_gdb_breakpoint_at (CORE_ADDR where)
|
||||||
{
|
{
|
||||||
struct process_info *proc = current_process ();
|
struct process_info *proc = current_process ();
|
||||||
struct breakpoint *bp = proc->breakpoints;
|
struct breakpoint *bp;
|
||||||
|
|
||||||
while (bp != NULL)
|
for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
|
||||||
{
|
if (bp->type == gdb_breakpoint && bp->raw->pc == where)
|
||||||
if (bp->pc == where)
|
return bp;
|
||||||
return bp;
|
|
||||||
bp = bp->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
delete_breakpoint_at (CORE_ADDR addr)
|
set_gdb_breakpoint_at (CORE_ADDR where)
|
||||||
{
|
{
|
||||||
struct breakpoint *bp = find_breakpoint_at (addr);
|
struct breakpoint *bp;
|
||||||
if (bp != NULL)
|
|
||||||
delete_breakpoint (bp);
|
if (breakpoint_data == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
bp = set_breakpoint_at (where, NULL);
|
||||||
|
if (bp == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bp->type = gdb_breakpoint;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
delete_gdb_breakpoint_at (CORE_ADDR addr)
|
||||||
|
{
|
||||||
|
struct breakpoint *bp;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (breakpoint_data == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
bp = find_gdb_breakpoint_at (addr);
|
||||||
|
if (bp == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
err = delete_breakpoint (bp);
|
||||||
|
if (err)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
gdb_breakpoint_here (CORE_ADDR where)
|
||||||
|
{
|
||||||
|
struct breakpoint *bp = find_gdb_breakpoint_at (where);
|
||||||
|
|
||||||
|
return (bp != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -185,7 +368,6 @@ set_reinsert_breakpoint (CORE_ADDR stop_at)
|
|||||||
struct breakpoint *bp;
|
struct breakpoint *bp;
|
||||||
|
|
||||||
bp = set_breakpoint_at (stop_at, NULL);
|
bp = set_breakpoint_at (stop_at, NULL);
|
||||||
|
|
||||||
bp->type = reinsert_breakpoint;
|
bp->type = reinsert_breakpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,13 +385,7 @@ delete_reinsert_breakpoints (void)
|
|||||||
if (bp->type == reinsert_breakpoint)
|
if (bp->type == reinsert_breakpoint)
|
||||||
{
|
{
|
||||||
*bp_link = bp->next;
|
*bp_link = bp->next;
|
||||||
|
release_breakpoint (proc, bp);
|
||||||
/* If something goes wrong, maybe this is a shared library
|
|
||||||
breakpoint, and the shared library has been unmapped.
|
|
||||||
Assume the breakpoint is gone anyway. */
|
|
||||||
uninsert_breakpoint (bp);
|
|
||||||
free (bp);
|
|
||||||
|
|
||||||
bp = *bp_link;
|
bp = *bp_link;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -221,7 +397,7 @@ delete_reinsert_breakpoints (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
uninsert_breakpoint (struct breakpoint *bp)
|
uninsert_raw_breakpoint (struct raw_breakpoint *bp)
|
||||||
{
|
{
|
||||||
if (bp->inserted)
|
if (bp->inserted)
|
||||||
{
|
{
|
||||||
@ -245,9 +421,9 @@ uninsert_breakpoint (struct breakpoint *bp)
|
|||||||
void
|
void
|
||||||
uninsert_breakpoints_at (CORE_ADDR pc)
|
uninsert_breakpoints_at (CORE_ADDR pc)
|
||||||
{
|
{
|
||||||
struct breakpoint *bp;
|
struct raw_breakpoint *bp;
|
||||||
|
|
||||||
bp = find_breakpoint_at (pc);
|
bp = find_raw_breakpoint_at (pc);
|
||||||
if (bp == NULL)
|
if (bp == NULL)
|
||||||
{
|
{
|
||||||
/* This can happen when we remove all breakpoints while handling
|
/* This can happen when we remove all breakpoints while handling
|
||||||
@ -261,11 +437,11 @@ uninsert_breakpoints_at (CORE_ADDR pc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bp->inserted)
|
if (bp->inserted)
|
||||||
uninsert_breakpoint (bp);
|
uninsert_raw_breakpoint (bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reinsert_raw_breakpoint (struct breakpoint *bp)
|
reinsert_raw_breakpoint (struct raw_breakpoint *bp)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -285,16 +461,16 @@ reinsert_raw_breakpoint (struct breakpoint *bp)
|
|||||||
void
|
void
|
||||||
reinsert_breakpoints_at (CORE_ADDR pc)
|
reinsert_breakpoints_at (CORE_ADDR pc)
|
||||||
{
|
{
|
||||||
struct breakpoint *bp;
|
struct raw_breakpoint *bp;
|
||||||
|
|
||||||
bp = find_breakpoint_at (pc);
|
bp = find_raw_breakpoint_at (pc);
|
||||||
if (bp == NULL)
|
if (bp == NULL)
|
||||||
{
|
{
|
||||||
/* This can happen when we remove all breakpoints while handling
|
/* This can happen when we remove all breakpoints while handling
|
||||||
a step-over. */
|
a step-over. */
|
||||||
if (debug_threads)
|
if (debug_threads)
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"Could not find breakpoint at 0x%s "
|
"Could not find raw breakpoint at 0x%s "
|
||||||
"in list (reinserting).\n",
|
"in list (reinserting).\n",
|
||||||
paddress (pc));
|
paddress (pc));
|
||||||
return;
|
return;
|
||||||
@ -314,9 +490,9 @@ check_breakpoints (CORE_ADDR stop_pc)
|
|||||||
|
|
||||||
while (bp)
|
while (bp)
|
||||||
{
|
{
|
||||||
if (bp->pc == stop_pc)
|
if (bp->raw->pc == stop_pc)
|
||||||
{
|
{
|
||||||
if (!bp->inserted)
|
if (!bp->raw->inserted)
|
||||||
{
|
{
|
||||||
warning ("Hit a removed breakpoint?");
|
warning ("Hit a removed breakpoint?");
|
||||||
return;
|
return;
|
||||||
@ -326,7 +502,7 @@ check_breakpoints (CORE_ADDR stop_pc)
|
|||||||
{
|
{
|
||||||
*bp_link = bp->next;
|
*bp_link = bp->next;
|
||||||
|
|
||||||
delete_breakpoint (bp);
|
release_breakpoint (proc, bp);
|
||||||
|
|
||||||
bp = *bp_link;
|
bp = *bp_link;
|
||||||
continue;
|
continue;
|
||||||
@ -348,34 +524,24 @@ set_breakpoint_data (const unsigned char *bp_data, int bp_len)
|
|||||||
int
|
int
|
||||||
breakpoint_here (CORE_ADDR addr)
|
breakpoint_here (CORE_ADDR addr)
|
||||||
{
|
{
|
||||||
struct process_info *proc = current_process ();
|
return (find_raw_breakpoint_at (addr) != NULL);
|
||||||
struct breakpoint *bp;
|
|
||||||
|
|
||||||
for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
|
|
||||||
if (bp->pc == addr)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
breakpoint_inserted_here (CORE_ADDR addr)
|
breakpoint_inserted_here (CORE_ADDR addr)
|
||||||
{
|
{
|
||||||
struct process_info *proc = current_process ();
|
struct raw_breakpoint *bp;
|
||||||
struct breakpoint *bp;
|
|
||||||
|
|
||||||
for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
|
bp = find_raw_breakpoint_at (addr);
|
||||||
if (bp->pc == addr && bp->inserted)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
return (bp != NULL && bp->inserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
|
check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
|
||||||
{
|
{
|
||||||
struct process_info *proc = current_process ();
|
struct process_info *proc = current_process ();
|
||||||
struct breakpoint *bp = proc->breakpoints;
|
struct raw_breakpoint *bp = proc->raw_breakpoints;
|
||||||
CORE_ADDR mem_end = mem_addr + mem_len;
|
CORE_ADDR mem_end = mem_addr + mem_len;
|
||||||
|
|
||||||
for (; bp != NULL; bp = bp->next)
|
for (; bp != NULL; bp = bp->next)
|
||||||
@ -401,7 +567,8 @@ check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
|
|||||||
copy_offset = start - bp->pc;
|
copy_offset = start - bp->pc;
|
||||||
buf_offset = start - mem_addr;
|
buf_offset = start - mem_addr;
|
||||||
|
|
||||||
memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len);
|
if (bp->inserted)
|
||||||
|
memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,7 +576,7 @@ void
|
|||||||
check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
|
check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
|
||||||
{
|
{
|
||||||
struct process_info *proc = current_process ();
|
struct process_info *proc = current_process ();
|
||||||
struct breakpoint *bp = proc->breakpoints;
|
struct raw_breakpoint *bp = proc->raw_breakpoints;
|
||||||
CORE_ADDR mem_end = mem_addr + mem_len;
|
CORE_ADDR mem_end = mem_addr + mem_len;
|
||||||
|
|
||||||
for (; bp != NULL; bp = bp->next)
|
for (; bp != NULL; bp = bp->next)
|
||||||
@ -449,7 +616,7 @@ delete_all_breakpoints (void)
|
|||||||
struct process_info *proc = current_process ();
|
struct process_info *proc = current_process ();
|
||||||
|
|
||||||
while (proc->breakpoints)
|
while (proc->breakpoints)
|
||||||
delete_breakpoint (proc->breakpoints);
|
delete_breakpoint_1 (proc, proc->breakpoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release all breakpoints, but do not try to un-insert them from the
|
/* Release all breakpoints, but do not try to un-insert them from the
|
||||||
@ -458,12 +625,15 @@ delete_all_breakpoints (void)
|
|||||||
void
|
void
|
||||||
free_all_breakpoints (struct process_info *proc)
|
free_all_breakpoints (struct process_info *proc)
|
||||||
{
|
{
|
||||||
struct breakpoint *bp;
|
struct raw_breakpoint *raw_bp;
|
||||||
|
|
||||||
|
for (raw_bp = proc->raw_breakpoints; raw_bp != NULL; raw_bp = raw_bp->next)
|
||||||
|
raw_bp->inserted = 0;
|
||||||
|
|
||||||
|
/* Note: use PROC explicitly instead of deferring to
|
||||||
|
delete_all_breakpoints --- CURRENT_INFERIOR may already have been
|
||||||
|
released when we get here. There should be no call to
|
||||||
|
current_process from here on. */
|
||||||
while (proc->breakpoints)
|
while (proc->breakpoints)
|
||||||
{
|
delete_breakpoint_1 (proc, proc->breakpoints);
|
||||||
bp = proc->breakpoints;
|
|
||||||
proc->breakpoints = bp->next;
|
|
||||||
free (bp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,10 @@
|
|||||||
/* Breakpoints are opaque. */
|
/* Breakpoints are opaque. */
|
||||||
struct breakpoint;
|
struct breakpoint;
|
||||||
|
|
||||||
/* Returns TRUE if breakpoints are supported on this target. */
|
/* Create a new GDB breakpoint at WHERE. Returns -1 if breakpoints
|
||||||
|
are not supported on this target, 0 otherwise. */
|
||||||
|
|
||||||
int breakpoints_supported (void);
|
int set_gdb_breakpoint_at (CORE_ADDR where);
|
||||||
|
|
||||||
/* Returns TRUE if there's any breakpoint at ADDR in our tables,
|
/* Returns TRUE if there's any breakpoint at ADDR in our tables,
|
||||||
inserted, or not. */
|
inserted, or not. */
|
||||||
@ -38,6 +39,10 @@ int breakpoint_here (CORE_ADDR addr);
|
|||||||
|
|
||||||
int breakpoint_inserted_here (CORE_ADDR addr);
|
int breakpoint_inserted_here (CORE_ADDR addr);
|
||||||
|
|
||||||
|
/* Returns TRUE if there's a GDB breakpoint set at ADDR. */
|
||||||
|
|
||||||
|
int gdb_breakpoint_here (CORE_ADDR where);
|
||||||
|
|
||||||
/* Create a new breakpoint at WHERE, and call HANDLER when
|
/* Create a new breakpoint at WHERE, and call HANDLER when
|
||||||
it is hit. HANDLER should return 1 if the breakpoint
|
it is hit. HANDLER should return 1 if the breakpoint
|
||||||
should be deleted, 0 otherwise. */
|
should be deleted, 0 otherwise. */
|
||||||
@ -45,10 +50,10 @@ int breakpoint_inserted_here (CORE_ADDR addr);
|
|||||||
struct breakpoint *set_breakpoint_at (CORE_ADDR where,
|
struct breakpoint *set_breakpoint_at (CORE_ADDR where,
|
||||||
int (*handler) (CORE_ADDR));
|
int (*handler) (CORE_ADDR));
|
||||||
|
|
||||||
/* Delete a breakpoint previously inserted at ADDR with
|
/* Delete a GDB breakpoint previously inserted at ADDR with
|
||||||
set_breakpoint_at. */
|
set_gdb_breakpoint_at. */
|
||||||
|
|
||||||
void delete_breakpoint_at (CORE_ADDR addr);
|
int delete_gdb_breakpoint_at (CORE_ADDR addr);
|
||||||
|
|
||||||
/* Set a reinsert breakpoint at STOP_AT. */
|
/* Set a reinsert breakpoint at STOP_AT. */
|
||||||
|
|
||||||
|
@ -191,6 +191,7 @@ struct dll_info
|
|||||||
|
|
||||||
struct sym_cache;
|
struct sym_cache;
|
||||||
struct breakpoint;
|
struct breakpoint;
|
||||||
|
struct raw_breakpoint;
|
||||||
struct process_info_private;
|
struct process_info_private;
|
||||||
|
|
||||||
struct process_info
|
struct process_info
|
||||||
@ -209,6 +210,9 @@ struct process_info
|
|||||||
/* The list of memory breakpoints. */
|
/* The list of memory breakpoints. */
|
||||||
struct breakpoint *breakpoints;
|
struct breakpoint *breakpoints;
|
||||||
|
|
||||||
|
/* The list of raw memory breakpoints. */
|
||||||
|
struct raw_breakpoint *raw_breakpoints;
|
||||||
|
|
||||||
/* Private target data. */
|
/* Private target data. */
|
||||||
struct process_info_private *private;
|
struct process_info_private *private;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user