Subversion Repositories HelenOS

Rev

Rev 3623 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2008 Jiri Svoboda
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup generic
  30.  * @{
  31.  */
  32.  
  33. /**
  34.  * @file
  35.  * @brief   Udebug hooks and data structure management.
  36.  *
  37.  * Udebug is an interface that makes userspace debuggers possible.
  38.  */
  39.  
  40. #include <synch/waitq.h>
  41. #include <debug.h>
  42. #include <udebug/udebug.h>
  43. #include <errno.h>
  44. #include <arch.h>
  45.  
  46.  
  47. /** Initialize udebug part of task structure.
  48.  *
  49.  * Called as part of task structure initialization.
  50.  * @param ut    Pointer to the structure to initialize.
  51.  */
  52. void udebug_task_init(udebug_task_t *ut)
  53. {
  54.     mutex_initialize(&ut->lock, MUTEX_PASSIVE);
  55.     ut->dt_state = UDEBUG_TS_INACTIVE;
  56.     ut->begin_call = NULL;
  57.     ut->not_stoppable_count = 0;
  58.     ut->evmask = 0;
  59. }
  60.  
  61. /** Initialize udebug part of thread structure.
  62.  *
  63.  * Called as part of thread structure initialization.
  64.  * @param ut    Pointer to the structure to initialize.
  65.  */
  66. void udebug_thread_initialize(udebug_thread_t *ut)
  67. {
  68.     mutex_initialize(&ut->lock, MUTEX_PASSIVE);
  69.     waitq_initialize(&ut->go_wq);
  70.  
  71.     ut->go_call = NULL;
  72.     ut->uspace_state = NULL;
  73.     ut->go = false;
  74.     ut->stoppable = true;
  75.     ut->active = false;
  76.     ut->cur_event = 0; /* none */
  77. }
  78.  
  79. /** Wait for a GO message.
  80.  *
  81.  * When a debugging event occurs in a thread or the thread is stopped,
  82.  * this function is called to block the thread until a GO message
  83.  * is received.
  84.  *
  85.  * @param wq    The wait queue used by the thread to wait for GO messages.
  86.  */
  87. static void udebug_wait_for_go(waitq_t *wq)
  88. {
  89.     int rc;
  90.     ipl_t ipl;
  91.  
  92.     ipl = waitq_sleep_prepare(wq);
  93.  
  94.     wq->missed_wakeups = 0; /* Enforce blocking. */
  95.     rc = waitq_sleep_timeout_unsafe(wq, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);
  96.  
  97.     waitq_sleep_finish(wq, rc, ipl);
  98. }
  99.  
  100. /** Do a preliminary check that a debugging session is in progress.
  101.  *
  102.  * This only requires the THREAD->udebug.lock mutex (and not TASK->udebug.lock
  103.  * mutex). For an undebugged task, this will never block (while there could be
  104.  * collisions by different threads on the TASK mutex), thus improving SMP
  105.  * perormance for undebugged tasks.
  106.  *
  107.  * @return  True if the thread was in a debugging session when the function
  108.  *      checked, false otherwise.
  109.  */
  110. static bool udebug_thread_precheck(void)
  111. {
  112.     bool res;
  113.  
  114.     mutex_lock(&THREAD->udebug.lock);
  115.     res = THREAD->udebug.active;
  116.     mutex_unlock(&THREAD->udebug.lock);
  117.  
  118.     return res;
  119. }
  120.  
  121. /** Start of stoppable section.
  122.  *
  123.  * A stoppable section is a section of code where if the thread can be stoped. In other words,
  124.  * if a STOP operation is issued, the thread is guaranteed not to execute
  125.  * any userspace instructions until the thread is resumed.
  126.  *
  127.  * Having stoppable sections is better than having stopping points, since
  128.  * a thread can be stopped even when it is blocked indefinitely in a system
  129.  * call (whereas it would not reach any stopping point).
  130.  */
  131. void udebug_stoppable_begin(void)
  132. {
  133.     int nsc;
  134.     call_t *db_call, *go_call;
  135.  
  136.     ASSERT(THREAD);
  137.     ASSERT(TASK);
  138.  
  139.     /* Early check for undebugged tasks */
  140.     if (!udebug_thread_precheck()) {
  141.         return;
  142.     }
  143.  
  144.     mutex_lock(&TASK->udebug.lock);
  145.  
  146.     nsc = --TASK->udebug.not_stoppable_count;
  147.  
  148.     /* Lock order OK, THREAD->udebug.lock is after TASK->udebug.lock */
  149.     mutex_lock(&THREAD->udebug.lock);
  150.     ASSERT(THREAD->udebug.stoppable == false);
  151.     THREAD->udebug.stoppable = true;
  152.  
  153.     if (TASK->udebug.dt_state == UDEBUG_TS_BEGINNING && nsc == 0) {
  154.         /*
  155.          * This was the last non-stoppable thread. Reply to
  156.          * DEBUG_BEGIN call.
  157.          */
  158.  
  159.         db_call = TASK->udebug.begin_call;
  160.         ASSERT(db_call);
  161.  
  162.         TASK->udebug.dt_state = UDEBUG_TS_ACTIVE;
  163.         TASK->udebug.begin_call = NULL;
  164.  
  165.         IPC_SET_RETVAL(db_call->data, 0);
  166.         ipc_answer(&TASK->answerbox, db_call);     
  167.  
  168.     } else if (TASK->udebug.dt_state == UDEBUG_TS_ACTIVE) {
  169.         /*
  170.          * Active debugging session
  171.          */
  172.  
  173.         if (THREAD->udebug.active == true &&
  174.             THREAD->udebug.go == false) {
  175.             /*
  176.              * Thread was requested to stop - answer go call
  177.              */
  178.  
  179.             /* Make sure nobody takes this call away from us */
  180.             go_call = THREAD->udebug.go_call;
  181.             THREAD->udebug.go_call = NULL;
  182.             ASSERT(go_call);
  183.  
  184.             IPC_SET_RETVAL(go_call->data, 0);
  185.             IPC_SET_ARG1(go_call->data, UDEBUG_EVENT_STOP);
  186.  
  187.             THREAD->udebug.cur_event = UDEBUG_EVENT_STOP;
  188.  
  189.                 ipc_answer(&TASK->answerbox, go_call);
  190.         }
  191.     }
  192.  
  193.     mutex_unlock(&THREAD->udebug.lock);
  194.         mutex_unlock(&TASK->udebug.lock);
  195. }
  196.  
  197. /** End of a stoppable section.
  198.  *
  199.  * This is the point where the thread will block if it is stopped.
  200.  * (As, by definition, a stopped thread must not leave its stoppable section).
  201.  */
  202. void udebug_stoppable_end(void)
  203. {
  204.     /* Early check for undebugged tasks */
  205.     if (!udebug_thread_precheck()) {
  206.         return;
  207.     }
  208.  
  209. restart:
  210.     mutex_lock(&TASK->udebug.lock);
  211.     mutex_lock(&THREAD->udebug.lock);
  212.  
  213.     if (THREAD->udebug.active && THREAD->udebug.go == false) {
  214.         TASK->udebug.begin_call = NULL;
  215.         mutex_unlock(&THREAD->udebug.lock);
  216.         mutex_unlock(&TASK->udebug.lock);
  217.  
  218.         udebug_wait_for_go(&THREAD->udebug.go_wq);
  219.  
  220.         goto restart;
  221.         /* Must try again - have to lose stoppability atomically. */
  222.     } else {
  223.         ++TASK->udebug.not_stoppable_count;
  224.         ASSERT(THREAD->udebug.stoppable == true);
  225.         THREAD->udebug.stoppable = false;
  226.  
  227.         mutex_unlock(&THREAD->udebug.lock);
  228.         mutex_unlock(&TASK->udebug.lock);
  229.     }
  230. }
  231.  
  232. /** Upon being scheduled to run, check if the current thread should stop.
  233.  *
  234.  * This function is called from clock().
  235.  */
  236. void udebug_before_thread_runs(void)
  237. {
  238.     /* Check if we are supposed to stop. */
  239.     udebug_stoppable_begin();
  240.     udebug_stoppable_end();
  241. }
  242.  
  243. /** Syscall event hook.
  244.  *
  245.  * Must be called before and after servicing a system call. This generates
  246.  * a SYSCALL_B or SYSCALL_E event, depending on the value of @a end_variant.
  247.  */
  248. void udebug_syscall_event(unative_t a1, unative_t a2, unative_t a3,
  249.     unative_t a4, unative_t a5, unative_t a6, unative_t id, unative_t rc,
  250.     bool end_variant)
  251. {
  252.     call_t *call;
  253.     udebug_event_t etype;
  254.  
  255.     etype = end_variant ? UDEBUG_EVENT_SYSCALL_E : UDEBUG_EVENT_SYSCALL_B;
  256.  
  257.     /* Early check for undebugged tasks */
  258.     if (!udebug_thread_precheck()) {
  259.         return;
  260.     }
  261.  
  262.     mutex_lock(&TASK->udebug.lock);
  263.     mutex_lock(&THREAD->udebug.lock);
  264.  
  265.     /* Must only generate events when in debugging session and is go. */
  266.     if (THREAD->udebug.active != true || THREAD->udebug.go == false ||
  267.         (TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) {
  268.         mutex_unlock(&THREAD->udebug.lock);
  269.         mutex_unlock(&TASK->udebug.lock);
  270.         return;
  271.     }
  272.  
  273.     //printf("udebug_syscall_event\n");
  274.     call = THREAD->udebug.go_call;
  275.     THREAD->udebug.go_call = NULL;
  276.  
  277.     IPC_SET_RETVAL(call->data, 0);
  278.     IPC_SET_ARG1(call->data, etype);
  279.     IPC_SET_ARG2(call->data, id);
  280.     IPC_SET_ARG3(call->data, rc);
  281.     //printf("udebug_syscall_event/ipc_answer\n");
  282.  
  283.     THREAD->udebug.syscall_args[0] = a1;
  284.     THREAD->udebug.syscall_args[1] = a2;
  285.     THREAD->udebug.syscall_args[2] = a3;
  286.     THREAD->udebug.syscall_args[3] = a4;
  287.     THREAD->udebug.syscall_args[4] = a5;
  288.     THREAD->udebug.syscall_args[5] = a6;
  289.  
  290.     /*
  291.      * Make sure udebug.go is false when going to sleep
  292.      * in case we get woken up by DEBUG_END. (At which
  293.      * point it must be back to the initial true value).
  294.      */
  295.     THREAD->udebug.go = false;
  296.     THREAD->udebug.cur_event = etype;
  297.  
  298.     ipc_answer(&TASK->answerbox, call);
  299.  
  300.     mutex_unlock(&THREAD->udebug.lock);
  301.     mutex_unlock(&TASK->udebug.lock);
  302.  
  303.     udebug_wait_for_go(&THREAD->udebug.go_wq);
  304. }
  305.  
  306. /** Thread-creation event hook combined with attaching the thread.
  307.  *
  308.  * Must be called when a new userspace thread is created in the debugged
  309.  * task. Generates a THREAD_B event. Also attaches the thread @a t
  310.  * to the task @a ta.
  311.  *
  312.  * This is necessary to avoid a race condition where the BEGIN and THREAD_READ
  313.  * requests would be handled inbetween attaching the thread and checking it
  314.  * for being in a debugging session to send the THREAD_B event. We could then
  315.  * either miss threads or get some threads both in the thread list
  316.  * and get a THREAD_B event for them.
  317.  *
  318.  * @param t Structure of the thread being created. Not locked, as the
  319.  *      thread is not executing yet.
  320.  * @param ta    Task to which the thread should be attached.
  321.  */
  322. void udebug_thread_b_event_attach(struct thread *t, struct task *ta)
  323. {
  324.     call_t *call;
  325.  
  326.     mutex_lock(&TASK->udebug.lock);
  327.     mutex_lock(&THREAD->udebug.lock);
  328.  
  329.     thread_attach(t, ta);
  330.  
  331.     LOG("udebug_thread_b_event\n");
  332.     LOG("- check state\n");
  333.  
  334.     /* Must only generate events when in debugging session */
  335.     if (THREAD->udebug.active != true) {
  336.         LOG("- udebug.active: %s, udebug.go: %s\n",
  337.             THREAD->udebug.active ? "yes(+)" : "no(-)",
  338.             THREAD->udebug.go ? "yes(-)" : "no(+)");
  339.         mutex_unlock(&THREAD->udebug.lock);
  340.         mutex_unlock(&TASK->udebug.lock);
  341.         return;
  342.     }
  343.  
  344.     LOG("- trigger event\n");
  345.  
  346.     call = THREAD->udebug.go_call;
  347.     THREAD->udebug.go_call = NULL;
  348.     IPC_SET_RETVAL(call->data, 0);
  349.     IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_B);
  350.     IPC_SET_ARG2(call->data, (unative_t)t);
  351.  
  352.     /*
  353.      * Make sure udebug.go is false when going to sleep
  354.      * in case we get woken up by DEBUG_END. (At which
  355.      * point it must be back to the initial true value).
  356.      */
  357.     THREAD->udebug.go = false;
  358.     THREAD->udebug.cur_event = UDEBUG_EVENT_THREAD_B;
  359.  
  360.     ipc_answer(&TASK->answerbox, call);
  361.  
  362.     mutex_unlock(&THREAD->udebug.lock);
  363.     mutex_unlock(&TASK->udebug.lock);
  364.  
  365.     LOG("- sleep\n");
  366.     udebug_wait_for_go(&THREAD->udebug.go_wq);
  367. }
  368.  
  369. /** Thread-termination event hook.
  370.  *
  371.  * Must be called when the current thread is terminating.
  372.  * Generates a THREAD_E event.
  373.  */
  374. void udebug_thread_e_event(void)
  375. {
  376.     call_t *call;
  377.  
  378.     mutex_lock(&TASK->udebug.lock);
  379.     mutex_lock(&THREAD->udebug.lock);
  380.  
  381.     LOG("udebug_thread_e_event\n");
  382.     LOG("- check state\n");
  383.  
  384.     /* Must only generate events when in debugging session. */
  385.     if (THREAD->udebug.active != true) {
  386. /*      printf("- udebug.active: %s, udebug.go: %s\n",
  387.             THREAD->udebug.active ? "yes(+)" : "no(-)",
  388.             THREAD->udebug.go ? "yes(-)" : "no(+)");*/
  389.         mutex_unlock(&THREAD->udebug.lock);
  390.         mutex_unlock(&TASK->udebug.lock);
  391.         return;
  392.     }
  393.  
  394.     LOG("- trigger event\n");
  395.  
  396.     call = THREAD->udebug.go_call;
  397.     THREAD->udebug.go_call = NULL;
  398.     IPC_SET_RETVAL(call->data, 0);
  399.     IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_E);
  400.  
  401.     /* Prevent any further debug activity in thread. */
  402.     THREAD->udebug.active = false;
  403.     THREAD->udebug.cur_event = 0;       /* none */
  404.     THREAD->udebug.go = false;  /* set to initial value */
  405.  
  406.     ipc_answer(&TASK->answerbox, call);
  407.  
  408.     mutex_unlock(&THREAD->udebug.lock);
  409.     mutex_unlock(&TASK->udebug.lock);
  410.  
  411.     /*
  412.      * This event does not sleep - debugging has finished
  413.      * in this thread.
  414.      */
  415. }
  416.  
  417. static void breakpoint_trap_event(uintptr_t addr, udebug_event_t etype)
  418. {
  419.     call_t *call;
  420.  
  421.     mutex_lock(&TASK->udebug.lock);
  422.     mutex_lock(&THREAD->udebug.lock);
  423.  
  424.     /* Must only generate events when in debugging session and have go. */
  425.     if (THREAD->udebug.active != true || THREAD->udebug.go == false) {
  426.         mutex_unlock(&THREAD->udebug.lock);
  427.         mutex_unlock(&TASK->udebug.lock);
  428.         return;
  429.     }
  430.  
  431.     /* Verify that the event is enabled */
  432.     if ((TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) {
  433.         mutex_unlock(&THREAD->udebug.lock);
  434.         mutex_unlock(&TASK->udebug.lock);
  435.         return;
  436.     }
  437.  
  438.     LOG("udebug_breakpoint/trap_event\n");
  439.     call = THREAD->udebug.go_call;
  440.     THREAD->udebug.go_call = NULL;
  441.  
  442.     IPC_SET_RETVAL(call->data, 0);
  443.     IPC_SET_ARG1(call->data, etype);
  444.     IPC_SET_ARG2(call->data, addr);
  445.  
  446.     /*
  447.      * Make sure udebug.go is false when going to sleep
  448.      * in case we get woken up by DEBUG_END. (At which
  449.      * point it must be back to the initial true value).
  450.      */
  451.     THREAD->udebug.go = false;
  452.     THREAD->udebug.cur_event = etype;
  453.  
  454.     LOG("- send answer\n");
  455.     ipc_answer(&TASK->answerbox, call);
  456.  
  457.     mutex_unlock(&THREAD->udebug.lock);
  458.     mutex_unlock(&TASK->udebug.lock);
  459.  
  460.     udebug_wait_for_go(&THREAD->udebug.go_wq);
  461. }
  462.  
  463. void udebug_breakpoint_event(uintptr_t addr)
  464. {
  465.     breakpoint_trap_event(addr, UDEBUG_EVENT_BREAKPOINT);
  466. }
  467.  
  468. void udebug_trap_event(uintptr_t addr)
  469. {
  470.     breakpoint_trap_event(addr, UDEBUG_EVENT_TRAP);
  471. }
  472.  
  473. /**
  474.  * Terminate task debugging session.
  475.  *
  476.  * Gracefully terminates the debugging session for a task. If the debugger
  477.  * is still waiting for events on some threads, it will receive a
  478.  * FINISHED event for each of them.
  479.  *
  480.  * @param ta    Task structure. ta->udebug.lock must be already locked.
  481.  * @return  Zero on success or negative error code.
  482.  */
  483. int udebug_task_cleanup(struct task *ta)
  484. {
  485.     thread_t *t;
  486.     link_t *cur;
  487.     int flags;
  488.     ipl_t ipl;
  489.  
  490.     LOG("udebug_task_cleanup()\n");
  491.     LOG("task %" PRIu64 "\n", ta->taskid);
  492.  
  493.     if (ta->udebug.dt_state != UDEBUG_TS_BEGINNING &&
  494.         ta->udebug.dt_state != UDEBUG_TS_ACTIVE) {
  495.         LOG("udebug_task_cleanup(): task not being debugged\n");
  496.         return EINVAL;
  497.     }
  498.  
  499.     /* Finish debugging of all userspace threads */
  500.     for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
  501.         t = list_get_instance(cur, thread_t, th_link);
  502.  
  503.         mutex_lock(&t->udebug.lock);
  504.  
  505.         ipl = interrupts_disable();
  506.         spinlock_lock(&t->lock);
  507.  
  508.         flags = t->flags;
  509.  
  510.         spinlock_unlock(&t->lock);
  511.         interrupts_restore(ipl);
  512.  
  513.         /* Only process userspace threads. */
  514.         if ((flags & THREAD_FLAG_USPACE) != 0) {
  515.             /* Prevent any further debug activity in thread. */
  516.             t->udebug.active = false;
  517.             t->udebug.cur_event = 0;    /* none */
  518.  
  519.             /* Is the thread still go? */
  520.             if (t->udebug.go == true) {
  521.                 /*
  522.                 * Yes, so clear go. As active == false,
  523.                  * this doesn't affect anything.
  524.                  */
  525.                 t->udebug.go = false;  
  526.  
  527.                 /* Answer GO call */
  528.                 LOG("answer GO call with EVENT_FINISHED\n");
  529.                 IPC_SET_RETVAL(t->udebug.go_call->data, 0);
  530.                 IPC_SET_ARG1(t->udebug.go_call->data,
  531.                     UDEBUG_EVENT_FINISHED);
  532.  
  533.                 ipc_answer(&ta->answerbox, t->udebug.go_call);
  534.                 t->udebug.go_call = NULL;
  535.             } else {
  536.                 /*
  537.                  * Debug_stop is already at initial value.
  538.                  * Yet this means the thread needs waking up.
  539.                  */
  540.  
  541.                 /*
  542.                  * t's lock must not be held when calling
  543.                  * waitq_wakeup.
  544.                  */
  545.                 waitq_wakeup(&t->udebug.go_wq, WAKEUP_FIRST);
  546.             }
  547.         }
  548.         mutex_unlock(&t->udebug.lock);
  549.     }
  550.  
  551.     ta->udebug.dt_state = UDEBUG_TS_INACTIVE;
  552.     ta->udebug.debugger = NULL;
  553.  
  554.     return 0;
  555. }
  556.  
  557.  
  558. /** @}
  559.  */
  560.