diff options
author | andrew <andrew@FreeBSD.org> | 2015-07-31 15:32:32 +0000 |
---|---|---|
committer | andrew <andrew@FreeBSD.org> | 2015-07-31 15:32:32 +0000 |
commit | 481594651d5d1f0b1ac000c391c0b25eec416996 (patch) | |
tree | 85141915777ace55bad63c019d5e536d42cb8a6b | |
parent | 8ddbbce4f69a8cfe3301e07feb3310636b7017ea (diff) | |
download | FreeBSD-src-481594651d5d1f0b1ac000c391c0b25eec416996.zip FreeBSD-src-481594651d5d1f0b1ac000c391c0b25eec416996.tar.gz |
Load the stack in stack_save and stack_save_td. This uses the generalised
unwind_frame function to read each stack frame until either the pc or stack
are no longer withing the kernel's address space.
Obtained from: ABT Systems Ltd
Sponsored by: The FreeBSD Foundation
-rw-r--r-- | sys/arm64/arm64/stack_machdep.c | 32 | ||||
-rw-r--r-- | sys/conf/files.arm64 | 4 |
2 files changed, 32 insertions, 4 deletions
diff --git a/sys/arm64/arm64/stack_machdep.c b/sys/arm64/arm64/stack_machdep.c index 7449eaa..72a9ab9 100644 --- a/sys/arm64/arm64/stack_machdep.c +++ b/sys/arm64/arm64/stack_machdep.c @@ -40,21 +40,49 @@ __FBSDID("$FreeBSD$"); #include <machine/pcb.h> #include <machine/stack.h> +static void +stack_capture(struct stack *st, struct unwind_state *frame) +{ + + stack_zero(st); + while (1) { + unwind_frame(frame); + if (!INKERNEL((vm_offset_t)frame->fp) || + !INKERNEL((vm_offset_t)frame->pc)) + break; + if (stack_put(st, frame->pc) == -1) + break; + } +} + void stack_save_td(struct stack *st, struct thread *td) { + struct unwind_state frame; if (TD_IS_SWAPPED(td)) panic("stack_save_td: swapped"); if (TD_IS_RUNNING(td)) panic("stack_save_td: running"); - stack_zero(st); /* ARM64TODO */ + frame.sp = td->td_pcb->pcb_sp; + frame.fp = td->td_pcb->pcb_x[29]; + frame.pc = td->td_pcb->pcb_x[30]; + + stack_capture(st, &frame); } void stack_save(struct stack *st) { + struct unwind_state frame; + uint64_t sp; + + __asm __volatile("mov %0, sp" : "=&r" (sp)); + + frame.sp = sp; + frame.fp = (uint64_t)__builtin_frame_address(0); + frame.pc = (uint64_t)stack_save; - stack_zero(st); /* ARM64TODO */ + stack_capture(st, &frame); } diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index a26d95a..6a8c966 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -40,14 +40,14 @@ arm64/arm64/mp_machdep.c optional smp arm64/arm64/nexus.c standard arm64/arm64/pic_if.m standard arm64/arm64/pmap.c standard -arm64/arm64/stack_machdep.c standard +arm64/arm64/stack_machdep.c optional ddb | stack arm64/arm64/support.S standard arm64/arm64/swtch.S standard arm64/arm64/sys_machdep.c standard arm64/arm64/trap.c standard arm64/arm64/uio_machdep.c standard arm64/arm64/uma_machdep.c standard -arm64/arm64/unwind.c optional ddb | kdtrace_hooks +arm64/arm64/unwind.c optional ddb | kdtrace_hooks | stack arm64/arm64/vfp.c standard arm64/arm64/vm_machdep.c standard crypto/blowfish/bf_enc.c optional crypto | ipsec |