diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2007-04-02 14:33:59 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2007-04-02 14:33:59 +0000 |
commit | d8ec87b49c8e16e9bd9429bb0778b68798c97768 (patch) | |
tree | 21c2490eabdb21860485e4556744effe0d3429a2 /cpukit/libmisc/stackchk/check.c | |
parent | 2007-04-02 Ralf Corsépius <ralf.corsepius@rtems.org> (diff) | |
download | rtems-d8ec87b49c8e16e9bd9429bb0778b68798c97768.tar.bz2 |
2007-04-02 Joel Sherrill <joel@OARcorp.com>
* libmisc/stackchk/check.c: Add code to check validity of frame pointer
in addition to the pattern area being overwritten. Also do some
cleanup.
Diffstat (limited to '')
-rw-r--r-- | cpukit/libmisc/stackchk/check.c | 197 |
1 files changed, 70 insertions, 127 deletions
diff --git a/cpukit/libmisc/stackchk/check.c b/cpukit/libmisc/stackchk/check.c index 7da28dade8..5d154c3fee 100644 --- a/cpukit/libmisc/stackchk/check.c +++ b/cpukit/libmisc/stackchk/check.c @@ -6,7 +6,7 @@ * CPU grows up or down and installs the correct * extension routines for that direction. * - * COPYRIGHT (c) 1989-2006. + * COPYRIGHT (c) 1989-2007. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -37,21 +37,14 @@ #define DONT_USE_FATAL_EXTENSION #include <assert.h> -#include <stdio.h> #include <string.h> #include <stdlib.h> +#include <rtems/bspIo.h> #include <rtems/stackchk.h> #include "internal.h" /* - * This variable contains the name of the task which "blew" the stack. - * It is NULL if the system is all right. - */ - -Thread_Control *Stack_check_Blown_task; - -/* * The extension table for the stack checker. */ @@ -76,11 +69,35 @@ rtems_extensions_table rtems_stack_checker_extension_table = { Stack_check_Control Stack_check_Pattern; /* + * Helper function to report if the actual stack pointer is in range. + * + * NOTE: This uses a GCC specific method. + */ + +static inline boolean Stack_check_Frame_pointer_in_range( + Stack_Control *the_stack +) +{ + void *sp = __builtin_frame_address(0); + + #if defined(__GNUC__) + if ( sp < the_stack->area ) { + printk( "Stack Pointer Too Low!\n" ); + return FALSE; + } + if ( sp > (the_stack->area + the_stack->size) ) { + printk( "Stack Pointer Too High!\n" ); + return FALSE; + } + #endif + return TRUE; +} + +/* * Where the pattern goes in the stack area is dependent upon * whether the stack grow to the high or low area of the memory. * */ - #if ( CPU_STACK_GROWS_UP == TRUE ) #define Stack_check_Get_pattern_area( _the_stack ) \ @@ -95,6 +112,7 @@ Stack_check_Control Stack_check_Pattern; #else + #define Stack_check_Get_pattern_area( _the_stack ) \ ((Stack_check_Control *) ((char *)(_the_stack)->area + HEAP_OVERHEAD)) @@ -141,20 +159,10 @@ static int stack_check_initialized = 0; void rtems_stack_checker_initialize( void ) { -#if 0 - rtems_status_code status; - Objects_Id id_ignored; -#endif uint32_t *p; -#if 0 - uint32_t i; - uint32_t api_index; - Thread_Control *the_thread; - Objects_Information *information; -#endif if (stack_check_initialized) - return; + return; /* * Dope the pattern and fill areas @@ -171,17 +179,6 @@ void rtems_stack_checker_initialize( void ) p[3] = 0x600D0D06; }; -#if 0 - status = rtems_extension_create( - rtems_build_name( 'S', 'T', 'C', 'K' ), - &Stack_check_Extension_table, - &id_ignored - ); - assert ( status == RTEMS_SUCCESSFUL ); -#endif - - Stack_check_Blown_task = 0; - /* * If installed by a task, that task will not get setup properly * since it missed out on the create hook. This will cause a @@ -189,36 +186,6 @@ void rtems_stack_checker_initialize( void ) * So pretend here that we actually ran create and begin extensions. */ - /* XXX - * - * Technically this has not been done for any task created before this - * happened. So just run through them and fix the situation. - */ -#if 0 - if (_Thread_Executing) { - rtems_stack_checker_create_extension( - _Thread_Executing, - _Thread_Executing - ); - } -#endif - -#if 0 - for ( api_index = 1; - api_index <= OBJECTS_APIS_LAST ; - api_index++ ) { - if ( !_Objects_Information_table[ api_index ] ) - continue; - information = _Objects_Information_table[ api_index ][ 1 ]; - if ( information ) { - for ( i=1 ; i <= information->maximum ; i++ ) { - the_thread = (Thread_Control *)information->local_table[ i ]; - rtems_stack_checker_create_extension( the_thread, the_thread ); - } - } - } -#endif - /* * If appropriate, setup the interrupt stack for high water testing * also. @@ -295,56 +262,47 @@ void rtems_stack_checker_begin_extension( * Report a blown stack. Needs to be a separate routine * so that interrupt handlers can use this too. * - * Caller must have set the Stack_check_Blown_task. - * * NOTE: The system is in a questionable state... we may not get * the following message out. */ -void Stack_check_report_blown_task(void) +void Stack_check_report_blown_task( + Thread_Control *running, + boolean pattern_ok +) { - Stack_Control *stack; - Thread_Control *running; - - running = Stack_check_Blown_task; - stack = &running->Start.Initial_stack; + Stack_Control *stack = &running->Start.Initial_stack; - fprintf( - stderr, + printk( "BLOWN STACK!!! Offending task(%p): id=0x%08" PRIx32 "; name=0x%08" PRIx32, running, running->Object.id, (uint32_t) running->Object.name ); - fflush(stderr); if (rtems_configuration_get_user_multiprocessing_table()) - fprintf( - stderr, - "; node=%" PRId32 "\n", + printk( + "; node=%d\n", rtems_configuration_get_user_multiprocessing_table()->node ); else - fprintf(stderr, "\n"); - fflush(stderr); + printk( "\n"); - fprintf( - stderr, - " stack covers range %p - %p" PRIx32 " (%" PRId32 " bytes)\n", + printk( + " stack covers range %p - %p (%d bytes)\n", stack->area, stack->area + stack->size - 1, stack->size); - fflush(stderr); - fprintf( - stderr, - " Damaged pattern begins at 0x%08lx and is %ld bytes long\n", - (unsigned long) Stack_check_Get_pattern_area(stack), - (long) PATTERN_SIZE_BYTES); - fflush(stderr); + if ( !pattern_ok ) { + printk( + " Damaged pattern begins at 0x%08lx and is %ld bytes long\n", + (unsigned long) Stack_check_Get_pattern_area(stack), + (long) PATTERN_SIZE_BYTES); + } - rtems_fatal_error_occurred( (uint32_t ) "STACK BLOWN" ); + rtems_fatal_error_occurred( (uint32_t) "STACK BLOWN" ); } /*PAGE @@ -357,16 +315,24 @@ void rtems_stack_checker_switch_extension( Thread_Control *heir ) { - void *pattern; - if ( running->Object.id == 0 ) /* skip system tasks */ - return; - pattern = (void *) - Stack_check_Get_pattern_area(&running->Start.Initial_stack)->pattern; + Stack_Control *the_stack = &running->Start.Initial_stack; + void *pattern; + boolean sp_ok; + boolean pattern_ok = TRUE; + + pattern = (void *) Stack_check_Get_pattern_area(the_stack)->pattern; + + + /* + * Check for an out of bounds stack pointer and then an overwrite + */ - if (0 != memcmp( pattern, - (void *) Stack_check_Pattern.pattern, PATTERN_SIZE_BYTES)) { - Stack_check_Blown_task = running; - Stack_check_report_blown_task(); + sp_ok = Stack_check_Frame_pointer_in_range( the_stack ); + pattern_ok = (!memcmp( pattern, + (void *) Stack_check_Pattern.pattern, PATTERN_SIZE_BYTES)); + + if ( !sp_ok || !pattern_ok ) { + Stack_check_report_blown_task( running, pattern_ok ); } } @@ -462,7 +428,7 @@ void Stack_check_Dump_threads_usage( if ( info->is_string ) { name = (char *) the_thread->Object.name; } else { - u32_name = (uint32_t )the_thread->Object.name; + u32_name = (uint32_t) the_thread->Object.name; name[ 0 ] = (u32_name >> 24) & 0xff; name[ 1 ] = (u32_name >> 16) & 0xff; name[ 2 ] = (u32_name >> 8) & 0xff; @@ -478,8 +444,7 @@ void Stack_check_Dump_threads_usage( name[ 4 ] = '\0'; } - fprintf(stdout, "0x%08" PRIx32 " %4s %p - %p" - " %8" PRId32 " %8" PRId32 "\n", + printk("0x%08" PRIx32 " %4s %p - %p %8" PRId32 " %8" PRId32 "\n", the_thread ? the_thread->Object.id : ~0, name, stack->area, @@ -514,38 +479,16 @@ void rtems_stack_checker_fatal_extension( void rtems_stack_checker_report_usage( void ) { - uint32_t i; - uint32_t api_index; - Thread_Control *the_thread; - uint32_t hit_running = 0; - Objects_Information *information; - if (stack_check_initialized == 0) return; - fprintf(stdout,"Stack usage by thread\n"); - fprintf(stdout, + printk("Stack usage by thread\n"); + printk( " ID NAME LOW HIGH AVAILABLE USED\n" ); - for ( api_index = 1 ; - api_index <= OBJECTS_APIS_LAST ; - api_index++ ) { - if ( !_Objects_Information_table[ api_index ] ) - continue; - information = _Objects_Information_table[ api_index ][ 1 ]; - if ( information ) { - for ( i=1 ; i <= information->maximum ; i++ ) { - the_thread = (Thread_Control *)information->local_table[ i ]; - Stack_check_Dump_threads_usage( the_thread ); - if ( the_thread == _Thread_Executing ) - hit_running = 1; - } - } - } - - if ( !hit_running ) - Stack_check_Dump_threads_usage( _Thread_Executing ); + /* iterate over all threads and dump the usage */ + rtems_iterate_over_all_threads( Stack_check_Dump_threads_usage ); /* dump interrupt stack info if any */ Stack_check_Dump_threads_usage((Thread_Control *) -1); |