Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 80487bc5 in mainline


Ignore:
Timestamp:
2010-01-25T21:40:13Z (10 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
e515b21a
Parents:
0d21b53
Message:

Allow taskdump to read register state and extract PC, FP (not implemented for all arches).

Files:
8 added
7 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/udebug/udebug.h

    r0d21b53 r80487bc5  
    2727 */
    2828
    29 /** @addtogroup generic 
     29/** @addtogroup generic
    3030 * @{
    3131 */
     
    8383UDEBUG_M_ARGS_READ,
    8484
     85/** Read thread's userspace register state (istate_t).
     86 *
     87 * - ARG2 - thread identification
     88 * - ARG3 - destination address in the caller's address space
     89 *
     90 * or, on error, retval will be
     91 * - ENOENT - thread does not exist
     92 * - EBUSY - register state not available
     93 */
     94UDEBUG_M_REGS_READ,
     95
    8596/** Read the list of the debugged tasks's threads.
    8697 *
     
    122133} udebug_method_t;
    123134
    124                                
     135
    125136typedef enum {
    126137        UDEBUG_EVENT_FINISHED = 1,      /**< Debuging session has finished */
  • kernel/generic/include/udebug/udebug_ops.h

    r0d21b53 r80487bc5  
    4949int udebug_args_read(thread_t *t, void **buffer);
    5050
     51int udebug_regs_read(thread_t *t, void **buffer);
     52
    5153int udebug_mem_read(unative_t uspace_addr, size_t n, void **buffer);
    5254
  • kernel/generic/src/udebug/udebug_ipc.c

    r0d21b53 r80487bc5  
    287287        ipc_answer(&TASK->kb.box, call);
    288288}
     289
     290/** Receive a REGS_READ call.
     291 *
     292 * Reads the thread's register state (istate structure).
     293 */
     294static void udebug_receive_regs_read(call_t *call)
     295{
     296        thread_t *t;
     297        unative_t uspace_addr;
     298        unative_t to_copy;
     299        void *buffer;
     300        int rc;
     301
     302        t = (thread_t *) IPC_GET_ARG2(call->data);
     303
     304        rc = udebug_regs_read(t, &buffer);
     305        if (rc < 0) {
     306                IPC_SET_RETVAL(call->data, rc);
     307                ipc_answer(&TASK->kb.box, call);
     308                return;
     309        }
     310
     311        /*
     312         * Make use of call->buffer to transfer data to caller's userspace
     313         */
     314
     315        uspace_addr = IPC_GET_ARG3(call->data);
     316        to_copy = sizeof(istate_t);
     317
     318        IPC_SET_RETVAL(call->data, 0);
     319        /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
     320           same code in process_answer() can be used
     321           (no way to distinguish method in answer) */
     322        IPC_SET_ARG1(call->data, uspace_addr);
     323        IPC_SET_ARG2(call->data, to_copy);
     324
     325        call->buffer = buffer;
     326
     327        ipc_answer(&TASK->kb.box, call);
     328}
     329
    289330
    290331/** Process an MEM_READ call.
     
    374415                udebug_receive_args_read(call);
    375416                break;
     417        case UDEBUG_M_REGS_READ:
     418                udebug_receive_regs_read(call);
     419                break;
    376420        case UDEBUG_M_MEM_READ:
    377421                udebug_receive_mem_read(call);
  • kernel/generic/src/udebug/udebug_ops.c

    r0d21b53 r80487bc5  
    449449 * this function will fail with an EINVAL error code.
    450450 *
    451  * @param buffer        The buffer for storing thread hashes.
     451 * @param t             Thread where call arguments are to be read.
     452 * @param buffer        Place to store pointer to new buffer.
     453 * @return              EOK on success, ENOENT if @a t is invalid, EINVAL
     454 *                      if thread state is not valid for this operation.
    452455 */
    453456int udebug_args_read(thread_t *t, void **buffer)
     
    481484}
    482485
     486/** Read the register state of the thread.
     487 *
     488 * The contents of the thread's istate structure are copied to a newly
     489 * allocated buffer and a pointer to it is written to @a buffer. The size of
     490 * the buffer will be sizeof(istate_t).
     491 *
     492 * Currently register state cannot be read if the thread is inside a system
     493 * call (as opposed to an exception). This is an implementation limit.
     494 *
     495 * @param t             Thread whose state is to be read.
     496 * @param buffer        Place to store pointer to new buffer.
     497 * @return              EOK on success, ENOENT if @a t is invalid, EINVAL
     498 *                      if thread is not in valid state, EBUSY if istate
     499 *                      is not available.
     500 */
     501int udebug_regs_read(thread_t *t, void **buffer)
     502{
     503        istate_t *state, *state_buf;
     504        int rc;
     505
     506        /* Prepare a buffer to hold the data. */
     507        state_buf = malloc(sizeof(istate_t), 0);
     508
     509        /* On success, this will lock t->udebug.lock */
     510        rc = _thread_op_begin(t, false);
     511        if (rc != EOK) {
     512                return rc;
     513        }
     514
     515        state = t->udebug.uspace_state;
     516        if (state == NULL) {
     517                _thread_op_end(t);
     518                return EBUSY;
     519        }
     520
     521        /* Copy to the allocated buffer */
     522        memcpy(state_buf, state, sizeof(istate_t));
     523
     524        _thread_op_end(t);
     525
     526        *buffer = (void *) state_buf;
     527        return 0;
     528}
     529
    483530/** Read the memory of the debugged task.
    484531 *
  • uspace/app/taskdump/taskdump.c

    r0d21b53 r80487bc5  
    4141#include <task.h>
    4242#include <kernel/mm/as.h>
     43#include <libarch/istate.h>
    4344#include <macros.h>
    4445#include <assert.h>
     
    5859static void print_syntax();
    5960static int threads_dump(void);
     61static int thread_dump(uintptr_t thash);
    6062static int areas_dump(void);
    6163static int area_dump(as_area_info_t *area);
     
    229231        for (i = 0; i < n_threads; i++) {
    230232                printf(" [%d] hash: 0x%lx\n", 1+i, thash_buf[i]);
     233
     234                thread_dump(thash_buf[i]);
    231235        }
    232236        putchar('\n');
     
    291295}
    292296
     297static int thread_dump(uintptr_t thash)
     298{
     299        istate_t istate;
     300        uintptr_t pc, fp;
     301        int rc;
     302
     303        rc = udebug_regs_read(phoneid, thash, &istate);
     304        if (rc < 0) {
     305                printf("Failed reading registers (%d).\n", rc);
     306                return EIO;
     307        }
     308
     309        pc = istate_get_pc(&istate);
     310        fp = istate_get_fp(&istate);
     311
     312        printf("Thread 0x%lx crashed at PC 0x%lx. FP 0x%lx\n", thash, pc, fp);
     313        printf("Istate hexdump:\n");
     314        hex_dump(0, &istate, (sizeof(istate_t) + 15) & ~15);
     315
     316        return EOK;
     317}
     318
    293319static int area_dump(as_area_info_t *area)
    294320{
  • uspace/lib/libc/generic/udebug.c

    r0d21b53 r80487bc5  
    9797}
    9898
     99int udebug_regs_read(int phoneid, thash_t tid, void *buffer)
     100{
     101        return async_req_3_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_REGS_READ,
     102            tid, (sysarg_t)buffer);
     103}
     104
    99105int udebug_go(int phoneid, thash_t tid, udebug_event_t *ev_type,
    100106    sysarg_t *val0, sysarg_t *val1)
  • uspace/lib/libc/include/udebug.h

    r0d21b53 r80487bc5  
    5151int udebug_mem_read(int phoneid, void *buffer, uintptr_t addr, size_t n);
    5252int udebug_args_read(int phoneid, thash_t tid, sysarg_t *buffer);
     53int udebug_regs_read(int phoneid, thash_t tid, void *buffer);
    5354int udebug_go(int phoneid, thash_t tid, udebug_event_t *ev_type,
    5455        sysarg_t *val0, sysarg_t *val1);
Note: See TracChangeset for help on using the changeset viewer.