Exemplo n.º 1
0
Arquivo: Libdw.c Projeto: momiken/ghc
Backtrace *libdwGetBacktrace(LibdwSession *session) {
    if (session->cur_bt != NULL) {
        sysErrorBelch("Already collecting backtrace. Uh oh.");
        return NULL;
    }

    Backtrace *bt = backtraceAlloc();
    session->cur_bt = bt;

    int pid = getpid();
    int ret = dwfl_getthread_frames(session->dwfl, pid,
                                    getBacktraceFrameCb, session);
    if (ret == -1)
        sysErrorBelch("Failed to get stack frames of current process: %s",
                      dwfl_errmsg(dwfl_errno()));

    session->cur_bt = NULL;
    return bt;
}
Exemplo n.º 2
0
void
output_right(enum tof type, struct process *proc, struct library_symbol *libsym,
             struct timedelta *spent)
{
    assert(! options.summary);

    struct prototype *func = lookup_symbol_prototype(proc, libsym);
    if (func == NULL)
        return;

    if (current_proc != NULL
            && (current_proc != proc
                || current_depth != proc->callstack_depth)) {
        fprintf(options.output, " <unfinished ...>\n");
        current_proc = NULL;
    }
    if (current_proc != proc) {
        begin_of_line(proc, type == LT_TOF_FUNCTIONR, 1);
#ifdef USE_DEMANGLE
        current_column +=
            fprintf(options.output, "<... %s resumed> ",
                    options.demangle ? my_demangle(libsym->name)
                    : libsym->name);
#else
        current_column +=
            fprintf(options.output, "<... %s resumed> ", libsym->name);
#endif
    }

    struct callstack_element *stel
            = &proc->callstack[proc->callstack_depth - 1];

    struct fetch_context *context = stel->fetch_context;

    /* Fetch & enter into dictionary the retval first, so that
     * other values can use it in expressions.  */
    struct value retval;
    bool own_retval = false;
    if (context != NULL) {
        value_init(&retval, proc, NULL, func->return_info, 0);
        own_retval = true;
        if (fetch_retval(context, type, proc, func->return_info,
                         &retval) < 0)
            value_set_type(&retval, NULL, 0);
        else if (stel->arguments != NULL
                 && val_dict_push_named(stel->arguments, &retval,
                                        "retval", 0) == 0)
            own_retval = false;
    }

    if (stel->arguments != NULL)
        output_params(stel->arguments, stel->out.params_left,
                      val_dict_count(stel->arguments),
                      &stel->out.need_delim);

    current_column += fprintf(options.output, ") ");
    tabto(options.align - 1);
    fprintf(options.output, "= ");

    if (context != NULL && retval.type != NULL) {
        struct format_argument_data data = { &retval, stel->arguments };
        format_argument_cb(options.output, &data);
    }

    if (own_retval)
        value_destroy(&retval);

    if (opt_T) {
        assert(spent != NULL);
        fprintf(options.output, " <%lu.%06d>",
                (unsigned long) spent->tm.tv_sec,
                (int) spent->tm.tv_usec);
    }

    fprintf(options.output, "\n");

#if defined(HAVE_LIBUNWIND)
    if (options.bt_depth > 0
            && proc->unwind_priv != NULL
            && proc->unwind_as != NULL) {
        unw_cursor_t cursor;
        arch_addr_t ip, function_offset;
        struct library *lib = NULL;
        int unwind_depth = options.bt_depth;
        char fn_name[100];
        const char *lib_name;
        size_t distance;

        /* Verify that we can safely cast arch_addr_t* to
         * unw_word_t*.  */
        (void)sizeof(char[1 - 2*(sizeof(unw_word_t)
                                 != sizeof(arch_addr_t))]);
        unw_init_remote(&cursor, proc->unwind_as, proc->unwind_priv);
        while (unwind_depth) {

            int rc = unw_get_reg(&cursor, UNW_REG_IP,
                                 (unw_word_t *) &ip);
            if (rc < 0) {
                fprintf(options.output, " > Error: %s\n",
                        unw_strerror(rc));
                goto cont;
            }

            /* We are looking for the library with the base address
             * closest to the current ip.  */
            lib_name = "unmapped_area";
            distance = (size_t) -1;
            lib = proc->libraries;
            while (lib != NULL) {
                /* N.B.: Assumes sizeof(size_t) ==
                 * sizeof(arch_addr_t).
                 * Keyword: double cast.  */
                if ((ip >= lib->base) &&
                        ((size_t)(ip - lib->base)
                         < distance)) {
                    distance = ip - lib->base;
                    lib_name = lib->pathname;
                }
                lib = lib->next;
            }

            rc = unw_get_proc_name(&cursor, fn_name,
                                   sizeof(fn_name),
                                   (unw_word_t *) &function_offset);
            if (rc == 0 || rc == -UNW_ENOMEM)
                fprintf(options.output, " > %s(%s+%p) [%p]\n",
                        lib_name, fn_name, function_offset, ip);
            else
                fprintf(options.output, " > %s(??\?) [%p]\n",
                        lib_name, ip);

cont:
            if (unw_step(&cursor) <= 0)
                break;
            unwind_depth--;
        }
        fprintf(options.output, "\n");
    }
#endif /* defined(HAVE_LIBUNWIND) */

#if defined(HAVE_LIBDW)
    if (options.bt_depth > 0 && proc->leader->dwfl != NULL) {
        int frames = options.bt_depth;
        if (dwfl_getthread_frames(proc->leader->dwfl, proc->pid,
                                  frame_callback, &frames) < 0) {
            // Only print an error if we couldn't show anything.
            // Otherwise just show there might be more...
            if (frames == options.bt_depth)
                fprintf(stderr,
                        "dwfl_getthread_frames tid %d: %s\n",
                        proc->pid, dwfl_errmsg(-1));
            else
                fprintf(options.output, " > [...]\n");
        }
        fprintf(options.output, "\n");
    }
#endif /* defined(HAVE_LIBDW) */

    current_proc = NULL;
    current_column = 0;
}