diff options
Diffstat (limited to 'nuttx/arch/arm/src/armv7-m')
-rw-r--r-- | nuttx/arch/arm/src/armv7-m/Kconfig | 6 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-m/up_initialstate.c | 10 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-m/up_stackcheck.c | 40 |
3 files changed, 56 insertions, 0 deletions
diff --git a/nuttx/arch/arm/src/armv7-m/Kconfig b/nuttx/arch/arm/src/armv7-m/Kconfig index a154a4c5c..9c55068d5 100644 --- a/nuttx/arch/arm/src/armv7-m/Kconfig +++ b/nuttx/arch/arm/src/armv7-m/Kconfig @@ -57,3 +57,9 @@ config ARMV7M_OABI_TOOLCHAIN ---help--- Most of the older buildroot toolchains are OABI and are named arm-nuttx-elf- vs. arm-nuttx-eabi- +config ARMV7M_STACKCHECK + bool "Steck for stack overflow on function calls" + default n + ---help--- + This check uses R10 to check for a stack overflow within function calls. This has a performance impact, + but will be able to catch hard to find stack overflows. diff --git a/nuttx/arch/arm/src/armv7-m/up_initialstate.c b/nuttx/arch/arm/src/armv7-m/up_initialstate.c index c19d32f11..04089f8ac 100644 --- a/nuttx/arch/arm/src/armv7-m/up_initialstate.c +++ b/nuttx/arch/arm/src/armv7-m/up_initialstate.c @@ -93,6 +93,16 @@ void up_initial_state(struct tcb_s *tcb) xcp->regs[REG_SP] = (uint32_t)tcb->adj_stack_ptr; +#ifdef CONFIG_ARMV7M_STACKCHECK + /* Set the stack limit value */ + + xcp->regs[REG_R10] = (uint32_t)tcb->stack_alloc_ptr + 64; + + /* Fill the stack with a watermark value */ + + memset(tcb->stack_alloc_ptr, 0xff, tcb->adj_stack_size); +#endif + /* Save the task entry point (stripping off the thumb bit) */ xcp->regs[REG_PC] = (uint32_t)tcb->start & ~1; diff --git a/nuttx/arch/arm/src/armv7-m/up_stackcheck.c b/nuttx/arch/arm/src/armv7-m/up_stackcheck.c new file mode 100644 index 000000000..e8f02a863 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_stackcheck.c @@ -0,0 +1,40 @@ + + +void __cyg_profile_func_enter(void *func, void *caller) __attribute__((naked, no_instrument_function)); +void __cyg_profile_func_exit(void *func, void *caller) __attribute__((naked, no_instrument_function)); +void __stack_overflow_trap(void) __attribute__((naked, no_instrument_function)); + +void +__stack_overflow_trap(void) +{ + /* if we get here, the stack has overflowed */ + asm ( "b ."); +} + +void +__cyg_profile_func_enter(void *func, void *caller) +{ + asm volatile ( + " mrs r2, ipsr \n" /* Check whether we are in interrupt mode */ + " cmp r2, #0 \n" /* since we don't switch r10 on interrupt entry, we */ + " bne 2f \n" /* can't detect overflow of the interrupt stack. */ + " \n" + " sub r2, sp, #68 \n" /* compute stack pointer as though we just stacked a full frame */ + " mrs r1, control \n" /* Test CONTROL.FPCA to see whether we also need room for the FP */ + " tst r1, #4 \n" /* context. */ + " beq 1f \n" + " sub r2, r2, #136 \n" /* subtract FP context frame size */ + "1: \n" + " cmp r2, r10 \n" /* compare stack with limit */ + " bgt 2f \n" /* stack is above limit and thus OK */ + " b __stack_overflow_trap\n" + "2: \n" + " bx lr \n" + ); +} + +void +__cyg_profile_func_exit(void *func, void *caller) +{ + asm volatile("bx lr"); +} |