Загрузка данных


#include <libunwind.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_FRAMES 64
#define MAX_NAME 256
#define MAX_EDGES 1024

typedef struct {
    char caller[MAX_NAME];
    char callee[MAX_NAME];
} Edge;

static Edge edges[MAX_EDGES];
static int edge_count = 0;

// Add edge if not duplicate
static void add_edge(const char* caller, const char* callee) {
    for (int i = 0; i < edge_count; i++) {
        if (strcmp(edges[i].caller, caller) == 0 && strcmp(edges[i].callee, callee) == 0)
            return;
    }
    if (edge_count < MAX_EDGES) {
        strncpy(edges[edge_count].caller, caller, MAX_NAME - 1);
        strncpy(edges[edge_count].callee, callee, MAX_NAME - 1);
        edge_count++;
    }
}

// Capture current stack and build call graph edges
void capture_call_graph(void) {
    unw_context_t ctx;
    unw_cursor_t cur;
    unw_getcontext(&ctx);
    unw_init_local(&cur, &ctx);

    char frames[MAX_FRAMES][MAX_NAME];
    int count = 0;

    while (unw_step(&cur) > 0 && count < MAX_FRAMES) {
        unw_word_t ip;
        unw_get_reg(&cur, UNW_REG_IP, &ip);
        frames[count][0] = '\0';
        if (unw_get_proc_name(&cur, frames[count], MAX_NAME, NULL) != 0)
            snprintf(frames[count], MAX_NAME, "0x%lx", (unsigned long)ip);
        count++;
    }

    // Stack: frames[0]=current, frames[1]=caller, ...
    // Create caller -> callee edges
    for (int i = 1; i < count; i++) {
        add_edge(frames[i], frames[i - 1]);
    }
}

// Output graph in DOT format
void print_graph(void) {
    printf("digraph call_graph {\n");
    for (int i = 0; i < edge_count; i++) {
        printf("  \"%s\" -> \"%s\";\n", edges[i].caller, edges[i].callee);
    }
    printf("}\n");
}

// Example call chain
void leaf_func(void) { capture_call_graph(); }
void mid_func(void) { leaf_func(); }
void root_func(void) { mid_func(); }

int main(void) {
    root_func();
    print_graph();
    return 0;
}

// Compile: gcc call_graph.c -o call_graph -lunwind -lunwind-x86_64
// Visualize: ./call_graph | dot -Tpng -o graph.png