diff -r c1f20ce4abcf -r 3e88ff8f41d5 kerneltest/e32test/heap/t_heapcheck.cpp --- a/kerneltest/e32test/heap/t_heapcheck.cpp Tue Aug 31 16:34:26 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,652 +0,0 @@ -// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). -// All rights reserved. -// This component and the accompanying materials are made available -// under the terms of the License "Eclipse Public License v1.0" -// which accompanies this distribution, and is available -// at the URL "http://www.eclipse.org/legal/epl-v10.html". -// -// Initial Contributors: -// Nokia Corporation - initial contribution. -// -// Contributors: -// -// Description: -// e32test\debug\t_heapcorruption.cpp -// This is a test application that will cause heap corruption -// to generate BTrace events (EHeapCorruption). -// -// - -// Include Files -#include -#include -#include -#include -#include "dla.h" -#include "slab.h" -#include "page_alloc.h" -#include "heap_hybrid.h" - -LOCAL_D RTest test(_L("T_HEAPCHECK")); - -TUint32 gSeed = 0xb504f334; - -_LIT(KLitHeapCheck,"Heap Check"); - - -TUint32 Random() -{ - gSeed *= 69069; - gSeed += 41; - return gSeed; -} - -TInt RandomNumber(TInt aMin, TInt aMax) -{ - TInt y = aMax - aMin; - if ( y <= 0 ) - return aMax; - TUint32 x = Random() & 0xff; - TInt s = 0; - while ( y > (0x100 << s) ) - { - s++; - } - return (aMin + (x << s) % y); -} - - -/** -Friend class of RHeapHybrid to access to hybrid heap metadata -*/ -class TestHybridHeap -{ - public: - TBool Init(); - TBool Check(); - TUint8* Alloc(TInt aLth); - TUint8* ReAlloc(TAny* aBfr, TInt aLth, TInt aMode); - void Free(TAny* aBfr); - TInt AllocLen(TAny* aBfr); - TInt AllocSize(TInt& aTotalAllocSize); - TBool SlabAllocatorExists(); - TBool PageAllocatorExists(); - TBool SlabsCreated(); - TBool CorruptSmallBin(); - TBool CorruptTreeBin(); - TBool ConfigurePageAllocator(); - TInt CopyPageBitmap(TUint8* aBitmap, TInt aLth); - TBool RestorePageBitmap(TUint8* aBitmap, TInt aLth); - void AllocateSomeBuffers(TUint8** aBfrs, TInt aMinLth, TInt MaxLth, TInt aCount); - TBool PrintHeapInitData(); - - private: - RHybridHeap* iHybridHeap; -}; - - - -TBool TestHybridHeap::Init() -{ - RHybridHeap::STestCommand cmd; - cmd.iCommand = RHybridHeap::EHeapMetaData; - RAllocator& heap = User::Allocator(); - TInt ret = heap.DebugFunction(RHeap::EHybridHeap, &cmd, 0); - if (ret != KErrNone) - return EFalse; - iHybridHeap = (RHybridHeap*) cmd.iData; - - return ETrue; -} - -TBool TestHybridHeap::Check() -{ - if ( iHybridHeap ) - { - iHybridHeap->Check(); - } - - return EFalse; -} - -TUint8* TestHybridHeap::Alloc(TInt aLth) -{ - if ( iHybridHeap ) - { - return (TUint8*)iHybridHeap->Alloc(aLth); - } - - return NULL; -} - -TUint8* TestHybridHeap::ReAlloc(TAny* aBfr, TInt aLth, TInt aMode) -{ - if ( iHybridHeap ) - { - return (TUint8*)iHybridHeap->ReAlloc(aBfr, aLth, aMode); - } - - return NULL; -} - -void TestHybridHeap::Free(TAny* aBfr) -{ - if ( iHybridHeap ) - { - iHybridHeap->Free(aBfr); - } -} - -TInt TestHybridHeap::AllocLen(TAny* aBfr) -{ - if ( iHybridHeap ) - { - return iHybridHeap->AllocLen(aBfr); - } - return 0; -} - -TInt TestHybridHeap::AllocSize(TInt& aTotalAllocSize) -{ - aTotalAllocSize = 0; - if ( iHybridHeap ) - { - return iHybridHeap->AllocSize(aTotalAllocSize); - } - return 0; -} - -TBool TestHybridHeap::SlabAllocatorExists() -{ - TBool status = EFalse; - if ( iHybridHeap ) - { - status = !iHybridHeap->iDLOnly; - } - - return status; -} - -TBool TestHybridHeap::PageAllocatorExists() -{ - TBool status = EFalse; - if ( iHybridHeap ) - { - status = (!iHybridHeap->iDLOnly && (iHybridHeap->iPageThreshold < 31)); - } - - return status; -} - -TBool TestHybridHeap::SlabsCreated() -{ - TBool status = EFalse; - if ( iHybridHeap ) - { - status = (iHybridHeap->iSlabThreshold != 0); - } - - return status; -} - -TBool TestHybridHeap::ConfigurePageAllocator() -{ - TBool status = EFalse; - if ( iHybridHeap ) - { - RHybridHeap::STestCommand conf; - conf.iCommand = RHybridHeap::ESetConfig; - conf.iConfig.iPagePower = 14; // 16 Kb - if ( iHybridHeap->DebugFunction(RHeap::EHybridHeap, (TAny*)&conf ) == KErrNone ) - status = ETrue; - } - - return status; -} - - -TBool TestHybridHeap::CorruptTreeBin() -{ - TBool status = EFalse; - if ( iHybridHeap ) - { - TUint i; - for (i = 0; i < NTREEBINS; ++i) - { - tbinptr* tb = TREEBIN_AT(&iHybridHeap->iGlobalMallocState, i); - tchunkptr t = *tb; - if ( t ) - { - // Corrupt tree bin by writing erroneous index value - t->iIndex ++; - return ETrue; - } - } - } - - return status; -} - -TBool TestHybridHeap::CorruptSmallBin() -{ - TBool status = EFalse; - if ( iHybridHeap ) - { - TUint i; - for (i = 0; i < NSMALLBINS; ++i) - { - sbinptr b = SMALLBIN_AT(&iHybridHeap->iGlobalMallocState, i); - mchunkptr p = b->iBk; - if ( p != b ) - { - b->iBk = b; - status = ETrue; - } - } - } - - return status; -} - -TInt TestHybridHeap::CopyPageBitmap(TUint8* aBitmap, TInt aLth) -{ - TInt lth = 0; - if ( iHybridHeap && (aLth > (TInt) sizeof(iHybridHeap->iBitMapBuffer)) ) - {// Dirty version - memcpy(aBitmap, &iHybridHeap->iBitMapBuffer[0], sizeof(iHybridHeap->iBitMapBuffer)); - lth = sizeof(iHybridHeap->iBitMapBuffer) << 3; - } - - return lth; -} - -TBool TestHybridHeap::RestorePageBitmap(TUint8* aBitmap, TInt aLth) -{ - TBool status = EFalse; - if ( iHybridHeap && ((aLth >> 3) <= (TInt) sizeof(iHybridHeap->iBitMapBuffer)) ) - {// Dirty version - memcpy(&iHybridHeap->iBitMapBuffer[0], aBitmap, (aLth >> 3)); - status = ETrue; - } - - return status; -} - -void TestHybridHeap::AllocateSomeBuffers(TUint8** aBfrs, TInt aMinLth, TInt MaxLth, TInt aCount ) -{ - - TInt loop = RandomNumber(2, 8); - - while ( loop ) - { - // allocate all buffers - TInt i; - for (i=0; iiCellCount, iHybridHeap->iTotalAllocSize); - return (count != 0); -} - - -// Local Functions -LOCAL_D TInt HeapCheckTestThread(TAny* param) -{ - TInt t = *((TInt*)param); - TUint8* bfrs[256]; - Mem::FillZ(bfrs, sizeof(bfrs)); - TestHybridHeap heap; - test(heap.Init()); - - switch( t ) - { - case 1: - { - // Overwrite Doug Lea buffer and check() - heap.AllocateSomeBuffers(bfrs, 0x40, 0xfff0, 256); - test(heap.PrintHeapInitData()); - TUint8 *p = heap.Alloc(64); - test( p != NULL ); - Mem::FillZ(p, 80); // Heap corrupted - heap.Check(); // This should cause panic - break; - } - - case 2: - // Corrupt a smallbin and check - { - TInt i = 0; - TBool smallbin_corrupted = EFalse; - while ( !smallbin_corrupted ) - { - heap.AllocateSomeBuffers(bfrs, 0x4, 0xff, 256); - smallbin_corrupted = heap.CorruptSmallBin(); - i ++; - if ( i > 9 ) - break; - } - test(smallbin_corrupted); - test(heap.PrintHeapInitData()); - heap.Check(); // This should cause panic - } - break; - - case 3: - // Corrupt a treebin and check - { - TInt i = 0; - TBool treebin_corrupted = EFalse; - while ( !treebin_corrupted ) - { - heap.AllocateSomeBuffers(bfrs, 0x100, 0x4000, 256); - treebin_corrupted = heap.CorruptTreeBin(); - i ++; - if ( i > 9 ) - break; - } - test(treebin_corrupted); - test(heap.PrintHeapInitData()); - heap.Check(); // This should cause panic - break; - } - - case 10: - // Overwrite slab buffer and check - { - TInt i = 0; - TBool slabs_created = EFalse; - if ( !heap.SlabAllocatorExists() ) - { - User::Panic(KLitHeapCheck, ETHeapDebugUnmatchedCallToCheckHeap); - } - - while ( !slabs_created ) - { - // Allocate enough buffers to cause slab allocator to be - // initialised - heap.AllocateSomeBuffers(bfrs, 0x4, 0x2000, 256); - slabs_created = heap.SlabsCreated(); - i ++; - if ( i > 9 ) - break; - } - test(slabs_created); - test(heap.PrintHeapInitData()); - i = 0; - TUint8* p[10]; - while ( i < 10 ) - { - p[i] = heap.Alloc(24); - test( p[i] != NULL ); - i ++; - } - i = 0; - while ( i < 10 ) - { - heap.Free(p[i]); - i +=2; - } - p[0] = heap.Alloc(24); - test( p[0] != NULL ); - memset((TUint8*)(Floor(p[0], SLABSIZE) + sizeof(slabhdr)), 0xee, KMaxSlabPayload); // Heap corrupted - heap.Check(); // This should cause panic - break; - } - - case 11: - // Corrupt slab header - { - TInt i = 0; - TBool slabs_created = EFalse; - if ( !heap.SlabAllocatorExists() ) - { - User::Panic(KLitHeapCheck, ETHeapDebugUnmatchedCallToCheckHeap); - } - - while ( !slabs_created ) - { - // Allocate enough buffers to cause slab allocator to be - // initialised - heap.AllocateSomeBuffers(bfrs, 0x4, 0x2000, 256); - slabs_created = heap.SlabsCreated(); - i ++; - if ( i > 9 ) - break; - } - test(slabs_created); - test(heap.PrintHeapInitData()); - TUint8* p = heap.Alloc(28); - test(p != NULL); - p = Floor(p, SLABSIZE); - *(TUint32*)p = 0xffeeddcc; - heap.Check(); // This should cause panic - break; - } - - case 20: - // Corrupt page bitmap data and check - { - if ( !heap.PageAllocatorExists() ) - { - User::Panic(KLitHeapCheck, ETHeapDebugUnmatchedCallToCheckHeap); - } - test(heap.ConfigurePageAllocator()); - // Allocate some buffers to cause slab allocator to be - // initialised - heap.AllocateSomeBuffers(bfrs, 0x4000, 0x10000, 16); - test(heap.PrintHeapInitData()); - TUint8* bitmap = heap.Alloc(128); // For saved bitmap - test(bitmap != NULL); - TInt bit_lth = heap.CopyPageBitmap(bitmap, 128); - test(bit_lth != 0); - memset(bitmap, 0xee, (bit_lth>>3)); // corrupt bitmap data - heap.RestorePageBitmap(bitmap, bit_lth); - heap.Check(); // This should cause panic - break; - } - - case 21: - // Corrupt page bitmap with a earlier freed "ghost" buffer info - { - if ( !heap.PageAllocatorExists() ) - { - User::Panic(KLitHeapCheck, ETHeapDebugUnmatchedCallToCheckHeap); - } - test(heap.ConfigurePageAllocator()); - // Allocate some buffers to cause slab allocator to be - // initialised - heap.AllocateSomeBuffers(bfrs, 0x4000, 0x10000, 16); - test(heap.PrintHeapInitData()); - TUint8* bitmap = heap.Alloc(128); // For saved bitmap - test(bitmap != NULL); - TUint8* p = heap.Alloc(0x8000); // One more page buffer - TInt bit_lth = heap.CopyPageBitmap(bitmap, 128); - test(bit_lth != 0); - heap.Free(p); - heap.RestorePageBitmap(bitmap, bit_lth); - heap.Check(); // This should cause panic - break; - } - - default: - break; - } - - User::Invariant(); // Should not reach here - return 0; -} - - -class TestHeapCheck -{ - public: - void TestCheck(void); - TInt TestThreadExit(RThread& aThread, TExitType aExitType, TInt aExitReason); -}; - - -TInt TestHeapCheck::TestThreadExit(RThread& aThread, TExitType aExitType, TInt aExitReason) -{ - // Disable JIT debugging. - TBool justInTime=User::JustInTime(); - User::SetJustInTime(EFalse); - - TRequestStatus status; - aThread.Logon(status); - aThread.Resume(); - User::WaitForRequest(status); - if (aExitType != aThread.ExitType()) - return KErrGeneral; - - if ( (status.Int() == ETHeapDebugUnmatchedCallToCheckHeap) && (aThread.ExitReason() == ETHeapDebugUnmatchedCallToCheckHeap)) - { - CLOSE_AND_WAIT(aThread); - // Put JIT debugging back to previous status. - User::SetJustInTime(justInTime); - return KErrNotSupported; - } - - if ( status.Int() == ERTestFailed ) - return KErrGeneral; - - if ( aExitReason > 0 ) - { - if (aExitReason != status.Int()) - return KErrGeneral; - - if (aExitReason != aThread.ExitReason()) - return KErrGeneral; - } - - CLOSE_AND_WAIT(aThread); - - // Put JIT debugging back to previous status. - User::SetJustInTime(justInTime); - return KErrNone; - -} - -void TestHeapCheck::TestCheck() -{ - TInt type; - TInt r; - - test.Next(_L("Testing Doug Lea allocator check")); - { - type = 1; - RThread thread; - test(thread.Create(_L("Check UserHeap"),HeapCheckTestThread, KDefaultStackSize, 0x1000, 0x400000, (TAny*) &type)== KErrNone); - test(TestThreadExit(thread, EExitPanic, ETHeapBadCellAddress)==KErrNone); - - type = 2; - test(thread.Create(_L("Check UserHeap"),HeapCheckTestThread, KDefaultStackSize, 0x1000, 0x400000, (TAny*) &type)==KErrNone); - test(TestThreadExit(thread, EExitPanic, ETHeapBadCellAddress)==KErrNone); - - type = 3; - test(thread.Create(_L("Check UserHeap"),HeapCheckTestThread, KDefaultStackSize, 0x1000, 0x400000, (TAny*) &type)==KErrNone); - test(TestThreadExit(thread, EExitPanic, ETHeapBadCellAddress)==KErrNone); - - } - - test.Next(_L("Testing Slab allocator check")); - { - type = 10; - RThread thread; - test(thread.Create(_L("Check UserHeap"),HeapCheckTestThread, KDefaultStackSize, 0x1000, 0x400000, (TAny*) &type)==KErrNone); - r = TestThreadExit(thread, EExitPanic, ETHeapBadCellAddress); - if ( r != KErrNotSupported ) - { - test(r==KErrNone); - - type = 11; - RThread thread; - test(thread.Create(_L("Check UserHeap"),HeapCheckTestThread, KDefaultStackSize, 0x1000, 0x400000, (TAny*) &type)==KErrNone); - test(TestThreadExit(thread, EExitPanic, ETHeapBadCellAddress)==KErrNone); - } - else test.Printf(_L("Slab allocator does not exist, testes bypassed\n")); - } - - test.Next(_L("Testing Page allocator check")); - { - type = 20; - RThread thread; - test(thread.Create(_L("Check UserHeap"),HeapCheckTestThread, KDefaultStackSize, 0x1000, 0x800000, (TAny*) &type)==KErrNone); - r = TestThreadExit(thread, EExitPanic, KErrNone); // Accept any panic reason here - if ( r != KErrNotSupported ) - { - test(r==KErrNone); - - type = 21; - RThread thread; - test(thread.Create(_L("Check UserHeap"),HeapCheckTestThread, KDefaultStackSize, 0x1000, 0x800000, (TAny*) &type)==KErrNone); - test(TestThreadExit(thread, EExitPanic, KErrNone)==KErrNone); // Accept any panic reason here - } - else test.Printf(_L("Page allocator does not exist, testes bypassed\n")); - } - -} - - - - -// Global Functions - -GLDEF_C TInt E32Main(void) - { - - test.Title(); - - test.Start(_L("Testing Heap Check function")); - - TestHeapCheck T; - - T.TestCheck(); - - test.End(); - - return(0); - } -