summaryrefslogtreecommitdiffstats
path: root/cpukit/libmisc/stackchk
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-20 08:47:44 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-21 07:59:03 +0200
commit4221d932b43094f3aaf4a8dca1aa6bd4db13df4e (patch)
treee1a4074221c6a2f30c73ab00144f709695158bf1 /cpukit/libmisc/stackchk
parentstackchk: Remove heap hack (diff)
downloadrtems-4221d932b43094f3aaf4a8dca1aa6bd4db13df4e.tar.bz2
stackchk: Improve support for interrupt stacks
Prepare the interrupt stack which may be used by the boot processor as initialization stack with the stack sanity pattern. Check the interrupt stack of the current processor in the thread begin and switch extension. Update #3459.
Diffstat (limited to 'cpukit/libmisc/stackchk')
-rw-r--r--cpukit/libmisc/stackchk/check.c113
1 files changed, 84 insertions, 29 deletions
diff --git a/cpukit/libmisc/stackchk/check.c b/cpukit/libmisc/stackchk/check.c
index a3b7190ca3..29fa81480f 100644
--- a/cpukit/libmisc/stackchk/check.c
+++ b/cpukit/libmisc/stackchk/check.c
@@ -33,7 +33,10 @@
#include <rtems/bspIo.h>
#include <rtems/printer.h>
#include <rtems/stackchk.h>
+#include <rtems/sysinit.h>
+#include <rtems/score/address.h>
#include <rtems/score/percpu.h>
+#include <rtems/score/smp.h>
#include <rtems/score/threadimpl.h>
/*
@@ -65,12 +68,12 @@ static bool Stack_check_Initialized;
/*
* The "magic pattern" used to mark the end of the stack.
*/
-static const uint32_t Stack_check_Pattern[] =
+static const uint32_t Stack_check_Sanity_pattern[] =
CPU_STACK_CHECK_PATTERN_INITIALIZER;
-#define PATTERN_SIZE_BYTES sizeof(Stack_check_Pattern)
+#define SANITY_PATTERN_SIZE_BYTES sizeof(Stack_check_Sanity_pattern)
-#define PATTERN_SIZE_WORDS RTEMS_ARRAY_SIZE(Stack_check_Pattern)
+#define SANITY_PATTERN_SIZE_WORDS RTEMS_ARRAY_SIZE(Stack_check_Sanity_pattern)
/*
* Helper function to report if the actual stack pointer is in range.
@@ -104,12 +107,12 @@ static inline bool Stack_check_Frame_pointer_in_range(
#if (CPU_STACK_GROWS_UP == TRUE)
#define Stack_check_Get_pattern( _the_stack ) \
((char *)(_the_stack)->area + \
- (_the_stack)->size - PATTERN_SIZE_BYTES )
+ (_the_stack)->size - SANITY_PATTERN_SIZE_BYTES )
#define Stack_check_Calculate_used( _low, _size, _high_water ) \
((char *)(_high_water) - (char *)(_low))
- #define Stack_check_usable_stack_start(_the_stack) \
+ #define Stack_check_Usable_stack_start(_the_stack) \
((_the_stack)->area)
#else
@@ -119,8 +122,8 @@ static inline bool Stack_check_Frame_pointer_in_range(
#define Stack_check_Calculate_used( _low, _size, _high_water) \
( ((char *)(_low) + (_size)) - (char *)(_high_water) )
- #define Stack_check_usable_stack_start(_the_stack) \
- ((char *)(_the_stack)->area + PATTERN_SIZE_BYTES)
+ #define Stack_check_Usable_stack_start(_the_stack) \
+ ((char *)(_the_stack)->area + SANITY_PATTERN_SIZE_BYTES)
#endif
@@ -128,8 +131,8 @@ static inline bool Stack_check_Frame_pointer_in_range(
* The assumption is that if the pattern gets overwritten, the task
* is too close. This defines the usable stack memory.
*/
-#define Stack_check_usable_stack_size(_the_stack) \
- ((_the_stack)->size - PATTERN_SIZE_BYTES)
+#define Stack_check_Usable_stack_size(_the_stack) \
+ ((_the_stack)->size - SANITY_PATTERN_SIZE_BYTES)
#if defined(RTEMS_SMP)
static Stack_Control Stack_check_Interrupt_stack[ CPU_MAXIMUM_PROCESSORS ];
@@ -141,15 +144,30 @@ static Stack_Control Stack_check_Interrupt_stack[ 1 ];
* Fill an entire stack area with BYTE_PATTERN. This will be used
* to check for amount of actual stack used.
*/
-#define Stack_check_Dope_stack(_stack) \
- memset((_stack)->area, BYTE_PATTERN, (_stack)->size)
+static void Stack_check_Dope_stack( Stack_Control *stack )
+{
+ memset(
+ Stack_check_Usable_stack_start( stack ),
+ BYTE_PATTERN,
+ Stack_check_Usable_stack_size( stack )
+ );
+}
-static bool Stack_check_Is_pattern_valid(const Thread_Control *the_thread)
+static void Stack_check_Add_sanity_pattern( Stack_Control *stack )
+{
+ memcpy(
+ Stack_check_Get_pattern( stack ),
+ Stack_check_Sanity_pattern,
+ SANITY_PATTERN_SIZE_BYTES
+ );
+}
+
+static bool Stack_check_Is_sanity_pattern_valid( const Stack_Control *stack )
{
return memcmp(
- Stack_check_Get_pattern(&the_thread->Start.Initial_stack),
- Stack_check_Pattern,
- PATTERN_SIZE_BYTES
+ Stack_check_Get_pattern( stack ),
+ Stack_check_Sanity_pattern,
+ SANITY_PATTERN_SIZE_BYTES
) == 0;
}
@@ -163,12 +181,8 @@ bool rtems_stack_checker_create_extension(
{
Stack_check_Initialized = true;
- Stack_check_Dope_stack(&the_thread->Start.Initial_stack);
- memcpy(
- Stack_check_Get_pattern(&the_thread->Start.Initial_stack),
- Stack_check_Pattern,
- PATTERN_SIZE_BYTES
- );
+ Stack_check_Dope_stack( &the_thread->Start.Initial_stack );
+ Stack_check_Add_sanity_pattern( &the_thread->Start.Initial_stack );
return true;
}
@@ -201,6 +215,17 @@ void rtems_stack_checker_begin_extension( Thread_Control *executing )
stack->area = cpu_self->interrupt_stack_low;
stack->size = (size_t) ( (char *) cpu_self->interrupt_stack_high -
(char *) cpu_self->interrupt_stack_low );
+
+ /*
+ * Sanity pattern has been added by Stack_check_Prepare_interrupt_stack()
+ */
+ if ( !Stack_check_Is_sanity_pattern_valid( stack ) ) {
+ rtems_fatal(
+ RTEMS_FATAL_SOURCE_STACK_CHECKER,
+ rtems_build_name( 'I', 'N', 'T', 'R' )
+ );
+ }
+
Stack_check_Dope_stack( stack );
}
@@ -245,9 +270,9 @@ static void Stack_check_report_blown_task(
if (!pattern_ok) {
printk(
"damaged pattern area (%lu Bytes): 0x%08" PRIxPTR " .. 0x%08" PRIxPTR "\n",
- (unsigned long) PATTERN_SIZE_BYTES,
+ (unsigned long) SANITY_PATTERN_SIZE_BYTES,
(intptr_t) pattern_area,
- (intptr_t) (pattern_area + PATTERN_SIZE_BYTES)
+ (intptr_t) (pattern_area + SANITY_PATTERN_SIZE_BYTES)
);
}
@@ -276,17 +301,27 @@ void rtems_stack_checker_switch_extension(
{
bool sp_ok;
bool pattern_ok;
+ const Stack_Control *stack;
/*
* Check for an out of bounds stack pointer or an overwrite
*/
sp_ok = Stack_check_Frame_pointer_in_range( running );
- pattern_ok = Stack_check_Is_pattern_valid( running );
+ pattern_ok = Stack_check_Is_sanity_pattern_valid( &running->Start.Initial_stack );
if ( !sp_ok || !pattern_ok ) {
Stack_check_report_blown_task( running, pattern_ok );
}
+
+ stack = &Stack_check_Interrupt_stack[ _SMP_Get_current_processor() ];
+
+ if ( stack->area != NULL && !Stack_check_Is_sanity_pattern_valid( stack ) ) {
+ rtems_fatal(
+ RTEMS_FATAL_SOURCE_STACK_CHECKER,
+ rtems_build_name( 'I', 'N', 'T', 'R' )
+ );
+ }
}
/*
@@ -305,7 +340,7 @@ bool rtems_stack_checker_is_blown( void )
/*
* Stack_check_find_high_water_mark
*/
-static inline void *Stack_check_find_high_water_mark(
+static inline void *Stack_check_Find_high_water_mark(
const void *s,
size_t n
)
@@ -332,7 +367,7 @@ static inline void *Stack_check_find_high_water_mark(
* match pattern
*/
- base += PATTERN_SIZE_WORDS;
+ base += SANITY_PATTERN_SIZE_WORDS;
for (ebase = base + length; base < ebase; base++)
if (*base != U32_PATTERN)
return (void *) base;
@@ -354,10 +389,10 @@ static bool Stack_check_Dump_stack_usage(
void *low;
void *high_water_mark;
- low = Stack_check_usable_stack_start(stack);
- size = Stack_check_usable_stack_size(stack);
+ low = Stack_check_Usable_stack_start(stack);
+ size = Stack_check_Usable_stack_size(stack);
- high_water_mark = Stack_check_find_high_water_mark(low, size);
+ high_water_mark = Stack_check_Find_high_water_mark(low, size);
if ( high_water_mark )
used = Stack_check_Calculate_used( low, size, high_water_mark );
@@ -459,3 +494,23 @@ void rtems_stack_checker_report_usage( void )
rtems_print_printer_printk(&printer);
rtems_stack_checker_report_usage_with_plugin( &printer );
}
+
+static void Stack_check_Prepare_interrupt_stack( void )
+{
+ uint32_t cpu_self_index;
+ Stack_Control stack;
+
+ cpu_self_index = _SMP_Get_current_processor();
+ stack.size = rtems_configuration_get_interrupt_stack_size();
+ stack.area = _Addresses_Add_offset(
+ _Configuration_Interrupt_stack_area_begin,
+ cpu_self_index * stack.size
+ );
+ Stack_check_Add_sanity_pattern( &stack );
+}
+
+RTEMS_SYSINIT_ITEM(
+ Stack_check_Prepare_interrupt_stack,
+ RTEMS_SYSINIT_BSP_WORK_AREAS,
+ RTEMS_SYSINIT_ORDER_SECOND
+);