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