From 55d7626db75b1b5323aa5ba16b3cbc0a985462fe Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Wed, 11 Jul 2007 20:56:10 +0000 Subject: 2007-07-11 Joel Sherrill * libcsupport/src/malloc.c: Clean up Malloc debug code. * score/include/rtems/score/heap.h: Spacing. * score/inline/rtems/score/thread.inl: * score/src/heapfree.c. Clean up and add explicit check of the address being freed actually being in the heap. * score/src/heapwalk.c: Switch to printk and do not call abort. --- cpukit/ChangeLog | 9 +++++ cpukit/libcsupport/src/malloc.c | 7 ++-- cpukit/score/include/rtems/score/heap.h | 2 +- cpukit/score/inline/rtems/score/thread.inl | 39 +++++++++++++++++++++- cpukit/score/src/heapfree.c | 25 ++++++++------ cpukit/score/src/heapwalk.c | 53 ++++++++++++++++-------------- 6 files changed, 97 insertions(+), 38 deletions(-) diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog index 227c9548b3..0910148134 100644 --- a/cpukit/ChangeLog +++ b/cpukit/ChangeLog @@ -1,3 +1,12 @@ +2007-07-11 Joel Sherrill + + * libcsupport/src/malloc.c: Clean up Malloc debug code. + * score/include/rtems/score/heap.h: Spacing. + * score/inline/rtems/score/thread.inl: + * score/src/heapfree.c. Clean up and add explicit check of the address + being freed actually being in the heap. + * score/src/heapwalk.c: Switch to printk and do not call abort. + 2007-07-06 Joel Sherrill * libmisc/stackchk/check.c: Make checking the integrity of the pattern diff --git a/cpukit/libcsupport/src/malloc.c b/cpukit/libcsupport/src/malloc.c index 21648c52f6..16d69025d0 100644 --- a/cpukit/libcsupport/src/malloc.c +++ b/cpukit/libcsupport/src/malloc.c @@ -94,6 +94,8 @@ size_t RTEMS_Malloc_Sbrk_amount; #ifdef RTEMS_DEBUG #define MALLOC_STATS #define MALLOC_DIRTY +/*#define MALLOC_ARENA_CHECK +void checkMallocArena(void); */ #endif #ifdef MALLOC_STATS @@ -282,7 +284,8 @@ void *malloc( { size_t actual_size = 0; uint32_t current_depth; - Protected_heap_Get_block_size(&RTEMS_Malloc_Heap, ptr, &actual_size); + void *ptr = return_this; + _Protected_heap_Get_block_size(&RTEMS_Malloc_Heap, ptr, &actual_size); MSBUMP(lifetime_allocated, actual_size); current_depth = rtems_malloc_stats.lifetime_allocated - rtems_malloc_stats.lifetime_freed; @@ -464,7 +467,7 @@ void free( #ifdef MALLOC_STATS { size_t size; - if (Protected_heap_Get_block_size(&RTEMS_Malloc_Heap, ptr, &size) ) { + if (_Protected_heap_Get_block_size(&RTEMS_Malloc_Heap, ptr, &size) ) { MSBUMP(lifetime_freed, size); } } diff --git a/cpukit/score/include/rtems/score/heap.h b/cpukit/score/include/rtems/score/heap.h index b5a5a66779..4c5ecfb58f 100644 --- a/cpukit/score/include/rtems/score/heap.h +++ b/cpukit/score/include/rtems/score/heap.h @@ -497,7 +497,7 @@ extern uint32_t _Heap_Block_allocate( #define _HAssert(cond_) \ do { \ - if(the_heap->stats.instance && !(cond_)) \ + if (the_heap->stats.instance && !(cond_)) \ __assert(__FILE__, __LINE__, #cond_); \ } while(0) diff --git a/cpukit/score/inline/rtems/score/thread.inl b/cpukit/score/inline/rtems/score/thread.inl index 44d626d71c..dbd95c6ca3 100644 --- a/cpukit/score/inline/rtems/score/thread.inl +++ b/cpukit/score/inline/rtems/score/thread.inl @@ -6,7 +6,7 @@ */ /* - * COPYRIGHT (c) 1989-2006. + * COPYRIGHT (c) 1989-2007. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -139,10 +139,47 @@ RTEMS_INLINE_ROUTINE void _Thread_Deallocate_fp( void ) * This routine prevents dispatching. */ +#if defined(RTEMS_HEAVY_STACK_DEBUG) || defined(RTEMS_HEAVY_MALLOC_DEBUG) + #include + #include + #include + #include +#endif + RTEMS_INLINE_ROUTINE void _Thread_Disable_dispatch( void ) { + extern boolean rtems_stack_checker_is_blown( void ); + extern void malloc_walk(size_t, size_t); + + /* + * This check is very brutal to system performance but is very helpful + * at finding blown stack problems. If you have a stack problem and + * need help finding it, then uncomment this code. Every system + * call will check the stack and since mutexes are used frequently + * in most systems, you might get lucky. + */ + #if defined(RTEMS_HEAVY_STACK_DEBUG) + if (_System_state_Is_up(_System_state_Get()) && (_ISR_Nest_level == 0)) { + if ( rtems_stack_checker_is_blown() ) { + printk( "Stack blown!!\n" ); + rtems_fatal_error_occurred( 99 ); + } + } + #endif + _Thread_Dispatch_disable_level += 1; RTEMS_COMPILER_MEMORY_BARRIER(); + + /* + * This check is even more brutal than the other one. This enables + * malloc heap integrity checking upon entry to every system call. + */ + #if defined(RTEMS_HEAVY_MALLOC_DEBUG) + if ( _Thread_Dispatch_disable_level == 1 ) { + extern Heap_Control RTEMS_Malloc_Heap; + _Heap_Walk( &RTEMS_Malloc_Heap,99, FALSE ); + } + #endif } /** diff --git a/cpukit/score/src/heapfree.c b/cpukit/score/src/heapfree.c index e0e2e72d85..30667036d6 100644 --- a/cpukit/score/src/heapfree.c +++ b/cpukit/score/src/heapfree.c @@ -1,7 +1,7 @@ /* * Heap Handler * - * COPYRIGHT (c) 1989-1999. + * COPYRIGHT (c) 1989-2007. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -40,18 +40,23 @@ boolean _Heap_Free( void *starting_address ) { - Heap_Block *the_block; - Heap_Block *next_block; + Heap_Block *the_block; + Heap_Block *next_block; uint32_t the_size; uint32_t next_size; Heap_Statistics *const stats = &the_heap->stats; - boolean next_is_free; + boolean next_is_free; + + if ( !_Addresses_Is_in_range( + starting_address, (void *)the_heap->start, (void *)the_heap->final ) ) { + _HAssert(starting_address != NULL); + return( FALSE ); + } _Heap_Start_of_block( the_heap, starting_address, &the_block ); if ( !_Heap_Is_block_in( the_heap, the_block ) ) { - _HAssert(starting_address == NULL); - _HAssert(FALSE); + _HAssert( FALSE ); return( FALSE ); } @@ -59,12 +64,12 @@ boolean _Heap_Free( next_block = _Heap_Block_at( the_block, the_size ); if ( !_Heap_Is_block_in( the_heap, next_block ) ) { - _HAssert(FALSE); + _HAssert( FALSE ); return( FALSE ); } if ( !_Heap_Is_prev_used( next_block ) ) { - _HAssert(FALSE); + _HAssert( FALSE ); return( FALSE ); } @@ -77,14 +82,14 @@ boolean _Heap_Free( Heap_Block *const prev_block = _Heap_Block_at( the_block, -prev_size ); if ( !_Heap_Is_block_in( the_heap, prev_block ) ) { - _HAssert(FALSE); + _HAssert( FALSE ); return( FALSE ); } /* As we always coalesce free blocks, the block that preceedes prev_block must have been used. */ if ( !_Heap_Is_prev_used ( prev_block) ) { - _HAssert(FALSE); + _HAssert( FALSE ); return( FALSE ); } diff --git a/cpukit/score/src/heapwalk.c b/cpukit/score/src/heapwalk.c index 424a1302dd..db8555cd87 100644 --- a/cpukit/score/src/heapwalk.c +++ b/cpukit/score/src/heapwalk.c @@ -1,7 +1,7 @@ /* * Heap Handler * - * COPYRIGHT (c) 1989-1999. + * COPYRIGHT (c) 1989-2007. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -20,6 +20,8 @@ #include #include #include +#include +#include /*PAGE * @@ -62,20 +64,23 @@ boolean _Heap_Walk( int error = 0; int passes = 0; + do_dump = FALSE; /* * We don't want to allow walking the heap until we have * transferred control to the user task so we watch the * system state. */ +/* if ( !_System_state_Is_up( _System_state_Get() ) ) - return FALSE; + return TRUE; +*/ if (source < 0) source = the_heap->stats.instance; if (do_dump == TRUE) - printf("\nPASS: %d start %p final %p first %p last %p begin %p end %p\n", + printk("\nPASS: %d start %p final %p first %p last %p begin %p end %p\n", source, the_block, end, _Heap_First(the_heap), _Heap_Last(the_heap), the_heap->begin, the_heap->end); @@ -85,12 +90,12 @@ boolean _Heap_Walk( */ if (!_Heap_Is_prev_used(the_block)) { - printf("PASS: %d !HEAP_PREV_USED flag of 1st block isn't set\n", source); + printk("PASS: %d !HEAP_PREV_USED flag of 1st block isn't set\n", source); error = 1; } if (the_block->prev_size != the_heap->page_size) { - printf("PASS: %d !prev_size of 1st block isn't page_size\n", source); + printk("PASS: %d !prev_size of 1st block isn't page_size\n", source); error = 1; } @@ -100,32 +105,32 @@ boolean _Heap_Walk( boolean prev_used = _Heap_Is_prev_used(the_block); if (do_dump) { - printf("PASS: %d block %p size %d(%c)", + printk("PASS: %d block %p size %d(%c)", source, the_block, the_size, (prev_used ? 'U' : 'F')); if (prev_used) - printf(" prev_size %d", the_block->prev_size); + printk(" prev_size %d", the_block->prev_size); else - printf(" (prev_size) %d", the_block->prev_size); + printk(" (prev_size) %d", the_block->prev_size); } if (!_Heap_Is_block_in(the_heap, next_block)) { - if (do_dump) printf("\n"); - printf("PASS: %d !block %p is out of heap\n", source, next_block); + if (do_dump) printk("\n"); + printk("PASS: %d !block %p is out of heap\n", source, next_block); error = 1; break; } if (!_Heap_Is_prev_used(next_block)) { if (do_dump) - printf( " prev %p next %p", the_block->prev, the_block->next); + printk( " prev %p next %p", the_block->prev, the_block->next); if (_Heap_Block_size(the_block) != next_block->prev_size) { - if (do_dump) printf("\n"); - printf("PASS: %d !front and back sizes don't match", source); + if (do_dump) printk("\n"); + printk("PASS: %d !front and back sizes don't match", source); error = 1; } if (!prev_used) { - if (do_dump || error) printf("\n"); - printf("PASS: %d !two consecutive blocks are free", source); + if (do_dump || error) printk("\n"); + printk("PASS: %d !two consecutive blocks are free", source); error = 1; } @@ -134,22 +139,22 @@ boolean _Heap_Walk( while(block != the_block && block != tail) block = block->next; if(block != the_block) { - if (do_dump || error) printf("\n"); - printf("PASS: %d !the_block not in the free list", source); + if (do_dump || error) printk("\n"); + printk("PASS: %d !the_block not in the free list", source); error = 1; } } } - if (do_dump || error) printf("\n"); + if (do_dump || error) printk("\n"); if (the_size < the_heap->min_block_size) { - printf("PASS: %d !block size is too small\n", source); + printk("PASS: %d !block size is too small\n", source); error = 1; break; } if (!_Heap_Is_aligned( the_size, the_heap->page_size)) { - printf("PASS: %d !block size is misaligned\n", source); + printk("PASS: %d !block size is misaligned\n", source); error = 1; } @@ -160,19 +165,19 @@ boolean _Heap_Walk( } if (the_block != end) { - printf("PASS: %d !last block address isn't equal to 'final'\n", source); + printk("PASS: %d !last block address isn't equal to 'final'\n", source); error = 1; } if (_Heap_Block_size(the_block) != the_heap->page_size) { - printf("PASS: %d !last block's size isn't page_size\n", source); + printk("PASS: %d !last block's size isn't page_size\n", source); error = 1; } if(do_dump && error) - abort(); + _Internal_error_Occurred( INTERNAL_ERROR_CORE, TRUE, 0xffff0000 ); - return error == 0; + return error; } #endif /* defined(RTEMS_HEAP_DEBUG) */ -- cgit v1.2.3