bunkum

an old and silly c99 web server with some fun features
Log | Files | Refs | README

profile.c (2451B)


      1 #define _GNU_SOURCE
      2 
      3 #include <string.h>
      4 #include <errno.h>
      5 #include <stdio.h>
      6 
      7 #include <sys/types.h>
      8 #include <signal.h>
      9 #include <unistd.h>
     10 
     11 #include <sys/ptrace.h>
     12 #include <sys/wait.h>
     13 #include <sys/fcntl.h>
     14 
     15 #include <pthread.h>
     16 #include <libunwind.h>
     17 #include <libunwind-ptrace.h>
     18 
     19 #include "log.h"
     20 #include "profile.h"
     21 
     22 vec_t profile(pid_t tid) {
     23     vec_t stack = vec_new(MAX_SYMLEN);    
     24     errno = 0;
     25     ptrace(PTRACE_ATTACH, tid);
     26     kill(tid, SIGSTOP);
     27     waitpid(tid, NULL, 0);
     28     void* ui = _UPT_create(tid);
     29     unw_cursor_t c;
     30     unw_addr_space_t as = unw_create_addr_space(&_UPT_accessors, 0);
     31     unw_init_remote(&c, as, ui);
     32     do {
     33         unw_word_t offset;
     34         char fname[MAX_SYMLEN] = {0};
     35         int resp = unw_get_proc_name(&c, fname, sizeof(fname), &offset);
     36         vec_push(&stack, fname);
     37     } while(unw_step(&c) > 0);
     38     _UPT_resume(as, &c, ui);
     39     _UPT_destroy(ui);
     40     kill(tid, SIGSTOP);
     41     waitpid(tid, NULL, 0);
     42     ptrace(PTRACE_DETACH, tid, NULL, NULL);
     43     return stack;
     44 }
     45 
     46 struct profile_node profile_node_new(char* name) {
     47     struct profile_node out = {
     48         .children = vec_new(sizeof(struct profile_node)),
     49         .samples = 0,
     50         .symbol = {0}
     51     };
     52     strcpy(out.symbol, name);
     53     return out;
     54 }
     55 
     56 struct profile_node profile_res_new() {
     57     return profile_node_new("");
     58 }
     59 
     60 int cmp_prof_node(void* _a, void* _b) {
     61     struct profile_node* a = _a;
     62     struct profile_node* b = _b;
     63     return strcmp(a->symbol, b->symbol);    
     64 }
     65 
     66 void profile_proc_stack(struct profile_node* prof_res, vec_t* stack) {
     67     if (stack->vec_sz == 0) return; 
     68     struct profile_node* node = prof_res;
     69     for (int i = stack->vec_sz-1; i > 0; i--) {
     70         char* sym = vec_get(stack, i);
     71         int index = vec_check(&node->children, sym, cmp_prof_node);
     72         if (index == -1) {
     73             struct profile_node new = profile_node_new(sym);
     74             vec_push(&node->children, &new);
     75             index = node->children.vec_sz - 1;
     76         }
     77         node = vec_get(&node->children, index);
     78         node->samples += 1;
     79     }
     80 }
     81 
     82 void profile_dump(struct profile_node* prof_res, int indent) {
     83     struct profile_node* node = prof_res;
     84     if (indent >= 0) {
     85         for (int i = 0; i < indent; i++) printf("  ");
     86         printf("%s (%d) \n", node->symbol, node->samples);
     87     }
     88     for (int i = 0; i < node->children.vec_sz; i++) {
     89         profile_dump(vec_get(&node->children, i), indent+1);
     90     }
     91 }