HelenOS sources
This source file includes following definitions.
- stack_trace_ctx
- stack_trace
- stack_trace_istate
- resolve_kernel_address
- resolve_uspace_address
#include <stacktrace.h>
#include <stdbool.h>
#include <interrupt.h>
#include <symtab.h>
#include <stdio.h>
#include <debug/line.h>
#define STACK_FRAMES_MAX  20
void stack_trace_ctx(stack_trace_ops_t *ops, stack_trace_context_t *ctx)
{
        int cnt = 0;
        uintptr_t fp;
        uintptr_t pc;
        while ((cnt++ < STACK_FRAMES_MAX) &&
            (ops->stack_trace_context_validate(ctx))) {
                const char *symbol = NULL;
                uintptr_t symbol_addr = 0;
                const char *file_name = NULL;
                const char *dir_name = NULL;
                int line = 0;
                int column = 0;
                
                pc = cnt == 1 ? ctx->pc : ctx->pc - 1;
                if (ops->symbol_resolve &&
                    ops->symbol_resolve(pc, 0, &symbol, &symbol_addr, &file_name, &dir_name, &line, &column)) {
                        if (symbol == NULL)
                                symbol = "<unknown>";
                        if (file_name == NULL && line == 0) {
                                printf("%p: %24s()+%zu\n", (void *) ctx->fp, symbol, ctx->pc - symbol_addr);
                        } else {
                                if (file_name == NULL)
                                        file_name = "<unknown>";
                                if (dir_name == NULL)
                                        dir_name = "<unknown>";
                                printf("%p: %20s()+%zu\t %s/%s:%d:%d\n",
                                    (void *) ctx->fp, symbol, ctx->pc - symbol_addr,
                                    dir_name, file_name, line, column);
                        }
                } else
                        printf("%p: %p()\n", (void *) ctx->fp, (void *) ctx->pc);
                if (!ops->return_address_get(ctx, &pc))
                        break;
                if (!ops->frame_pointer_prev(ctx, &fp))
                        break;
                ctx->fp = fp;
                ctx->pc = pc;
        }
}
void stack_trace(void)
{
        stack_trace_context_t ctx = {
                .fp = frame_pointer_get(),
                .pc = program_counter_get(),
                .istate = NULL
        };
        stack_trace_ctx(&kst_ops, &ctx);
        
        (void) frame_pointer_get();
}
void stack_trace_istate(istate_t *istate)
{
        stack_trace_context_t ctx = {
                .fp = istate_get_fp(istate),
                .pc = istate_get_pc(istate),
                .istate = istate
        };
        if (istate_from_uspace(istate))
                stack_trace_ctx(&ust_ops, &ctx);
        else
                stack_trace_ctx(&kst_ops, &ctx);
}
static bool
resolve_kernel_address(uintptr_t addr, int op_index,
    const char **symbol, uintptr_t *symbol_addr,
    const char **filename, const char **dirname,
    int *line, int *column)
{
        *symbol_addr = 0;
        *symbol = symtab_name_lookup(addr, symbol_addr, &kernel_sections);
        return debug_line_get_address_info(&kernel_sections, addr, op_index, filename, dirname, line, column) || *symbol_addr != 0;
}
static bool
resolve_uspace_address(uintptr_t addr, int op_index,
    const char **symbol, uintptr_t *symbol_addr,
    const char **filename, const char **dirname,
    int *line, int *column)
{
        if (TASK->debug_sections == NULL)
                return false;
        debug_sections_t *scs = TASK->debug_sections;
        *symbol_addr = 0;
        *symbol = symtab_name_lookup(addr, symbol_addr, scs);
        return debug_line_get_address_info(scs, addr, op_index, filename, dirname, line, column) || *symbol_addr != 0;
}
stack_trace_ops_t kst_ops = {
        .stack_trace_context_validate = kernel_stack_trace_context_validate,
        .frame_pointer_prev = kernel_frame_pointer_prev,
        .return_address_get = kernel_return_address_get,
        .symbol_resolve = resolve_kernel_address,
};
stack_trace_ops_t ust_ops = {
        .stack_trace_context_validate = uspace_stack_trace_context_validate,
        .frame_pointer_prev = uspace_frame_pointer_prev,
        .return_address_get = uspace_return_address_get,
        .symbol_resolve = resolve_uspace_address,
};
HelenOS homepage, sources at GitHub