/branches/tracing/kernel/generic/include/udebug.h |
---|
File deleted |
/branches/tracing/kernel/generic/include/udebug/udebug.h |
---|
0,0 → 1,97 |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_UDEBUG_H_ |
#define KERN_UDEBUG_H_ |
typedef enum { /* udebug_method_t */ |
/** Start debugging the recipient. |
* Causes all threads in the receiving task to stop. When they |
* are all stoped, an answer with retval 0 is generated. |
*/ |
UDEBUG_M_BEGIN = 1, |
/** Finish debugging the recipient. |
* Answers all pending GO and GUARD messages. |
*/ |
UDEBUG_M_END, |
/** Make sure the debugged task is still there. |
* This message is answered when the debugged task dies |
* or the debugging session ends. |
*/ |
UDEBUG_M_GUARD, |
/** Run a thread until a debugging event occurs. |
* This message is answered when the thread stops |
* in a debugging event. |
* |
* - ARG2 - id of the thread to run |
*/ |
UDEBUG_M_GO, |
/** Stop a thread being debugged. |
* Creates a special STOP event in the thread, causing |
* it to answer a pending GO message (if any). |
*/ |
UDEBUG_M_STOP, |
/** Read arguments of a syscall. |
* |
* - 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 |
*/ |
UDEBUG_M_ARGS_READ, |
/** Read the list of the debugged tasks's threads. |
* |
* - ARG2 - destination address in the caller's address space |
* - ARG3 - size of receiving buffer in bytes |
* |
* The kernel fills the buffer with a series of sysarg_t values |
* (thread ids). On answer, the kernel will set: |
* |
* - ARG1 - number of bytes that were actually copied |
* - ARG2 - number of bytes of the complete data |
* |
*/ |
UDEBUG_M_THREAD_READ, |
/** Read the list of the debugged tasks's memory. |
* |
* - ARG2 - destination address in the caller's address space |
* - ARG3 - source address in the recipient's address space |
* - ARG4 - size of receiving buffer in bytes |
* |
*/ |
UDEBUG_M_MEM_READ |
} udebug_method_t; |
typedef enum { |
UDEBUG_EVENT_SYSCALL |
} udebug_event_t; |
#ifdef KERNEL |
void udebug_syscall_event(unative_t a1, unative_t a2, unative_t a3, |
unative_t a4, unative_t a5, unative_t a6, unative_t id, unative_t rc); |
void udebug_stoppable_begin(void); |
void udebug_stoppable_end(void); |
#endif |
#endif |
/** @} |
*/ |
/branches/tracing/kernel/generic/include/udebug/udebug_ipc.h |
---|
0,0 → 1,17 |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_UDEBUG_IPC_H_ |
#define KERN_UDEBUG_IPC_H_ |
#include <ipc/ipc.h> |
int udebug_request_preprocess(call_t *call, phone_t *phone); |
#endif |
/** @} |
*/ |
/branches/tracing/kernel/generic/src/syscall/syscall.c |
---|
52,7 → 52,7 |
#include <sysinfo/sysinfo.h> |
#include <console/console.h> |
#include <console/klog.h> |
#include <udebug.h> |
#include <udebug/udebug.h> |
/** Print using kernel facility |
* |
/branches/tracing/kernel/generic/src/ipc/sysipc.c |
---|
42,6 → 42,7 |
#include <ipc/sysipc.h> |
#include <ipc/irq.h> |
#include <ipc/ipcrsc.h> |
#include <udebug/udebug_ipc.h> |
#include <arch/interrupt.h> |
#include <print.h> |
#include <syscall/copy.h> |
290,215 → 291,6 |
return 0; |
} |
static task_t *get_lock_callee_task(phone_t *phone) |
{ |
answerbox_t *answerbox; |
task_t *ta; |
// FIXME: locking!!! |
answerbox = phone->callee; |
ta = answerbox->task; |
spinlock_lock(&ta->lock); |
return ta; |
} |
static thread_t *get_task_thread_by_id(task_t *ta, thread_id_t tid) |
{ |
thread_t *t; |
link_t *cur; |
for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
t = list_get_instance(cur, thread_t, th_link); |
if (tid == t->tid) return t; |
} |
return NULL; |
} |
#include <console/klog.h> |
static int debug_begin(call_t *call, phone_t *phone) |
{ |
task_t *ta; |
klog_printf("debug_begin()"); |
ta = get_lock_callee_task(phone); |
klog_printf("debugging task %llu", ta->taskid); |
if (ta->being_debugged != false) { |
spinlock_unlock(&ta->lock); |
klog_printf("debug_begin(): busy error"); |
return EBUSY; |
} |
ta->being_debugged = true; |
ta->stop_request = true; |
ta->debug_begin_call = call; |
if (ta->not_stoppable_count == 0) { |
ta->debug_begin_call = NULL; |
ta->stop_request = false; |
spinlock_unlock(&ta->lock); |
klog_printf("debug_begin(): immediate backsend"); |
return 1; /* actually we need backsend with 0 retval */ |
} |
spinlock_unlock(&ta->lock); |
klog_printf("debug_begin() done (wait for stoppability)"); |
return 0; |
} |
static int debug_go(call_t *call, phone_t *phone) |
{ |
thread_t *t; |
task_t *ta; |
klog_printf("debug_go()"); |
ta = get_lock_callee_task(phone); |
ta->debug_go_call = call; |
t = get_task_thread_by_id(ta, IPC_GET_ARG2(call->data)); |
if (t == NULL) { |
spinlock_unlock(&ta->lock); |
return ENOENT; |
} |
klog_printf("debug_go(): waitq_wakeup"); |
waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
spinlock_unlock(&ta->lock); |
return 0; /* no backsend */ |
} |
static int debug_args_read(call_t *call, phone_t *phone) |
{ |
thread_t *t; |
task_t *ta; |
void *uspace_buffer; |
unative_t to_copy; |
int rc; |
klog_printf("debug_args_read()"); |
// FIXME: verify task/thread state |
ta = get_lock_callee_task(phone); |
klog_printf("task %llu", ta->taskid); |
t = get_task_thread_by_id(ta, IPC_GET_ARG2(call->data)); |
if (t == NULL) { |
spinlock_unlock(&ta->lock); |
return ENOENT; |
} |
uspace_buffer = (void *)IPC_GET_ARG3(call->data); |
to_copy = IPC_GET_ARG4(call->data); |
if (to_copy > 6 * sizeof(unative_t)) to_copy = 6 * sizeof(unative_t); |
rc = copy_to_uspace(uspace_buffer, t->syscall_args, to_copy); |
if (rc != 0) { |
spinlock_unlock(&ta->lock); |
klog_printf("debug_args_read() - copy failed"); |
return rc; |
} |
spinlock_unlock(&ta->lock); |
IPC_SET_ARG1(call->data, to_copy); |
klog_printf("debug_args_read() done"); |
return 1; /* actually need becksend with retval 0 */ |
} |
static int debug_thread_read(call_t *call, phone_t *phone) |
{ |
thread_t *t; |
link_t *cur; |
task_t *ta; |
unative_t *uspace_buffer; |
unative_t to_copy; |
int rc; |
unsigned copied, total; |
unsigned buf_size; |
unative_t tid; |
klog_printf("debug_thread_read()"); |
// FIXME: verify task/thread state |
ta = get_lock_callee_task(phone); |
klog_printf("task %llu", ta->taskid); |
uspace_buffer = (void *)IPC_GET_ARG2(call->data); |
buf_size = IPC_GET_ARG3(call->data); |
copied = total = 0; |
for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
t = list_get_instance(cur, thread_t, th_link); |
/* Not interested in kernel threads */ |
if ((t->flags & THREAD_FLAG_USPACE) == 0) |
continue; |
//FIXME: id cropped!! |
tid = (unative_t) t->tid; |
to_copy = sizeof(unative_t); |
if (copied + to_copy >= buf_size) |
to_copy = buf_size - copied; |
if (to_copy > 0) { |
rc = copy_to_uspace(uspace_buffer, &tid, to_copy); |
if (rc != 0) { |
spinlock_unlock(&ta->lock); |
klog_printf("debug_thread_read() - copy failed"); |
return rc; |
} |
} |
++uspace_buffer; |
total += sizeof(unative_t); |
copied += to_copy; |
} |
spinlock_unlock(&ta->lock); |
IPC_SET_ARG1(call->data, copied); |
IPC_SET_ARG2(call->data, total); |
klog_printf("debug_thread_read() done"); |
return 1; /* actually need becksend with retval 0 */ |
} |
#include <udebug.h> |
static int debug_request_preprocess(call_t *call, phone_t *phone) |
{ |
int rc; |
switch (IPC_GET_ARG1(call->data)) { |
case UDEBUG_M_BEGIN: |
rc = debug_begin(call, phone); |
return rc; |
case UDEBUG_M_GO: |
rc = debug_go(call, phone); |
return rc; |
case UDEBUG_M_ARGS_READ: |
rc = debug_args_read(call, phone); |
return rc; |
case UDEBUG_M_THREAD_READ: |
rc = debug_thread_read(call, phone); |
return rc; |
default: |
break; |
} |
return 0; |
} |
/** Called before the request is sent. |
* |
* @param call Call structure with the request. |
550,7 → 342,7 |
break; |
case IPC_M_DEBUG_ALL: |
/* actually need possibility of backsend with 0 result code */ |
rc = debug_request_preprocess(call, phone); |
rc = udebug_request_preprocess(call, phone); |
return rc; |
default: |
break; |
799,9 → 591,6 |
ipc_call_free(call); |
return (unative_t) rc; |
} |
if (TASK->being_debugged) |
klog_printf("call_async_slow: phone=%u, uspace_ptr=%u, arg0=%u", |
phoneid, (unsigned)data, call->data.args[0]); |
if (!(res = request_preprocess(call, phone))) |
ipc_call(phone, call); |
else |
/branches/tracing/kernel/generic/src/ipc/ipc.c |
---|
609,7 → 609,7 |
#include <ipc/ipcrsc.h> |
#include <console/klog.h> |
#include <syscall/copy.h> |
#include <udebug.h> |
#include <udebug/udebug.h> |
static void debug_mem_read(call_t *call) |
{ |
/branches/tracing/kernel/generic/src/udebug/udebug_ipc.c |
---|
0,0 → 1,226 |
/** @addtogroup generic |
* @{ |
*/ |
/** |
* @file |
* @brief Tdebug. |
*/ |
#include <console/klog.h> |
#include <proc/task.h> |
#include <proc/thread.h> |
#include <errno.h> |
#include <ipc/ipc.h> |
#include <syscall/copy.h> |
#include <udebug/udebug.h> |
#include <udebug/udebug_ipc.h> |
static task_t *get_lock_callee_task(phone_t *phone) |
{ |
answerbox_t *answerbox; |
task_t *ta; |
// FIXME: locking!!! |
answerbox = phone->callee; |
ta = answerbox->task; |
spinlock_lock(&ta->lock); |
return ta; |
} |
static thread_t *get_task_thread_by_id(task_t *ta, thread_id_t tid) |
{ |
thread_t *t; |
link_t *cur; |
for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
t = list_get_instance(cur, thread_t, th_link); |
if (tid == t->tid) return t; |
} |
return NULL; |
} |
static int udebug_rp_begin(call_t *call, phone_t *phone) |
{ |
task_t *ta; |
klog_printf("debug_begin()"); |
ta = get_lock_callee_task(phone); |
klog_printf("debugging task %llu", ta->taskid); |
if (ta->being_debugged != false) { |
spinlock_unlock(&ta->lock); |
klog_printf("debug_begin(): busy error"); |
return EBUSY; |
} |
ta->being_debugged = true; |
ta->stop_request = true; |
ta->debug_begin_call = call; |
if (ta->not_stoppable_count == 0) { |
ta->debug_begin_call = NULL; |
ta->stop_request = false; |
spinlock_unlock(&ta->lock); |
klog_printf("debug_begin(): immediate backsend"); |
return 1; /* actually we need backsend with 0 retval */ |
} |
spinlock_unlock(&ta->lock); |
klog_printf("debug_begin() done (wait for stoppability)"); |
return 0; |
} |
static int udebug_rp_go(call_t *call, phone_t *phone) |
{ |
thread_t *t; |
task_t *ta; |
klog_printf("debug_go()"); |
ta = get_lock_callee_task(phone); |
ta->debug_go_call = call; |
t = get_task_thread_by_id(ta, IPC_GET_ARG2(call->data)); |
if (t == NULL) { |
spinlock_unlock(&ta->lock); |
return ENOENT; |
} |
klog_printf("debug_go(): waitq_wakeup"); |
waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
spinlock_unlock(&ta->lock); |
return 0; /* no backsend */ |
} |
static int udebug_rp_args_read(call_t *call, phone_t *phone) |
{ |
thread_t *t; |
task_t *ta; |
void *uspace_buffer; |
unative_t to_copy; |
int rc; |
klog_printf("debug_args_read()"); |
// FIXME: verify task/thread state |
ta = get_lock_callee_task(phone); |
klog_printf("task %llu", ta->taskid); |
t = get_task_thread_by_id(ta, IPC_GET_ARG2(call->data)); |
if (t == NULL) { |
spinlock_unlock(&ta->lock); |
return ENOENT; |
} |
uspace_buffer = (void *)IPC_GET_ARG3(call->data); |
to_copy = IPC_GET_ARG4(call->data); |
if (to_copy > 6 * sizeof(unative_t)) to_copy = 6 * sizeof(unative_t); |
rc = copy_to_uspace(uspace_buffer, t->syscall_args, to_copy); |
if (rc != 0) { |
spinlock_unlock(&ta->lock); |
klog_printf("debug_args_read() - copy failed"); |
return rc; |
} |
spinlock_unlock(&ta->lock); |
IPC_SET_ARG1(call->data, to_copy); |
klog_printf("debug_args_read() done"); |
return 1; /* actually need becksend with retval 0 */ |
} |
static int udebug_rp_thread_read(call_t *call, phone_t *phone) |
{ |
thread_t *t; |
link_t *cur; |
task_t *ta; |
unative_t *uspace_buffer; |
unative_t to_copy; |
int rc; |
unsigned copied, total; |
unsigned buf_size; |
unative_t tid; |
klog_printf("debug_thread_read()"); |
// FIXME: verify task/thread state |
ta = get_lock_callee_task(phone); |
klog_printf("task %llu", ta->taskid); |
uspace_buffer = (void *)IPC_GET_ARG2(call->data); |
buf_size = IPC_GET_ARG3(call->data); |
copied = total = 0; |
for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
t = list_get_instance(cur, thread_t, th_link); |
/* Not interested in kernel threads */ |
if ((t->flags & THREAD_FLAG_USPACE) == 0) |
continue; |
//FIXME: id cropped!! |
tid = (unative_t) t->tid; |
to_copy = sizeof(unative_t); |
if (copied + to_copy >= buf_size) |
to_copy = buf_size - copied; |
if (to_copy > 0) { |
rc = copy_to_uspace(uspace_buffer, &tid, to_copy); |
if (rc != 0) { |
spinlock_unlock(&ta->lock); |
klog_printf("debug_thread_read() - copy failed"); |
return rc; |
} |
} |
++uspace_buffer; |
total += sizeof(unative_t); |
copied += to_copy; |
} |
spinlock_unlock(&ta->lock); |
IPC_SET_ARG1(call->data, copied); |
IPC_SET_ARG2(call->data, total); |
klog_printf("debug_thread_read() done"); |
return 1; /* actually need becksend with retval 0 */ |
} |
int udebug_request_preprocess(call_t *call, phone_t *phone) |
{ |
int rc; |
switch (IPC_GET_ARG1(call->data)) { |
case UDEBUG_M_BEGIN: |
rc = udebug_rp_begin(call, phone); |
return rc; |
case UDEBUG_M_GO: |
rc = udebug_rp_go(call, phone); |
return rc; |
case UDEBUG_M_ARGS_READ: |
rc = udebug_rp_args_read(call, phone); |
return rc; |
case UDEBUG_M_THREAD_READ: |
rc = udebug_rp_thread_read(call, phone); |
return rc; |
default: |
break; |
} |
return 0; |
} |
/** @} |
*/ |
/branches/tracing/kernel/generic/src/udebug/udebug.c |
---|
9,7 → 9,7 |
#include <synch/waitq.h> |
#include <console/klog.h> |
#include <udebug.h> |
#include <udebug/udebug.h> |
#include <arch.h> |
void udebug_stoppable_begin(void) |
/branches/tracing/kernel/Makefile |
---|
276,6 → 276,7 |
generic/src/ipc/ipcrsc.c \ |
generic/src/ipc/irq.c \ |
generic/src/udebug/udebug.c \ |
generic/src/udebug/udebug_ipc.c \ |
generic/src/security/cap.c \ |
generic/src/sysinfo/sysinfo.c |
/branches/tracing/uspace/lib/libc/include/udebug.h |
---|
7,7 → 7,7 |
#ifndef LIBC_UDEBUG_H_ |
#define LIBC_UDEBUG_H_ |
#include <kernel/udebug.h> |
#include <kernel/udebug/udebug.h> |
#endif |