Subversion Repositories HelenOS

Rev

Rev 2853 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /** @addtogroup sctrace
  2.  * @{
  3.  */
  4. /** @file
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <unistd.h>
  9. #include <syscall.h>
  10. #include <ipc/ipc.h>
  11. #include <fibril.h>
  12. #include <errno.h>
  13. #include <udebug.h>
  14.  
  15. #include "syscalls.h"
  16. #include "errors.h"
  17. #include "debug_api.h"
  18.  
  19. #define TIDBUF_SIZE 64
  20. unsigned threadid_buf[TIDBUF_SIZE];
  21. unsigned n_threads;
  22.  
  23. int phoneid;
  24. int abort_trace;
  25.  
  26. volatile int print_cs;
  27.  
  28. void fcs_begin(volatile int *csvar)
  29. {
  30.     while (*csvar != 0) {
  31.         fibril_yield();
  32.         printf(" \b");
  33.     }
  34.  
  35.     *csvar = 1;
  36. }
  37.  
  38. void fcs_end(volatile int *csvar)
  39. {
  40.     *csvar = 0;
  41. }
  42.  
  43. int task_connect(int taskid)
  44. {
  45.     int rc;
  46.  
  47.     printf("ipc_connect_task(%d)...\n", taskid);
  48.     rc = ipc_connect_kbox(taskid);
  49.     printf("-> %d\n", rc);
  50.     phoneid = rc;
  51.     if (rc < 0) return rc;
  52.  
  53.     printf("debug_begin()\n");
  54.     rc = debug_begin(phoneid);
  55.     printf("-> %d\n", rc);
  56.     if (rc < 0) return rc;
  57.  
  58.     return 0;
  59. }
  60.  
  61. int get_thread_list(void)
  62. {
  63.     int rc;
  64.     int tb_copied;
  65.     int tb_needed;
  66.     int i;
  67.  
  68.  
  69.     printf("send IPC_M_DEBUG_THREAD_READ message\n");
  70.     rc = debug_thread_read(phoneid, (unsigned)threadid_buf,
  71.         TIDBUF_SIZE*sizeof(unsigned), &tb_copied, &tb_needed);
  72.     printf("-> %d\n", rc);
  73.     if (rc < 0) return rc;
  74.  
  75.     n_threads = tb_copied / sizeof(unsigned);
  76.  
  77.     printf("thread IDs:");
  78.     for (i=0; i<n_threads; i++) {
  79.         printf(" %u", threadid_buf[i]);
  80.     }
  81.     printf("\ntotal of %u threads\n", tb_needed/sizeof(unsigned));
  82.  
  83.     return 0;
  84. }
  85.  
  86. void print_sc_retval(int retval, rv_type_t rv_type)
  87. {
  88.     printf (" -> ");
  89.     if (rv_type == RV_INTEGER) {
  90.         printf("%d", retval);
  91.     } else if (rv_type == RV_HASH) {
  92.         printf("0x%08x", retval);
  93.     } else if (rv_type == RV_ERRNO) {
  94.         if (retval >= -15 && retval <= 0) {
  95.             printf("%d %s (%s)", retval,
  96.                 err_desc[retval].name,
  97.                 err_desc[retval].desc);
  98.         } else {
  99.             printf("%d", retval);
  100.         }
  101.     } else if (rv_type == RV_INT_ERRNO) {
  102.         if (retval >= -15 && retval < 0) {
  103.             printf("%d %s (%s)", retval,
  104.                 err_desc[retval].name,
  105.                 err_desc[retval].desc);
  106.         } else {
  107.             printf("%d", retval);
  108.         }
  109.     }
  110.     putchar('\n');
  111. }
  112.  
  113. void print_sc_args(unsigned *sc_args, int n)
  114. {
  115.     int i;
  116.  
  117.     putchar('(');
  118.     if (n > 0) printf("%d", sc_args[0]);
  119.     for (i=1; i<n; i++) {
  120.         printf(", %d", sc_args[i]);
  121.     }
  122.     putchar(')');
  123. }
  124.  
  125. void sc_ipc_call_async_slow(unsigned *sc_args)
  126. {
  127.     unsigned ipc_args[6];
  128.     int rc;
  129.  
  130.     memset(ipc_args, 0, sizeof(ipc_args));
  131.     rc = debug_mem_read(phoneid, ipc_args, sc_args[1], sizeof(ipc_args));
  132.  
  133.     if (rc >= 0) {
  134.         printf("args: (%u, %u, %u, %u, %u, %u)\n",
  135.             ipc_args[0], ipc_args[1], ipc_args[2],
  136.             ipc_args[3], ipc_args[4], ipc_args[5]);
  137.     }
  138. }
  139.  
  140. void trace_loop(void *thread_idx_arg)
  141. {
  142.     int rc;
  143.     unsigned sc_args[6];
  144.     unsigned copied;
  145.     unsigned ev_type;
  146.     unsigned sc_id;
  147.     int sc_rc;
  148.     int rv_type;
  149.     unsigned thread_idx;
  150.  
  151.     thread_idx = (unsigned)thread_idx_arg;
  152.     printf("trace_loop(%d)\n", thread_idx);
  153.  
  154.     while (!abort_trace) {
  155.  
  156.         /* Run thread until a syscall is executed */
  157.         rc = debug_go(phoneid, threadid_buf[thread_idx],
  158.             &ev_type, &sc_id, &sc_rc);
  159.  
  160.         printf("rc = %d, ev_type=%d\n", rc, ev_type);
  161.         if (ev_type == UDEBUG_EVENT_FINISHED) {
  162.             printf("thread %u debugging finished\n", threadid_buf[thread_idx]);
  163.             break;
  164.         }
  165.  
  166.         /* Read syscall arguments */
  167.         if (rc >= 0) {
  168.             rc = debug_args_read(phoneid, threadid_buf[thread_idx],
  169.                 sc_args);
  170.         }
  171.  
  172. //      printf("[%d]:begin\n", thread_idx);
  173.         fcs_begin(&print_cs);
  174. //      printf("[%d]:inside\n", thread_idx);
  175.  
  176.         printf("[%d] ", thread_idx);
  177.  
  178.         /* Print syscall name, id and arguments */
  179.         if (rc >= 0) {
  180.             printf("%s", syscall_desc[sc_id].name);
  181.             print_sc_args(sc_args, syscall_desc[sc_id].n_args);
  182.             rv_type = syscall_desc[sc_id].rv_type;
  183.             print_sc_retval(sc_rc, rv_type);
  184.         }
  185.  
  186. //      printf("[%d]:end\n", thread_idx);
  187.         fcs_end(&print_cs);
  188.  
  189.         switch (sc_id) {
  190.         case SYS_IPC_CALL_ASYNC_SLOW:
  191.             sc_ipc_call_async_slow(sc_args);
  192.             break;
  193.         default:
  194.             break;
  195.         }
  196.     }
  197.  
  198.     printf("trace_loop(%d) exiting\n", thread_idx);
  199. }
  200.  
  201.  
  202. void trace_active_task(void)
  203. {
  204.     int taskid;
  205.     int i;
  206.     int rc;
  207.     fid_t fid;
  208.  
  209.     printf("Syscall Tracer\n");
  210.     printf("Press 'c' to connect\n");
  211.     while ((i = getchar()) != 'c')
  212.         putchar(i);
  213.  
  214.     taskid = 14;
  215.     rc = task_connect(taskid);
  216.     if (rc < 0) {
  217.         printf("Failed to connect to task %d\n", taskid);
  218.         return;
  219.     }
  220.  
  221.     printf("Connected to task %d\n", taskid);
  222.  
  223.     rc = get_thread_list();
  224.     if (rc < 0) {
  225.         printf("Failed to get thread list (error %d)\n", rc);
  226.         return;
  227.     }
  228.  
  229.     abort_trace = 0;
  230.  
  231.     for (i = 0; i < n_threads; i++) {
  232.         fid = fibril_create(trace_loop, (void *)i);
  233.         if (fid == 0) {
  234.             printf("Warning: Failed creating fibril\n");
  235.         }
  236.         fibril_add_ready(fid);
  237.     }
  238.  
  239.     getchar();
  240.  
  241.     printf("terminate debugging session...\n");
  242.     abort_trace = 1;
  243.     debug_end(phoneid);
  244.     ipc_hangup(phoneid);
  245.  
  246.     printf("done\n");
  247.     return;
  248. }
  249.  
  250. int main(void)
  251. {
  252.     print_cs = 0;
  253.  
  254.     while (1) {
  255.         trace_active_task();
  256.     }
  257. }
  258.  
  259. /** @}
  260.  */
  261.