Exemplo n.º 1
0
MuBacktrace*
get_backtrace(int skip)
{
    MuBacktrace* trace, **out;
    void* buffer[100];
    int num_frames;
    int i;
    char** symbols;

    num_frames = backtrace(buffer, sizeof(buffer) / sizeof(*buffer));
    symbols = backtrace_symbols(buffer, num_frames);

    out = &trace;

    for (i = skip; i < num_frames; i++)
    {
        *out = calloc(1, sizeof(MuBacktrace));
        fill_backtrace(*out, symbols[i]);
        out = &(*out)->up;
    }
             
    *out = NULL;

    return trace;
}
Exemplo n.º 2
0
Arquivo: main.c Projeto: KurSh/crxprof
int
main(int argc, char *argv[])
{
    bool need_exit = false;
    ptrace_context ptrace_ctx;
    program_params params;
    struct itimerval itv;
    struct proc_timer proc_time;
    calltree_node *root = NULL;

    g_progname = argv[0];
    if (!parse_args(&params, argc, argv))
        usage();

    print_message("Reading symbols (list of function)");
    init_fndescr(params.pid);
    if (params.just_print_symbols) {
        print_symbols();
        free_fndescr();
        exit(0);
    }

    if (!reset_process_time(&proc_time, params.pid, params.prof_method)) {
        free_fndescr();
        errx(2, "Failed to retrieve process time");
    }


    print_message("Attaching to process: %d", params.pid);
    memset(&ptrace_ctx, 0, sizeof(ptrace_ctx));
    if (!trace_init(params.pid, &ptrace_ctx))
        err(1, "Failed to initialize unwind internals");

    signal(SIGCHLD, on_sigchld);
    if (ptrace(PTRACE_ATTACH, params.pid, 0, 0) == -1) {
        int saved_errno = errno;
        warn("ptrace(PTRACE_ATTACH) failed");
        if (saved_errno == EPERM) {
            printf("You have to see NOTES section of `man crxprof' for workarounds.\n");
        }
        exit(2);
    }

    if (do_wait(&ptrace_ctx, true) != WR_STOPPED)
        err(1, "Error occured while stopping the process");

    if (ptrace(PTRACE_CONT, params.pid, 0, 0) < 0)
        err(1, "Error occured while stopping the process 2");


    /* interval timer for snapshots */
    itv.it_interval.tv_sec = 0;
    itv.it_interval.tv_usec = params.us_sleep;
    itv.it_value = itv.it_interval;

    signal(SIGALRM, on_sigalarm);
    if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
        err(1, "setitimer failed");

    print_message("Starting profile (interval %dms)", params.us_sleep / 1000);
    print_message("Press ^C once to show profile, twice to quit");
    signal(SIGINT, on_sigint);

    /* drop first meter since it contains our preparations */
    (void)get_process_dt(&proc_time); 

    while(!need_exit)
    {
        waitres_t wres = WR_NOTHING;
        sleep(1);
        
        if (timer_alarmed) {
            uint64_t proc_dt = get_process_dt(&proc_time);
            bool need_prof = (params.prof_method == PROF_REALTIME);

            if (params.prof_method == PROF_CPUTIME) {
                char st = get_procstate(&ptrace_ctx);
                if (st == 'R')
                    need_prof = true;
            }

            if (need_prof) {
                kill(params.pid, SIGSTOP);
                wres = do_wait(&ptrace_ctx, true);
                if (wres == WR_STOPPED) {
                    int signo_cont = (ptrace_ctx.stop_signal == SIGSTOP) ? 0 : ptrace_ctx.stop_signal;

                    if (!get_backtrace(&ptrace_ctx))
                        err(2, "failed to get backtrace of process");

                    /* continue tracee ASAP */
                    if (ptrace_verbose(PTRACE_CONT, params.pid, 0, signo_cont) < 0)
                        err(1, "ptrace(PTRACE_CONT) failed");

                    ptrace_ctx.nsnaps++;
                    if (fill_backtrace(proc_dt, &ptrace_ctx.stk, &root))
                        ptrace_ctx.nsnaps_accounted++;
                }
            }
        }

        if (wres != WR_FINISHED && wres != WR_NEED_DETACH) {
            wres = discard_wait(&ptrace_ctx);
        }


        if (sigint_caught_twice) {
            need_exit = true;
        } else if (sigint_caught || wres == WR_FINISHED || wres == WR_NEED_DETACH) {
            if (root) {
                print_message("%" PRIu64 " snapshot interrputs got (%" PRIu64 " dropped)", 
                    ptrace_ctx.nsnaps, ptrace_ctx.nsnaps - ptrace_ctx.nsnaps_accounted);

                visualize_profile(root, &params.vprops);
                if (params.dumpfile)
                    dump_profile(root, params.dumpfile);
            } else
                print_message("No symbolic snapshot caught yet!");
    
            sigint_caught = false;
        }

        if (wres == WR_FINISHED || wres == WR_NEED_DETACH) {
            if (wres == WR_NEED_DETACH)
                (void)ptrace_verbose(PTRACE_DETACH, params.pid, 0, ptrace_ctx.stop_signal);

            need_exit = true;
        }
    }

    free_fndescr();
    trace_free(&ptrace_ctx);
    if (root)
        calltree_destroy(root);

    return 0;
}