Subversion Repositories HelenOS

Rev

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