@@ 12,6 12,7 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
+
#include "CrashCatcherPriv.h"
/* Implementation of ARMv7-M assembly language code to trap exceptions and call CrashCatcher_Entry(). */
@@ 19,28 20,32 @@
.syntax unified
.arch armv7-m
- /* Called on Hard Fault exception. Stacks important registers and calls CrashCatcher_Entry().
+ /*
+ * Called on Hard Fault exception.
+ * Stacks important registers and calls CrashCatcher_Entry().
+ */
- extern "C" void HardFault_Handler(void);
- */
+ /* extern "C" void HardFault_Handler(void); */
.global HardFault_Handler
.type HardFault_Handler, %function
.thumb_func
HardFault_Handler:
- /* Push the following onto the stack (see CrashCatcherExceptionRegisters structure). The g_crashCatcherStack buffer
- is reserved for use as the stack while CrashCatcher is running.
- msp
- psp
- exceptionPSR
- r4
- r5
- r6
- r7
- r8
- r9
- r10
- r11
- exceptionLR */
+ /* Push the following onto the stack (see CrashCatcherExceptionRegisters structure).
+ * The g_crashCatcherStack buffer is reserved for use as the stack while CrashCatcher is running.
+ * msp
+ * psp
+ * exceptionPSR
+ * r4
+ * r5
+ * r6
+ * r7
+ * r8
+ * r9
+ * r10
+ * r11
+ * exceptionLR
+ */
+
// Prevent double fault
ldr r0, =crash_orig_stack
ldr r0, [r0]
@@ 53,126 58,117 @@ HardFault_Handler:
mrs r1, msp
ldr sp, =(g_crashCatcherStack + 4 * CRASH_CATCHER_STACK_WORD_COUNT)
push.w {r1-r11,lr}
- // Call original console dump
- ldr r0,=crash_orig_stack
- str sp, [r0]
- mov sp, r1
- ldr r0,=crash_orig_stack
- ldr sp, [r0]
+ // Preserve current CrashCatcher's stack pointer value
+ ldr r0, =crash_orig_stack
+ str sp, [r0]
// Call CrashCatcher_Entry with first argument pointing to registers that were just stacked.
- mov r0, sp
- ldr r2,=CrashCatcher_Entry // Stack frame exception return
+ mov r0, sp // Set CrashCatcher's stack as first argument to CrashCatcher_Entry
+ ldr r2, =CrashCatcher_Entry // Stack frame exception return function
mrs r3, psp
- str r2, [r3, #0x18]
- str r0, [r3]
- orr lr, lr, #4 // Back to user stack
- orr lr, lr, #8 // Back to user mode
- bx lr // Return from exception and jump to the CatchCatcher_Entry
- b .
-
+ str r2, [r3, #0x18] // Overwrite existing return address with CrashCatcher_Entry address
+ str r0, [r3] // Switch PSP to CrashCatcher's stack
+ orr lr, lr, #4 // Use PSP after return
+ orr lr, lr, #8 // Switch to thread mode upon returning
+ bx lr // Return from exception
+ b . // Just in case
// Let assembler know that we have hit the end of the HardFault_Handler function.
.pool
- .size HardFault_Handler, .-HardFault_Handler
-
-
+ .size HardFault_Handler, .-HardFault_Handler
- /* Called from CrashCatcher core to copy all floating point registers to supplied buffer. The supplied buffer must
- be large enough to contain 33 32-bit values (S0-S31 & FPSCR).
+ /*
+ * Called from CrashCatcher core to copy all floating point registers to supplied buffer.
+ * The supplied buffer must be large enough to contain 33 32-bit values (S0-S31 & FPSCR).
+ */
- void CrashCatcher_CopyAllFloatingPointRegisters(uint32_t* pBuffer);
- */
+ /* void CrashCatcher_CopyAllFloatingPointRegisters(uint32_t* pBuffer); */
.global CrashCatcher_CopyAllFloatingPointRegisters
.type CrashCatcher_CopyAllFloatingPointRegisters, %function
.thumb_func
CrashCatcher_CopyAllFloatingPointRegisters:
#if CRASH_CATCHER_WITH_FPU
- // Grab a copy of FPSCR before issuing any other FP instructions.
- vmrs r1, fpscr
- // Move s0 - s31 to pBuffer.
- vstmia.32 r0!, {s0 - s31}
-
- // Move fpscr to pBuffer.
- str r1, [r0]
+ vmrs r1, fpscr // Grab a copy of FPSCR before issuing any other FP instructions.
+ vstmia.32 r0!, {s0 - s31} // Move s0 - s31 to pBuffer.
+ str r1, [r0] // Move fpscr to pBuffer.
#endif
- // Return to caller.
- bx lr
-
+ bx lr // Return to caller.
.pool
- .size CrashCatcher_CopyAllFloatingPointRegisters, .-CrashCatcher_CopyAllFloatingPointRegisters
+ .size CrashCatcher_CopyAllFloatingPointRegisters, .-CrashCatcher_CopyAllFloatingPointRegisters
+ /*
+ * Called from CrashCatcher core to copy upper 16 floating point registers to supplied buffer.
+ * The supplied buffer must be large enough to contain 16 32-bit values (S16-S31).
+ */
- /* Called from CrashCatcher core to copy upper 16 floating point registers to supplied buffer. The supplied buffer
- must be large enough to contain 16 32-bit values (S16-S31).
-
- void CrashCatcher_CopyUpperFloatingPointRegisters(uint32_t* pBuffer);
- */
+ /* void CrashCatcher_CopyUpperFloatingPointRegisters(uint32_t* pBuffer); */
.global CrashCatcher_CopyUpperFloatingPointRegisters
.type CrashCatcher_CopyUpperFloatingPointRegisters, %function
.thumb_func
CrashCatcher_CopyUpperFloatingPointRegisters:
#if CRASH_CATCHER_WITH_FPU
- // Move s16 - s31 to pBuffer.
- vstmia.32 r0!, {s16 - s31}
+ vstmia.32 r0!, {s16 - s31} // Move s16 - s31 to pBuffer.
#endif
- // Return to caller.
- bx lr
-
+ bx lr // Return to caller.
.pool
- .size CrashCatcher_CopyUpperFloatingPointRegisters, .-CrashCatcher_CopyUpperFloatingPointRegisters
+ .size CrashCatcher_CopyUpperFloatingPointRegisters, .-CrashCatcher_CopyUpperFloatingPointRegisters
/*
- This function is called by the SVC #1 syscall
- and then collect stack data for the crash dump
- which will be run in the second stage
- It also changes stack to the static internal
- due to possibility of corruption of the oryginal
- stack frame
- extern "C" void _StackTrace_Dump_svc_1(void);
- */
+ * This function is called by the SVC #1 syscall
+ * and then collect stack data for the crash dump
+ * which will be run in the second stage.
+ * It also changes stack to the static internal
+ * due to possibility of corruption of the original
+ * stack frame.
+ */
+
+ /* extern "C" void _StackTrace_Dump_svc_1(void); */
.global _StackTrace_Dump_svc_1
.type _StackTrace_Dump_svc_1 , %function
.thumb_func
_StackTrace_Dump_svc_1:
+ // Preserve exception stack frame
mrs r3, xpsr
mrs r2, psp
mrs r1, msp
ldr sp, =(g_crashCatcherStack + 4 * CRASH_CATCHER_STACK_WORD_COUNT)
push.w {r1-r11,lr}
+ // Preserve current CrashCatcher's stack pointer value for use in second stage below
ldr r0, =crash_orig_stack
str sp, [r0]
- mov sp, r1
- bx lr
+ mov sp, r1 // Switch back to original stack
+ bx lr // Return from exception
.pool
- .size _StackTrace_Dump_svc_1, .-_StackTrace_Dump_svc_1
-
-
- /* This function is the second stage of the crash dump
- crash orig stack should contain valid stack from
- the exception and now crash catcher should be able
- to read stack frame pointer and dump data in the
- user mode from the second part of the exit function
- In our model crash newer return to the caller so
- we can use simply branch without care about unstacking
- extern "C" void _StackTrace_Dump_stage_2(void);
- */
+ .size _StackTrace_Dump_svc_1, .-_StackTrace_Dump_svc_1
+
+
+ /*
+ * This function is the second stage of the crash dump
+ * 'crash_orig_stack' should contain valid stack from
+ * the exception, so that CrashCatcher is able to read
+ * stack frame pointer and dump data in the user mode
+ * from the second part of the exit function.
+ * In our model CrashCatcher never returns to the
+ * caller, so simple branch is enough, without caring
+ * about proper unstacking.
+ */
+
+ /* extern "C" void _StackTrace_Dump_stage_2(void); */
.global _StackTrace_Dump_stage_2
.type _StackTrace_Dump_stage_2 , %function
.thumb_func
_StackTrace_Dump_stage_2:
- ldr r0, =crash_orig_stack
- ldr r0, [r0]
- b CrashCatcher_Entry
+ ldr r0, =crash_orig_stack
+ ldr r0, [r0] // Pass CrashCatcher's stack as a first argument to CrashCatcher_Entry
+ b CrashCatcher_Entry // Jump to CrashCatcher_Entry
.pool
- .size _StackTrace_Dump_stage_2, .-_StackTrace_Dump_stage_2
+ .size _StackTrace_Dump_stage_2, .-_StackTrace_Dump_stage_2
.data
- crash_orig_stack: .long 0
-
+ crash_orig_stack: .long 0 // Stores CrashCatcher stack pointer position