103 lines
2.2 KiB
C
103 lines
2.2 KiB
C
/*
|
|
* stack related functions
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Library General Public License version 2.
|
|
*/
|
|
|
|
#include <libcflat.h>
|
|
#include <stack.h>
|
|
|
|
#define MAX_DEPTH 20
|
|
|
|
static void print_stack(const void **return_addrs, int depth,
|
|
bool top_is_return_address)
|
|
{
|
|
int i = 0;
|
|
|
|
printf("\tSTACK:");
|
|
|
|
/* @addr indicates a non-return address, as expected by the stack
|
|
* pretty printer script. */
|
|
if (depth > 0 && !top_is_return_address) {
|
|
printf(" @%lx", (unsigned long) return_addrs[0]);
|
|
i++;
|
|
}
|
|
|
|
for (; i < depth; i++) {
|
|
printf(" %lx", (unsigned long) return_addrs[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
void dump_stack(void)
|
|
{
|
|
const void *return_addrs[MAX_DEPTH];
|
|
int depth;
|
|
|
|
depth = backtrace(return_addrs, MAX_DEPTH);
|
|
print_stack(&return_addrs[1], depth ? depth - 1 : 0, true);
|
|
}
|
|
|
|
void dump_frame_stack(const void *instruction, const void *frame)
|
|
{
|
|
const void *return_addrs[MAX_DEPTH];
|
|
int depth;
|
|
|
|
return_addrs[0] = instruction;
|
|
depth = backtrace_frame(frame, &return_addrs[1], MAX_DEPTH - 1);
|
|
print_stack(return_addrs, depth + 1, false);
|
|
}
|
|
|
|
#ifndef HAVE_ARCH_BACKTRACE
|
|
int backtrace(const void **return_addrs, int max_depth)
|
|
{
|
|
static int walking;
|
|
int depth = 0;
|
|
void *addr;
|
|
|
|
if (walking) {
|
|
printf("RECURSIVE STACK WALK!!!\n");
|
|
return 0;
|
|
}
|
|
walking = 1;
|
|
|
|
/* __builtin_return_address requires a compile-time constant argument */
|
|
#define GET_RETURN_ADDRESS(i) \
|
|
if (max_depth == i) \
|
|
goto done; \
|
|
addr = __builtin_return_address(i); \
|
|
if (!addr) \
|
|
goto done; \
|
|
return_addrs[i] = __builtin_extract_return_addr(addr); \
|
|
depth = i + 1; \
|
|
|
|
GET_RETURN_ADDRESS(0)
|
|
GET_RETURN_ADDRESS(1)
|
|
GET_RETURN_ADDRESS(2)
|
|
GET_RETURN_ADDRESS(3)
|
|
GET_RETURN_ADDRESS(4)
|
|
GET_RETURN_ADDRESS(5)
|
|
GET_RETURN_ADDRESS(6)
|
|
GET_RETURN_ADDRESS(7)
|
|
GET_RETURN_ADDRESS(8)
|
|
GET_RETURN_ADDRESS(9)
|
|
GET_RETURN_ADDRESS(10)
|
|
GET_RETURN_ADDRESS(11)
|
|
GET_RETURN_ADDRESS(12)
|
|
GET_RETURN_ADDRESS(13)
|
|
GET_RETURN_ADDRESS(14)
|
|
GET_RETURN_ADDRESS(15)
|
|
GET_RETURN_ADDRESS(16)
|
|
GET_RETURN_ADDRESS(17)
|
|
GET_RETURN_ADDRESS(18)
|
|
GET_RETURN_ADDRESS(19)
|
|
GET_RETURN_ADDRESS(20)
|
|
|
|
#undef GET_RETURN_ADDRESS
|
|
|
|
done:
|
|
walking = 0;
|
|
return depth;
|
|
}
|
|
#endif /* HAVE_ARCH_BACKTRACE */
|