summaryrefslogtreecommitdiffstats
path: root/cpukit/libmisc/stackchk/check.c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2007-05-11 20:01:37 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2007-05-11 20:01:37 +0000
commit4da36c1af360e69771bb38a44d1a754f3f027b4f (patch)
tree084efe7f0fe34f927482fd041fb42473a84b6a96 /cpukit/libmisc/stackchk/check.c
parent2007-05-11 Joel Sherrill <joel.sherrill@OARcorp.com> (diff)
downloadrtems-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.c390
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");