Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2831 → Rev 2832

/branches/tracing/uspace/app/sctrace/sctrace.c
0,0 → 1,195
/** @addtogroup sctrace
* @{
*/
/** @file
*/
 
#include <stdio.h>
#include <unistd.h>
#include <syscall.h>
#include <ipc/ipc.h>
#include <udebug.h>
 
#include "syscalls.h"
#include "errors.h"
#include "debug_api.h"
 
#define TIDBUF_SIZE 64
unsigned threadid_buf[TIDBUF_SIZE];
 
int phoneid;
 
int task_connect(int taskid)
{
int rc;
 
printf("ipc_connect_task(%d)...\n", taskid);
rc = ipc_connect_kbox(taskid);
printf("-> %d\n", rc);
phoneid = rc;
if (rc < 0) return rc;
 
printf("debug_begin()\n");
rc = debug_begin(phoneid);
printf("-> %d\n", rc);
if (rc < 0) return rc;
 
return 0;
}
 
int get_thread_list(void)
{
int rc;
int tb_copied;
int tb_needed;
int i;
 
 
printf("send IPC_M_DEBUG_THREAD_READ message\n");
rc = debug_thread_read(phoneid, (unsigned)threadid_buf,
TIDBUF_SIZE*sizeof(unsigned), &tb_copied, &tb_needed);
printf("-> %d\n", rc);
if (rc < 0) return rc;
 
printf("thread IDs:");
for (i=0; i<tb_copied / sizeof(unsigned); i++) {
printf(" %u", threadid_buf[i]);
}
printf("\ntotal of %u threads\n", tb_needed/sizeof(unsigned));
 
return 0;
}
 
void print_sc_retval(int retval, rv_type_t rv_type)
{
printf (" -> ");
if (rv_type == RV_INTEGER) {
printf("%d", retval);
} else if (rv_type == RV_HASH) {
printf("0x%08x", retval);
} else if (rv_type == RV_ERRNO) {
if (retval >= -15 && retval <= 0) {
printf("%d %s (%s)", retval,
err_desc[retval].name,
err_desc[retval].desc);
} else {
printf("%d", retval);
}
} else if (rv_type == RV_INT_ERRNO) {
if (retval >= -15 && retval < 0) {
printf("%d %s (%s)", retval,
err_desc[retval].name,
err_desc[retval].desc);
} else {
printf("%d", retval);
}
}
putchar('\n');
}
 
void print_sc_args(unsigned *sc_args, int n)
{
int i;
 
putchar('(');
if (n > 0) printf("%d", sc_args[0]);
for (i=1; i<n; i++) {
printf(", %d", sc_args[i]);
}
putchar(')');
}
 
void sc_ipc_call_async_slow(unsigned *sc_args)
{
unsigned ipc_args[6];
int rc;
 
memset(ipc_args, 0, sizeof(ipc_args));
rc = debug_mem_read(phoneid, ipc_args, sc_args[1], sizeof(ipc_args));
 
if (rc >= 0) {
printf("args: (%u, %u, %u, %u, %u, %u)\n",
ipc_args[0], ipc_args[1], ipc_args[2],
ipc_args[3], ipc_args[4], ipc_args[5]);
}
}
 
void trace_loop(void)
{
int rc;
unsigned sc_args[6];
unsigned copied;
unsigned ev_type;
unsigned sc_id;
int sc_rc;
int rv_type;
 
while (1) {
/* Run thread until a syscall is executed */
rc = debug_go(phoneid, threadid_buf[0],
&ev_type, &sc_id, &sc_rc);
 
/* Read syscall arguments */
if (rc >= 0) {
rc = debug_args_read(phoneid, threadid_buf[0],
sc_args);
}
 
/* Print syscall name, id and arguments */
if (rc >= 0) {
printf("%s", syscall_desc[sc_id].name);
print_sc_args(sc_args, syscall_desc[sc_id].n_args);
rv_type = syscall_desc[sc_id].rv_type;
print_sc_retval(sc_rc, rv_type);
}
 
switch (sc_id) {
case SYS_IPC_CALL_ASYNC_SLOW:
sc_ipc_call_async_slow(sc_args);
break;
default:
break;
}
}
}
 
 
void trace_active_task(void)
{
int taskid;
int i;
int rc;
 
printf("Syscall Tracer\n");
printf("Press 'c' to connect\n");
while ((i = getchar()) != 'c')
putchar(i);
 
taskid = 13;
rc = task_connect(taskid);
if (rc < 0) {
printf("Failed to connect to task %d\n", taskid);
return;
}
 
printf("Connected to task %d\n", taskid);
 
rc = get_thread_list();
if (rc < 0) {
printf("Failed to get thread list (error %d)\n", rc);
return;
}
 
trace_loop();
 
printf("done\n");
return;
}
 
int main(void)
{
trace_active_task();
}
 
/** @}
*/