|
#include <inttypes.h> |
|
#include <stdint.h> |
|
#include <stdio.h> |
|
#include <string.h> |
|
|
|
#define UNW_LOCAL_ONLY |
|
#include <libunwind.h> |
|
|
|
void print_stack_trace_libunwind() { |
|
|
|
printf("=== Stack trace from libunwind ===\n"); |
|
|
|
unw_cursor_t cursor; unw_context_t uc; |
|
unw_word_t pc, sp; |
|
|
|
unw_getcontext(&uc); |
|
unw_init_local(&cursor, &uc); |
|
|
|
while (unw_step(&cursor) > 0) { |
|
unw_get_reg(&cursor, UNW_REG_IP, &pc); |
|
unw_get_reg(&cursor, UNW_REG_SP, &sp); |
|
|
|
printf("Program counter: 0x%016" PRIxPTR "\n", (uintptr_t) pc); |
|
printf("Stack pointer: 0x%016" PRIxPTR "\n", (uintptr_t) sp); |
|
printf("\n"); |
|
} |
|
|
|
printf("=== End ===\n\n"); |
|
} |
|
|
|
void print_stack_trace_fp_chain() { |
|
printf("=== Stack trace from fp chain ===\n"); |
|
|
|
uintptr_t *fp; |
|
asm("mv %0, fp" : "=r"(fp) : : ); |
|
|
|
// When should this stop? |
|
while (fp) { |
|
printf("Return address: 0x%016" PRIxPTR "\n", fp[-1]); |
|
printf("Old stack pointer: 0x%016" PRIxPTR "\n", fp[-2]); |
|
printf("\n"); |
|
|
|
fp = (uintptr_t *) fp[-2]; |
|
} |
|
printf("=== End ===\n\n"); |
|
} |
|
|
|
int use_libunwind = 0, use_fp_chain = 0; |
|
|
|
void flip(unsigned n); |
|
void flap(unsigned n); |
|
|
|
void flip(unsigned n) { |
|
if (n == 0) { |
|
if (use_libunwind) |
|
print_stack_trace_libunwind(); |
|
|
|
if (use_fp_chain) |
|
print_stack_trace_fp_chain(); |
|
} else if ((n & 1) == 0) { |
|
flip(n >> 1); |
|
} else if ((n & 1) == 1) { |
|
flap(n >> 1); |
|
} |
|
|
|
printf("flip %u\n", n); |
|
} |
|
|
|
void flap(unsigned n) { |
|
if ((n & 1) == 0) { |
|
flip(n >> 1); |
|
} else if ((n & 1) == 1) { |
|
flap(n >> 1); |
|
} |
|
|
|
printf("flap %u\n", n); |
|
} |
|
|
|
int main(int argc, char *argv[]) { |
|
unsigned input; |
|
sscanf(argv[1], "%u", &input); |
|
|
|
for (int i = 2; i < argc; i ++) { |
|
if (strcmp(argv[i], "libunwind") == 0) |
|
use_libunwind = 1; |
|
|
|
if (strcmp(argv[i], "fp_chain") == 0) |
|
use_fp_chain = 1; |
|
} |
|
|
|
flip(input); |
|
return 0; |
|
} |