Changeset 29fd3878 in rtems for cpukit/libmisc/stackchk/check.c


Ignore:
Timestamp:
Apr 2, 2007, 2:34:39 PM (13 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Children:
a4afa90
Parents:
625ef85
Message:

2007-04-02 Joel Sherrill <joel@…>

  • libmisc/stackchk/check.c: Add code to check validity of frame pointer in addition to the pattern area being overwritten. Also do some cleanup.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libmisc/stackchk/check.c

    r625ef85 r29fd3878  
    77 *         extension routines for that direction.
    88 *
    9  *  COPYRIGHT (c) 1989-1999.
     9 *  COPYRIGHT (c) 1989-2007.
    1010 *  On-Line Applications Research Corporation (OAR).
    1111 *
     
    3838
    3939#include <assert.h>
    40 #include <stdio.h>
    4140#include <string.h>
    4241#include <stdlib.h>
    4342
     43#include <rtems/bspIo.h>
    4444#include <rtems/stackchk.h>
    4545#include "internal.h"
    46 
    47 /*
    48  *  This variable contains the name of the task which "blew" the stack.
    49  *  It is NULL if the system is all right.
    50  */
    51 
    52 Thread_Control *Stack_check_Blown_task;
    5346
    5447/*
     
    7871
    7972/*
     73 * Helper function to report if the actual stack pointer is in range.
     74 *
     75 * NOTE: This uses a GCC specific method.
     76 */
     77
     78static inline boolean Stack_check_Frame_pointer_in_range(
     79  Stack_Control *the_stack
     80)
     81{
     82  #if defined(__GNUC__)
     83    void *sp = __builtin_frame_address(0);
     84
     85    if ( sp < the_stack->area ) {
     86      printk( "Stack Pointer Too Low!\n" );
     87      return FALSE;
     88    }
     89    if ( sp > (the_stack->area + the_stack->size) ) {
     90      printk( "Stack Pointer Too High!\n" );
     91      return FALSE;
     92    }
     93  #endif
     94  return TRUE;
     95}
     96
     97/*
    8098 *  Where the pattern goes in the stack area is dependent upon
    8199 *  whether the stack grow to the high or low area of the memory.
     
    97115#else
    98116
     117
    99118#define Stack_check_Get_pattern_area( _the_stack ) \
    100119  ((Stack_check_Control *) ((char *)(_the_stack)->area + HEAP_OVERHEAD))
     
    149168void Stack_check_Initialize( void )
    150169{
    151 #if 0
    152   rtems_status_code    status;
    153   Objects_Id           id_ignored;
    154 #endif
    155170  uint32_t            *p;
    156 #if 0
    157   uint32_t             i;
    158   uint32_t             api_index;
    159   Thread_Control      *the_thread;
    160   Objects_Information *information;
    161 #endif
    162171
    163172  if (stack_check_initialized)
    164       return;
     173    return;
    165174
    166175  /*
     
    179188  };
    180189
    181 #if 0
    182   status = rtems_extension_create(
    183     rtems_build_name( 'S', 'T', 'C', 'K' ),
    184     &Stack_check_Extension_table,
    185     &id_ignored
    186   );
    187   assert ( status == RTEMS_SUCCESSFUL );
    188 #endif
    189 
    190   Stack_check_Blown_task = 0;
    191 
    192   /*
    193    * If installed by a task, that task will not get setup properly
    194    * since it missed out on the create hook.  This will cause a
    195    * failure on first switch out of that task.
    196    * So pretend here that we actually ran create and begin extensions.
    197    */
    198 
    199   /* XXX
    200    *
    201    *  Technically this has not been done for any task created before this
    202    *  happened.  So just run through them and fix the situation.
    203    */
    204 #if 0
    205   if (_Thread_Executing)
    206   {
    207       Stack_check_Create_extension(_Thread_Executing, _Thread_Executing);
    208   }
    209 #endif
    210 
    211 #if 0
    212   for ( api_index = 1;
    213         api_index <= OBJECTS_APIS_LAST ;
    214         api_index++ ) {
    215     if ( !_Objects_Information_table[ api_index ] )
    216       continue;
    217     information = _Objects_Information_table[ api_index ][ 1 ];
    218     if ( information ) {
    219       for ( i=1 ; i <= information->maximum ; i++ ) {
    220         the_thread = (Thread_Control *)information->local_table[ i ];
    221         Stack_check_Create_extension( the_thread, the_thread );
    222       }
    223     }
    224   }
    225 #endif
    226 
    227190  /*
    228191   * If appropriate, setup the interrupt stack for high water testing
     
    301264 *  so that interrupt handlers can use this too.
    302265 *
    303  *  Caller must have set the Stack_check_Blown_task.
    304  *
    305266 *  NOTE: The system is in a questionable state... we may not get
    306267 *        the following message out.
    307268 */
    308269
    309 void Stack_check_report_blown_task(void)
    310 {
    311     Stack_Control *stack;
    312     Thread_Control *running;
    313 
    314     running = Stack_check_Blown_task;
    315     stack = &running->Start.Initial_stack;
    316 
    317     fprintf(
    318         stderr,
     270void Stack_check_report_blown_task(
     271  Thread_Control *running,
     272  boolean         pattern_ok
     273)
     274{
     275    Stack_Control *stack = &running->Start.Initial_stack;
     276
     277    printk(
    319278        "BLOWN STACK!!! Offending task(%p): id=0x%08" PRIx32
    320279             "; name=0x%08" PRIx32,
     
    323282        (uint32_t) running->Object.name
    324283    );
    325     fflush(stderr);
    326284
    327285    if (rtems_configuration_get_user_multiprocessing_table())
    328         fprintf(
    329           stderr,
    330           "; node=%" PRId32 "\n",
     286        printk(
     287          "; node=%d\n",
    331288          rtems_configuration_get_user_multiprocessing_table()->node
    332289       );
    333290    else
    334         fprintf(stderr, "\n");
    335     fflush(stderr);
    336 
    337     fprintf(
    338         stderr,
    339         "  stack covers range %p - %p" PRIx32 " (%" PRId32 " bytes)\n",
     291        printk( "\n");
     292
     293    printk(
     294        "  stack covers range %p - %p (%d bytes)\n",
    340295        stack->area,
    341296        stack->area + stack->size - 1,
    342297        stack->size);
    343     fflush(stderr);
    344 
    345     fprintf(
    346         stderr,
    347         "  Damaged pattern begins at 0x%08lx and is %ld bytes long\n",
    348         (unsigned long) Stack_check_Get_pattern_area(stack),
    349         (long) PATTERN_SIZE_BYTES);
    350     fflush(stderr);
    351 
    352     rtems_fatal_error_occurred( (uint32_t  ) "STACK BLOWN" );
     298
     299    if ( !pattern_ok ) {
     300      printk(
     301          "  Damaged pattern begins at 0x%08lx and is %ld bytes long\n",
     302          (unsigned long) Stack_check_Get_pattern_area(stack),
     303          (long) PATTERN_SIZE_BYTES);
     304    }
     305
     306    rtems_fatal_error_occurred( (uint32_t) "STACK BLOWN" );
    353307}
    354308
     
    363317)
    364318{
    365   if ( running->Object.id == 0 )        /* skip system tasks */
    366     return;
    367 
    368   if (0 != memcmp( (void *) Stack_check_Get_pattern_area( &running->Start.Initial_stack)->pattern,
    369                   (void *) Stack_check_Pattern.pattern,
    370                   PATTERN_SIZE_BYTES))
    371   {
    372       Stack_check_Blown_task = running;
    373       Stack_check_report_blown_task();
     319  Stack_Control *the_stack = &running->Start.Initial_stack;
     320  void          *pattern;
     321  boolean        sp_ok;
     322  boolean        pattern_ok;
     323
     324  pattern = (void *) Stack_check_Get_pattern_area(the_stack)->pattern;
     325
     326
     327  /*
     328   *  Check for an out of bounds stack pointer and then an overwrite
     329   */
     330
     331  sp_ok = Stack_check_Frame_pointer_in_range( the_stack );
     332  pattern_ok = (!memcmp( pattern,
     333            (void *) Stack_check_Pattern.pattern, PATTERN_SIZE_BYTES));
     334
     335  if ( !sp_ok || !pattern_ok ) {
     336    Stack_check_report_blown_task( running, pattern_ok );
    374337  }
    375338}
     
    467430      name = (char *) the_thread->Object.name;
    468431    } else {
    469       u32_name = (uint32_t )the_thread->Object.name;
     432      u32_name = (uint32_t) the_thread->Object.name;
    470433      name[ 0 ] = (u32_name >> 24) & 0xff;
    471434      name[ 1 ] = (u32_name >> 16) & 0xff;
     
    483446  }
    484447
    485   fprintf(stdout, "0x%08" PRIx32 "  %4s  %p - %p"
    486              "   %8" PRId32 "   %8" PRId32 "\n",
     448  printk("0x%08" PRIx32 "  %4s  %p - %p   %8" PRId32 "   %8" PRId32 "\n",
    487449          the_thread ? the_thread->Object.id : ~0,
    488450          name,
     
    519481void Stack_check_Dump_usage( void )
    520482{
    521   uint32_t             i;
    522   uint32_t             api_index;
    523   Thread_Control      *the_thread;
    524   uint32_t             hit_running = 0;
    525   Objects_Information *information;
    526 
    527483  if (stack_check_initialized == 0)
    528484      return;
    529485
    530   fprintf(stdout,"Stack usage by thread\n");
    531   fprintf(stdout,
     486  printk("Stack usage by thread\n");
     487  printk(
    532488    "    ID      NAME       LOW        HIGH     AVAILABLE      USED\n"
    533489  );
    534490
    535   for ( api_index = 1 ;
    536         api_index <= OBJECTS_APIS_LAST ;
    537         api_index++ ) {
    538     if ( !_Objects_Information_table[ api_index ] )
    539       continue;
    540     information = _Objects_Information_table[ api_index ][ 1 ];
    541     if ( information ) {
    542       for ( i=1 ; i <= information->maximum ; i++ ) {
    543         the_thread = (Thread_Control *)information->local_table[ i ];
    544         Stack_check_Dump_threads_usage( the_thread );
    545         if ( the_thread == _Thread_Executing )
    546           hit_running = 1;
    547       }
    548     }
    549   }
    550 
    551   if ( !hit_running )
    552     Stack_check_Dump_threads_usage( _Thread_Executing );
     491  /* iterate over all threads and dump the usage */
     492  rtems_iterate_over_all_threads( Stack_check_Dump_threads_usage );
    553493
    554494  /* dump interrupt stack info if any */
Note: See TracChangeset for help on using the changeset viewer.