/branches/tracing/kernel/generic/include/proc/thread.h |
---|
207,6 → 207,7 |
/** Debugging stuff */ |
waitq_t go_wq; |
unative_t syscall_args[6]; |
istate_t *uspace_state; |
} thread_t; |
/** Thread list lock. |
/branches/tracing/kernel/generic/include/udebug/udebug.h |
---|
52,6 → 52,40 |
*/ |
UDEBUG_M_ARGS_READ, |
/** Read thread's userspace register state (istate_t). |
* |
* - ARG2 - thread identification |
* - ARG3 - destination address in the caller's address space |
* - ARG4 - size of receiving buffer in bytes |
* |
* on answer, the kernel will set: |
* |
* - ARG1 - actual size in bytes of data read |
* - ARG2 - total size in bytes of data available |
* |
* or, on error, retval will be |
* - ENOENT - thread does not exist |
* - EBUSY - register state not available |
*/ |
UDEBUG_M_REGS_READ, |
/** Write thread's userspace register state (istate_t). |
* |
* - ARG2 - thread identification |
* - ARG3 - source address in the caller's address space |
* - ARG4 - size of source data in bytes |
* |
* on answer, the kernel will set: |
* |
* - ARG1 - actual size in bytes of data copied |
* - ARG2 - max size in bytes that could have been copied |
* |
* or, on error, retval will be |
* - ENOENT - thread does not exist |
* - EBUSY - register state not available |
*/ |
UDEBUG_M_REGS_WRITE, |
/** Read the list of the debugged tasks's threads. |
* |
* - ARG2 - destination address in the caller's address space |
/branches/tracing/kernel/generic/src/interrupt/interrupt.c |
---|
86,8 → 86,13 |
void exc_dispatch(int n, istate_t *istate) |
{ |
ASSERT(n < IVT_ITEMS); |
if (THREAD) THREAD->uspace_state = istate; |
exc_table[n].f(n + IVT_FIRST, istate); |
if (THREAD) THREAD->uspace_state = NULL; |
/* This is a safe place to exit exiting thread */ |
if (THREAD && THREAD->interrupted && istate_from_uspace(istate)) |
thread_exit(); |
/branches/tracing/kernel/generic/src/proc/thread.c |
---|
342,7 → 342,9 |
avltree_node_initialize(&t->threads_tree_node); |
t->threads_tree_node.key = (uintptr_t) t; |
/* Init debugging stuff */ |
waitq_initialize(&t->go_wq); |
t->uspace_state = NULL; |
/* might depend on previous initialization */ |
thread_create_arch(t); |
/branches/tracing/kernel/generic/src/syscall/syscall.c |
---|
97,8 → 97,10 |
unative_t a4, unative_t a5, unative_t a6, unative_t id) |
{ |
unative_t rc; |
istate_t fake_state; |
if (id < SYSCALL_END) { |
THREAD->uspace_state = &fake_state; |
udebug_stoppable_begin(); |
rc = syscall_table[id](a1, a2, a3, a4, a5, a6); |
} else { |
113,6 → 115,7 |
udebug_syscall_event(a1, a2, a3, a4, a5, a6, id, rc); |
udebug_stoppable_end(); |
THREAD->uspace_state = NULL; |
return rc; |
} |
/branches/tracing/kernel/generic/src/udebug/udebug_ipc.c |
---|
127,6 → 127,96 |
return 1; /* actually need becksend with retval 0 */ |
} |
static int udebug_rp_regs_read(call_t *call, phone_t *phone) |
{ |
thread_t *t; |
task_t *ta; |
void *uspace_buffer; |
unative_t to_copy; |
int rc; |
istate_t *state; |
klog_printf("debug_regs_read()"); |
// FIXME: verify task/thread state |
state = THREAD->uspace_state; |
if (state == NULL) { |
klog_printf("debug_regs_read() - istate not available"); |
return EBUSY; |
} |
ta = get_lock_callee_task(phone); |
t = (thread_t *) IPC_GET_ARG2(call->data); |
if (!thread_exists(t)) { |
spinlock_unlock(&ta->lock); |
return ENOENT; |
} |
uspace_buffer = (void *)IPC_GET_ARG3(call->data); |
to_copy = IPC_GET_ARG4(call->data); |
if (to_copy > sizeof(istate_t)) to_copy = sizeof(istate_t); |
rc = copy_to_uspace(uspace_buffer, t->uspace_state, to_copy); |
if (rc != 0) { |
spinlock_unlock(&ta->lock); |
klog_printf("debug_regs_read() - copy failed"); |
return rc; |
} |
spinlock_unlock(&ta->lock); |
IPC_SET_ARG1(call->data, to_copy); |
IPC_SET_ARG2(call->data, sizeof(istate_t)); |
klog_printf("debug_regs_read() done"); |
return 1; /* actually need becksend with retval 0 */ |
} |
static int udebug_rp_regs_write(call_t *call, phone_t *phone) |
{ |
thread_t *t; |
task_t *ta; |
void *uspace_data; |
unative_t to_copy; |
int rc; |
istate_t *state; |
klog_printf("debug_regs_write()"); |
// FIXME: verify task/thread state |
state = THREAD->uspace_state; |
if (state == NULL) { |
klog_printf("debug_regs_write() - istate not available"); |
return EBUSY; |
} |
ta = get_lock_callee_task(phone); |
t = (thread_t *) IPC_GET_ARG2(call->data); |
if (!thread_exists(t)) { |
spinlock_unlock(&ta->lock); |
return ENOENT; |
} |
uspace_data = (void *)IPC_GET_ARG3(call->data); |
to_copy = IPC_GET_ARG4(call->data); |
if (to_copy > sizeof(istate_t)) to_copy = sizeof(istate_t); |
rc = copy_from_uspace(t->uspace_state, uspace_data, to_copy); |
if (rc != 0) { |
spinlock_unlock(&ta->lock); |
klog_printf("debug_regs_write() - copy failed"); |
return rc; |
} |
spinlock_unlock(&ta->lock); |
IPC_SET_ARG1(call->data, to_copy); |
IPC_SET_ARG2(call->data, sizeof(istate_t)); |
klog_printf("debug_regs_write() done"); |
return 1; /* actually need becksend with retval 0 */ |
} |
static int udebug_rp_thread_read(call_t *call, phone_t *phone) |
{ |
thread_t *t; |
200,6 → 290,12 |
case UDEBUG_M_ARGS_READ: |
rc = udebug_rp_args_read(call, phone); |
return rc; |
case UDEBUG_M_REGS_READ: |
rc = udebug_rp_regs_read(call, phone); |
return rc; |
case UDEBUG_M_REGS_WRITE: |
rc = udebug_rp_regs_write(call, phone); |
return rc; |
case UDEBUG_M_THREAD_READ: |
rc = udebug_rp_thread_read(call, phone); |
return rc; |