Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/udebug/udebug_ops.c

    r41df2827 r3698e44  
    4646#include <errno.h>
    4747#include <print.h>
     48#include <string.h>
    4849#include <syscall/copy.h>
    4950#include <ipc/ipc.h>
     
    209210
    210211                mutex_lock(&t->udebug.lock);
    211                 if ((t->flags & THREAD_FLAG_USPACE) != 0)
     212                if ((t->flags & THREAD_FLAG_USPACE) != 0) {
    212213                        t->udebug.active = true;
    213                 mutex_unlock(&t->udebug.lock);
     214                        mutex_unlock(&t->udebug.lock);
     215                        condvar_broadcast(&t->udebug.active_cv);
     216                } else {
     217                        mutex_unlock(&t->udebug.lock);
     218                }
    214219        }
    215220
     
    355360 *
    356361 * If the sequence is longer than @a buf_size bytes, only as much hashes
    357  * as can fit are copied. The number of thread hashes copied is stored
    358  * in @a n.
     362 * as can fit are copied. The number of bytes copied is stored in @a stored.
     363 * The total number of thread bytes that could have been saved had there been
     364 * enough space is stored in @a needed.
    359365 *
    360366 * The rationale for having @a buf_size is that this function is only
     
    364370 * @param buffer        The buffer for storing thread hashes.
    365371 * @param buf_size      Buffer size in bytes.
    366  * @param n             The actual number of hashes copied will be stored here.
    367  */
    368 int udebug_thread_read(void **buffer, size_t buf_size, size_t *n)
     372 * @param stored        The actual number of bytes copied will be stored here.
     373 * @param needed        Total number of hashes that could have been saved.
     374 */
     375int udebug_thread_read(void **buffer, size_t buf_size, size_t *stored,
     376    size_t *needed)
    369377{
    370378        thread_t *t;
    371379        link_t *cur;
    372380        unative_t tid;
    373         unsigned copied_ids;
     381        size_t copied_ids;
     382        size_t extra_ids;
    374383        ipl_t ipl;
    375384        unative_t *id_buffer;
     
    380389
    381390        /* Allocate a buffer to hold thread IDs */
    382         id_buffer = malloc(buf_size, 0);
     391        id_buffer = malloc(buf_size + 1, 0);
    383392
    384393        mutex_lock(&TASK->udebug.lock);
     
    396405        max_ids = buf_size / sizeof(unative_t);
    397406        copied_ids = 0;
     407        extra_ids = 0;
    398408
    399409        /* FIXME: make sure the thread isn't past debug shutdown... */
    400410        for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
    401                 /* Do not write past end of buffer */
    402                 if (copied_ids >= max_ids) break;
    403 
    404411                t = list_get_instance(cur, thread_t, th_link);
    405412
     
    409416
    410417                /* Not interested in kernel threads. */
    411                 if ((flags & THREAD_FLAG_USPACE) != 0) {
     418                if ((flags & THREAD_FLAG_USPACE) == 0)
     419                        continue;
     420
     421                if (copied_ids < max_ids) {
    412422                        /* Using thread struct pointer as identification hash */
    413423                        tid = (unative_t) t;
    414424                        id_buffer[copied_ids++] = tid;
     425                } else {
     426                        extra_ids++;
    415427                }
    416428        }
     
    422434
    423435        *buffer = id_buffer;
    424         *n = copied_ids * sizeof(unative_t);
     436        *stored = copied_ids * sizeof(unative_t);
     437        *needed = (copied_ids + extra_ids) * sizeof(unative_t);
     438
     439        return 0;
     440}
     441
     442/** Read task name.
     443 *
     444 * Returns task name as non-terminated string in a newly allocated buffer.
     445 * Also returns the size of the data.
     446 *
     447 * @param data          Place to store pointer to newly allocated block.
     448 * @param data_size     Place to store size of the data.
     449 *
     450 * @returns             EOK.
     451 */
     452int udebug_name_read(char **data, size_t *data_size)
     453{
     454        size_t name_size;
     455
     456        name_size = str_size(TASK->name) + 1;
     457        *data = malloc(name_size, 0);
     458        *data_size = name_size;
     459
     460        memcpy(*data, TASK->name, name_size);
    425461
    426462        return 0;
     
    437473 * this function will fail with an EINVAL error code.
    438474 *
    439  * @param buffer        The buffer for storing thread hashes.
     475 * @param t             Thread where call arguments are to be read.
     476 * @param buffer        Place to store pointer to new buffer.
     477 * @return              EOK on success, ENOENT if @a t is invalid, EINVAL
     478 *                      if thread state is not valid for this operation.
    440479 */
    441480int udebug_args_read(thread_t *t, void **buffer)
     
    469508}
    470509
     510/** Read the register state of the thread.
     511 *
     512 * The contents of the thread's istate structure are copied to a newly
     513 * allocated buffer and a pointer to it is written to @a buffer. The size of
     514 * the buffer will be sizeof(istate_t).
     515 *
     516 * Currently register state cannot be read if the thread is inside a system
     517 * call (as opposed to an exception). This is an implementation limit.
     518 *
     519 * @param t             Thread whose state is to be read.
     520 * @param buffer        Place to store pointer to new buffer.
     521 * @return              EOK on success, ENOENT if @a t is invalid, EINVAL
     522 *                      if thread is not in valid state, EBUSY if istate
     523 *                      is not available.
     524 */
     525int udebug_regs_read(thread_t *t, void **buffer)
     526{
     527        istate_t *state, *state_buf;
     528        int rc;
     529
     530        /* Prepare a buffer to hold the data. */
     531        state_buf = malloc(sizeof(istate_t), 0);
     532
     533        /* On success, this will lock t->udebug.lock */
     534        rc = _thread_op_begin(t, false);
     535        if (rc != EOK) {
     536                return rc;
     537        }
     538
     539        state = t->udebug.uspace_state;
     540        if (state == NULL) {
     541                _thread_op_end(t);
     542                return EBUSY;
     543        }
     544
     545        /* Copy to the allocated buffer */
     546        memcpy(state_buf, state, sizeof(istate_t));
     547
     548        _thread_op_end(t);
     549
     550        *buffer = (void *) state_buf;
     551        return 0;
     552}
     553
    471554/** Read the memory of the debugged task.
    472555 *
Note: See TracChangeset for help on using the changeset viewer.