| /* |
| * backtrace support (this is a modified lib/x86/stack.c) |
| * |
| * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com> |
| * |
| * This work is licensed under the terms of the GNU LGPL, version 2. |
| */ |
| #include <libcflat.h> |
| #include <stack.h> |
| |
| /* |
| * APCS stack frames are generated by code like this: |
| * | mov ip, sp |
| * | push {..., fp, ip, lr, pc} |
| * | sub fp, ip, #4 |
| */ |
| #ifdef APCS_FRAMES |
| # define FP_IDX -3 |
| # define LR_IDX -1 |
| #else |
| # define FP_IDX -1 |
| # define LR_IDX 0 |
| #endif |
| |
| int arch_backtrace_frame(const void *frame, const void **return_addrs, |
| int max_depth, bool current_frame) |
| { |
| static int walking; |
| int depth; |
| const unsigned long *fp = (unsigned long *)frame; |
| |
| if (current_frame) |
| fp = __builtin_frame_address(0); |
| |
| if (walking) { |
| printf("RECURSIVE STACK WALK!!!\n"); |
| return 0; |
| } |
| walking = 1; |
| |
| for (depth = 0; depth < max_depth; depth++) { |
| if (!fp) |
| break; |
| return_addrs[depth] = (void *)fp[LR_IDX]; |
| if (return_addrs[depth] == 0) |
| break; |
| fp = (unsigned long *)fp[FP_IDX]; |
| } |
| |
| walking = 0; |
| return depth; |
| } |