summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Snyder <msnyder@redhat.com>2008-06-12 20:48:52 +0000
committerMichael Snyder <msnyder@redhat.com>2008-06-12 20:48:52 +0000
commitf9ed6d4c15242c86feb285672a13094014abd3bc (patch)
tree7af6fdb2e01f345cf66fe50680578154c916e644
parent280e2d671ade34d52f35be6bee65968d1cd642fe (diff)
downloadgdb-msnyder-tracepoint-checkpoint-branch.tar.gz
* demo-target.c: Implement hooks for software breakpoints. (demo_remove_swbp): New function. (demo_set_swbp): New function. (demo_target): Set up method vectors for set/remove breakpoints. * demo-target.h: Export interface for software breakpoints. * demo-tfind.c: Implement software breakpoints. (tfind_insert_breakpoint): New function. (tfind_unlink_breakpoint): New function. (tfind_set_swbp): New function. (tfind_remove_swbp): New function. * demo-target.c: Implement hooks for continue_thread. (demo_continue_thread): call tfind_continue_thread. * demo-target.h: Export interface for tfind_continue_thread. * demo-tfind.c: Implement continue_thread with software breakpoints. (tfind_continue_thread): New function. Find a new frame based on software breakpoints.
-rw-r--r--rda/samples/ChangeLog20
-rw-r--r--rda/samples/demo-target.c56
-rw-r--r--rda/samples/demo-target.h13
-rw-r--r--rda/samples/demo-tfind.c205
4 files changed, 285 insertions, 9 deletions
diff --git a/rda/samples/ChangeLog b/rda/samples/ChangeLog
index 60d56cfc12d..38e1cdf6873 100644
--- a/rda/samples/ChangeLog
+++ b/rda/samples/ChangeLog
@@ -1,3 +1,23 @@
+2008-06-12 Michael Snyder <msnyder@specifix.com>
+
+ * demo-target.c: Implement hooks for software breakpoints.
+ (demo_remove_swbp): New function.
+ (demo_set_swbp): New function.
+ (demo_target): Set up method vectors for set/remove breakpoints.
+ * demo-target.h: Export interface for software breakpoints.
+ * demo-tfind.c: Implement software breakpoints.
+ (tfind_insert_breakpoint): New function.
+ (tfind_unlink_breakpoint): New function.
+ (tfind_set_swbp): New function.
+ (tfind_remove_swbp): New function.
+
+ * demo-target.c: Implement hooks for continue_thread.
+ (demo_continue_thread): call tfind_continue_thread.
+ * demo-target.h: Export interface for tfind_continue_thread.
+ * demo-tfind.c: Implement continue_thread with software breakpoints.
+ (tfind_continue_thread): New function. Find a new frame
+ based on software breakpoints.
+
2008-06-11 Michael Snyder <msnyder@specifix.com>
* demo-tfind.c (tfind_singlestep_program):
diff --git a/rda/samples/demo-target.c b/rda/samples/demo-target.c
index 7f56f4f9dd7..608f7475f34 100644
--- a/rda/samples/demo-target.c
+++ b/rda/samples/demo-target.c
@@ -44,6 +44,9 @@
#include "demo-target.h"
#include "gdbsched.h"
+struct gdbserv;
+struct gdbserv_reg;
+
/* This is a sample gdbserv target that demonstrates use of the RDA library
routines. It acts to gdb like a strange generic remote target. */
@@ -82,8 +85,17 @@ static void demo_sigkill_program (struct gdbserv* serv);
static void demo_continue_thread (struct gdbserv *serv,
struct gdbserv_thread *thread,
const struct gdbserv_reg *sigval);
- /* remove_breakpoint */
- /* set_breakpoint */
+
+static enum gdbserv_target_rc demo_remove_swbp (struct gdbserv * serv,
+ enum gdbserv_target_bp type,
+ struct gdbserv_reg *addr,
+ struct gdbserv_reg *len);
+
+static enum gdbserv_target_rc demo_set_swbp (struct gdbserv * serv,
+ enum gdbserv_target_bp type,
+ struct gdbserv_reg *addr,
+ struct gdbserv_reg *len);
+
/* process_target */
static void demo_detach (struct gdbserv* serv, struct gdbserv_target* target);
@@ -192,8 +204,8 @@ demo_target (struct gdbserv *serv, void *context)
target->cyclestep_program = demo_cyclestep_program;
target->sigkill_program = demo_sigkill_program;
target->continue_thread = demo_continue_thread;
- target->remove_breakpoint = NULL;
- target->set_breakpoint = NULL;
+ target->remove_breakpoint = demo_remove_swbp;
+ target->set_breakpoint = demo_set_swbp;
target->process_target_packet = NULL;
target->detach = demo_detach;
@@ -332,11 +344,11 @@ demo_restart_program (struct gdbserv* serv)
sched_break (serv, 1);
}
-
void
demo_singlestep_program (struct gdbserv* serv)
{
- sched_break (serv, tfind_singlestep_program (serv));
+ sched_break (serv,
+ tfind_singlestep_program (serv));
}
void
@@ -356,9 +368,8 @@ demo_continue_thread (struct gdbserv *serv,
struct gdbserv_thread *thread,
const struct gdbserv_reg *sigval)
{
- fprintf (stderr, "Resumed fictional target program - send break from gdb or wait a while.\n");
- /* Enqueue a break response */
- sched_break (serv, 10);
+ sched_break (serv,
+ tfind_continue_thread (serv, thread, sigval));
}
@@ -465,3 +476,30 @@ void
demo_flush_i_cache (struct gdbserv* serv)
{
}
+
+/*
+ * demo_remove_swbp -- remove software breakpoint
+ */
+
+static enum gdbserv_target_rc
+demo_remove_swbp (struct gdbserv *serv,
+ enum gdbserv_target_bp bptype,
+ struct gdbserv_reg *addr,
+ struct gdbserv_reg *len)
+{
+ return tfind_remove_swbp (serv, bptype, addr, len);
+}
+
+/*
+ * demo_set_swbp -- remove software breakpoint
+ */
+
+static enum gdbserv_target_rc
+demo_set_swbp (struct gdbserv *serv,
+ enum gdbserv_target_bp bptype,
+ struct gdbserv_reg *addr,
+ struct gdbserv_reg *len)
+{
+ return tfind_set_swbp (serv, bptype, addr, len);
+}
+
diff --git a/rda/samples/demo-target.h b/rda/samples/demo-target.h
index a99b8ec7066..679d7614f88 100644
--- a/rda/samples/demo-target.h
+++ b/rda/samples/demo-target.h
@@ -49,4 +49,17 @@ extern int (*demo_get_mem_hook) (unsigned long);
extern void demo_tfind_open (char *);
extern int tfind_singlestep_program (struct gdbserv *);
+extern int tfind_continue_thread (struct gdbserv *,
+ struct gdbserv_thread *,
+ const struct gdbserv_reg *);
+
+extern enum gdbserv_target_rc tfind_remove_swbp (struct gdbserv *,
+ enum gdbserv_target_bp,
+ struct gdbserv_reg *,
+ struct gdbserv_reg *);
+extern enum gdbserv_target_rc tfind_set_swbp (struct gdbserv *,
+ enum gdbserv_target_bp,
+ struct gdbserv_reg *,
+ struct gdbserv_reg *);
+
#endif
diff --git a/rda/samples/demo-tfind.c b/rda/samples/demo-tfind.c
index c4ca7c1f785..309d37c2c1f 100644
--- a/rda/samples/demo-tfind.c
+++ b/rda/samples/demo-tfind.c
@@ -388,6 +388,7 @@ tfind_singlestep_program (struct gdbserv *serv)
{
if (cur_frame == -1)
{
+ fprintf (stderr, "TFIND: fake singlestep (not at trace frame).\n");
return 2; /*sched_break (serv, 2);*/
}
else if (demo_reverse_flag == 0)
@@ -395,6 +396,7 @@ tfind_singlestep_program (struct gdbserv *serv)
if (cur_frame >= last_cached_frame - 1)
{
/* Stepped past the end of the tfind buffer. */
+ fprintf (stderr, "TFIND: stepped past end of trace buffer.\n");
demo_get_regs_hook = NULL;
demo_get_mem_hook = NULL;
cur_frame = -1;
@@ -403,6 +405,7 @@ tfind_singlestep_program (struct gdbserv *serv)
else
{
/* Increment cur_frame and schedule an immediate break. */
+ fprintf (stderr, "TFIND: stepi.\n");
cur_frame++;
return 0; /*sched_break (serv, 0);*/
}
@@ -412,6 +415,7 @@ tfind_singlestep_program (struct gdbserv *serv)
if (cur_frame == 0)
{
/* Stepped past the beginning of the tfind buffer. */
+ fprintf (stderr, "TFIND: backstepped past start of trace buffer.\n");
demo_get_regs_hook = NULL;
demo_get_mem_hook = NULL;
cur_frame = -1;
@@ -420,8 +424,209 @@ tfind_singlestep_program (struct gdbserv *serv)
else
{
/* Decrement cur_frame and schedule an immediate break. */
+ fprintf (stderr, "TFIND: reverse-stepi.\n");
cur_frame--;
return 0; /*sched_break (serv, 0);*/
}
}
}
+
+typedef struct tfind_breakpoint_type {
+ unsigned long addr;
+ unsigned long len;
+ struct tfind_breakpoint_type *next;
+} tfind_breakpoint;
+
+static tfind_breakpoint *tfind_bplist[5];
+
+int
+tfind_continue_thread (struct gdbserv *serv,
+ struct gdbserv_thread *thread,
+ const struct gdbserv_reg *sigval)
+{
+ int index_frame;
+ tfind_breakpoint *index_bp;
+
+ if (cur_frame == -1)
+ {
+ fprintf (stderr,
+ "TFIND: continue - send break from gdb or wait 10 seconds.\n");
+ /* Enqueue a break response after 10 seconds. */
+ return 10;
+ }
+ else if (demo_reverse_flag == 0)
+ {
+ /* Search forward for a breakpoint/checkpoint match. */
+ for (index_frame = cur_frame + 1;
+ index_frame < last_cached_frame;
+ index_frame++)
+ {
+ for (index_bp = tfind_bplist[GDBSERV_TARGET_BP_SOFTWARE];
+ index_bp != NULL;
+ index_bp = index_bp->next)
+ {
+ if (index_bp->addr == frame[index_frame].pc)
+ {
+ /* Hit breakpoint at index_frame. */
+ fprintf (stderr, "TFIND: continue / break\n");
+ cur_frame = index_frame;
+ /* Stop immediately. */
+ return 0;
+ }
+ }
+ }
+ /* No match. Run to end (set cur_frame to last valid one). */
+ fprintf (stderr, "TFIND: continue / end\n");
+ cur_frame = last_cached_frame - 1;
+ return 0;
+ }
+ else
+ {
+ /* Search backward for a breakpoint/checkpoint match. */
+ for (index_frame = cur_frame - 1;
+ index_frame >= 0;
+ index_frame--)
+ {
+ for (index_bp = tfind_bplist[GDBSERV_TARGET_BP_SOFTWARE];
+ index_bp != NULL;
+ index_bp = index_bp->next)
+ {
+ if (index_bp->addr == frame[index_frame].pc)
+ {
+ /* Hit breakpoint at index_frame. */
+ fprintf (stderr, "TFIND: reverse-continue / break\n");
+ cur_frame = index_frame;
+ /* Stop immediately. */
+ return 0;
+ }
+ }
+ }
+ /* No match. Stop at beginning (set cur_frame to 0). */
+ fprintf (stderr, "TFIND: reverse-continue / start\n");
+ cur_frame = 0;
+ return 0;
+ }
+}
+
+/*
+ * tfind_insert_breakpoint
+ *
+ * returns: 0 for fail, 1 for success
+ */
+
+static int
+tfind_insert_breakpoint (struct gdbserv *serv,
+ enum gdbserv_target_bp bptype,
+ struct gdbserv_reg *addr,
+ struct gdbserv_reg *len)
+{
+ tfind_breakpoint *this_bp;
+
+ switch (bptype) {
+ case GDBSERV_TARGET_BP_ACCESS:
+ case GDBSERV_TARGET_BP_HARDWARE:
+ case GDBSERV_TARGET_BP_READ:
+ default:
+ /* Can't do those. */
+ return 0;
+ break;
+ case GDBSERV_TARGET_BP_SOFTWARE:
+ case GDBSERV_TARGET_BP_WRITE:
+ this_bp = malloc (sizeof (tfind_breakpoint));
+ gdbserv_reg_to_ulong (serv, addr, &this_bp->addr);
+ gdbserv_reg_to_ulong (serv, len, &this_bp->len);
+ this_bp->next = tfind_bplist[bptype];
+ tfind_bplist[bptype] = this_bp;
+ return 1;
+ }
+}
+
+/*
+ * tfind_unlink_breakpoint
+ *
+ * returns: 0 for fail, 1 for success
+ */
+
+static int
+tfind_unlink_breakpoint (struct gdbserv *serv,
+ enum gdbserv_target_bp bptype,
+ struct gdbserv_reg *addr,
+ struct gdbserv_reg *len)
+{
+ tfind_breakpoint *this_bp, *tmp;
+ unsigned long laddr;
+ unsigned long llen;
+ switch (bptype) {
+ case GDBSERV_TARGET_BP_ACCESS:
+ case GDBSERV_TARGET_BP_HARDWARE:
+ case GDBSERV_TARGET_BP_READ:
+ default:
+ /* Can't do those. */
+ return 0;
+ break;
+ case GDBSERV_TARGET_BP_SOFTWARE:
+ case GDBSERV_TARGET_BP_WRITE:
+ /* Special case - list is empty. */
+ if (tfind_bplist[bptype] == NULL)
+ return 0;
+
+ gdbserv_reg_to_ulong (serv, addr, &laddr);
+ gdbserv_reg_to_ulong (serv, len, &llen);
+
+ /* Start from list head. */
+ this_bp = tfind_bplist[bptype];
+ /* Special case -- remove head of list. */
+ if (this_bp->addr == laddr &&
+ this_bp->len == llen)
+ {
+ tfind_bplist[bptype] = this_bp->next;
+ return 1;
+ }
+
+ /* Scan list. */
+ for (; this_bp && this_bp->next; this_bp = this_bp->next)
+ if (this_bp->next->addr == laddr &&
+ this_bp->next->len == llen)
+ {
+ /* Remove from middle of list. */
+ tmp = this_bp->next->next;
+ free (this_bp->next);
+ this_bp->next = tmp;
+ return 1;
+ }
+
+ /* Not found. */
+ return 0;
+ }
+}
+
+
+extern enum gdbserv_target_rc
+tfind_remove_swbp (struct gdbserv *serv,
+ enum gdbserv_target_bp bptype,
+ struct gdbserv_reg *addr,
+ struct gdbserv_reg *len)
+{
+ fprintf (stderr, "TFIND: Remove sw breakpoint type %d\n", bptype);
+ if (tfind_unlink_breakpoint (serv, bptype, addr, len) == 0)
+ {
+ fprintf (stderr, " FAILED!\n");
+ return GDBSERV_TARGET_RC_ERROR;
+ }
+ return GDBSERV_TARGET_RC_OK;
+}
+
+extern enum gdbserv_target_rc
+tfind_set_swbp (struct gdbserv *serv,
+ enum gdbserv_target_bp bptype,
+ struct gdbserv_reg *addr,
+ struct gdbserv_reg *len)
+{
+ fprintf (stderr, "TFIND: Set sw breakpoint type %d\n", bptype);
+ if (tfind_insert_breakpoint (serv, bptype, addr, len) == 0)
+ {
+ fprintf (stderr, " FAILED!\n");
+ return GDBSERV_TARGET_RC_ERROR;
+ }
+ return GDBSERV_TARGET_RC_OK;
+}