summaryrefslogtreecommitdiffstats
path: root/cpukit/libdebugger/rtems-debugger-target.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libdebugger/rtems-debugger-target.c')
-rw-r--r--cpukit/libdebugger/rtems-debugger-target.c126
1 files changed, 81 insertions, 45 deletions
diff --git a/cpukit/libdebugger/rtems-debugger-target.c b/cpukit/libdebugger/rtems-debugger-target.c
index 65b878469d..eac9498535 100644
--- a/cpukit/libdebugger/rtems-debugger-target.c
+++ b/cpukit/libdebugger/rtems-debugger-target.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2016 Chris Johns <chrisj@rtems.org>. All rights reserved.
+ * Copyright (c) 2016-2017 Chris Johns <chrisj@rtems.org>.
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -40,12 +41,15 @@
#include "rtems-debugger-threads.h"
/**
- * Frame signature.
+ * Exception local stack frame data to synchronise with the debugger
+ * server's events loop processor.
*/
-#define TARGET_FRAME_MAGIC_NUM (2)
-#define TARGET_FRAME_MAGIC 0xdeadbeef, 0xb2107016
-static const uint32_t
- frame_magic[TARGET_FRAME_MAGIC_NUM] = { TARGET_FRAME_MAGIC };
+typedef struct {
+ rtems_chain_node node;
+ rtems_id id;
+ CPU_Exception_frame* frame;
+ rtems_rx_cond cond;
+} rtems_debugger_exception;
#if TARGET_DEBUG
#include <rtems/bspIo.h>
@@ -53,9 +57,12 @@ static void target_printk(const char* format, ...) RTEMS_PRINTFLIKE(1, 2);
static void
target_printk(const char* format, ...)
{
+ rtems_interrupt_lock_context lock_context;
va_list ap;
va_start(ap, format);
+ rtems_debugger_printk_lock(&lock_context);
vprintk(format, ap);
+ rtems_debugger_printk_unlock(&lock_context);
va_end(ap);
}
#else
@@ -219,6 +226,11 @@ rtems_debugger_target_swbreak_insert(void)
if (target->breakpoint_size > 4)
memcpy(loc, &target->breakpoint[0], target->breakpoint_size);
else {
+ if (rtems_debugger_verbose())
+ rtems_debugger_printf("rtems-db: bp: in: %p %p %d %d %d\n",
+ loc, &target->breakpoint[0],
+ (int) target->breakpoint_size,
+ (int) i, (int) target->swbreaks.level);
switch (target->breakpoint_size) {
case 4:
loc[3] = target->breakpoint[3];
@@ -276,30 +288,22 @@ rtems_debugger_target_swbreak_remove(void)
rtems_debugger_target_exc_action
rtems_debugger_target_exception(CPU_Exception_frame* frame)
{
- volatile const uint32_t magic[3] = {
- (uint32_t) frame, TARGET_FRAME_MAGIC
- };
-
- (void) magic;
-
if (!rtems_interrupt_is_in_progress()) {
rtems_debugger_threads* threads = rtems_debugger->threads;
- #if USE_THREAD_EXECUTING
- Thread_Control* thread = _Thread_Executing;
- #else
- const Per_CPU_Control* cpu = _Per_CPU_Get_snapshot();
- Thread_Control* thread = _Per_CPU_Get_executing(cpu);
- #endif
- rtems_id* excludes;
+ Thread_Control* thread = _Thread_Get_executing();
const rtems_id tid = thread->Object.id;
+ rtems_id* excludes;
DB_UINT pc;
const rtems_debugger_thread_stepper* stepper;
+ rtems_debugger_exception target_exception;
size_t i;
target_printk("[} tid:%08" PRIx32 ": thread:%08" PRIxPTR
" frame:%08" PRIxPTR "\n",
tid, (intptr_t) thread, (intptr_t) frame);
+ rtems_debugger_lock();
+
/*
* If the thread is the debugger recover.
*/
@@ -307,9 +311,11 @@ rtems_debugger_target_exception(CPU_Exception_frame* frame)
if (rtems_debugger->target->memory_access) {
target_printk("[} server access fault\n");
rtems_debugger->target->memory_access = true;
+ rtems_debugger_unlock();
longjmp(rtems_debugger->target->access_return, -1);
}
target_printk("[} server exception\n");
+ rtems_debugger_unlock();
return rtems_debugger_target_exc_cascade;
}
@@ -327,6 +333,7 @@ rtems_debugger_target_exception(CPU_Exception_frame* frame)
* swbreak's contents.
*/
target_printk("[} tid:%08lx: excluded\n", tid);
+ rtems_debugger_unlock();
return rtems_debugger_target_exc_cascade;
}
}
@@ -340,18 +347,39 @@ rtems_debugger_target_exception(CPU_Exception_frame* frame)
stepper->thread->frame = frame;
rtems_debugger_target_thread_stepping(stepper->thread);
target_printk("[} tid:%08lx: stepping\n", tid);
+ rtems_debugger_unlock();
return rtems_debugger_target_exc_step;
}
target_printk("[} tid:%08lx: suspending\n", tid);
/*
- * Tag the thread as being debugged, wake the debug server's event thread,
- * then suspend this thread.
+ * Initialise the target exception data and queue ready for the debugger
+ * server's event processor to handle.
+ */
+ rtems_chain_initialize_node(&target_exception.node);
+ target_exception.frame = frame;
+ target_exception.id = tid;
+ _Condition_Initialize(&target_exception.cond);
+
+ rtems_chain_append_unprotected(&rtems_debugger->exception_threads,
+ &target_exception.node);
+
+ /*
+ * Signal the debug server's thread.
+ */
+ rtems_debugger_server_events_signal();
+
+ /*
+ * Block on the exception thread's condition variable unlocking the
+ * debugger's mutex and letting the server's thread run.
+ */
+ _Condition_Wait_recursive(&target_exception.cond, &rtems_debugger->lock);
+
+ /*
+ * Unlock the debugger's lock now the exception is resuming.
*/
- _Thread_Set_state(thread, STATES_DEBUGGER);
- rtems_debugger_server_events_wake();
- rtems_task_suspend(tid);
+ rtems_debugger_unlock();
target_printk("[} tid:%08lx: resuming\n", tid);
@@ -363,31 +391,39 @@ rtems_debugger_target_exception(CPU_Exception_frame* frame)
return rtems_debugger_target_exc_cascade;
}
-int
-rtems_debugger_target_set_exception_frame(rtems_debugger_thread* thread)
+void
+rtems_debugger_target_exception_thread(rtems_debugger_thread* thread)
{
- int r = 0;
+ rtems_chain_node* node;
thread->frame = NULL;
- thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_DEBUGGING;
- if ((thread->tcb->current_state & STATES_DEBUGGER) != 0) {
- CPU_Exception_frame* frame = NULL;
- DB_UINT* sp;
- int i;
- sp = (DB_UINT*) rtems_debugger_target_tcb_sp(thread);
- for (i = 0; i < 128; ++i) {
- if (sp[i] == frame_magic[0] && sp[i + 1] == frame_magic[1]) {
- frame = (CPU_Exception_frame*) sp[i + 2];
- break;
- }
+ thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION;
+ for (node = rtems_chain_first(&rtems_debugger->exception_threads);
+ !rtems_chain_is_tail(&rtems_debugger->exception_threads, node);
+ node = rtems_chain_next(node)) {
+ rtems_debugger_exception* target_exception = (rtems_debugger_exception*) node;
+ if (target_exception->id == thread->id) {
+ thread->frame = target_exception->frame;
+ thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION;
+ }
+ }
+}
+
+void
+rtems_debugger_target_exception_thread_resume(rtems_debugger_thread* thread)
+{
+ rtems_chain_node* node;
+ for (node = rtems_chain_first(&rtems_debugger->exception_threads);
+ !rtems_chain_is_tail(&rtems_debugger->exception_threads, node);
+ node = rtems_chain_next(node)) {
+ rtems_debugger_exception* target_exception = (rtems_debugger_exception*) node;
+ if (target_exception->id == thread->id) {
+ rtems_chain_extract(node);
+ thread->frame = NULL;
+ thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION;
+ _Condition_Signal(&target_exception->cond);
+ break;
}
- _Thread_Clear_state(thread->tcb, STATES_DEBUGGER);
- thread->frame = frame;
- if (frame != NULL)
- thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_DEBUGGING;
- else
- r = -1;
}
- return r;
}
int