75 lines
1.7 KiB
C
75 lines
1.7 KiB
C
#include <stdint.h>
|
|
#include "kernel.h"
|
|
|
|
void debug_stack_trace(unsigned int max_frames)
|
|
{
|
|
DEBUG("*** begin stack trace ***");
|
|
// Thanks GCC :)
|
|
uintptr_t* rbp = (uintptr_t*)__builtin_frame_address(0);
|
|
|
|
for (unsigned int frame=0; frame<max_frames && rbp != NULL; frame++)
|
|
{
|
|
// Return address, 1 word above saved rbp
|
|
uintptr_t rip = rbp[1];
|
|
uintptr_t offset = 0;
|
|
const char* name = debug_find_symbol(rip, &offset);
|
|
DEBUG("[%u] <0x%p> (%s+0x%x)", frame, (void*)rip, name, offset);
|
|
|
|
uintptr_t* next_rbp = (uintptr_t*)rbp[0];
|
|
|
|
// invalid rbp or we're at the end
|
|
if (next_rbp <= rbp || next_rbp == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
rbp = next_rbp;
|
|
}
|
|
DEBUG("*** end stack trace ***");
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
uint64_t addr;
|
|
const char *name;
|
|
} __attribute__((packed)) kernel_symbol_t;
|
|
|
|
__attribute__((weak)) extern kernel_symbol_t symbol_table[];
|
|
__attribute__((weak)) extern uint64_t symbol_count;
|
|
|
|
// binary search
|
|
const char* debug_find_symbol(uintptr_t rip, uintptr_t* offset)
|
|
{
|
|
if (!symbol_table || symbol_count == 0)
|
|
{
|
|
if (offset) *offset = 0;
|
|
return "???";
|
|
}
|
|
|
|
int low = 0, high = (int)symbol_count - 1;
|
|
int best = -1;
|
|
|
|
while (low <= high)
|
|
{
|
|
int mid = (low + high) / 2;
|
|
if (symbol_table[mid].addr <= rip)
|
|
{
|
|
best = mid;
|
|
low = mid + 1;
|
|
} else {
|
|
high = mid - 1;
|
|
}
|
|
}
|
|
|
|
if (best != -1)
|
|
{
|
|
if (offset)
|
|
{
|
|
*offset = rip - symbol_table[best].addr;
|
|
}
|
|
return symbol_table[best].name;
|
|
}
|
|
|
|
if (offset) *offset = 0;
|
|
return "unknown";
|
|
} |