diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2007-05-11 20:01:37 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2007-05-11 20:01:37 +0000 |
commit | 4da36c1af360e69771bb38a44d1a754f3f027b4f (patch) | |
tree | 084efe7f0fe34f927482fd041fb42473a84b6a96 /cpukit/libmisc/stackchk/check.c | |
parent | 2007-05-11 Joel Sherrill <joel.sherrill@OARcorp.com> (diff) | |
download | rtems-4da36c1af360e69771bb38a44d1a754f3f027b4f.tar.bz2 |
2007-05-11 Joel Sherrill <joel.sherrill@OARcorp.com>
* libmisc/cpuuse/cpuuse.c, libmisc/stackchk/check.c,
libmisc/stackchk/stackchk.h: Clean up as side-effect of making them
suitable for inclusion in the Users Guide.
Diffstat (limited to '')
-rw-r--r-- | cpukit/libmisc/stackchk/check.c | 390 |
1 files changed, 183 insertions, 207 deletions
diff --git a/cpukit/libmisc/stackchk/check.c b/cpukit/libmisc/stackchk/check.c index 5d154c3fee..37b91dab21 100644 --- a/cpukit/libmisc/stackchk/check.c +++ b/cpukit/libmisc/stackchk/check.c @@ -25,12 +25,9 @@ #include <inttypes.h> /* - * HACK - * the stack dump information should be printed by a "fatal" extension. + * The stack dump information may be printed by a "fatal" extension. * Fatal extensions only get called via rtems_fatal_error_occurred() * and not when rtems_shutdown_executive() is called. - * I hope/think this is changing so that fatal extensions are renamed - * to "shutdown" extensions. * When that happens, this #define should be deleted and all the code * it marks. */ @@ -45,27 +42,13 @@ #include "internal.h" /* - * The extension table for the stack checker. + * Variable to indicate when the stack checker has been initialized. */ - -rtems_extensions_table rtems_stack_checker_extension_table = { - rtems_stack_checker_create_extension, /* rtems_task_create */ - 0, /* rtems_task_start */ - 0, /* rtems_task_restart */ - 0, /* rtems_task_delete */ - rtems_stack_checker_switch_extension, /* task_switch */ - rtems_stack_checker_begin_extension, /* task_begin */ 0, /* task_exitted */ -#ifdef DONT_USE_FATAL_EXTENSION - 0, /* fatal */ -#else - rtems_stack_checker_fatal_extension, /* fatal */ -#endif -}; +static int Stack_check_Initialized = 0; /* * The "magic pattern" used to mark the end of the stack. */ - Stack_check_Control Stack_check_Pattern; /* @@ -73,7 +56,6 @@ Stack_check_Control Stack_check_Pattern; * * NOTE: This uses a GCC specific method. */ - static inline boolean Stack_check_Frame_pointer_in_range( Stack_Control *the_stack ) @@ -89,6 +71,8 @@ static inline boolean Stack_check_Frame_pointer_in_range( printk( "Stack Pointer Too High!\n" ); return FALSE; } + #else + #error "How do I check stack bounds on a non-GNU compiler?" #endif return TRUE; } @@ -96,72 +80,59 @@ static inline boolean Stack_check_Frame_pointer_in_range( /* * 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 ) \ - ((Stack_check_Control *) ((char *)(_the_stack)->area + \ - (_the_stack)->size - sizeof( Stack_check_Control ) )) +#if (CPU_STACK_GROWS_UP == TRUE) + #define Stack_check_Get_pattern_area( _the_stack ) \ + ((Stack_check_Control *) ((char *)(_the_stack)->area + \ + (_the_stack)->size - sizeof( Stack_check_Control ) )) -#define Stack_check_Calculate_used( _low, _size, _high_water ) \ - ((char *)(_high_water) - (char *)(_low)) + #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 + #define Stack_check_Get_pattern_area( _the_stack ) \ + ((Stack_check_Control *) ((char *)(_the_stack)->area + HEAP_OVERHEAD)) + #define Stack_check_Calculate_used( _low, _size, _high_water) \ + ( ((char *)(_low) + (_size)) - (char *)(_high_water) ) -#define Stack_check_Get_pattern_area( _the_stack ) \ - ((Stack_check_Control *) ((char *)(_the_stack)->area + HEAP_OVERHEAD)) - -#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 + sizeof(Stack_check_Control)) + #define Stack_check_usable_stack_start(_the_stack) \ + ((char *)(_the_stack)->area + sizeof(Stack_check_Control)) #endif +/* + * 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 - sizeof(Stack_check_Control)) - /* * Do we have an interrupt stack? * XXX it would sure be nice if the interrupt stack were also * stored in a "stack" structure! */ - - -Stack_Control stack_check_interrupt_stack; +Stack_Control Stack_check_Interrupt_stack; /* - * Fill an entire stack area with BYTE_PATTERN. - * This will be used by a Fatal extension to check for - * amount of actual stack used + * 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) -void -stack_check_dope_stack(Stack_Control *stack) -{ - memset(stack->area, BYTE_PATTERN, stack->size); -} - - -/*PAGE - * - * rtems_stack_checker_initialize +/* + * Stack_check_Initialize */ - -static int stack_check_initialized = 0; - -void rtems_stack_checker_initialize( void ) +void Stack_check_Initialize( void ) { - uint32_t *p; + uint32_t *p; - if (stack_check_initialized) + if (Stack_check_Initialized) return; /* @@ -171,83 +142,54 @@ void rtems_stack_checker_initialize( void ) for ( p = Stack_check_Pattern.pattern; p < &Stack_check_Pattern.pattern[PATTERN_SIZE_WORDS]; p += 4 - ) - { + ) { p[0] = 0xFEEDF00D; /* FEED FOOD to BAD DOG */ p[1] = 0x0BAD0D06; p[2] = 0xDEADF00D; /* DEAD FOOD GOOD DOG */ p[3] = 0x600D0D06; - }; - - /* - * If installed by a task, that task will not get setup properly - * since it missed out on the create hook. This will cause a - * failure on first switch out of that task. - * So pretend here that we actually ran create and begin extensions. - */ - + } + /* * If appropriate, setup the interrupt stack for high water testing * also. */ -#if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) - if (_CPU_Interrupt_stack_low && _CPU_Interrupt_stack_high) - { - stack_check_interrupt_stack.area = _CPU_Interrupt_stack_low; - stack_check_interrupt_stack.size = (char *) _CPU_Interrupt_stack_high - - (char *) _CPU_Interrupt_stack_low; - - stack_check_dope_stack(&stack_check_interrupt_stack); + #if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) + if (_CPU_Interrupt_stack_low && _CPU_Interrupt_stack_high) { + Stack_check_Interrupt_stack.area = _CPU_Interrupt_stack_low; + Stack_check_Interrupt_stack.size = (char *) _CPU_Interrupt_stack_high - + (char *) _CPU_Interrupt_stack_low; + Stack_check_Dope_stack(&Stack_check_Interrupt_stack); } -#endif - -#ifdef DONT_USE_FATAL_EXTENSION -#ifdef RTEMS_DEBUG - /* - * this would normally be called by a fatal extension - * handler, but we don't run fatal extensions unless - * we fatal error. - */ - atexit(rtems_stack_checker_report_usage); -#endif -#endif + #endif - stack_check_initialized = 1; + Stack_check_Initialized = 1; } -/*PAGE - * +/* * rtems_stack_checker_create_extension */ - boolean rtems_stack_checker_create_extension( Thread_Control *running, Thread_Control *the_thread ) { - if (!stack_check_initialized) - rtems_stack_checker_initialize(); + Stack_check_Initialize(); - if (the_thread /* XXX && (the_thread != _Thread_Executing) */ ) - stack_check_dope_stack(&the_thread->Start.Initial_stack); + if (the_thread) + Stack_check_Dope_stack(&the_thread->Start.Initial_stack); - return TRUE; + return TRUE; } -/*PAGE - * +/* * rtems_stack_checker_Begin_extension */ - void rtems_stack_checker_begin_extension( Thread_Control *the_thread ) { Stack_check_Control *the_pattern; - if (!stack_check_initialized) - rtems_stack_checker_initialize(); - if ( the_thread->Object.id == 0 ) /* skip system tasks */ return; @@ -256,60 +198,60 @@ void rtems_stack_checker_begin_extension( *the_pattern = Stack_check_Pattern; } -/*PAGE - * +/* * Stack_check_report_blown_task + * * Report a blown stack. Needs to be a separate routine * so that interrupt handlers can use this too. * * NOTE: The system is in a questionable state... we may not get * the following message out. */ - void Stack_check_report_blown_task( Thread_Control *running, boolean pattern_ok ) { - Stack_Control *stack = &running->Start.Initial_stack; + Stack_Control *stack = &running->Start.Initial_stack; - printk( - "BLOWN STACK!!! Offending task(%p): id=0x%08" PRIx32 - "; name=0x%08" PRIx32, - running, - running->Object.id, - (uint32_t) running->Object.name - ); - - if (rtems_configuration_get_user_multiprocessing_table()) - printk( - "; node=%d\n", - rtems_configuration_get_user_multiprocessing_table()->node - ); - else - printk( "\n"); - - printk( - " stack covers range %p - %p (%d bytes)\n", - stack->area, - stack->area + stack->size - 1, - stack->size); + printk( + "BLOWN STACK!!! Offending task(%p): id=0x%08" PRIx32 "; name=0x%08" PRIx32, + running, + running->Object.id, + (uint32_t) running->Object.name + ); - if ( !pattern_ok ) { + #if defined(RTEMS_MULTIPROCESSING) + if (rtems_configuration_get_user_multiprocessing_table()) { 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); + "; node=%d\n", + rtems_configuration_get_user_multiprocessing_table()->node + ); } + #else + printk( "\n" ); + #endif + + printk( + " stack covers range %p - %p (%d bytes)\n", + stack->area, + stack->area + stack->size - 1, + stack->size + ); - rtems_fatal_error_occurred( (uint32_t) "STACK BLOWN" ); + 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( 0x81 ); } -/*PAGE - * +/* * rtems_stack_checker_switch_extension */ - void rtems_stack_checker_switch_extension( Thread_Control *running, Thread_Control *heir @@ -322,7 +264,6 @@ void rtems_stack_checker_switch_extension( pattern = (void *) Stack_check_Get_pattern_area(the_stack)->pattern; - /* * Check for an out of bounds stack pointer and then an overwrite */ @@ -336,9 +277,38 @@ void rtems_stack_checker_switch_extension( } } +/* + * Check if blown + */ +boolean rtems_stack_checker_is_blown( void ) +{ + Stack_Control *the_stack = &_Thread_Executing->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 + */ + + 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 ) { + return TRUE; + } + return FALSE; +} + +/* + * Stack_check_find_high_water_mark + */ void *Stack_check_find_high_water_mark( const void *s, - size_t n + size_t n ) { const uint32_t *base, *ebase; @@ -347,38 +317,61 @@ void *Stack_check_find_high_water_mark( base = s; length = n/4; -#if ( CPU_STACK_GROWS_UP == TRUE ) - /* - * start at higher memory and find first word that does not - * match pattern - */ + #if ( CPU_STACK_GROWS_UP == TRUE ) + /* + * start at higher memory and find first word that does not + * match pattern + */ - base += length - 1; - for (ebase = s; base > ebase; base--) - if (*base != U32_PATTERN) - return (void *) base; -#else - /* - * start at lower memory and find first word that does not - * match pattern - */ + base += length - 1; + for (ebase = s; base > ebase; base--) + if (*base != U32_PATTERN) + return (void *) base; + #else + /* + * start at lower memory and find first word that does not + * match pattern + */ - base += PATTERN_SIZE_WORDS; - for (ebase = base + length; base < ebase; base++) - if (*base != U32_PATTERN) - return (void *) base; -#endif + base += PATTERN_SIZE_WORDS; + for (ebase = base + length; base < ebase; base++) + if (*base != U32_PATTERN) + return (void *) base; + #endif return (void *)0; } -/*PAGE - * +/* + * Report Name + */ + +char *Stack_check_Get_object_name( + Objects_Control *the_object, + char **name +) +{ + Objects_Information *info; + + info = _Objects_Get_information(the_object->id); + if ( info->is_string ) { + *name = (char *) the_object->name; + } else { + uint32_t u32_name = (uint32_t) the_object->name; + (*name)[ 0 ] = (u32_name >> 24) & 0xff; + (*name)[ 1 ] = (u32_name >> 16) & 0xff; + (*name)[ 2 ] = (u32_name >> 8) & 0xff; + (*name)[ 3 ] = (u32_name >> 0) & 0xff; + (*name)[ 4 ] = '\0'; + } + return *name; +} + +/* * Stack_check_Dump_threads_usage( - * Try to print out how much stack was actually used by the task. * + * Try to print out how much stack was actually used by the task. */ - void Stack_check_Dump_threads_usage( Thread_Control *the_thread ) @@ -389,8 +382,7 @@ void Stack_check_Dump_threads_usage( Stack_Control *stack; uint32_t u32_name; char name_str[5]; - char *name; - Objects_Information *info; + char *name; if ( !the_thread ) return; @@ -399,18 +391,15 @@ void Stack_check_Dump_threads_usage( * XXX HACK to get to interrupt stack */ - if (the_thread == (Thread_Control *) -1) - { - if (stack_check_interrupt_stack.area) - { - stack = &stack_check_interrupt_stack; - the_thread = 0; - } - else - return; - } - else - stack = &the_thread->Start.Initial_stack; + if (the_thread == (Thread_Control *) -1) { + if (Stack_check_Interrupt_stack.area) { + stack = &Stack_check_Interrupt_stack; + the_thread = 0; + } + else + return; + } else + stack = &the_thread->Start.Initial_stack; low = Stack_check_usable_stack_start(stack); size = Stack_check_usable_stack_size(stack); @@ -424,17 +413,7 @@ void Stack_check_Dump_threads_usage( name = name_str; if ( the_thread ) { - info = _Objects_Get_information(the_thread->Object.id); - if ( info->is_string ) { - name = (char *) the_thread->Object.name; - } else { - 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; - name[ 3 ] = (u32_name >> 0) & 0xff; - name[ 4 ] = '\0'; - } + name = Stack_check_Get_object_name( &the_thread->Object, &name ); } else { u32_name = rtems_build_name('I', 'N', 'T', 'R'); name[ 0 ] = (u32_name >> 24) & 0xff; @@ -445,32 +424,29 @@ void Stack_check_Dump_threads_usage( } printk("0x%08" PRIx32 " %4s %p - %p %8" PRId32 " %8" PRId32 "\n", - the_thread ? the_thread->Object.id : ~0, - name, - stack->area, - stack->area + stack->size - 1, - size, - used + the_thread ? the_thread->Object.id : ~0, + name, + stack->area, + stack->area + stack->size - 1, + size, + used ); } -/*PAGE - * +/* * rtems_stack_checker_fatal_extension */ - -void rtems_stack_checker_fatal_extension( +#ifndef DONT_USE_FATAL_EXTENSION + void rtems_stack_checker_fatal_extension( Internal_errors_Source source, boolean is_internal, uint32_t status -) -{ -#ifndef DONT_USE_FATAL_EXTENSION + ) + { if (status == 0) - rtems_stack_checker_report_usage(); + rtems_stack_checker_report_usage(); + } #endif -} - /*PAGE * @@ -479,7 +455,7 @@ void rtems_stack_checker_fatal_extension( void rtems_stack_checker_report_usage( void ) { - if (stack_check_initialized == 0) + if (Stack_check_Initialized == 0) return; printk("Stack usage by thread\n"); |