aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2010-04-01 14:25:34 +0000
committerPedro Alves <palves@redhat.com>2010-04-01 14:25:34 +0000
commit8b07ae33f0743a5dbad03cb4a76987f6db7fc38c (patch)
treec4fd50f0088748c74d0af003b576db1ea1f8fe3b /gdb/gdbserver
parent86b17b608f08cee1e23221f28d79f9dc47352976 (diff)
downloadgdb-8b07ae33f0743a5dbad03cb4a76987f6db7fc38c.zip
gdb-8b07ae33f0743a5dbad03cb4a76987f6db7fc38c.tar.gz
gdb-8b07ae33f0743a5dbad03cb4a76987f6db7fc38c.tar.bz2
* 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.
Diffstat (limited to 'gdb/gdbserver')
-rw-r--r--gdb/gdbserver/ChangeLog58
-rw-r--r--gdb/gdbserver/linux-low.c54
-rw-r--r--gdb/gdbserver/linux-x86-low.c4
-rw-r--r--gdb/gdbserver/mem-break.c322
-rw-r--r--gdb/gdbserver/mem-break.h15
-rw-r--r--gdb/gdbserver/server.h4
6 files changed, 362 insertions, 95 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 9831ef3..eb6c0ba 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -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>
* linux-low.c (status_pending_p_callback): Fix comment.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index ad68179..84f549c 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -1740,7 +1740,8 @@ retry:
if (debug_threads)
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
@@ -1755,11 +1756,18 @@ retry:
/* Check If GDB would be interested in this event. If GDB wanted
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
|| event_child->last_resume_kind == resume_step
|| 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
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");
if (event_child->stopped_by_watchpoint)
fprintf (stderr, "Stopped by watchpoint.\n");
+ if (gdb_breakpoint_here (event_child->stop_pc))
+ fprintf (stderr, "Stopped by GDB breakpoint.\n");
if (debug_threads)
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;
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 (debug_threads)
- fprintf (stderr,
- "Need step over [LWP %ld]? yes, found breakpoint at 0x%s\n",
- lwpid_of (lwp), paddress (pc));
+ /* Don't step over a breakpoint that GDB expects to hit
+ though. */
+ if (gdb_breakpoint_here (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
- that find_inferior stops looking. */
- current_inferior = saved_inferior;
+ current_inferior = saved_inferior;
+ return 0;
+ }
+ 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. */
- lwp->need_step_over = 0;
- return 1;
+ /* We've found an lwp that needs stepping over --- return 1 so
+ that find_inferior stops looking. */
+ 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;
diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
index fe5d46e..1f9e1b1 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
@@ -431,6 +431,8 @@ x86_insert_point (char type, CORE_ADDR addr, int len)
struct process_info *proc = current_process ();
switch (type)
{
+ case '0':
+ return set_gdb_breakpoint_at (addr);
case '2':
case '3':
case '4':
@@ -448,6 +450,8 @@ x86_remove_point (char type, CORE_ADDR addr, int len)
struct process_info *proc = current_process ();
switch (type)
{
+ case '0':
+ return delete_gdb_breakpoint_at (addr);
case '2':
case '3':
case '4':
diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c
index 33de80c..5256cb7 100644
--- a/gdb/gdbserver/mem-break.c
+++ b/gdb/gdbserver/mem-break.c
@@ -26,9 +26,53 @@ int breakpoint_len;
#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. */
enum bkpt_type
{
+ /* A GDB breakpoint, requested with a Z0 packet. */
+ gdb_breakpoint,
+
/* A basic-software-single-step breakpoint. */
reinsert_breakpoint,
@@ -37,38 +81,57 @@ enum bkpt_type
other_breakpoint,
};
+/* A high level (in gdbserver's perspective) breakpoint. */
struct breakpoint
{
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. */
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,
- 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);
};
-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)
{
struct process_info *proc = current_process ();
- struct breakpoint *bp;
+ struct raw_breakpoint *bp;
int err;
if (breakpoint_data == NULL)
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->pc = where;
+ bp->refcount = 1;
err = (*the_target->read_memory) (where, bp->old_data,
breakpoint_len);
@@ -97,8 +160,8 @@ set_raw_breakpoint_at (CORE_ADDR where)
/* Link the breakpoint in. */
bp->inserted = 1;
- bp->next = proc->breakpoints;
- proc->breakpoints = bp;
+ bp->next = proc->raw_breakpoints;
+ proc->raw_breakpoints = bp;
return bp;
}
@@ -107,10 +170,11 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
{
struct process_info *proc = current_process ();
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? */
return NULL;
@@ -118,6 +182,8 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
bp = xcalloc (1, sizeof (struct breakpoint));
bp->type = other_breakpoint;
+
+ bp->raw = raw;
bp->handler = handler;
bp->next = proc->breakpoints;
@@ -126,11 +192,84 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
return bp;
}
-static void
-delete_breakpoint (struct breakpoint *todel)
+static int
+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;
+ int err;
bp = proc->breakpoints;
bp_link = &proc->breakpoints;
@@ -141,9 +280,12 @@ delete_breakpoint (struct breakpoint *todel)
{
*bp_link = bp->next;
- uninsert_breakpoint (bp);
- free (bp);
- return;
+ err = release_breakpoint (proc, bp);
+ if (err != 0)
+ return err;
+
+ bp = *bp_link;
+ return 0;
}
else
{
@@ -153,30 +295,71 @@ delete_breakpoint (struct breakpoint *todel)
}
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 *
-find_breakpoint_at (CORE_ADDR where)
+find_gdb_breakpoint_at (CORE_ADDR where)
{
struct process_info *proc = current_process ();
- struct breakpoint *bp = proc->breakpoints;
+ struct breakpoint *bp;
- while (bp != NULL)
- {
- if (bp->pc == where)
- return bp;
- bp = bp->next;
- }
+ for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
+ if (bp->type == gdb_breakpoint && bp->raw->pc == where)
+ return bp;
return NULL;
}
-void
-delete_breakpoint_at (CORE_ADDR addr)
+int
+set_gdb_breakpoint_at (CORE_ADDR where)
{
- struct breakpoint *bp = find_breakpoint_at (addr);
- if (bp != NULL)
- delete_breakpoint (bp);
+ struct 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
@@ -185,7 +368,6 @@ set_reinsert_breakpoint (CORE_ADDR stop_at)
struct breakpoint *bp;
bp = set_breakpoint_at (stop_at, NULL);
-
bp->type = reinsert_breakpoint;
}
@@ -203,13 +385,7 @@ delete_reinsert_breakpoints (void)
if (bp->type == reinsert_breakpoint)
{
*bp_link = bp->next;
-
- /* 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);
-
+ release_breakpoint (proc, bp);
bp = *bp_link;
}
else
@@ -221,7 +397,7 @@ delete_reinsert_breakpoints (void)
}
static void
-uninsert_breakpoint (struct breakpoint *bp)
+uninsert_raw_breakpoint (struct raw_breakpoint *bp)
{
if (bp->inserted)
{
@@ -245,9 +421,9 @@ uninsert_breakpoint (struct breakpoint *bp)
void
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)
{
/* This can happen when we remove all breakpoints while handling
@@ -261,11 +437,11 @@ uninsert_breakpoints_at (CORE_ADDR pc)
}
if (bp->inserted)
- uninsert_breakpoint (bp);
+ uninsert_raw_breakpoint (bp);
}
static void
-reinsert_raw_breakpoint (struct breakpoint *bp)
+reinsert_raw_breakpoint (struct raw_breakpoint *bp)
{
int err;
@@ -285,16 +461,16 @@ reinsert_raw_breakpoint (struct breakpoint *bp)
void
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)
{
/* 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 "
+ "Could not find raw breakpoint at 0x%s "
"in list (reinserting).\n",
paddress (pc));
return;
@@ -314,9 +490,9 @@ check_breakpoints (CORE_ADDR stop_pc)
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?");
return;
@@ -326,7 +502,7 @@ check_breakpoints (CORE_ADDR stop_pc)
{
*bp_link = bp->next;
- delete_breakpoint (bp);
+ release_breakpoint (proc, bp);
bp = *bp_link;
continue;
@@ -348,34 +524,24 @@ set_breakpoint_data (const unsigned char *bp_data, int 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;
+ return (find_raw_breakpoint_at (addr) != NULL);
}
int
breakpoint_inserted_here (CORE_ADDR addr)
{
- struct process_info *proc = current_process ();
- struct breakpoint *bp;
+ struct raw_breakpoint *bp;
- for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
- if (bp->pc == addr && bp->inserted)
- return 1;
+ bp = find_raw_breakpoint_at (addr);
- return 0;
+ return (bp != NULL && bp->inserted);
}
void
check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
{
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;
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;
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)
{
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;
for (; bp != NULL; bp = bp->next)
@@ -449,7 +616,7 @@ delete_all_breakpoints (void)
struct process_info *proc = current_process ();
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
@@ -458,12 +625,15 @@ delete_all_breakpoints (void)
void
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)
- {
- bp = proc->breakpoints;
- proc->breakpoints = bp->next;
- free (bp);
- }
+ delete_breakpoint_1 (proc, proc->breakpoints);
}
diff --git a/gdb/gdbserver/mem-break.h b/gdb/gdbserver/mem-break.h
index 2953d03..01087fd 100644
--- a/gdb/gdbserver/mem-break.h
+++ b/gdb/gdbserver/mem-break.h
@@ -25,9 +25,10 @@
/* Breakpoints are opaque. */
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,
inserted, or not. */
@@ -38,6 +39,10 @@ int breakpoint_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
it is hit. HANDLER should return 1 if the breakpoint
should be deleted, 0 otherwise. */
@@ -45,10 +50,10 @@ int breakpoint_inserted_here (CORE_ADDR addr);
struct breakpoint *set_breakpoint_at (CORE_ADDR where,
int (*handler) (CORE_ADDR));
-/* Delete a breakpoint previously inserted at ADDR with
- set_breakpoint_at. */
+/* Delete a GDB breakpoint previously inserted at ADDR with
+ 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. */
diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
index 54d80ed..88c6c5e 100644
--- a/gdb/gdbserver/server.h
+++ b/gdb/gdbserver/server.h
@@ -191,6 +191,7 @@ struct dll_info
struct sym_cache;
struct breakpoint;
+struct raw_breakpoint;
struct process_info_private;
struct process_info
@@ -209,6 +210,9 @@ struct process_info
/* The list of memory breakpoints. */
struct breakpoint *breakpoints;
+ /* The list of raw memory breakpoints. */
+ struct raw_breakpoint *raw_breakpoints;
+
/* Private target data. */
struct process_info_private *private;
};