@@ -314,6 +314,13 @@ exceptions_init:
mrs x2, spsr_el1
stp x1, x2, [sp, #S_PC]
+ /*
+ * Save a frame pointer using the link to allow unwinding of
+ * exceptions.
+ */
+ stp x29, x1, [sp, #S_FP]
+ add x29, sp, #S_FP
+
mov x0, \vec
mov x1, sp
mrs x2, esr_el1
@@ -349,6 +356,9 @@ exceptions_init:
eret
.endm
+.globl vector_stub_start
+vector_stub_start:
+
vector_stub el1t_sync, 0
vector_stub el1t_irq, 1
vector_stub el1t_fiq, 2
@@ -369,6 +379,9 @@ vector_stub el0_irq_32, 13
vector_stub el0_fiq_32, 14
vector_stub el0_error_32, 15
+.globl vector_stub_end
+vector_stub_end:
+
.section .text.ex
.macro ventry, label
@@ -25,6 +25,10 @@ int main(void)
OFFSET(S_PSTATE, pt_regs, pstate);
OFFSET(S_ORIG_X0, pt_regs, orig_x0);
OFFSET(S_SYSCALLNO, pt_regs, syscallno);
- DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs));
+
+ /* FP and LR (16 bytes) go on the frame above pt_regs */
+ DEFINE(S_FP, sizeof(struct pt_regs));
+ DEFINE(S_FRAME_SIZE, (sizeof(struct pt_regs) + 16));
+
return 0;
}
@@ -6,12 +6,16 @@
#include <stdbool.h>
#include <stack.h>
+extern char vector_stub_start, vector_stub_end;
+
int backtrace_frame(const void *frame, const void **return_addrs, int max_depth)
{
const void *fp = frame;
static bool walking;
void *lr;
int depth;
+ bool is_exception = false;
+ unsigned long addr;
if (walking) {
printf("RECURSIVE STACK WALK!!!\n");
@@ -31,6 +35,20 @@ int backtrace_frame(const void *frame, const void **return_addrs, int max_depth)
: );
return_addrs[depth] = lr;
+
+ /*
+ * If this is an exception, add 1 to the pointer so when the
+ * pretty_print_stacks script is run it would get the right
+ * address (it deducts 1 to find the call address, but we want
+ * the actual address).
+ */
+ if (is_exception)
+ return_addrs[depth] += 1;
+
+ /* Check if we are in the exception handlers for the next entry */
+ addr = (unsigned long)lr;
+ is_exception = (addr >= (unsigned long)&vector_stub_start &&
+ addr < (unsigned long)&vector_stub_end);
}
walking = false;