--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/analyzetool/dynamicmemoryhook/src/customuser.cpp Tue May 25 14:22:58 2010 +0300
@@ -0,0 +1,518 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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: Definitions for the class CustomUser.
+*
+*/
+
+#include <f32file.h>
+#include <utf.h>
+#include "customuser.h"
+#include "analyzetoolmainallocator.h"
+#include "analyzetoolallocator.h"
+#include "atlog.h"
+#include "analyzetoolmemoryallocator.h"
+#include "analyzetoolpanics.pan"
+#include "atstorageservercommon.h"
+#include "atdriveinfo.h"
+#include <analyzetool/analyzetooltraceconstants.h>
+
+#ifdef USE_CLEANER_DLL
+// Global variable to detect dll attach & detach in process.
+// Note! This is initialized after SetupThreadHeap so its not usable there.
+// This is used to store the main thread id and track when the process ends
+// to load the cleaner dll with call back feature to cleanup allocator at the
+// last possible phase.
+#include <analyzetool/analyzetoolcleaner.h>
+
+// CONSTANTS
+const TInt KAToolCleanerOrdinal = 1;
+
+class TAnalyzeToolGlobalTracker : public TAnalyzeToolCleanerBase
+ {
+public:
+ /* Main thread id */
+ TThreadId iMainId;
+
+ /* Inform if panic occured */
+ TBool iPanic;
+
+ // -----------------------------------------------------------------------------
+ // TAnalyzeToolGlobalTracker::TAnalyzeToolGlobalTracker()
+ // C++ default constructor
+ // -----------------------------------------------------------------------------
+ //
+ TAnalyzeToolGlobalTracker()
+ {
+ LOGSTR1( "ATMH TAnalyzeToolGlobalTracker::TAnalyzeToolGlobalTracker()" );
+
+ iPanic = EFalse; // no panic occured
+ iMainId = RThread().Id(); // set main thread id
+ LOGSTR2( "ATMH TAnalyzeToolGlobalTracker() > Main id set: %d",
+ iMainId.operator TUint() );
+ }
+
+ // -----------------------------------------------------------------------------
+ // TAnalyzeToolGlobalTracker::~TAnalyzeToolGlobalTracker()
+ // Destructor.
+ // -----------------------------------------------------------------------------
+ //
+ ~TAnalyzeToolGlobalTracker()
+ {
+ LOGSTR1( "ATMH TAnalyzeToolGlobalTracker::~TAnalyzeToolGlobalTracker()" );
+
+ // We dont load dll if panic has happened (uninstallation has been done).
+ if ( iPanic )
+ {
+ LOGSTR1( "ATMH ~TAnalyzeToolGlobalTracker > Panic set not loading cleaner dll." );
+ return;
+ }
+
+ LOGSTR1( "ATMH ~TAnalyzeToolGlobalTracker > about to load cleaner dll" );
+ // Load cleaner library and set a call back to our cleanup
+ RLibrary lib;
+ TInt error( lib.Load( KATCleanerDllName ) );
+ if ( error == KErrNone )
+ {
+ // Set address to point to ourself
+ TLibraryFunction func = lib.Lookup( KAToolCleanerOrdinal ); // Ordinal 1 of the dll
+ ATCLEANERTABLE* cleaner = (ATCLEANERTABLE*) func(); // Use function to get address
+ cleaner->At( 0 ) = (TUint32) this; // Set address
+ LOGSTR1( "ATMH ~TAnalyzeToolGlobalTracker() > cleaner dll loaded and call back set" );
+ }
+ else
+ {
+ // Error loading cleanup dll
+ LOGSTR2( "ATMH ~TAnalyzeToolGlobalTracker() > cleaner dll load error(%i) uninstalling allocator now!",
+ error );
+ Cleanup();
+ }
+ }
+
+ // -----------------------------------------------------------------------------
+ // TAnalyzeToolGlobalTracker::Cleanup()
+ //
+ // -----------------------------------------------------------------------------
+ //
+ void Cleanup()
+ {
+ LOGSTR1( "ATMH TAnalyzeToolGlobalTracker::Cleanup() - allocator uninstall" );
+
+ // Uninstall allocator
+ ( (RAnalyzeToolMemoryAllocator&) User::Allocator() ).Uninstall();
+ }
+
+ };
+
+// Global variable definition.
+TAnalyzeToolGlobalTracker gGlobalTracker;
+#endif
+
+// CONSTANTS
+// When needed, update the version number directly inside _LIT macro.
+// Constant for the atool API(staticlib) version.
+_LIT( KAtoolApiVersion, "1.7.5" );
+
+// Version number buffer length
+const TInt KAtoolVersionNumberLength = 10;
+
+// Wrong version error code
+const TInt KAtoolVersionError = -1999;
+
+// Version number separator
+_LIT( KVersionSeparator, ";" );
+
+// Incorrect version error strings
+_LIT( KIncorrectText, "ERROR_OCCURED INCORRECT_ATOOL_VERSION [API v.%S][ATOOL v.%S]" );
+_LIT( KIncorrectTextTrace, "PCSS " );
+
+// -----------------------------------------------------------------------------
+// CustomUser::Panic()
+// Overloaded User::Panic() function
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CustomUser::Panic( const TDesC& aCategory, TInt aReason )
+ {
+ LOGSTR3( "ATMH CustomUser::Panic() %S %i", &aCategory, aReason );
+
+#ifdef USE_CLEANER_DLL
+ // Set global tracker that panic has happened.
+ gGlobalTracker.iPanic = ETrue;
+#endif
+
+ // Uninstall thread's RAllocator
+ ( (RAnalyzeToolMemoryAllocator&) User::Allocator() ).Uninstall();
+
+ // Call the "real" User::Panic()
+ User::Panic( aCategory, aReason );
+ }
+
+// -----------------------------------------------------------------------------
+// CustomUser::Exit()
+// Overloaded User::Exit() function
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CustomUser::Exit( TInt aReason )
+ {
+ LOGSTR3( "ATMH CustomUser::Exit() %i %i", aReason, RThread().Id().Id() );
+
+ if ( aReason != KAtoolVersionError )
+ {
+#ifdef USE_CLEANER_DLL
+ // Only uninstall allocator if its not the process main/first thread.
+ LOGSTR3( "ATMH CustomUser::Exit() - Thread id: %d - Main Id: %d",
+ RThread().Id().operator TUint(), gGlobalTracker.iMainId.operator TUint() );
+
+ if ( RThread().Id() != gGlobalTracker.iMainId )
+ {
+ LOGSTR2("ATMH CustomUser::Exit() - Calling allocator uninstall in thread: %d" , RThread().Id().operator TUint() );
+ ( (RAnalyzeToolMemoryAllocator&) User::Allocator() ).Uninstall();
+ }
+#else
+ // Uninstall thread's RAllocator
+ ( (RAnalyzeToolMemoryAllocator&) User::Allocator() ).Uninstall();
+ LOGSTR1( "ATMH CustomUser::Exit() - about to User::Exit" );
+#endif
+ }
+
+ // Call the "real" User::Exit()
+ User::Exit( aReason );
+ }
+
+// -----------------------------------------------------------------------------
+// CustomUser::SetCritical()
+// Overloaded User::SetCritical() function which returns
+// KErrNone, if successful; KErrArgument, if EAllThreadsCritical is
+// passed - this is a state associated with a process, and you use
+// User::SetProcessCritical() to set it.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CustomUser::SetCritical( User::TCritical aCritical )
+ {
+ LOGSTR1( "ATMH CustomUser::SetCritical()" );
+ // Check the given User::TCritical type
+ if ( aCritical == User::EAllThreadsCritical )
+ {
+ return KErrArgument;
+ }
+ else
+ {
+ return KErrNone;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CustomUser::SetProcessCritical()
+// Overloaded User::SetProcessCritical() function
+// KErrNone, if successful; KErrArgument, if either EProcessCritical or
+// EProcessPermanent is passed - these are states associated with a
+// thread, and you use User::SetCritical() to set them.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CustomUser::SetProcessCritical( User::TCritical aCritical )
+ {
+ LOGSTR1( "ATMH CustomUser::SetProcessCritical()" );
+ // Check the given User::TCritical type
+ if ( aCritical == User::EProcessCritical ||
+ User::EProcessPermanent == aCritical )
+ {
+ return KErrArgument;
+ }
+ else
+ {
+ return KErrNone;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CustomUser::SetupThreadHeap()
+// Overloaded UserHeap::SetupThreadHeap function
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CustomUser::SetupThreadHeap( TBool aNotFirst,
+ SStdEpocThreadCreateInfo& aInfo, const TFileName& aFileName,
+ TUint32 aLogOption, TUint32 aIsDebug, const TATVersion& aVersion,
+ TUint32 aAllocCallStackSize, TUint32 aFreeCallStackSize,
+ TRefByValue<const TDesC> aFmt, ... )
+ {
+ LOGSTR1( "ATMH CustomUser::SetupThreadHeap()" );
+ LOGSTR2( "ATMH > Thread id(%d)", RThread().Id().operator TUint() );
+
+ // Add handling of the argument list here.
+
+ TInt ret( KErrNone );
+ // Check version number
+ TBuf<KAtoolVersionNumberLength> atoolVer;
+ if ( CheckVersion( aVersion, atoolVer ) != KErrNone )
+ {
+ LOGSTR1( "ATMH > Wrong API version > Inform user and Exit." );
+ ReportIncorrectVersion( aLogOption, aFileName, atoolVer );
+ return KAtoolVersionError;
+ }
+
+ // Check is this shared heap
+ if ( aInfo.iAllocator == NULL )
+ {
+ LOGSTR1( "ATMH creating a new heap" );
+ // RAllocator is NULL so heap is not shared, creating a new heap
+ ret = UserHeap::SetupThreadHeap( aNotFirst, aInfo );
+ __ASSERT_ALWAYS( KErrNone == ret, AssertPanic( EFailedToCreateHeap ) );
+
+#if ( SYMBIAN_VERSION_SUPPORT >= SYMBIAN_3 )
+ #ifndef __WINS__
+ // Set dummy Tls value
+ TAny* dummyPtr( NULL );
+ TInt setErr( UserSvr::DllSetTls( KDummyHandle, dummyPtr ) );
+ LOGSTR2( "ATMH > Set Tls err(%i)", setErr );
+ #endif
+#endif
+ // Install the RAllocator
+ aInfo.iAllocator = &InstallAllocator( aNotFirst, aFileName, aLogOption, aIsDebug,
+ aAllocCallStackSize, aFreeCallStackSize );
+ }
+ else
+ {
+ LOGSTR1( "ATMH sharing the heap" );
+ // The heap is shared. Acquire pointer to the original heap
+ RAnalyzeToolMemoryAllocator* allocator =
+ (RAnalyzeToolMemoryAllocator*) aInfo.iAllocator;
+ // Share the heap
+ allocator->ShareHeap();
+ // Switch thread heap
+ User::SwitchAllocator( allocator );
+ }
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CustomUser::InstallAllocator
+// Installs the RAllocator
+// -----------------------------------------------------------------------------
+//
+//lint -e{429} suppress "Custodial pointer 'allocator' has not been freed or returned"
+EXPORT_C RAllocator& CustomUser::InstallAllocator( TBool aNotFirst,
+ const TFileName& aFileName, TUint32 aLogOption, TUint32 aIsDebug,
+ TUint32 aAllocCallStackSize, TUint32 aFreeCallStackSize )
+ {
+ LOGSTR1( "ATMH CustomUser::InstallAllocator()" );
+
+ // Open handle to the device driver
+ RAnalyzeTool analyzetool;
+ TInt error = analyzetool.Open();
+
+ // Check if the device driver has already loaded
+ if ( KErrNone == error )
+ {
+ LOGSTR1( "ATMH CustomUser::InstallAllocator() - analyzetool.Open() returned KErrNone" );
+ // The device driver has already loaded
+ // Get pointer to the main thread allocator
+ TMainThreadParamsBuf params;
+ params().iProcessId = RProcess().Id().operator TUint();
+ error = analyzetool.MainThreadAlloctor( params );
+
+ __ASSERT_ALWAYS( KErrNone == error, AssertPanic( ECantOpenHandle ) );
+
+ // Close handle to the device driver
+ analyzetool.Close();
+
+ // Is this the first thread of the program
+ if ( params().iAlone )
+ {
+ LOGSTR1( "ATMH CustomUser::InstallAllocator() - first thread of the program" );
+ // Only one thread in the program. Must be main thread
+ RAnalyzeToolMainAllocator* allocator =
+ new RAnalyzeToolMainAllocator( aNotFirst, aFileName, aLogOption,
+ aIsDebug, aAllocCallStackSize, aFreeCallStackSize );
+
+ __ASSERT_ALWAYS( allocator != NULL, AssertPanic( ENoMemory ) );
+
+ // Change threads allocator
+ User::SwitchAllocator( allocator );
+
+ // Return reference to the RAllocator
+ return *allocator;
+ }
+ // This is not the first thread. A new thread with a new heap created
+ else
+ {
+ LOGSTR1( "ATMH CustomUser::InstallAllocator() - create a new allocator for the new thread" );
+ // Create new RAllocator with handles from the main thread
+ RAnalyzeToolAllocator* allocator = new RAnalyzeToolAllocator(
+ aNotFirst,
+ ((RAnalyzeToolMainAllocator*)params().iAllocator)->StorageServer(),
+ ((RAnalyzeToolMainAllocator*)params().iAllocator)->Codeblocks(),
+ ((RAnalyzeToolMainAllocator*)params().iAllocator)->Mutex(),
+ ((RAnalyzeToolMainAllocator*)params().iAllocator)->ProcessId(),
+ ((RAnalyzeToolMainAllocator*)params().iAllocator)->AnalyzeTool(),
+ ((RAnalyzeToolMainAllocator*)params().iAllocator)->StorageServerOpen(),
+ ((RAnalyzeToolMainAllocator*)params().iAllocator)->LogOption(),
+ ((RAnalyzeToolMainAllocator*)params().iAllocator)->AllocMaxCallStack(),
+ ((RAnalyzeToolMainAllocator*)params().iAllocator)->FreeMaxCallStack() );
+
+ __ASSERT_ALWAYS( allocator != NULL, AssertPanic( ENoMemory ) );
+
+ // Change threads allocator
+ User::SwitchAllocator( allocator );
+
+ // Return reference to the RAllocator
+ return *allocator;
+ }
+ }
+ // The device driver does not exists so this must be the first thread
+ else
+ {
+ LOGSTR1( "ATMH CustomUser::InstallAllocator() - analyzetool.Open() returned error, creating DD" );
+ RAnalyzeToolMainAllocator* allocator =
+ new RAnalyzeToolMainAllocator( aNotFirst, aFileName, aLogOption, aIsDebug,
+ aAllocCallStackSize, aFreeCallStackSize );
+
+ __ASSERT_ALWAYS( allocator != NULL, AssertPanic( ENoMemory ) );
+
+ // Change threads allocator
+ User::SwitchAllocator( allocator );
+
+ // Return reference to the RAllocator
+ return *allocator;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CustomUser::CheckVersion
+// Check atool version
+// -----------------------------------------------------------------------------
+//
+TInt CustomUser::CheckVersion( const TATVersion& aVersion, TDes& aToolVersion )
+ {
+ LOGSTR2( "ATMH CustomUser::CheckVersion(), aVersion( %S )", &aVersion );
+
+ TFileName version;
+ version.Copy( aVersion );
+ TBuf<KAtoolVersionNumberLength> apiVer;
+
+ // Find separator place
+ TInt findplace( version.Find( KVersionSeparator() ) );
+ // Parse API version first [x.x.x;x.x.x]
+ if ( findplace >= 0 && findplace <= apiVer.MaxLength() )
+ {
+ apiVer.Copy( version.Mid( 0, findplace ) );
+ version.Delete( 0, findplace + KVersionSeparator().Length() );
+ }
+
+ if ( version.Length() <= aToolVersion.MaxLength() )
+ {
+ aToolVersion.Copy( version );
+ if ( aToolVersion.Compare( KAtoolApiVersion ) == KErrNone &&
+ apiVer.Length() == 0 )
+ {
+ // Support 1.5.0 version (Version info: [1.5.0])
+ apiVer.Copy( version );
+ }
+ }
+
+ LOGSTR3( "ATMH > API version( %S ), ATOOL version( %S )",
+ &apiVer, &aToolVersion );
+
+ // Check version numbers
+ if ( apiVer.Compare( KAtoolApiVersion ) == KErrNone )
+ {
+ return KErrNone;
+ }
+ return KErrCancel;
+ }
+
+// -----------------------------------------------------------------------------
+// CustomUser::ReportIncorrectVersion
+// Function for showing incorrect version information
+// -----------------------------------------------------------------------------
+//
+void CustomUser::ReportIncorrectVersion( const TUint32 aLogOption,
+ const TFileName& aFileName, const TDes& aToolVersion )
+ {
+ LOGSTR2( "ATMH CustomUser::ReportIncorrectVersion(), aFileName( %S )",
+ &aFileName );
+
+ switch ( aLogOption )
+ {
+ case EATLogToFile:
+ {
+ LOGSTR1( "ATMH ReportIncorrectVersion > EATLogToFile" );
+
+ // A handle to a file server session.
+ RFs fs;
+ // Creates and opens a file,
+ // and performs all operations on a single open file.
+ RFile file;
+ // Create full path buffer
+ TBuf<KMaxFileName> logFileBuf;
+ // Connects a client to the file server.
+ TInt err( fs.Connect() );
+
+ if ( !err )
+ {
+ err = TATDriveInfo::CreatePath( logFileBuf, aFileName, fs );
+
+ // Replace file if exists
+ if ( err && err != KErrAlreadyExists )
+ {
+ LOGSTR2( "ATMH > TATDriveInfo::CreatePath() err( %i )", err );
+ return;
+ }
+
+ // Replace file if exists (drive C)
+ err = file.Replace( fs, logFileBuf, EFileWrite );
+
+ // Write to file
+ if ( !err )
+ {
+ err = file.Write( KDataFileVersion );
+ // Error msg buffer
+ TBuf8<KMaxFileName> msg;
+ // Write the error code to the buffer
+ logFileBuf.Format( KIncorrectText, &KAtoolApiVersion, &aToolVersion );
+ CnvUtfConverter::ConvertFromUnicodeToUtf8( msg, logFileBuf );
+ err = file.Write( msg );
+ }
+ // Closes the file.
+ file.Close();
+ }
+
+ LOGSTR2( "ATMH > File err( %i )", err );
+ // Closes the handle.
+ fs.Close();
+ }
+ break;
+
+ case EATUseDefault:
+ case EATLogToTrace:
+ {
+ LOGSTR1( "ATMH > ReportIncorrectVersion > EATLogToTrace" );
+ // Error msg buffer
+ TBuf<KMaxFileName> msg;
+ msg.Copy( KIncorrectTextTrace );
+ msg.Append( KIncorrectText );
+ TBuf<KMaxFileName> traceMsg;
+ // Write the error code to the buffer
+ traceMsg.Format( msg, &KAtoolApiVersion, &aToolVersion );
+ RDebug::Print( traceMsg );
+ }
+ break;
+
+ default:
+ {
+ LOGSTR1( "ATMH > ReportIncorrectVersion > default" );
+ }
+ break;
+ }
+ }
+
+// End of File