Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2812 → Rev 2813

/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