# HG changeset patch # User hgs # Date 1273784367 -10800 # Node ID a71a3e32a2ae49c63597be5e3aaa3b49c73e6f7e # Parent ccab7f1f8266bfe2b810d758bbd7bcb2775a7802 201019 diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/analyzetoolcleaner/bwins/atoolcleaneru.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/analyzetoolcleaner/bwins/atoolcleaneru.def Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,3 @@ +EXPORTS + ?GetCallBackAddress@@YAPAV?$TFixedArray@K$09@@XZ @ 1 NONAME ; class TFixedArray<unsigned long, 10> * GetCallBackAddress(void) + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/analyzetoolcleaner/eabi/atoolcleaneru.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/analyzetoolcleaner/eabi/atoolcleaneru.def Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,3 @@ +EXPORTS + _Z18GetCallBackAddressv @ 1 NONAME + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/analyzetoolcleaner/group/analyzetoolcleaner.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/analyzetoolcleaner/group/analyzetoolcleaner.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,39 @@ +/* +* 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: The .mmp file for atoolcleaner. +* +*/ + +#include <platform_paths.hrh> + +TARGET atoolcleaner.dll +TARGETTYPE dll +UID 0x1000008d 0x2002DC71 +CAPABILITY ALL -TCB +EPOCALLOWDLLDATA + +SMPSAFE + +SOURCEPATH ../src +SOURCE analyzetoolcleaner.cpp + +USERINCLUDE ../inc +USERINCLUDE ../../inc + +OS_LAYER_SYSTEMINCLUDE + +LIBRARY euser.lib +LIBRARY flogger.lib + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/analyzetoolcleaner/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/analyzetoolcleaner/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,8 @@ +PRJ_PLATFORMS +ARMV5 WINSCW + +PRJ_EXPORTS +../inc/analyzetoolcleaner.h OS_LAYER_PLATFORM_EXPORT_PATH(analyzetool/analyzetoolcleaner.h) + +PRJ_MMPFILES +analyzetoolcleaner.mmp diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/analyzetoolcleaner/inc/analyzetoolcleaner.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/analyzetoolcleaner/inc/analyzetoolcleaner.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,63 @@ +/* +* 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 TAnalyzeToolCleanerBase. +* +*/ + +#ifndef __ANALYZETOOLCLEANER_H__ +#define __ANALYZETOOLCLEANER_H__ + +// INCLUDES +#include <e32std.h> + +// CONSTANTS +#define ATCLEANERTABLESIZE 10 +#define ATCLEANERTABLE TFixedArray<TUint32, ATCLEANERTABLESIZE> +_LIT( KATCleanerDllName, "atoolcleaner.dll" ); + +// CLASS DECLARATION + +/** +* Cleaner base class +*/ +class TAnalyzeToolCleanerBase + { +public: + /** + * Cleanup function which uninstall allocator + */ + virtual void Cleanup() = 0; + }; + +// CLASS DECLARATION + +/** +* Cleaner class +*/ +class THookCleaner + { +public: + /** + * C++ default constructor. + */ + THookCleaner(); + + /** + * Destructor. + */ + ~THookCleaner(); + + ATCLEANERTABLE iTable; + }; +#endif // __ANALYZETOOLCLEANER_H__ diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/analyzetoolcleaner/src/analyzetoolcleaner.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/analyzetoolcleaner/src/analyzetoolcleaner.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,67 @@ +/* +* 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: THookCleaner implementation +* +*/ + +// INCLUDES +#include "analyzetoolcleaner.h" +#include <e32debug.h> +#include "atlog.h" + +// Global cleaner object +static THookCleaner cleaner; + +// ordinal 1 +EXPORT_C ATCLEANERTABLE* GetCallBackAddress() + { + LOGSTR1( "ATC GetCallBackAddress()" ); + + return &( cleaner.iTable ); + } + +// ----------------------------------------------------------------------------- +// THookCleaner::THookCleaner() +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +THookCleaner::THookCleaner() + { + LOGSTR1( "ATC THookCleaner::THookCleaner()" ); + + iTable.Reset(); + } + +// ----------------------------------------------------------------------------- +// THookCleaner::~THookCleaner() +// Destructor. +// ----------------------------------------------------------------------------- +// +THookCleaner::~THookCleaner() + { + LOGSTR1( "ATC THookCleaner::~THookCleaner()" ); + + for ( TUint i = 0; i < ATCLEANERTABLESIZE; i++ ) + { + if ( iTable.At( i ) ) + { + TAnalyzeToolCleanerBase* obj = + ( TAnalyzeToolCleanerBase* ) iTable.At( i ); + obj->Cleanup(); + } + } + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/group/atool.vcproj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/group/atool.vcproj Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,375 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="9.00" + Name="atool" + ProjectGUID="{2C50DD86-958B-4189-8DA2-DB388C71F65F}" + RootNamespace="atool" + Keyword="Win32Proj" + TargetFrameworkVersion="131072" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="Debug" + IntermediateDirectory="Debug" + ConfigurationType="1" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + TreatWChar_tAsBuiltInType="false" + UsePrecompiledHeader="0" + PrecompiledHeaderThrough="..\inc\stdafx.h" + WarningLevel="4" + Detect64BitPortabilityProblems="false" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="..\lib\xerces-c_2.lib ..\lib\dbghelp.lib Version.lib" + OutputFile="..\install\atool.exe" + LinkIncremental="2" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(OutDir)/atool.pdb" + SubSystem="1" + RandomizedBaseAddress="1" + DataExecutionPrevention="0" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="Release" + IntermediateDirectory="Release" + ConfigurationType="1" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="..\" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" + RuntimeLibrary="0" + TreatWChar_tAsBuiltInType="false" + UsePrecompiledHeader="0" + WarningLevel="4" + Detect64BitPortabilityProblems="false" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="..\lib\xerces-c_2.lib ..\lib\dbghelp.lib Version.lib" + OutputFile="..\install\atool.exe" + LinkIncremental="1" + GenerateDebugInformation="true" + SubSystem="1" + OptimizeReferences="2" + EnableCOMDATFolding="2" + RandomizedBaseAddress="1" + DataExecutionPrevention="0" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + <File + RelativePath="..\src\arguments.cpp" + > + </File> + <File + RelativePath="..\src\atool.cpp" + > + </File> + <File + RelativePath="..\src\cataddr2line.cpp" + > + </File> + <File + RelativePath="..\src\cataddr2lineserver.cpp" + > + </File> + <File + RelativePath="..\src\catalloc.cpp" + > + </File> + <File + RelativePath="..\src\catallocs.cpp" + > + </File> + <File + RelativePath="..\src\CATBase.cpp" + > + </File> + <File + RelativePath="..\src\CATDataSaver.cpp" + > + </File> + <File + RelativePath="..\src\CATDatParser.cpp" + > + </File> + <File + RelativePath="..\src\catdbghelper.cpp" + > + </File> + <File + RelativePath="..\src\catfilereader.cpp" + > + </File> + <File + RelativePath="..\src\CATMemoryAddress.cpp" + > + </File> + <File + RelativePath="..\src\CATMmp.cpp" + > + </File> + <File + RelativePath="..\src\CATModule2.cpp" + > + </File> + <File + RelativePath="..\src\CATParseTraceFile.cpp" + > + </File> + <File + RelativePath="..\src\CATParseXML.cpp" + > + </File> + <File + RelativePath="..\src\CATProject.cpp" + > + </File> + <File + RelativePath="..\src\catromsymbol.cpp" + > + </File> + <File + RelativePath="..\src\helps.cpp" + > + </File> + <File + RelativePath="..\src\librarychecks.cpp" + > + </File> + <File + RelativePath="..\src\stdafx.cpp" + > + </File> + <File + RelativePath="..\src\utility.cpp" + > + </File> + <File + RelativePath="..\src\version.cpp" + > + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + <File + RelativePath="..\inc\ATCommonDefines.h" + > + </File> + <File + RelativePath="..\inc\cataddr2line.h" + > + </File> + <File + RelativePath="..\inc\cataddr2lineserver.h" + > + </File> + <File + RelativePath="..\inc\catalloc.h" + > + </File> + <File + RelativePath="..\inc\catallocs.h" + > + </File> + <File + RelativePath="..\inc\CATBase.h" + > + </File> + <File + RelativePath="..\inc\CATDataSaver.h" + > + </File> + <File + RelativePath="..\inc\CATDatParser.h" + > + </File> + <File + RelativePath="..\inc\catdbghelper.h" + > + </File> + <File + RelativePath="..\inc\catfilereader.h" + > + </File> + <File + RelativePath="..\inc\CATMemoryAddress.h" + > + </File> + <File + RelativePath="..\inc\CATMmp.h" + > + </File> + <File + RelativePath="..\inc\CATModule2.h" + > + </File> + <File + RelativePath="..\inc\CATParseTraceFile.h" + > + </File> + <File + RelativePath="..\inc\CATParseXML.h" + > + </File> + <File + RelativePath="..\inc\CATProject.h" + > + </File> + <File + RelativePath="..\inc\catromsymbol.h" + > + </File> + <File + RelativePath="..\inc\iaddresstoline.h" + > + </File> + <File + RelativePath="..\inc\stdafx.h" + > + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" + > + </Filter> + <File + RelativePath=".\ReadMe.txt" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,22 @@ +/* +* 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: +* +*/ + + +PRJ_EXPORTS +../install/atool.exe +/tools/ +../install/addr2line.exe +/tools/ +../install/xerces-c_2_7.dll +/tools/ diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/ATCommonDefines.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/ATCommonDefines.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,598 @@ +/* +* 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: Common defines for cpp files. +* +*/ + + +#ifndef __ATCOMMONDEFINES_H__ +#define __ATCOMMONDEFINES_H__ + +#include "../inc/stdafx.h" + +using namespace std; + +/** +* Atool return code. +*/ +struct AT_RETURN_CODE { + /** + * Enumeration containing all return codes used by atool. + * When error happens this value set as the exit code. + * Note! Values can be only added not modified/deleted. + */ + enum RETURN_CODE { + /* basic */ + OK = 0, /** All ok. */ + INVALID_ARGUMENT_ERROR = 1, /** Arguments failty. */ + AT_LIBS_MISSING = 2, /** Missing at libraries cannot compile hooked apps. */ + CANNOT_FIND_EPOCROOT = 3, /** Epocroot not set. */ + UNHANDLED_EXCEPTION = 4, /** General return code when unhandled exception occurs. */ + /* compile errors */ + MAKEFILE_ERROR = 5, /** Cannot read/create etc makefiles sbs1/2. */ + COMPILE_ERROR = 6, /** Some error related to compilation of code. */ + UNKNOWN = 7, /** General compilation error not specific. */ + NO_SUPPORTED_MODULES_ERROR = 8, /** Cannot find supported modules from project. */ + KERNEL_SIDE_MODULE_ERROR = 9, /** Cannot find supported modules from project because kernel side. */ + /* Analyze errors */ + WRONG_DATA_FILE_VERSION = 10, /** Invalid data file version in internal gathering mode. */ + INVALID_DATA_FILE = 11, /** Data file content invalid. */ + ANALYZE_ERROR = 12, /** General error in analyze part not specific. */ + EMPTY_DATA_FILE = 13, /** Data file is empty. */ + SYMBOL_FILE_ERROR = 14, /** Symbol file content invalid or do not exist. */ + /* building&releasing errors */ + RELEASABLES_ERROR = 20, /** Cannot find the binaries of module. */ + RESTORE_MODULES_ERROR = 21, /** Error restoring mmp file to original. */ + CREATING_TEMP_CPP_ERROR = 22, /** Error creating temporary cpps to store variables to s60 core.*/ + CLEANING_TEMP_ERROR = 23, /** Error cleaning atool_temp folder from module. */ + READ_MAKEFILE_ERROR = 24, /** Some error when reading makefile of module / project (sbs1/2). */ + MODIFY_MODULES_ERROR = 25, /** Error modifying module mmp file. */ + INVALID_MMP_DEFINED = 27, /** Specified module does not exist in project. */ + /* Attribute file related */ + WRITE_ATTRIBUTES_ERROR = 30, /** Error writing the cfg file into atool_temp folder (contains arguments).*/ + READ_ATTRIBUTES_ERROR = 31, /** Error reading hooking related arguments from cfg file. */ + /* User issued exit */ + USER_ISSUED_EXIT = 40, /** User aborted the run of application. */ + }; +}; + +// Debug logging to console +extern bool g_bDebugConsole; +// Debug logging to windows api debug +extern bool g_bDebugDbgView; +// Debug (low level functions). +extern bool g_bDebugLowLevel; + +// Temporary directory definition's. +const char AT_TEMP_DIR[] = "atool_temp"; +const char AT_TEMP_LST_DIR[] = "atool_temp\\static_lsts\\"; + +// makefile dir is used in atool.cpp to check will we use sbs2 (in analyze and clear) +#define RAPTOR_MAKEFILE_DIR "atool_temp\\build" + +// Atool version number and date +#define ATOOL_VERSION "1.9.1" // NOTE! This version number is written also to temporary cpp file. +#define ATOOL_DATE "29th April 2010" + +// Default/min/max call stack sizes +const int AT_ALLOC_CALL_STACK_SIZE_DEFAULT = 40; +const int AT_FREE_CALL_STACK_SIZE_DEFAULT = 0; +const int AT_CALL_STACK_SIZE_MIN = 0; +const int AT_CALL_STACK_SIZE_MAX = 256; + +// What version of data file contains timestamps in dll's. +const int AT_DLL_TIMESTAMP_DATA_VERSION = 2; + +// Constant compatibility string in temporary cpp. +// Api version ; current version. +#define ATOOL_COMPATIBILITY_STRING "1.7.5;1.9.1" + +// Datafile version +#define AT_DATA_FILE_VERSION "DATA_FILE_VERSION 11" + +// Latest dbghelp.dll version +const int DBGHELP_VERSION_MAJ = 6; +const int DBGHELP_VERSION_MIN = 3; +const int DBGHELP_VERSION_BUILD = 0; +const int DBGHELP_VERSION_REVIS = 0; +const char DBGHELP_DLL_NAME[] = "dbghelp.dll"; + + +// Build summary constants +const string AT_BUILD_SUMMARY_HEADER = "\n### AnalyzeTool ###\n### Build Summary ###\n\n"; +const string AT_BUILD_SUMMARY_INSTRUMENTED_BUILD_COMPLETE = "Instrumented build complete: "; +const string AT_BUILD_SUMMARY_TARGET = "\tTarget: "; +const string AT_BUILD_SUMMARY_FAILED = "Build failed: "; +const string AT_BUILD_SUMMARY_ERRORS = "\tErrors: "; +const string AT_BUILD_SUMMARY_DATA_FILE_NAME = "\tInternal data gathering filename: "; +const string AT_BUILD_SUMMARY_NORMAL_BUILD_COMPLETE = "Normal build complete: "; +const string AT_BUILD_SUMMARY_STATIC_LIBRARY = "\tModule is static library."; +const string AT_BUILD_SUMMARY_UNSUPPORTED_TARGET_TYPE = "\tModule has unsupported target type."; +const string AT_BUILD_SUMMARY_UNSUPPORTED_COMPILE_DEFINITION = "\tModule defined unsupported compile definition."; +const string AT_BUILD_SUMMARY_BUILD_TYPE = "Build type: "; +const string AT_BUILD_SUMMARY_BUILD_TARGET = "Build target: "; +const string AT_BUILD_SUMMARY_BUILD_PLATFORM = "Build platform: "; +const string AT_BUILD_SUMMARY_BUILD_VARIANT = "Build variant: "; +const string AT_BUILD_SUMMARY_LOGGING_MODE = "Data gathering mode: "; +const string AT_BUILD_SUMMARY_ALLOC_CALL_STACK_SIZE = "Allocation call stack size: "; +const string AT_BUILD_SUMMARY_FREE_CALL_STACK_SIZE = "Free call stack size: "; +const string AT_BUILD_SUMMARY_FILE = "monitored internal"; +const string AT_BUILD_SUMMARY_TRACE = "monitored external"; +const string AT_BUILD_SUMMARY_TRACE_FAST = "external"; + +const string AT_UNSUPPORTED_TARGET_TYPE = "\tModule has unsupported target type."; +const string AT_UNSUPPORTED_COMPILE_DEFINITION = "\tModule defined unsupported compile definition."; + +// List of locations under epocroot where analyzetool.h can be found. +// Add all possible to this list so core version information can be read +// from file. +const string AT_CORE_INCLUDE_FILE_WITH_VERSION_NUMBER[] = { + "epoc32\\include\\domain\\osextensions\\analyzetool\\analyzetool.h", + "epoc32\\include\\oem\\analyzetool\\analyzetool.h", + "epoc32\\include\\platform\\analyzetool\\analyzetool.h" +}; +const string AT_CORE_VERSION_NUMBER_TAG = "ANALYZETOOL_CORE_VERSION_FOR_CLE"; + +// Temporary cpp name +const char AT_TEMP_CPP_LOWER_START[] = "0a1b2c3d_atool_temp_"; +const char AT_TEMP_CPP_LOWER_END[] = ".cpp"; + +const char TAB_CHAR_VALUE = 9; +const char SPACE_CHAR_VALUE = 32; + +// Bldmake error msg +#define AT_BLDMAKE_ERROR "AnalyzeTool : bldmake bldfiles error.\n" + +// File copy/move/etc... message definitions +#define AT_MSG "AnalyzeTool : " +#define AT_MSG_SYSTEM_CALL "AnalyzeTool : System call, " +#define AT_FILE_TO " to " + +// -c messages +#define AT_CLEANING_DONE "AnalyzeTool : Cleaning done." +#define AT_CLEANING_NOTHING_FOUND "AnalyzeTool : Nothing found to clean." + +// Analyzing data without process start or dll load +#define AT_ANALYZE_INSUFFICIENT_LOGGING_DATA "Insufficient logging data to locate code lines for memory addresses.\nLogging has been started after process start." +#define AT_ANALYZE_NO_PROCESS_START "AnalyzeTool : No processes start information found in test run data." +#define AT_ANALYZE_NO_DLL_LOAD "AnalyzeTool : No dll load information found in test run data." +#define AT_ANALYZE_CANNOT_PINPOINT "AnalyzeTool : Memory addresses cannot be pinpointed." +#define AT_ANALYZE_ABNORMAL_EXIT "Abnormal process end" + +// Analyzing without map / lst files +#define AT_ANALYZE_MISSING_LST_MAP_FILES "AnalyzeTool : Missing lst or map files, memory addresses shown only to module level.\n" +//#define AT_UNINSTRUMENT_FAILED_IN_ANALYZE_MESSAGE "AnalyzeTool: Error creating map/lst files, leaks shown only to module level.\nRun atool -u to try create lst/map files again after binaries build successfully.\n" + +// Mmp error msg +#define INVALID_MMP_ERROR "AnalyzeTool : Error, Specified mmp is invalid.\n" + +// Make error msg +#define MAKE_ERROR "AnalyzeTool : Error, Running make.\n" + +#define AT_NOT_BEEN_BUILD_ERROR "AnalyzeTool : Error, project has not been build using AnalyzeTool.\n" + +// Makefile errors +#define LEVEL1_MAKEFILE_ERROR "AnalyzeTool : Error, reading level 1 makefile.\n" +#define LEVEL2_MAKEFILE_ERROR "AnalyzeTool : Error, reading level 2 makefile.\n" +#define MAKEFILE_ERROR_TIP "AnalyzeTool : Tip, your environment might require you to use -variant [target] argument.\n"; + +//Variant messages +#define INVALID_VARIANT_ERROR "AnalyzeTool : Error,Specified variant is invalid.\n" +#define USING_DEFAULT_VARIANT_MESSAGE "AnalyzeTool : Note, Using DEFAULT variant.\n" +#define NO_DEFAULT_VARIANT_ERROR "AnalyzeTool : Error, environment does not specify DEFAULT variant (No variant support?).\n" + +// Variant dir is the dir where all variants are defined +#define VARIANT_DIR "\\epoc32\\tools\\variant\\" + +// Variants defined extension name of the variant must equal filename +#define VARIANT_FILE_EXTENSION ".VAR" + +//Max file name length +const int MAX_FILENAME_LENGTH = 1024; + +//Max line length when reading lines from text file.2048 should be enought. +const int MAX_LINE_LENGTH = 2048*8; + +// ATs project file name to store project attributes +#define AT_PROJECT_ATTRIBUTES_FILE_NAME "project.cfg" +const string AT_PROJECT_ATTRIBUTES_SEPARATOR( ":$:" ); + +// ATs level1 makefile name +#define AT_LEVEL_1_MAKEFILE_NAME "main.at" + +// ATs level2 makefiles extension +#define AT_LEVEL_2_MAKEFILE_EXT "atm" + +//Default logging level +const int DEFAULT_LOGGING_LEVEL = 3; + +//Minimun value of logging level +const int MIN_LOGGING_LEVEL = 0; + +//Maximun value of logging level +const int MAX_LOGGING_LEVEL = 3; + +//Const char represeting dash +const char DASH = '\\'; + +/** + * Table of file extension not to delete + * from atools temp directory when compiling + * note define all in lowercase + */ +const string TEMP_EXTENSION_NO_DELETE[] = { + "xml", + "dat", + "tmp", + "cpp", + "at", + "atm", + "cfg" +}; + +// Allowed characters/digits, other than these will be filtered out when using CATBase FilterString +const char CFILTERSTRING[] = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_"; + +/** + * Table of unsupported target types + * (i.e. mmp file syntax targettype in makefile) + * List of target types which will not be hooked: +*/ +const string UNSUPPORTED_TARGET_TYPES[] = { + "CTL", + "ECOMIIC", + "IMPLIB", + "KDLL", + "KEXT", + "KLIB", + "LDD", + /* "LIB", currently have own vector in project.*/ + "MDA", + "MDL", + "NONE", + "NOTIFIER", + "PDD", + "RDL", + "STDLIB", + "VAR" +}; + +/** +* Kernel side target types +*/ +const string KERNEL_SIDE_TARGET_TYPES[] = { + "VAR", + "LDD", + "PDD", + "KEXT" +}; + +// Kernel mode compile definition +const string KERNEL_MODE_COMPILE_DEFINITION = "__KERNEL_MODE__"; + +/** +* MMP file changes for AT +* Note "SOURCE 0a1b2c3d_atool_temp_TARGET.cpp" is added also. +*/ +const string MMPFILECHANGES[] = { + "//*** AnalyzeTool changes start ***", + "SOURCEPATH atool_temp", + "LIBRARY AToolMemoryHook.lib", + "STATICLIBRARY AToolStaticLib.lib", + "OPTION ARMCC --interleave", + "//*** AnalyzeTool changes end ***" +}; + +//MMP file changes for AT +//For targettype Dll +const string MMPFILECHANGES_DLL[] = { + "//*** AnalyzeTool changes start ***", + "OPTION ARMCC --interleave", + "//*** AnalyzeTool changes end ***" +}; + +// Trace file constants definitions +#define LABEL_DATA_FILE_VERSION "DATA_FILE_VERSION" +#define LABEL_PROCESS_START "PROCESS_START" +#define LABEL_DLL_LOAD "DLL_LOAD" +#define LABEL_DLL_UNLOAD "DLL_UNLOAD" +#define LABEL_MEM_LEAK "MEM_LEAK" +#define LABEL_PROCESS_END "PROCESS_END" +#define LABEL_ERROR_OCCURED "ERROR_OCCURED" +#define LABEL_HANDLE_LEAK "HANDLE_LEAK" +#define LABEL_TEST_START "TEST_START" +#define LABEL_TEST_END "TEST_END" +#define LABEL_LOGGING_CANCELLED "LOGGING_CANCELLED" + +// AddressToLine related constants + +#define LABEL_ABNORMAL "ABNORMAL" +const int FUNCTIONS_OFFSET_IN_MAP_FILE_ARMV5 = 0x8000; +const int FUNCTIONS_OFFSET_IN_GCCE = 0x8000; +const int FUNCTIONS_OFFSET_IN_MAP_FILE_WINSCW = 0x400000; +#define TEXT_NO_HANDLE_LEAKS "No handle leaks." + +// Make file constant labels +#define MAKEFILE_TARGETTYPE_STRING "# TargetType " +#define MAKEFILE_BASIC_TARGETTYPE_STRING "# BasicTargetType " +#define MAKEFILE_TARGET_STRING "# Target " +#define MAKEFILE_FEATURE_VARIANT_NAME "# FeatureVariantName " +#define MAKEFILE_FEATURE_VARIANT_UREL_LABEL "# FeatureVariantURELLabel " +#define MAKEFILE_FEATURE_VARIANT_UDEB_LABEL "# FeatureVariantUDEBLabel " +#define UDEB_OPTIMIZATION_LEVEL 0 + +// Listing file contant labels +#define LST_FILE_SOURCE_FILE_LABEL "Source file:" + +/** +* Struct for saving module info from .dat file and number of leaks in module. +*/ +struct DLL_LOAD_INFO +{ + string sModuleName; /** name of the code segment/binary */ + unsigned long iStartAddress; /** start address of code segment (in memory) */ + unsigned long iEndAddress; /** end address of code segment (in memory) */ + int iLeaks; /** leak count in this code segment */ + unsigned long iPID; /** process id which loaded this code segment */ + int iSubTestStartOpenHandles; /** open handle count when sub test started */ + int iSubTestEndOpenHandles; /** open handle count when sub test ended */ + // Load/Unload times, note these are micro seconds from 1970 so size is huge. + unsigned long long iLoadTime; /** code segment load time */ + unsigned long long iUnloadTime; /** code segment unload time */ + /** + * Default constructor to set default values + */ + DLL_LOAD_INFO() { + iStartAddress = 0; + iEndAddress = 0; + iLeaks = 0; + iPID = 0; + iSubTestStartOpenHandles = 0; + iSubTestEndOpenHandles = 0; + iLoadTime = 0; + iUnloadTime = 0; + }; +}; + +/** +* Struct for saving symbol information from listing file +*/ +struct LINE_IN_FILE +{ + int iLine; /** line number */ + string sFileName; /** filename */ + string sFunction; /** function / symbol */ + string sMangledName; /** function / symbol name in mangled / coded form */ + string sLstName; /** listing filename */ +}; + +/** +* Struct for saving symbol information from map file +*/ +struct MAP_FUNC_INFO +{ + int iAddress; /** memory address (start of symbol) */ + int iFuncLength; /** symbol length */ + string sMangledName;/** symbol name in mangled / coded form */ + string sWholeLine; /** whole symbol line from map file */ + string sFunctionName; /** symbol clear name */ +}; + +/** +* State that represents the outcome +* of locating memory address code line from module +*/ +enum ADDRESS_TO_LINE_STATE { + no_map_data = 0, /** Map data was missing */ + out_of_function_range, /** Could not locate it to any function */ + mangled_symbol_name, /** symbol name but mangled / coded form */ + only_function_name, /** Only got function name not code line */ + succesfull /** Have line number, function, etc...*/ +}; + +/** +* Struct to store detail data and state when +* locating memory addresses code lines +*/ +struct ADDRESS_TO_LINE_ITEM { + ADDRESS_TO_LINE_STATE eState; /** outcome */ + string sFileName; /** Filename of address */ + string sFunctionName; /** Function name of address */ + string sMangledFunctionName; /** function/Symbol name */ + int iFunctionLineNumber; /** Functions line number */ + int iExactLineNumber; /** Exact line number of address */ +}; + +/** +* Struct to store memory leaks +* call stack entry data +*/ +struct CALL_STACK_ITEM { + string sAddress; /** Address in string */ + int iAddress; /** Address in number (converted)*/ + int iLocation; /** Location. i.e. corresponds m_vDllLoadModList's index*/ + int iCalculatedLeakAddress; /** calculated address from code segment start */ + bool bBuildUdeb; /** Optimization level */ + string sModuleName; /** Modules name were leak is*/ + ADDRESS_TO_LINE_ITEM addressToLine; /** Data from locating code line for memory address */ +}; + +/** +* Enumerations used in argument structure. +*/ +enum MAIN_SWITCH +{ + SWITCH_UNKNOWN = 0, /** not defined */ + SWITCH_ANALYZE = 1, /** analyze */ + SWITCH_HOOK = 2, /** compile/instrument */ + SWITCH_UNHOOK = 3, /** uninstrument */ + SWITCH_PARSE_TRACE = 5, /** parse raw data */ + SWITCH_CLEAN = 6, /** clean AT changes */ + SWITCH_VERSION = 9, /** display version infromation */ + SWITCH_HELP = 10, /** show help with syntax examples */ + SWITCH_DBGHELP_VERSION = 11 +}; + +/** +* Enumeration used when hooking project. +*/ +enum HOOK_SWITCH +{ + HOOK_UNKNOWN = 0, /** not defined */ + HOOK_INTERNAL, /** monitored internal data gathering */ + HOOK_EXTERNAL, /** monitored external data gathering */ + HOOK_EXTERNAL_FAST, /** external data gathering */ + HOOK_EXTENSION_INTERNAL, /** Extension call, monitored internal data gathering */ + HOOK_EXTENSION_EXTERNAL, /** Extension call, monitored external data gathering */ + HOOK_EXTENSION_EXTERNAL_FAST, /** Extension call, external data gathering */ + HOOK_EXTENSION_UNINSTRUMENT, /** Extension call, uninstrument (post-build)*/ + HOOK_EXTENSION_FAILED, /** Extension call, build failed, cleanup */ + HOOK_OLD_EXTENSION_INSTRUMENT, /** Old extension call, instrument project */ + HOOK_OLD_EXTENSION_UNINSTRUMENT, /** Old extension call, uninstrument project */ + HOOK_OLD_EXTENSION_FAILED /** Old extension call, cleanup */ +}; + +/** +* Represents hooking parameters, these are set +* by the user arguments from command line. +*/ +struct ARGUMENTS_HOOK +{ + bool bNoBuild; /** Only intrument project? (no build) */ + bool bDataFileName; /** Is internal data gathering filename defined */ + bool bAbldTest; /** Is build only for test modules (abld test build.. */ + string sDataFileName; /** Internal data gathering filename */ + int iBuildSystem; /** 1 = sbs, 2 = raptor */ + int iLoggingMode; /** Just for old parameter parsing. 1=trace, 2=file, 0=? */ + int iAllocCallStackSize; /** Call stack size when memory allocated */ + int iFreeCallStackSize; /** Call stack size when memory freed */ + string sBuildCmd; /** Original build command / user defined or given */ + vector<string> vBuildCmd; /** Build command split in vector */ + string sPlatform; /** Build platform */ + string sBuildType; /** Build type (udeb/urel) */ + string sFeatureVariant; /** Build variant defined */ + vector<string> vTargetPrograms; /** User defined single or multiple modules from project? */ + /** + * Default constructor to set default values. + */ + ARGUMENTS_HOOK() + { + bNoBuild = false; + bAbldTest = false; + bDataFileName = false; + sDataFileName = ""; + iBuildSystem = 0; + iLoggingMode = 0; + iAllocCallStackSize = AT_ALLOC_CALL_STACK_SIZE_DEFAULT; + iFreeCallStackSize = AT_FREE_CALL_STACK_SIZE_DEFAULT; + sBuildCmd = ""; + sPlatform = ""; + sBuildType = ""; + sFeatureVariant = ""; + vTargetPrograms.clear(); + }; +}; + +/** +* Represents analyze parameters, these are set +* by the user arguments from command line. +*/ +struct ARGUMENTS_ANALYZE +{ + string sDataFile; /** Data file to be analyzed */ + string sOutputFile; /** Output file */ + bool bSymbolFile; /** Is rom/rofs symbol file(s) defined? */ + vector<string> vSymbolFiles; /** Collection of symbol files */ + int iLoggingLevel; /** Logging level of report */ + /** + * Default constructor to set default values. + */ + ARGUMENTS_ANALYZE() + { + sDataFile = ""; + sOutputFile = ""; + bSymbolFile = false; + iLoggingLevel = 3; + }; +}; + +/** +* Represents raw trace parsing parameters, these are set +* by the user arguments from command line. +*/ +struct ARGUMENTS_PARSE +{ + bool bDataFile; /** Is raw data file defined */ + string sDataFile; /** Raw data file (input) */ + bool bOutputFile; /** Is output file defined */ + string sOutputFile; /** Output (AT specific data file)*/ + /** + * Default constructor to set default values. + */ + ARGUMENTS_PARSE() + { + bDataFile = false; + sDataFile = ""; + bOutputFile = false; + sOutputFile = ""; + }; +}; + + +/** +* Represents main parameters, these are set +* by the user arguments from command line. +*/ +struct ARGUMENTS +{ + // Base arguments. + MAIN_SWITCH eMainSwitch; /** mandatory/main parameter */ + HOOK_SWITCH eHookSwitch; /** if compile/instrument its "mode" */ + bool bHelp; /** show help? */ + bool bDebugConsole; /** enable debug logging to console? */ + bool bDebugDbgView; /** enable debug logging to win api? */ + bool bDebugLowLevel; /** enable debug logging for also low level functions? */ + bool bEnableSbs2; /** use raptor as build system? */ + ARGUMENTS_HOOK HOOK; /** hooking/instrument/compiling attributes */ + ARGUMENTS_ANALYZE ANALYZE; /** analyze related attributes */ + ARGUMENTS_PARSE PARSE; /** parsing related attributes */ + /** + * Default constructor to set default values. + */ + ARGUMENTS() + { + eMainSwitch = SWITCH_UNKNOWN; + eHookSwitch = HOOK_UNKNOWN; + bHelp = false; + bDebugConsole = false; + bDebugDbgView = false; + bEnableSbs2 = false; + }; +}; + +// DEBUG MACROS +// constant string for all beginning of all debug messages +const char START_LOG_MESSAGE[] = "*** CLE "; +// Log normal function entry (AAA = class::function ) +#define LOG_FUNC_ENTRY( AAA ) { if( g_bDebugDbgView) { stringstream strs; strs << START_LOG_MESSAGE << "ENTRY: " << AAA << endl; OutputDebugString( strs.str().c_str() ); } else if ( g_bDebugConsole ) { stringstream strs; strs << START_LOG_MESSAGE << "ENTRY: " << AAA << endl; cout << strs.str(); } } +// Log normal function exit +#define LOG_FUNC_EXIT( AAA ){ if( g_bDebugDbgView) { stringstream strs; strs << START_LOG_MESSAGE << "EXIT: " << AAA << endl; OutputDebugString( strs.str().c_str() ); } else if ( g_bDebugConsole ) { stringstream strs; strs << START_LOG_MESSAGE << "EXIT: " << AAA << endl; cout << strs.str(); } } +// Log low level function entry +#define LOG_LOW_FUNC_ENTRY( AAA ) { if ( g_bDebugLowLevel ) { if( g_bDebugDbgView) { stringstream strs; strs << START_LOG_MESSAGE << AAA << endl; OutputDebugString( strs.str().c_str() ); } else if ( g_bDebugConsole ) { stringstream strs; strs << START_LOG_MESSAGE << AAA << endl; cout << strs.str(); } } } +// Log low level function exit +#define LOG_LOW_FUNC_EXIT( AAA ) { if ( g_bDebugLowLevel ) { if( g_bDebugDbgView) { stringstream strs; strs << START_LOG_MESSAGE << AAA << endl; OutputDebugString( strs.str().c_str() ); } else if ( g_bDebugConsole ) { stringstream strs; strs << START_LOG_MESSAGE << AAA << endl; cout << strs.str(); } } } +// Log stringstream (string, int, etc..) i.e. string1 << int1 << "log this" +#define LOG_STRING( AAA ) { if( g_bDebugDbgView) { stringstream strs; strs << START_LOG_MESSAGE << AAA << endl; OutputDebugString( strs.str().c_str() ); } else if ( g_bDebugConsole ) { stringstream strs; strs << START_LOG_MESSAGE << AAA << endl; cout << strs.str(); } } + +#endif \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/CATBase.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/CATBase.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,418 @@ +/* +* 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: Defines CATBase "utility" class. +* +*/ + +#ifndef __CATBASE_H__ +#define __CATBASE_H__ + +#include "../inc/ATCommonDefines.h" + +/** +* This class implements lot of utility type of functions used all around atool project. +* All functions are static so they can be used without inheritance of this class. But still +* this is a base class of almost all others. +*/ +class CATBase +{ +public: + + /** + * Constructor + */ + CATBase(); + + /** + * Destructor + */ + virtual ~CATBase(void); + +public: + + /** + * FilterExtraSpaces + * Filters/replaces multiple continuous spaces with single. Won't leave + * spaces in start or end of string. + * @param sString to filter. + * @return void. + */ + static void FilterExtraSpaces( string& sString ); + + /** + * Convert hex value in string to signed decimal. + * @param sHex + * @param iDec + * @return true if successful + */ + static bool hexToDec( string& sHex, int& iDec ); + + /** + * Convert hex value in string to unsigned decimal + * @param sHex + * @param iDec + * @return true if successful + */ + static bool hexToDec( string& sHex, unsigned int& iDec ); + + /** + * Convert hex value in string to unsigned long. + * @param sHex + * @param ulDec + * @return true if successful + */ + static bool hexToDec( string& sHex, unsigned long& ulDec ); + + /** + * Convert hex value in string to unsigned long long. + * @param sHex + * @param ullDec + * @return true if successful + */ + static bool hexToDec( string& sHex, unsigned long long& ullDec ); + + /** + * Convert hex value to integer + * @param value + * @return unsigned long + */ + static unsigned long _httoi(const TCHAR *value); + + /** + * Convert integer to hex string. + * @param i + * @return hex string + */ + static string NumberToHexString( unsigned int i ); + + /** + * Convert long to hex string. + * @param i + * @return hex string + */ + static string NumberToHexString( unsigned long i ); + + /** + * Helper function checks is given character hex. + * @param value value to check. + * @return true if value is hex char. + */ + static bool IsHexCharacter(const TCHAR *value); + + /** + * Parse string to vector of strings using + * separator. (Tokenizer with delimeter). + * @param sInput string to split + * @char separator + * return vector<string> + */ + static vector<string> ParseStringToVector( const string& sInput, char separator ); + + /** + * Remove spaces and tabulatures from beginning and + * end of given string. + * @param sInput String to trim. + */ + static void TrimString( string& sInput ); + + /** + * Searches files with given extension from path. + * @param pPathAndExt path with extension + * @return string filename + */ + static string GetFileNameUsingExt( const char* pPathAndExt ); + + /** + * Changes all BackSlash characters to Slash character from string. + * @param sInput String including backslashes. + * @return String without backslashes. + */ + static string ChangeSlashToBackSlash( string sInput ); + + /** + * Changes given string to uppercase + * @param sInput + */ + static void ChangeToUpper( string& sInput ); + + /** + * Converts any uppercase letter to lowercase. + * + * @param sInput Reference to string. + */ + static void ChangeToLower( string& sInput ); + + /** + * Filter string out of unwanted characters. The list of allowed + * characters is defined in CFILTERSTRING. + * @param sString string to filter. + * @return filtered string. + */ + static string FilterString( const string& sString ); + + /** + * Removes path and extension from given filename string + * @param sFileName + * @param bReverseFindExt if true extension will be looked starting from end + * @return string + */ + static string RemovePathAndExt( string sFileName, bool bReverseFindExt = false ); + + /** + * Check if given file exists. + * @param pFilename Pointer to file name. + * @return False If file does not exists. + */ + static bool FileExists( const char* pFilename ); + + /** + * Check if given file is flagged read only. + * @param pFileName pointer to file name + * @return true if read only flag set. + */ + static bool IsFileReadOnly( const char* pFileName ); + + /** + * Set file read only. + * @param pFileName Pointer to file name + * @return true if successful. + */ + static bool SetFileReadOnly( const char* pFileName ); + + /** + * Set file writable (remove read only flag). + * + * @param pFilename Pointer to file name. + * @return true if successful. + */ + static bool SetFileWritable( const char* pFileName ); + + /** + * Copy file to given path + * @param sFile + * @param sToPath + * @return true if successful + */ + static bool FileCopyToPath(const string& sFile, const string& sToPath); + + /** + * Move file to given path + * @param sFile File to be moved + * @param sToPath path where to move file + * @return true if successful + */ + static bool FileMoveToPath(const string& sFile, const string& sToPath); + + /** + * Delete file + * Note! if file does not exists no error message is displayed + * but function returns false + * @param sFile File to be deleted + * @param bPrint display messages or not, default true + * @return true if successful + */ + static bool FileDelete(const string& sFile, bool bPrint = true ); + + /** + * Delete dir + * Note! if dir does not exists no error message is displayed + * but function returns false. + * This function wont delete directory if string does not contain + * AT_TEMP... + * @param sDir Directory to be deleted + * @param bPrint display message or not, default true + * @return true if successful + */ + static bool DirDelete(const string& sDir, bool bPrint = true ); + + /** + * Create dir + * Note! if dir cannot be created no error message is displayed + * but function returns false. + * @param sDir Directory to be deleted + * @param pPrint display message or not, default true + * @return true if successful + */ + static bool DirCreate(const string& sDir, bool pPrint = true ); + + /** + * Create temp path string for given + * mmpfile (full path+mmpname) + * @param sMmpFileWithPath + * @return string containing full path to + * AnalyzeTool temporary directory + */ + static string CreateTempPath(const string& sMmpFileWithPath); + + /** + * Search files with extensions from given path. + * @param pPathAndExt path with extension definition + * @param bPrintErrors do print errors? + * @param sErrorLog errors + * @return true if found. + */ + static bool SearchFileWithExtension( const char* pPathAndExt, bool bPrintErrors, string& sErrorLog ); + + /** + * Helper function to parse filename or path from given string + * @param bFileName if true returns filename otherwise the path + * @param sInput string where to get path or filename + * @return string filename or path + */ + static string GetPathOrFileName( bool bFileName, string sInput ); + + /** + * Function returns string from begin of given string until next space, + * characters until next space are removed from sInput string. + * + * @param sInput Line where data is separated with spaces. + * @param bEraseFromInput If true characters before space will be removed. + * @return string String until next space. + */ + static string GetStringUntilNextSpace( string& sInput, bool bEraseFromInput = true ); + + /** + * Convert unix path to windows + * @param sPath + */ + static void ConvertUnixPathToWin( string& sPath ); + + /** + * Create Temporary AT Cpp file + * @param sId unique id to add in file name + * @param sPath where to create + * @param sS60FileName of the logging file + * @param iLogOption logging mode + * @param iIsDebug build type + * @param iAllocCallStackSize + * @param iFreeCallStackSize + * @return true if successful + */ + static bool CreateTemporaryCpp( const string& sId + ,const string& sPath + ,const string& sS60FileName + ,int iLogOption + ,int iIsDebug + ,int iAllocCallStackSize + ,int iFreeCallStackSize ); + /** + * Acquire a list of files in given directory + * @param sDirectory can end to \ or x but not to * + * @param bListDirs if true directories will be listed as well, default false + * @param bAddPathToFile if true given sDirectory path is added to file string, default false + * @return vector<string> list of files in folder + */ + static vector<string> DirList(const string& sDirectory, bool bListDirs = false, bool bAddPathToFile = false); + + /** + * Get extension from given "file" string + * returns string after last . if any otherwise returns same + * what was given + * @param sString + * @return string string after last '.' if no '.' returns given string + */ + static string GetExtension(const string& sString); + + /** + * Convert TCHAR pointer to string + * @param charArray to convert + * @return string + */ + static string ConvertTCHARtoString(TCHAR* charArray); + + /** + * if given string contains two dots '.' this will remove + * all characters after first '.' + */ + static void RemoveAllAfterDotIfTwoDots(string& sString); + + /** + * checks given file is it data file + * @param sFile + * @return true if it is datafile + */ + static bool IsDataFile( string sFile ); + + /** + * Parses a path string containing ".." to a valid + * path without relations. If given string does + * not contain relations it will not be changed + * @param sPathString + * @return void + */ + static void ParseRelativePathString(string& sPathString); + + /** + * Remove relative path ".." from string + * @param sString string to remove from + * @param iDots index of ".." + * @return void + */ + static void RemoveRelativePath(string& sString, size_t iDots); + + /** + * Check if given directory exists. + * + * @param pDirname Pointer to directory name. + * @return False If directory does not exists. + */ + static bool DirectoryExists( const char* pDirname ); + + /** + * Checks from constant array is this targettype + * unsupported by AT + * @param sTargetType type to check + * @return true if it is supported by atool + */ + static bool IsTargetTypeSupported(string sTargetType); + + /** + * Checks from constant array is this targettype + * kernel side. + * @param sTargetType type to check + * @return true if it is kernel type + */ + static bool IsTargetTypeKernelSide(string sTargetType); + + /** + * Check is given variant defined in environment.(SBS v.1) + * @param sEpocroot + * @param sVariantName + * @return true if it is. + */ + static bool CheckVariant( const string& sEpocroot, const string& sVariantName ); + + /** + * Check has the environment defined "DEFAULT" variant + * @param sEpocRoot + * @return true if it is + */ + static bool IsDefaultVariant( const string& sEpocRoot ); + + /** + * Check is all character ascii + * @param pInput pointer to characters + * @param iLength length of the string + * @return true if all character are ascii + */ + static bool IsAscii( const char* pInput, const unsigned int iLength ); + + /** + * Get current environments epocroot. + * @param sEpocRoot value is stored in this if successful. + * @return true if successful. + */ + static bool GetEpocRoot( string& sEpocRoot ); +}; +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/CATDatParser.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/CATDatParser.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,283 @@ +/* +* 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: Defines CATDatParser class and its used enumerations. +* +*/ + + +#ifndef __CATDatParser_H__ +#define __CATDatParser_H__ + +// Includes. +#include "ATCommonDefines.h" +#include "CATBase.h" +#include "CATDataSaver.h" + +// Forward declarations. +class CATModule2; +class CATMemoryAddress; +class CATRomSymbol; + +/** +* Provides the analyze feature for AnalyzeTool specific data file. +* Is used by CATProject. Uses CATModule2 and/or CATRomSymbol to locate symbols or +* codelines of memory addressses. Uses CATDataSaver to create report. +*/ +class CATDatParser : public CATBase +{ + +public: + /** + * enumeration representing the "mode" depending on build system + */ + enum ANALYZE_MODE + { + SBS_1 = 0, + SBS_2 = 1 + }; + /** + * Representing current process state + */ + enum PROCESS_STATE + { + not_started = 0, + ongoing = 1, + stopped = 2 + }; + + /** + * Constructor. + */ + CATDatParser(); + +#ifndef MODULE_TEST +private: +#endif + /** + * Real constructor. + */ + void Construct(); + + /** + * Prevent copy + */ + CATDatParser& operator =( const CATDatParser& /*other*/ ) { } + CATDatParser( const CATDatParser& /*other*/ ) { } + +public: + /** + * Constructor for SBS2 + * @param pModules pointer to vector containing project modules + */ + CATDatParser( vector<CATModule2*>* pModules ); + + /** + * Destructor + */ + ~CATDatParser(); + + /** + * Set offset to be used with mapfiles + * @param iOffSet + */ + void SetOffSet( int iOffSet ); + + /** + * Get offset value + * @return int + */ + int GetOffSet( ) const; + + /** + * Analyze data file set + * This method includes try/catch in parsing + * @return int error codes specified in CATProject (0=OK) + */ + int Analyze(); + + /** + * Set log level + * @param iLogLevel + */ + void SetLogLevel(int iLogLevel); + /** + * Get Log level + * @return int + */ + int GetLogLevel() const ; + + /** + * Set data file to be analyzed + * @param sInputFile + */ + void SetInputFile(const string& sInputFile); + + /** + * Set output file + * @param sOutputFile + */ + void SetOutputFile(const string& sOutputFile); + + /** + * Set rom symbol file(s). + * @param sRomSymbolFile + */ + void SetRomSymbolFiles(const vector<string>& vRomSymbolFile); + + /** + * Set print flag + * @param pPringFlag + */ + void SetPringFlag( bool bPrintFlag ); + + /** + * Set addr2line.exe pinpoint state + * @param bInput + */ + void SetAddr2lineExeState( bool bInput ); + + /** + * Set project platform. + * @param sPlatform platform. + */ + void SetProjectPlatform( const string& sPlatform ); + + /** + * Set projects build type. Use enumeration defined in CATProject. + * @param eBuildType. + */ + void SetProjectBuildType( int eBuildType ); + +#ifndef MODULE_TEST +private: +#endif + + /** + * Start parsing datafile + * @return error codes defined in CATProject + */ + int Parse(); + + /** + * Helper functio to print header of report + */ + void Header(); + + /** + * Helper functio to print footer of report + */ + void Footer(); + + /** + * Helper function reseting/clearing all + * member variables related to parsing + */ + void ClearParsingVariables(); + + // Helpers for data file tags + bool ParseProcessStart( string& sLine ); + bool ParseDllLoad( string& sLine ); + bool ParseDllUnload( string& sLine ); + bool ParseMemLeak( string& sLine ); + bool ParseProcessEnd( string& sLine ); + bool ParseHandleLeak( string& sLine ); + bool ParseTestStart( string& sLine ); + bool ParseTestEnd( string& sLine ); + bool ParseLoggingCancelled( string& sLine ); + bool ParseErrorOccured( string& sLine ); + + void PrintMemLeak(const string& sTime, + const string& sLeakSize, + const string& sLeakAddr, + const string& sModuleName); + + // Utilities + string ConvertTimeToLocalTime( string sInputTime ); + + /** + * Create a winscw module into pModules vector. + * Used when we have dll load of module not in project to create them + * after this they are used in locating code lines. + * @param sBinaryName name of the binary with extension. + * @return true if successful. + */ + bool CreateWinscwModule( const string& sBinaryName ); + +#ifndef MODULE_TEST +private: +#endif + + void CleanMemoryAddresses(); + + // Members + unsigned int m_iDataVersion; // Version of data file. + int m_eProcess_state; // is process started, etc.. + bool m_bProcessStartFound; + bool m_bDllLoadFound; + int m_iLogLevel; // specified logging level + string m_sInputFile; // input file + vector<string> m_vRomSymbolFiles; // Rom symbol file. + string m_sOutputFile; // output file + string m_sInputFileTemp; // temporary input file (parsed from trace) + ifstream m_In; // Handle to input file + // Datasaver + CATDataSaver m_DataSaver; + + // Modules to be used in pinpointing + vector<CATModule2*>* m_pModules; + + // Rom symbol file. + CATRomSymbol* m_pRomSymbol; + + // Build type from dat. + int m_eBuildType; + // Build type from project. + int m_eProjectBuildType; + // Offset of map file. + int m_iOffSet; + // Platform of project. + string m_sProjectPlatform; + + // Process related + unsigned long m_iCurrentProcessId; + string m_sCurrentProcessName; + int m_iTotalRuns; + int m_iSuccesfullRuns; + + // Leak counting related + int m_iTotalNumberOfLeaks; + bool m_bSubtestOnGoing; + int m_iPinPointedLeaks; + int m_iPinPointedSubTestLeaks; + int m_iLeakNumber; + + // Handle count related + int m_iSubtestStartHandleCount; + vector<string> m_vHandleLeaks; + + // Module related + vector<DLL_LOAD_INFO> m_vDllLoadModList; + vector<DLL_LOAD_INFO> m_vDllLoadModListSubTest; + + // Sbs 1 support functions + int FindModuleUsingAddress( unsigned long iAddress ) const; + //int FindModuleUsingPID( unsigned long iPID ) const; + int FindModuleUsingName( const char* pModName ); + + // Memory addresses + vector<CATMemoryAddress*> m_vMemoryAddress; + +}; +#endif +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/CATDataSaver.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/CATDataSaver.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,214 @@ +/* +* 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: Defines CATDataSaver class and element type enumeration. +* +*/ + + +#ifndef __CATDATASAVER_H__ +#define __CATDATASAVER_H__ + +#include <xercesc/dom/DOM.hpp> +#include <xercesc/framework/LocalFileFormatTarget.hpp> +#include "ATCommonDefines.h" + +/** +* Represents element types +*/ +enum element_types +{ + RESULT = 0, + RUN, + LEAK, + CALLSTACK, + ITEM, + RUN_END, + ERROR_IN_RUN, + MEM_LEAKS, + MEM_LEAK_MODULE, + HANDLE_LEAKS, + HANDLE_LEAK_MODULE, + TEST_START, + TEST_END, + SUBTEST_MEM_LEAKS, + SUBTEST_MEM_LEAK_MODULE, + LOGGING_CANCELLED, + SUBTEST_HANDLE_LEAKS +}; + +//#define CARBIDE_DATA 0 +#define XML_DATA 1 +#define TEXT_DATA 2 + +/** +* TProvides features for creating the analyze report in +* basic text or XML formats. Uses xerces library for XML output. +*/ +class CATDataSaver +{ + +public: + + /** + * Constructor. + */ + CATDataSaver( void ); + + /** + * Destructor. + */ + ~CATDataSaver(void); + + /** + * Save all lines to file with given format. + * @param pFileName Pointer to file name. + * @param iDataToSave Format of data. + */ + void SaveLinesToFile( const char* pFileName, int iDataToSave ); + + /** + * Prints all saved lines to screen. + */ + void PrintLinesToScreen( void ); + + /** + * Adds saved line to first in database. + */ + void AddLineToFirst( void ); + + /** + * Adds saved line to last in database. + */ + void AddLineToLast(); + + /** + * Adds string to current line. + * @param pData string to add + * @param bSaveCarbideData add string to xml? + */ + void AddString( const char* pData, bool bSaveCarbideData = false ); + + /** + * Converts integer to string and adds it to current line. + * @param iValue integer value to add + * @param bSaveCarbideData add string to xml? + */ + void AddInteger( int iValue, bool bSaveCarbideData = false ); + + /** + * Sets logging level. + * If value is invalid DEFAULT_LOGGING_LEVEL is used + * value must be between MIN_LOGGING_LEVEL and MAX_LOGGING_LEVEL + * @param iLoggingLevel Logging level. + */ + void SetLoggingLevel( int iLoggingLevel ); + + /** + * Gets logging level. + * @return Logging level. + */ + int GetLoggingLevel( void ); + + /** + * Sets print immediately flag. + * @param bPrintImmediately + */ + void SetPrintFlag( bool bPrintImmediately ); + + /** + * Sets data header for carbide data. + */ + void SaveCarbideDataHeader( void ); + + /** + * Initializes xercer xml parser. + */ + bool InitXML( void ); + + /** + * Writes data to xml tree. + * @param sInput data + * @param iElementType element to write + */ + void SaveXML( string sInput, int iElementType ); + + /** + * Converts char* -> wchar_t*. + * @param str + * @return LPWSTR + */ + static LPWSTR CharToWChar( const char* str ); + + /** + * Converts wchar_t* -> char*. + * @param sInput + * @param Source + */ + static void WCharToChar( string& sInput, const WCHAR* Source ); + + /** + * Set is build type debug? + * @param bUdebBuild true if build type debug + */ + void SetBuild( bool bUdebBuild ); + + /** + * Add xml data for extension + * @param sInput data + */ + void AddCarbideData( const string& sInput ); + + /** + * Convert given integer to string + * @param iValueToConvert + * @return string + */ + static string IntegerToString( int iValueToConvert ); + +#ifndef MODULE_TEST +private: +#endif + vector<string> m_vLines; + string m_sLine; + string m_sCarbideDataLine; + + string m_sCarbideDataHeader; + + int m_iLoggingLevel; + int m_iRunNumber; + bool m_bPrintImmediately; + bool m_bXMLInitOk; + bool m_bUdebBuild; + + xercesc::DOMDocument* m_pDomDoc; + xercesc::DOMElement* m_pRootElem; + xercesc::DOMElement* m_pCurrentLeakElem; + xercesc::DOMWriter* m_Serializer; + xercesc::DOMElement* m_pRunElement; + xercesc::DOMElement* m_pMemoryLeaks; + xercesc::DOMElement* m_pHandleLeaks; + xercesc::DOMElement* m_pCurrentSubTestElem; + xercesc::DOMElement* m_pSubtestMemoryLeaks; + + /** + * Utility to get sub string from string using char as separator + * @param sInput + * @param cCharacter + * @return string + */ + string GetStringUntilNextGivenChar( string& sInput, char cCharacter ); + +}; + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/CATMemoryAddress.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/CATMemoryAddress.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,202 @@ +/* +* 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: Defines the CATMemoryAddress class. +* +*/ + + +#ifndef __CATMEMORYADDRESS_H__ +#define __CATMEMORYADDRESS_H__ + +#include "../inc/ATCommonDefines.h" + +/** +* Represents a single memory address / call stack item. +* State tells the "success" of locating the symbol / code line. +* Contains some utility functions used in this feature. +*/ +class CATMemoryAddress +{ +public: + /** + * Enumeration representing the state of locating code lines. + */ + enum ADDRESS_TO_LINE_STATE + { + OUT_OF_PROCESS = 0, /** Not located code line.*/ + OUT_OF_RANGE, /** Outside functions range. */ + SYMBOL, /** Symbol/ Function located (no codeline) */ + FUNCTION, /** Function and line number.*/ + EXACT /** Exact code line located with all information.*/ + }; + /** + * Constructor + * @param sAddress + * @param iOffSet value used if need to use offset value + */ + CATMemoryAddress( string& sAddress, unsigned long iOffSet ); + /** + * Destructor + */ + virtual ~CATMemoryAddress(); + /** + * Find which binary this address belongs to. + * Sets also the offsetfrommodulestart. + * @param vDlls container of binarys to find from. + * @return true if found + */ + bool FindSetModuleName(vector<DLL_LOAD_INFO>* vDlls); + /** + * Get vector index to which module we found this address to belong to. + * @return -1 if not set. + */ + int GetDllLoadInfoIndex(); + /** + * Note return value includes the set offset. + * So this value is not binary start - address. + * Instead it is. + * memory address - binary start address + offset + * @return adress + */ + unsigned long GetOffSetFromModuleStart(); + /** + * Get the binary start address + * @return binary start address + */ + unsigned long GetModuleStartAddress() const; + /** + * Set time + * @param ullTime + */ + void SetTime( unsigned long long& ullTime ); + /** + * Get time + * @return unsigned long long + */ + unsigned long long GetTime(); + /** + * Set address + * @param sAddess + */ + void SetAddress( string& sAddress ); + /** + * Get address string + * @return string + */ + string GetAddressString(); + /** + * Set address + * @param iAddress + */ + void SetAddress( unsigned long iAddress ); + /** + * Get Address + * @return unsigned long + */ + unsigned long GetAddress(); + /** + * Set module name + * @param sModuleName + */ + void SetModuleName( string& sModuleName ); + /** + * Get module name + * @return string + */ + string GetModuleName(); + /** + * Set state of locating code line + * @param eState + */ + void SetAddressToLineState( ADDRESS_TO_LINE_STATE eState ); + /** + * Get current state of locating code line + * @return int + */ + int GetAddressToLineState(); + /** + * Set filename + * @param sFileName + */ + void SetFileName(string& sFileName); + /** + * Get filename + * @return string + */ + string GetFileName(); + /** + * Set function name + * @param sFunctionName + */ + void SetFunctionName(string& sFunctionName); + /** + * Get function name + * @return string + */ + string GetFunctionName(); + /** + * Set function line number + * @param iFunctionLineNumber + */ + void SetFunctionLineNumber(int iFunctionLineNumber); + /** + * Get function line number + * @return int + */ + int GetFunctionLineNumber(); + /** + * Set exact line number + * @param iExactLineNumber + */ + void SetExactLineNumber(int iExactLineNumber); + /** + * Get exact line number + * @return int + */ + int GetExactLineNumber(); + /** + * Set module start address + * @param iAddress + */ + void SetModuleStartAddress(unsigned long iAddress); + +#ifndef MODULE_TEST +private: +#endif + // Used offset to add to addresses + unsigned long m_iOffSet; + // Address related members + string m_sAddress; + unsigned long m_iAddress; + + // Time (microseconds from 1970) + unsigned long long m_iTime; + + // Module related members(if FindSetModule is successful) + string m_sModuleName; + unsigned long m_iOffSetFromModuleStart; + unsigned long m_iModuleStartAddress; + + // Module to which address belong. + int m_iDllLoadinfoIndex; + + // Pin pointing related members + int m_ePinPointState; + string m_sFileName; + string m_sFunctionName; + + int m_iFunctionLineNumber; + int m_iExactLineNumber; +}; +#endif \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/CATMmp.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/CATMmp.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,106 @@ +/* +* 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: Class responsible of handling mmp files. +* +*/ + + +#ifndef __CATMMP_H__ +#define __CATMMP_H__ + +// Includes +#include "ATCommonDefines.h" +#include "CATBase.h" + +/** +* CATMmp represents mmp file of module. +* All mmp file related actions are done using this class. +* @author +*/ +class CATMmp : public CATBase +{ + +public: + + // Constructor + CATMmp(); + + // Destructor + ~CATMmp(); + + string m_sMmpFile; /** The mmp file with path */ + + /** + * Makes AnalyzeTool changes to given mmp file. + * @param sTargetType target type of module i.e. exe / dll + * @param sId unique identification string added to source file name + * @return true if editing was successful. + */ + bool EditMmpFile(const string& sTargetType, const string& sId); + + /** + * Backups mmp file to atool_temp/file + * to path/atool_temp/filename.mmp.tmp. + * Calling this function results always to + * none edited mmp & none edited backup. + * @return true if successful. + */ + bool BackupMmpFile(); + + /** + * Restores backup from temporary directory (replacing current). + * @return true if successful. + */ + bool RestoreMmpFile(); + + /** + * VerifyAndRecover mmp file. + * Wont change mmp if it is not edited + * Replaces mmp file using backup if it exists and it is + * not edited otherwise removes changes from mmp file. + * @return true if successful + */ + bool VerifyAndRecover(); + +#ifndef MODULE_TEST +private: +#endif + /** + * Checks if the given mmp file is modified by AT + * @param bBackup if true checks backup + * @return bool true if it is edited + */ + bool IsMmpEdited(bool bBackup = false ); + + /** + * CreateBackupPath creates string containinig + * full path to backup mmp file + */ + string CreateMmpBackupPath(); + + /** + * Removes AnalyzeTool changes from given file + * @param bBackup if true removes changes from backup + * @return true if successfully removed changes + */ + bool RemoveMmpFileChanges(bool bBackup = false); + + /** + * Removes write protections from mmp file and its backup if exists. + * @return true if successful. + */ + bool RemoveWriteProtections(); + +}; +#endif \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/CATModule2.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/CATModule2.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,545 @@ +/* +* 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: Class representing a module in project (sbs2). +* +*/ + + +#ifndef __CATMODULE2_H__ +#define __CATMODULE2_H__ + +// Includes. +#include "ATCommonDefines.h" +#include "CATBase.h" +#include "CATMmp.h" + +// Forward declarations. +class CATMemoryAddress; +class IAddressToLine; + +/** +* CATModule2 represents a module/component (single binary) in project. +* CATProject contains a collection of these. +*/ +class CATModule2 : public CATBase +{ + +public: + /** + * Constructor. + */ + CATModule2(void); + + /** + * Destructor. + */ + ~CATModule2(void); + + /** + * Read modules attributes from SBS v.1 makefile. + * Also copies makefile to temporary directory if successful. + */ + bool ReadMakeFile(); + + /** + * Read modules attributes from SBS v.1 makefile. + * From make file which is in modules temporary directory. + */ + bool ReadMakeFileFromTemp(); + + /** + * Add sources using line where source files separated by spaces. + * @param sSourceLine. + */ + void AddSources(string& sSourceLine); + + /** + * Add sources by giving source file and its corresponding listing file. + * @param sSourceFile + * @param sLstFile + */ + void AddSource(const string& sSourceFile, const string& sLstFile); + + /** + * Create AT temporary cpp file for module. + * @param sS60FileName. + * @param eLoggingMode. + * @param eBuildType. + * @param iAllocCallStackSize. + * @param iFreeCallStackSize. + * @return true if successful. + */ + bool CreateTempCpp(const string& sS60FileName + , int eLoggingMode + , int eBuildType + , int iAllocCallStackSize + , int iFreeCallStackSize ); + + /** + * Add AT changes to modules mmp file. + * @return true if successful. + */ + bool ModifyMmp(); + + /** + * Restore any changes made to modules mmp file. + * @return true if successful. + */ + bool RestoreMmp(); + + /** + * Verify tha mmp does not contain AnalyzeTool made changes. + * If it does contain them will remove them manually or using backup. + * @return true if successful. + */ + bool VerifyAndRecoverMmp(); + + /** + * Copy modules releasables to its temporary dir. + * This includes map & lst files. + * @return true if successful. + */ + bool CopyReleasables(); + + /** + * Copy modules listing files to given directory. + * After copy they will be deleted. + * @param sDir target directory. + * @return true if successful. + */ + bool CopyLstFilesToDir( const string& sDir ); + + /** + * Delete modules lst files from their source + * directories. + * @return true if succesfful. + */ + bool DeleteLstFilesFromSrc(); + + /** + * Clean modules temporary directory of files, + * not defined in UNDELETE list. + * @return true if successful + */ + bool CleanTemporaryDir(); + + /** + * Delete modules temporary directory. + * @return true if successful. + */ + bool DeleteTemporaryDir(); + + /** + * Locate codeline of given memory address. + * Given address must be calculated to correspond map file addresses. + * @param pMemoryAddress object where to store results. + * @return true if successful. + */ + bool AddressToLine(CATMemoryAddress* pMemoryAddress); + + /** + * Check does modules symbol file(s) exist. + * @return true if it exists. + */ + bool SymbolFileExist( void ); + + /** + * Check does modules map file(s) exists. + * @return true if it exists. + */ + bool MapFileExist( void ); + + /** + * Check does modules binary file(s) exist. + * @return true if it exists. + */ + bool BinaryFileExist( void ); + +#ifndef MODULE_TEST +private: +#endif + + /** + * Read modules attributes from make file. + */ + bool ReadMakeFilePrivate(); + + /** + * Locate codeline of given memory address (winscw platform). + * Given address must be calculated to correspond map file addresses. + * @param pMemoryAddress object where to store results. + * @return true if successful. + */ + bool AddressToLineWinscw(CATMemoryAddress* pMemoryAddress ); + + /** + * Locate codeline of given memory address (armv5 platform). + * Given address must be calculated to correspond map file addresses. + * @param pMemoryAddress object where to store results. + * @return true if successful. + */ + bool AddressToLineArmv5(CATMemoryAddress* pMemoryAddress ); + + /** + * Locate codeline of given memory address. + * Given address must be calculated to correspond map file addresses. + * @param pMemoryAddress object where to store results. + * @return true if successful. + */ + bool AddressToLineAddr2lineExe( CATMemoryAddress* pMemoryAddress ); + + /** + * Search map file data (symbols) using given address. + * @param iAddress memory address. + * @return index of the symbol or -1 if not found. + */ + int GetSymbolIndexUsingAddress(unsigned long iAddress) const; + + /** + * Search listing files data using the given symbol name. + * @param sSymbolName symbols name to find. + * @return index of the found lst data or -1 if not found. + */ + int GetLineInFileIndexUsingSymbolName(const string& sSymbolName) const; + + /** + * Search the exact code line from given file. + * @param sFileName listing file to search from. + * @param iLine functions line number. + * @param iFromFuncAddress how many bytes from functions start. + * @return line number or -1 if not found. + */ + int FindLeakCodeLine( string& sFileName, int iLine, unsigned long iFromFuncAddress ) const; + +public: + + /** + * Set used build system (CATProject::BUILD_SYSTEM). + * @param eBuildSystem. + */ + void SetBuildSystem( int eBuildSystem ); + + /** + * Get defined build system. + * @return int CATProject::BUILD_SYSTEM + */ + int GetBuildSystem( void ) const ; + + /** + * Set SBS v.1 makefile. + * @param sMakeFile + */ + void SetMakeFile( const string& sMakeFile ); + + /** + * Get SBS v.1 makefile. + * @return string makefile. + */ + string GetMakeFile( void ) const; + + /** + * Initialize module ready for locating code lines. + * with memory addresses (reads map and listing files). + * return true if successful. + */ + bool InitializeAddressToLine(); + + /** + * Set modules mmp file. + * This also creates temporary dir if it is missing. + * @return true if successful. + */ + bool SetMmpFile(const string& sMmpFile); + + /** + * Create modules own temporary directory. + * @return true if successful. + */ + bool CreateTemporaryDirectory(); + + /** + * Get modules mmp file. + * @return mmp file. + */ + string GetMmpFile() const; + + /** + * Get modules atool_temp directory path. + * @return atool_temp directory path. + */ + string GetTempPath() const; + + /** + * Get S60 logging file name. + * @return s60 logging file name. + */ + string GetS60FileName() const; + + /** + * Set target binary name. + * @param sTarget binary file name. + */ + void SetTarget(const string& sTarget); + + /** + * Get target binary name. + * @return modules binary file name. + */ + string GetTarget() const; + + /** + * Set binary target type. + * @param sTargetType binary target type. + */ + void SetTargetType(const string& sTargetType); + + /** + * Get binary target type. + * @return binary target type. + */ + string GetTargetType() const; + + /** + * Set requested binary target file extension. + * @param sRequestedTargetExt binary target file extension. + */ + void SetRequestedTargetExt( const string& sRequestedTargetExt ); + + /** + * Get requested binary target file extension. + * @return binary target file extension. + */ + string GetRequestedTargetExt() const; + + /** + * Get full name of modules binary. + * @return modules binary files full name. + */ + string GetBinaryName() const; + + /** + * Set variant platform. + * @param sVariantPlatform variant platform. + */ + void SetVariantPlatform(const string& sVariantPlatform); + + /** + * Get variant platform. + * @return variant platform. + */ + string GetVariantPlatform() const; + + /** + * Set variant type. + * @param sVariantType variant type. + */ + void SetVariantType(const string& sVariantType); + + /** + * Get variant type. + * @return variant type. + */ + string GetVariantType() const; + + /** + * Set feature variant. + * @param sFeatureVariant feature variant. + */ + void SetFeatureVariant(const string& sFeatureVariant); + + /** + * Get feature variant. + * @return feature variant. + */ + string GetFeatureVariant() const; + + /** + * Set feature variant name. + * @param sFeatureVariantName feature variant name. + */ + void SetFeatureVariantName(const string& sFeatureVariantName); + + /** + * Get feature variant name. + * @return feature variant name. + */ + string GetFeatureVariantName() const; + + /** + * Set release path. + * @param sReleasePath release path. + */ + void SetReleasePath(const string& sReleasePath); + + /** + * Get release path. + * @return release path. + */ + string GetReleasePath() const; + + /** + * Set full variant path. + * @param sFullVariantPath full variant path. + */ + void SetFullVariantPath(const string& sFullVariantPath); + + /** + * Get full variant path. + * @return full variant path. + */ + string GetFullVariantPath() const; + + /** + * Set compile definition(s) of the module. + * @param sCompileDefinitions + */ + void SetCompileDefinitions( const string& sCompileDefinitions ); + + /** + * Get compile definition(s) of the module. + * @return compile definition(s). + */ + string GetCompileDefinitions() const; + + /** + * Is modules target type udeb? + * @return true if modules target type is udeb. + */ + bool IsUDEB() const; + + /** + * Is module build successfully? + * This includes check of listing and map files from temporary directory. + * @return true if module build successfully. + */ + bool IsMakeSuccessfull(); + + /** + * Get error string. This includes possible erros what are generated when + * IsMakeSuccesfull is called. + * @return error string. + */ + string GetErrors() const; + + /** + * Create build complete file to modules temporary directory. + * @return true if build complete file created successfully. + */ + bool CreateBuildCompleteFile( void ); + + /** + * Read map file (armv5 platform). + * @return true if map file read successfully. + */ + bool ReadMapFileArmv5(); + + /** + * Set compile info text + * @param sCompileInfoText + */ + void SetCompileInfoText( string sCompileInfoText ); + + /** + * Get compile info text + * @return compile info text + */ + string GetCompileInfoText() const; + +#ifndef MODULE_TEST +private: +#endif + + /** + * Struct for saving source information + * sCpp is source file. + * sLst sources corresponding lst file. + * bStatic true if source information from static library. + */ + struct SOURCE + { + bool bStatic; + string sCpp; + string sLst; + SOURCE() : bStatic(false), sCpp(""), sLst("") {} + }; + + // Build system + int m_eBuildSystem; + // Sbs v.1 makefile + string m_sMakeFile; + // Mmp file. + CATMmp m_Mmp; + // Temporary directory with path. + string m_sTempPath; + // Target. + string m_sTarget; + // Target type. + string m_sTargetType; + // True target extension. + string m_sRequestedTargetExt; + // Variant platform. + string m_sVariantPlatform; + // Variant type. + string m_sVariantType; + // Feature variant. + string m_sFeatureVariant; + // Feature variant name. + string m_sFeatureVariantName; + // Release path (releasables). + string m_sReleasePath; + // Full variant path (path to releasables). + string m_sFullVariantPath; + // String to store information of compile + string m_sCompileInfoText; + // String to store possible error messages. + string m_sErrors; + // Compile definition(s) + string m_sCompileDefinitions; + // Source files. + vector<SOURCE> m_vSources; + // Listing data. + vector<LINE_IN_FILE> m_vLineInFile; + // Modules map data (symbols). + vector<MAP_FUNC_INFO> m_vMapFileFuncList; + // File logging mode filename. + string m_sS60FileName; + // Is all data loaded for address to code line functions. + bool m_bAddressToLineInitialized; + // Read listing files (armv5 platform). + bool ReadListingFilesArmv5(); + // Get listing file name of given source file. + string GetLstNameOfSource(string sSource) const; + // Copy listing files to temporary directory. + bool CopyLstFilesToTemp(); + // Copy map file to temporary directory. + bool CopyMapFileToTemp(); + // Get full map file name. + string GetMapFile() const; + // Get full symbol file name. + string GetSymbolFile() const; + // Get full binary file name. + string GetBinaryFile() const; + // Helper function to check is platform armv5. + bool IsPlatformArmv5() const; + // Get "unique" id of module + string GetUniqueId() const; + // Sbs v.1 variant urel label. + string m_sFeatureVariantURELLabel; + // Sbs v.1 variant udeb label. + string m_sFeatureVariantUDEBLabel; + // Object used to get codelines of memory addresses. + IAddressToLine* m_pAddressToLine; +}; +#endif +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/CATParseTraceFile.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/CATParseTraceFile.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,91 @@ +/* +* 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 class CATParseTrace, CProcessData and +* CSubTestData. +* +*/ + + +#ifndef __CATPARSETRACEFILE_H__ +#define __CATPARSETRACEFILE_H__ + +#include "../inc/ATCommonDefines.h" +#include "../inc/CATDataSaver.h" +#include "../inc/CATBase.h" +#include "../inc/catallocs.h" + +/** +* Parses raw trace data to AnalyzeTool specific data file. +*/ +class CATParseTraceFile : public CATBase +{ +public: + /** + * Constructor + */ + CATParseTraceFile(); + + /** + * Main function to start parse. + * + * @param pFileName A trace file name + * @param pOutputFileName Pointer to output file name + */ + bool StartParse( const char* pFileName, const char* pOutputFileName ); + + /** + * Get data saver + * @return CATDataSaver* + */ + CATDataSaver* GetDataSaver(void); + +#ifndef MODULE_TEST +private: +#endif + CATDataSaver m_DataSaver; /** Data saver */ +}; + +/** +* Represents data of a single subtest. +*/ +class CSubTestData : public CATAllocs +{ +public: + // Members + + bool bRunning; /** Is sub test running */ + vector<string> vData; /** data */ + string sSubTestName; /** test name */ + string sStartTime; /** start time */ + string sEndTime; /** end time */ + string sSubTestStartHandleCount; /** handle count at start */ + string sSubTestEndHandleCount; /** handle count at end */ +}; + +/** +* Represents data of a single run. +*/ +class CProcessData : public CATAllocs +{ +public: + // Members + + bool bProcessOnGoing; /** is process on going */ + int iProcessID; /** process id (pid)*/ + vector<string> vData; /** data */ + vector<string> vHandleLeaks; /** handle leak(s) */ + vector<CSubTestData> vSubTests; /** process sub test(s) */ +}; + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/CATParseXML.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/CATParseXML.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,46 @@ +/* +* 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: Declarations for the class CATParseXML. +* +*/ + + +#ifndef __CATPARSEXML_H__ +#define __CATPARSEXML_H__ + +#include "../inc/ATCommonDefines.h" + +/** +* CATParseXML is used to parse xml data. +*/ +class CATParseXML +{ +public: + /** + * Constructor + */ + CATParseXML(void); + + /** + * Destructor + */ + virtual ~CATParseXML(void); + + /** + * Find epocroot path in xml file + * @param sourcePath Location of the xml file + */ + string GetEpocRootPathFromXML(const char* sourcePath); +}; +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/CATProject.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/CATProject.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,629 @@ +/* +* 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: Class representing a project. +* +*/ + + +#ifndef __CATPROJECT_H__ +#define __CATPROJECT_H__ + +#include "ATCommonDefines.h" +#include "CATBase.h" + +class CATModule2; +class CATDatParser; + +// Raptor cmd and makefile constants used +#define RAPTOR_CMD_BASE "sbs -b bld.inf --makefile=atool_temp/build/make_build --config=" +#define RAPTOR_MAKEFILE "atool_temp\\build\\make_build.default" +#define RAPTOR_MAKEFILE_LOG " --logfile=atool_temp\\build\\makefile.xml" +#define RAPTOR_BUILD_LOG " --logfile=atool_temp\\build\\build.xml" +#define RAPTOR_REALLYCLEAN_LOG " --logfile=atool_temp\\build\\reallyclean.xml" +#define RAPTOR_BUILD_LOG_NAME "atool_temp\\build\\build.xml" +#define RAPTOR_LISTING_LOG " --logfile=atool_temp\\build\\listing.xml" + +#define RAPTOR_NOBUILD_SWITCH " --nobuild" +#define RAPTOR_MAKEFILE_SWITCH "--makefile=atool_temp/build/make_build" + + +// Raptor makefile constant variable names +#define RAPTOR_PROJECT_META "PROJECT_META:=" +#define RAPTOR_SOURCE "SOURCE:=" +#define RAPTOR_TARGET "TARGET:=" +#define RAPTOR_TARGETYPE "TARGETTYPE:=" +#define RAPTOR_REQUESTEDTARGETEXT "REQUESTEDTARGETEXT:=" +#define RAPTOR_VARIANTPLATFORM "VARIANTPLATFORM:=" +#define RAPTOR_VARIANTTYPE "VARIANTTYPE:=" +#define RAPTOR_FEATUREVARIANT "FEATUREVARIANT:=" +#define RAPTOR_FEATUREVARIANTNAME "FEATUREVARIANTNAME:=" +#define RAPTOR_RELEASEPATH "RELEASEPATH:=" +#define RAPTOR_FULLVARIANTPATH "FULLVARIANTPATH:=" +#define RAPTOR_COMPILE_DEFINITIONS "CDEFS:=" + +// Sbs v.1 makefile constants. +#define MAKEFILE_SEARCH_STRING "@perl -S checksource.pl" +#define MMPFILE_SEARCH_STRING "PRJ_MMPFILES MMP" +#define MMPTESTFILE_SEARCH_STRING "PRJ_TESTMMPFILES MMP" +#define SOURCE_PATH "SOURCEPATH" +#define SOURCE_STRING "SOURCE" +#define TARGET_STRING "TARGET" + +/** +* CATProject represents a project (collection of modules). +* It has to be set mode in which it operates like +* compile / analyze and necessary parameters for that. +* Then call Run method which also returs error codes +* defined in AT_ERROR_CODES enumeration. +* @author +*/ +class CATProject : public CATBase +{ +public: + + /** + * Enumeration representing used build systems + */ + enum BUILD_SYSTEM { + SBS_V1 = 1, + SBS_V2 = 2 + }; + + /** + * Enumeration representing the mode project is run. + */ + enum PROJECT_MODE { + COMPILE = 0, + INSTRUMENT = 1, + UNINSTRUMENT = 2, + UNINSTRUMENT_FAILED =3, + FAILED = 4, + CLEAN = 5, + ANALYZE = 6, + INSTRUMENT_CONSOLE = 7, + UNINSTRUMENT_CONSOLE = 8, + FAILED_CONSOLE = 9, + NOT_DEFINED = 10 + }; + + /** + * Enumeration repserenting the logging mode. + */ + enum LOGGING_MODE { + DEFAULT = 0, + FILE = 1, + TRACE = 2, + TRACE_FAST = 3 + }; + + /** + * Enumeration representing build type. + */ + enum BUILD_TYPE { + UREL = 0, + UDEB = 1 + }; + +public: + + /** + * Constructor + */ + CATProject(); + + /** + * Destructor + */ + ~CATProject(); + + /** + * Set arguments. + * @param arguments. + * @return true if arguments ok. + */ + bool SetArguments( ARGUMENTS& arguments ); + + /** + * Set build system to be used with project. + * See BUILD_SYSTEM enumeration for available systems. + * @param eSystem system. + */ + void SetBuildSystem( BUILD_SYSTEM eSystem ); + + /** + * Set mode which to run. + * See PROJECT_MODE enumeration for available modes. + * @param eMode mode. + */ + void SetMode(PROJECT_MODE eMode); + + /** + * Get project mode. + * @return mode of project. + */ + int GetMode() const; + + /** + * Set epocroot. + * @param sEpocroot + */ + void SetEpocRoot( const string& sEpocRoot ); + + /** + * Set project platform. + * @param sPlatform platform. + */ + void SetPlatform( const string& sPlatform ); + + /** + * Set variant. + * @sVariant variant. + */ + void SetVariant( const string& sVariant ); + + /** + * Set logging mode. See LOGGING_MODE enumeration for available modes. + * @param eLogginMode logging mode. + */ + void SetLoggingMode( LOGGING_MODE eLoggingMode); + + /** + * Set build type. See BUILD_TYPE enumeration for available types. + * @param eType build type. + */ + void SetBuildType( BUILD_TYPE eType ); + + /** + * Set S60 logging filename. + * @param sFileName filename. + */ + void SetS60FileName( const string& sFileName); + + /** + * Set target module. + * @param sTargetModule target module name. + */ + void SetTargetModule( const string& sTargetModule ); + + /** + * Set multiple target modules used in project. + * @param vTargetModules target module names. + */ + void SetTargetModules( const vector<string>& vTargetModules ); + + /** + * Set Binary target name to create analysis results to. + * @param sBinaryTarget binary target name. + */ + void SetBinaryTarget( const string& sBinaryTarget ); + + /** + * Set data file to analyze. + * @param sDataFile datafile. + */ + void SetDataFile( const string& sDataFile ); + + /** + * Set rom symbol file(s) used in analyze. + * @param sRomSymbolFile. + */ + void SetRomSymbolFiles(const vector<string>& vRomSymbolFiles); + + /** + * Set the logging level of analysis report. + * @param iLogLevel log level. + */ + void SetLogLevel( int iLogLevel ); + + /** + * Set the size of allocation call stack to be written in temporary cpp. + * @param iAllocCallStackSize + */ + void SetAllocCallStackSize( int iAllocCallStackSize ); + + /** + * Set the size of free call stack to be written in temporary cpp. + * @param iFreeCallStackSize + */ + void SetFreeCallStackSize( int iFreeCallStackSize ); + + /** + * Set the output file name to store analyse report. + * @param sDataFileOutput data file name. + */ + void SetDataFileOutput( const string& sDataFileOutput ); + + /** + * Set build command used in compile phase. + * @param sBuildCommand build command. + */ + void SetBuildCommand( const string& sBuildCommand ); + + /** + * Run the set mode. + * @return error code. + */ + int Run(); + + /** + * Run recovery, used when "instatly" need to recover modules and exit. + */ + int RunRecoveryAndExit(); + + /** + * Get build type string. + * @param eType type from which to get correponding string. + * @return types corresponding string. + */ + static string GetBuildTypeString( int eType ); + + /** + * Reads projects configuration file if it exists. + * @return false in case the data contains information that project is uninstrumented. Otherwise returns always true. + */ + bool IsUninstrumented(); + +#ifndef MODULE_TEST +private: +#endif + /** + * Run compiling in console. + * @return error code. + */ + int RunCompile( void ); + + /** + * Run cleaning project. + * @return error code. + */ + int RunClean( void ); + + /** + * Run running analyze. + * @return error code. + */ + int RunAnalyze( void ); + + /** + * Run instrumenting of project for Carbide extension (pre-build). + * @return error code. + */ + int RunInstrument( void ); + + /** + * Run uninstrumenting of project for Carbide extension (post-build). + * @return error code. + */ + int RunUninstrument( void ); + + /** + * Run uninstrumenting of project for Carbide extension(post-build), when build failed. + * @return error code. + */ + int RunUninstrumentFailed( void ); + + /** + * Run console instrumenting. + * @return error code. + */ + int RunInstrumentConsole( void ); + + /** + * Run Console uninstrumenting. + * @return error code. + */ + int RunUninstrumentConsole( void ); + + /** + * Run console uninstrumenting, when build failed. + * @return error code. + */ + int RunFailedConsole( void ); + + /** + * Show summary of compilation. + */ + void DisplayCompileSummary( void ); + + /** + * Show summary, build target, build type, logging mode... + */ + void DisplayBuildSummary( void ); + + /** + * Create make files. + * @return true if successful + */ + bool CreateMakeFile( void ); + /** + * Create SBS v.1 make files. + * @return true if successful. + */ + bool CreateMakeFileSbs1( void ); + /** + * Copy sbs1 makefile to temporary folder. + * @return true if successful. + */ + bool CopyMakeFileSbs1ToTemporaryFolder( void ); + /** + * Run really clean in SBS v.1. + * @return true if successful. + */ + bool RunReallyCleanSbs1( void ); + /** + * Run really clean in SBS v.2. + * @return true if successful. + */ + bool RunReallyCleanSbs2( void ); + /** + * Run export in SBS v.1. + * @return true if successful. + */ + bool RunExportSbs1( void ); + /** + * Create make files (level2) SBS v.1. + * @return true if successful. + */ + bool CreateMakeFileSbs1Level2( void ); + /** + * Create makefile SBS v.2. + * @return true if successful. + */ + bool CreateMakeFileSbs2( void ); + /** + * Read makefile. + * @return true if successful. + */ + bool ReadMakeFile( void ); + /** + * Read SBS v.1 makefile. + * @return true if successful. + */ + bool ReadMakeFileSbs1( void ); + /** + * Read SBS v.1 makefile (Level1). + * @return true if successful. + */ + bool ReadMakeFileSbs1Level1( void ); + /** + * Read SBS v.2 makefiles. + * @return true if successful. + */ + bool ReadMakeFileSbs2( void ); + /** + * Read specified SBS v.2 makefile. + * @param sMakeFile makefile to be read. + * @return true if succesful. + */ + bool ReadMakeFileSbs2( string& sMakeFile ); + + /** + * Filter unsupported and static libraries to their own vectors. + * Unsupported include kernel types, modules with kernel mode compile definition. + * @return true if successful. + */ + bool FilterModules(); + + /** + * Creates temporary directories for all modules + * in member vector. + * @return true if successful. + */ + bool CreateTemporaryDirectories(); + + /** + * Creates tempororary cpp files for all modules + * in member vector. + * @return true if successful. + */ + bool CreateTemporaryCpps(); + + /** + * Hooks all modules in member vector + * (modifies mmp files) + * @return true if successful + */ + bool ModifyModules( void ); + + /** + * Unhooks all modules in member vector + * (removes changes from mmp files) + * @return true if successful + */ + bool RestoreModules( void ); + + /** + * Verifys that member vectors modules + * mmp files unchanged. Restores if they are + * from backup or from original. + * @return true if successful + */ + bool VerifyAndRecoverModules( void ); + + /** + * Runs compilation. + * @return true if successful. + */ + bool Compile( void ); + /** + * @return true if successful. + */ + bool CompileSbs1( void ); + /** + * @return true if successful. + */ + bool CompileSbs2( void ); + + /** + * Runs listing creatation. + * @return true if successful + */ + bool CreateListings( void ); + /** + * @return true if successful. + */ + bool CreateListingsSbs1( void ); + /** + * @return true if successful. + */ + bool CreateListingsSbs2( void ); + /** + * Copies releasables of modules including lst & map files + * for all modules in project to their temporary directories. + * @return true if successful. + */ + bool CopyReleasables( void ); + /** + * Deletes all atool_temp directories + * of member vector modules. + * @return true if successful. + */ + bool DeleteTemporaryDirs( void ); + /** + * Deletes files from atool_temp directory + * of member vector modules which extension not defined + * in TEMP_EXTENSION_NO_DELETE table. + * @return true if successful. + */ + bool CleanTemporaryDirs( void ); + /** + * Writes class attributes to a file + * under atool_temp directory. + * @return true if successful. + */ + bool WriteAttributes( void ) const; + /** + * Read class attributes from a file + * under atool_temp directory. + * @return true if successful. + */ + bool ReadAttributes( void ); + + /** + * Creates atool_temp directory if it does not + * exist in current directory. + * @return true if successful. + */ + bool MakeTempDirIfNotExist( void ); + +#ifndef MODULE_TEST +private: +#endif + + /** + * Clean all module vectors. + */ + void CleanModuleVectors(); + + /** + * Get build type as string. + * @return buildtype string. + */ + string GetBuildTypeString(); + + /** + * Helper function to add target module(s) + * if any defined in class to given sbs command. + * @param sCmd command to add modules to. + */ + void AddTargetModuleIfDefined(string& sCmd); + + /** + * Run given system/abld command to all defined target modules in vector. + * Space char (if its missing) will be added to given command + one target + * module at a time. + * @param sCommand sCommand to run. + * @return true if none system call sets error level other than 0. + */ + bool RunAbldCommandToAllTargets( const string& sCommand ); + + /** + * Check is target module in project. + * If no modules / targets defined return value is true. + * @return true if target module is in project. + */ + bool IsTargetModuleInProject( void ) const; + + /** + * Initializes member make file variable with correct full path to point (epoc32/build)... + * @return true if successful. + */ + bool InitSbs1MakeFileWithPath(); + + /** + * Initializes member make file variable with correct full path to (atoo_temp...) + * @return true if successful. + */ + bool InitSbs1MakeFileWithPathToTemp(); + +#ifndef MODULE_TEST +private: +#endif + // System current directory. + char m_cCurrentDir[ MAX_LINE_LENGTH ]; + // Projects build system + int m_eBuildSystem; + // Project modules. + vector<CATModule2*> m_vModules; + // Static libraries. + vector<CATModule2*> m_vStaticLibraries; + // Unsupported project modules. + vector<CATModule2*> m_vUnsupportedModules; + // Run mode. + int m_eMode; + // Logging level (used in analyse). + int m_iLoggingLevel; + // Is project unsinstrumented. + bool m_bUninstrumented; + // Is build just for test modules + bool m_bAbldTest; + // Build command. + string m_sBuildCommand; + // Epocroot + string m_sEpocRoot; + // Platform i.e. armv5. + string m_sPlatform; + // SBS2 variant. + string m_sVariant; + // Logging mode (used in compile,instrumenting). + int m_eLoggingMode; + // Allocation call stack size + int m_iAllocCallStackSize; + // Free call stack size + int m_iFreeCallStackSize; + // Build type udeb / urel. + int m_eBuildType; + // Sbs v.1 level 1 make file + string m_sMakeFile; + // User given S60 log file name. + string m_sS60FileName; + // Target module. + string m_sTargetModule; + // Target modules (used in carbide instrumenting). + vector<string> m_vTargetModules; + // Binary target (used in analyse). + string m_sBinaryTarget; + // User given datafile to analyse. + string m_sDataFile; + // + vector<string> m_vRomSymbolFiles; + // Temporary data file name if user gave trace file. + string m_sDataFileTemp; + // User given output file to store analyse results. + string m_sDataFileOutput; + // Analyser object. + CATDatParser* m_pAnalyzer; +}; +#endif +// End of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/cataddr2line.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/cataddr2line.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,130 @@ +/* +* 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: Windows debug api implementation for IAddressToLine interface. +* +*/ + +#ifndef __CATADDR2LINE_H__ +#define __CATADDR2LINE_H__ + +#include "iaddresstoline.h" +#include "../inc/cataddr2lineserver.h" + +// Allowed characters in output. +//const char ADDR2LINEALLOWEDCHARS[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :/\\_.-"; + +/** +* Implements addresstoline interface using one of the GNU binutils tool called addr2line. +* This is used on gcce platform. In release build type also map files are used. +*/ +class CATAddr2line : public IAddressToLine +{ + +public: + + /** + * Constructor + */ + CATAddr2line(); + + /** + * Open binary. + * @sString Full filename with path to binary. + * @iLong base address of binary. + * @return true if successful. + */ + bool Open( const string& sString, const unsigned long iLong); + + /** + * Get error string. In case of any method failed use this to acquire details on error. + * @return error string. + */ + string GetError( void ); + + /** + * Close binary. + * @return true if succesful. + */ + bool Close( void ); + + /** + * Locate code line and file for given address. + * @result + * @return true if successful. + */ + bool AddressToLine( CATMemoryAddress* result ); + +#ifndef MODULE_TEST +private: +#endif + + // Modules map data (symbols). + vector<MAP_FUNC_INFO> m_vMapFileFuncList; + + //Map file name + string m_sMapFileName; + + //Addr2line server class + CATAddr2lineServer server; + + /** + * Get function name for given address. + * @iAddress Memory address as unsigned long. + * @return Function name as string or empty string if not found. + */ + string GetFunctionNameUsingAddress( unsigned long iAddress ); + + /** + * Read map file (armv5 platform). + * @return true if map file read successfully. + */ + bool ReadMapFileArmv5(); + + //Note: New filtering functions commented out until they are taken into use. + //These were part of task which would filter unwanted characters, etc.. from results. + + /** + * Filter any char not defined in constant + * ADDR2LINEALLOWEDCHARS from given string. + * @param sString string to be filtered. + */ + //void FilterString( string &sString ); + + /** + * Find first occurence of LF/CR from string. + * @param sString string to find LF/CR. + * @return position of first occurence. + */ + //size_t FindLineFeed( const string& sString ); + + /** + * Erase all LF/CR from start of the string until other + * characters are found. + * @param sString string to erase LF/CR. + */ + //void EraseUntilNoLineFeed( string& sString ); + + /** + * Split string containing multiple lines with mixed line feeds to + * vector of lines. + * @sMultiLineString string containing multiple lines. + * @return vector containing one line per cell. + */ + //vector<string> SplitToStrings( string& sMultiLineString ); + + //Debugging for addr2line task. + //ofstream debug; +}; + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/cataddr2lineserver.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/cataddr2lineserver.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,93 @@ +/* +* 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: Defines CATAddr2lineServer class. +* +*/ + +#ifndef __CATADDR2LINESERVER_H__ +#define __CATADDR2LINESERVER_H__ + +// Includes. +#include "ATCommonDefines.h" + +#define BUFSIZE 4096 + +/** +* This class "runs" the addr2line binary as a server for CATAddr2Line. +* It redirects the pipes from the tool. +*/ +class CATAddr2lineServer +{ +public: + + //Creator + CATAddr2lineServer(); + + //Destructor + ~CATAddr2lineServer(); + + /** + * Get function name for given address. + * @sFullPathAndBinaryName + * @return True if initialization succesfull. + */ + bool Initialize( const string& sFullPathAndBinaryName ); + + /** + * Write data to a pipe. + * @sAddress + */ + VOID WriteToPipe( const string& sAddress ); + + /** + * Read data to a pipe. + * @return Data from pipe. + */ + string ReadFromPipe(VOID); + + /** + * Gets process created state. + * @return True if process created successfully. + */ + bool GetProcessCreatedState( void ); + +#ifndef MODULE_TEST +private: +#endif + + HANDLE m_hChildStdinRd, m_hChildStdinWr, m_hChildStdinWrDup, + m_hChildStdoutRd, m_hChildStdoutWr, m_hChildStdoutRdDup, + m_hChildErroutRd, m_hChildErroutWr, m_hChildErroutRdDup, + m_hSaveStdin, m_hSaveStdout, m_hSaveErrout; + + SECURITY_ATTRIBUTES m_saAttr; + string m_sFullPathAndBinaryName; + bool m_bProcessCreated; + + /** + * Creates child process for addr2line.exe. + * @return True if process created successfully. + */ + BOOL CreateChildProcess(VOID); + + /** + * Prints error and returns false. + * @param sInput error string. + * @return false. + */ + bool PrintErrorAndExit( const string sInput ); + + +}; +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/catalloc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/catalloc.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,59 @@ +/* +* 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: Defines CATAlloc class. +* +*/ + + +#ifndef __CATALLOC_H__ +#define __CATALLOC_H__ + +#include "../inc/ATCommonDefines.h" + +/** +* Class representing single memory allocation. +*/ +class CATAlloc +{ +public: + /** + * Constructor. + */ + CATAlloc() : m_iCSCount(0) {} + + /** + * Destructor. + */ + ~CATAlloc(){} + + /** + * Get alloc string after address, it contains: + * time, size, call stack.. + * @return string allocation string + */ + string GetAllocString(); + + // Members + + string m_sTime; /** Allocation time */ + + string m_sSize; /** Allocation size */ + + unsigned long m_iCSCount; /** Call stack address count */ + + map<unsigned long,string> m_vCallStack; /** Call stack where packet number is key */ + +}; +#endif +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/catallocs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/catallocs.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,87 @@ +/* +* 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: Defines CATAllocs "collection" class. +*/ + +#ifndef __CATALLOCS_H__ +#define __CATALLOCS_H__ + +#include "../inc/ATCommonDefines.h" +#include "../inc/CATBase.h" +#include "../inc/catalloc.h" + +/** +* Class representing a collection of memory allocations. +* It is used to acquire the data of memory leaks by giving all +* data on single allocations and frees. +*/ +class CATAllocs : public CATBase +{ +public: + + /** + * "old" alloc message (prior to 1.6). + * @param sAllocString allocation string + */ + void Alloc( const string& sAllocString ); + + /* + * Alloc header message (multimessage call stack). + * @param sAllocHString allocation string + */ + void AllocH( const string& sAllocHString ); + + /* + * Alloc fragment message (fragment of call stack in multimessage alloc). + * @param sAllocFString allocation string + */ + void AllocF( const string& sAllocFString ); + + /** + * Free message. + * @param sFreeString string + */ + void Free( const string& sFreeString ); + + /** + * Free header message. + * (not implemented yeat.) + * @param sFreeHString string + */ + void FreeH( const string& sFreeHString ); + + /** + * Free fragment message. + * (not implemented yeat.) + * @param sFreeFString string + */ + void FreeF( const string& sFreeFString ); + + /** + * Get "leak" list ordered by allocation time. + * @param vLeakList container where leaks stored + */ + void GetLeakList( vector<string>& vLeakList); + + /** + * Clear leaks. + */ + void ClearAllocs(); +#ifndef MODULE_TEST +private: +#endif + map<string, CATAlloc> m_vAllocs; /** Collection of allocation(s) */ +}; +#endif +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/catdbghelper.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/catdbghelper.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,97 @@ +/* +* 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: Defines the CATDbgHelper class. +* +*/ + + +#include "iaddresstoline.h" +// Static variable to represent state of dbghelper api. +static bool CDBGHELPER_OPEN = false; +static unsigned int CDBGHELPER_CLIENTS = 0; + +// Used "virtual" offset for all loaded modules and addresses. +// This is used so no module is loaded to the binary address range of atool.exe. +const unsigned long AT_VIRTUAL_OFFSET_DBGHELPER = 0x1000000; + +/** +* Provides feature to locate code lines using Windows Debug Api. This is done +* by using dbghelper library. Implements the IAddressToLine interface. +*/ +class CATDbgHelper : public IAddressToLine +{ + +public: + + /** + * Constructor + */ + CATDbgHelper(); + + /** + * Destructor + */ + ~CATDbgHelper(); + + /** + * Open binary. + * @sString Full filename with path to binary. + * @iLong base address of binary. + * @return true if successful. + */ + bool Open( const string& sString, const unsigned long iLong); + + /** + * Get error string. In case of any method failed use this to acquire details on error. + * @return error string. + */ + string GetError( void ); + + /** + * Close binary. + * @return true if succesful. + */ + bool Close( void ); + + /** + * Read map file for function's. + */ + void ReadMapFile( const string sMapFileName ); + + /** + * Locate code line and file for given address. + * @result + * @return true if successful. + */ + bool AddressToLine( CATMemoryAddress* result ); + + /** + * Try get function name for address (only when map is read). + * @result + * @return true if succesful. + */ + bool AddressToFunction( CATMemoryAddress* result ); + +#ifndef MODULE_TEST +private: +#endif + // Base address used. + DWORD64 m_BaseAddress; + // Map file read? + bool m_bMap; + // Map file functions. + vector<MAP_FUNC_INFO> m_vMapFileFuncList; + // Binary in file system. + PSTR m_pBinaryFile; +}; \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/catfilereader.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/catfilereader.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,86 @@ +/* +* 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: Defines CATFileReader class. +* +*/ + + +#ifndef __CATFILEREADER_H__ +#define __CATFILEREADER_H__ + +#include "ATCommonDefines.h" + +/** +* Provides a feature to read a file as single block into memory and parse it +* from there line by line (iterating). This can fail or be very slow if file +* size is bigger than available physical memory for process. +* But is faster when file fits in free physical memory. +*/ +class CATFileReader +{ +public: + /** + * Constructor. + */ + CATFileReader(); + /** + * Destructor. + */ + ~CATFileReader(); +#ifndef MODULE_TEST +private: +#endif + /** + * Prevent copy of this class. + */ + CATFileReader& operator =( const CATFileReader& /*other*/ ) { } + CATFileReader( const CATFileReader& /*other*/ ) { } +public: + /** + * Open/Read file. + * @param cFile file to be read/opened. + * @return true if succesful. + */ + bool Open( const char* cFile ); + /** + * Close file. + * @return true if succesful. + */ + bool Close( void ); + /** + * Get line from file. + * @sLine where line content is stored. + * @return true if lines left. + */ + bool GetLine( string& sLine ); + /** + * Set the line delimiter. + * @param cDelimiter char that ends the line. + */ + void SetDelimiter( char cDelimiter ); + /** + * Get current line delimiter. + * @return char that ends the line. + */ + char GetDelimiter() const; +#ifndef MODULE_TEST +private: +#endif + // Stream where file content is stored. + stringstream m_stream; + // Line delimiting character used. + char m_cDelimiter; +}; +#endif +// EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/catromsymbol.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/catromsymbol.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,196 @@ +/* +* 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: Defines CATRomSymbol, RofsBinary classes and Symbol +* structure. +* +*/ + + +#ifndef __CATROMSYMBOL_H__ +#define __CATROMSYMBOL_H__ + +#include "ATCommonDefines.h" +#include "iaddresstoline.h" + +const string ROM_SYMBOL_IDENTIFY_STRING = "80"; +const string ROFS_SYMBOL_IDENTIFY_STRING = "00"; +const int IDENTIFY_MAX_LINES_READ = 20; + +/** +* Represents a single symbol in a binary. +*/ +struct Symbol +{ + unsigned long iStartAddress; /** Start address */ + unsigned long iEndAddress; /** End address */ + string sFunction; /** Function/Symbol name */ + /** + * Default constructor for structure to set default values + */ + Symbol() { iStartAddress=0; iEndAddress=0; sFunction = ""; } + /** + * Empty destructor + */ + ~Symbol() {} +}; + + +/** +* Represents a single binary in ROM/ROFS which +* contains a collection of Symbols. +*/ +class RofsBinary { +public: + /** + * Constructor + */ + RofsBinary(); + /** + * Constructor + * @param sbinary + */ + RofsBinary( const string& sbinary ); + /** + * Destructor + */ + ~RofsBinary(); + + // Members + + string m_sBinary; /** Binary / code segment */ + vector<Symbol*> vSymbols; /** Collection of symbols */ +}; + +/** +* Implements IAddressToLine interface to acquire symbol information +* using memory addresses from rom/rofs symbol files. +*/ +class CATRomSymbol : public IAddressToLine +{ +public: + /** + * Constructor. + */ + CATRomSymbol(); + /** + * Destructor. + */ + virtual ~CATRomSymbol(); + bool m_bShowProgressMessages; /** "Flag" will we show progress when reading files */ + /** + * Empty functions does nothing returns false always. + * @param sString + * @param iLong + * @return true if successful. + */ + bool Open( const string& sString, const unsigned long iLong); + /** + * Set symbol files. + * This also checks that files exists and identifies them as rom/rofs. + * @param vSymbols + * @return bool + */ + bool SetSymbols( const vector<string>& vSymbols); + /** + * Get error string. In case of any method failed use this to acquire details on error. + * @return error string. + */ + string GetError( void ); + /** + * Close rom symbol file. + * @return true if succesful. + */ + bool Close( void ); + /** + * Locates symbol and binary name for given address if found in rom. + * @param result memory address object. + * @return true if successful. + */ + bool AddressToLine( CATMemoryAddress* result ); +#ifndef MODULE_TEST +private: +#endif + /** + * Represents the symbol files type + * (content is different / format ) + */ + enum SYMBOL_FILE_TYPE { + SYMBOL_FILE_INVALID = 0, /** not valid */ + SYMBOL_FILE_ROM, /** rom type */ + SYMBOL_FILE_ROFS /** rofs type */ + }; + /** + * Identify symbol file + * @param sFile + * @return int + */ + int IdentifySymbolFile( const string& sFile ); + /** + * Locate symbol and binary name for given address if found in rom. + * @param result + * @return bool + */ + bool AddressToLineRom( CATMemoryAddress* result ); + /** + * Locate symbol and binary name for given address if found in rofs. + * @param result + * @return bool + */ + bool AddressToLineRofs( CATMemoryAddress* result ); + /** + * Reads rom files. + * @return bool + */ + bool ReadRomFiles(); + /** + * Read specified rom file + * @param sFile + * @return bool + */ + bool ReadRomFile( const string& sFile ); + /** + * Read rofs files + * @return bool + */ + bool ReadRofsFiles(); + /** + * Read specified rofs file + * @param sFile + * @return bool + */ + bool ReadRofsFile( const string& sFile ); + /** + * Parse symbol from a line in rom/rofs file. + * @param sLine + * @param pSymbol + */ + void ParseSymbolFromLine( const string& sLine, Symbol* pSymbol ); +#ifndef MODULE_TEST +private: +#endif + + // Members + + bool m_bFilesIdentified; /** Have we identified symbol file(s) */ + bool m_bSymbolsRead; /** Have we read symbol file(s) */ + vector<string> m_vRomFiles; /** Rom symbol file(s) */ + vector<Symbol*> m_vRomCache; /** Cached rom symbols */ + vector<Symbol*> m_vRomSymbols; /** All rom symbols */ + unsigned long m_iRomStartAddress; /** Rom start address */ + unsigned long m_iRomEndAddress; /** Rom end address */ + vector<string> m_vRofsFiles; /** Rofs symbol file(s) */ + vector<RofsBinary*> m_vRofsBinaries; /** Rofs binaries */ + string m_sErrorMessage; /** Error message */ +}; +#endif \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/iaddresstoline.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/iaddresstoline.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,60 @@ +/* +* 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: Interface definition for locating code lines using memory addresses. +* +*/ +#ifndef __IADDRESSTOLINE_H__ +#define __IADDRESSTOLINE_H__ + +#include "ATCommonDefines.h" + +class CATMemoryAddress; + +/** +* Codeline locating interface. Thru this interface CATModule2 locates code lines +* using different implementations depending on platform. +*/ +class IAddressToLine +{ +public: + IAddressToLine() {}; + virtual ~IAddressToLine() {}; + /** + * Open binary. + * @sString + * @iNumber + * @return true if successful. + */ + virtual bool Open( const string& sString, const unsigned long iLong) = 0; + + /** + * Get error string. In case of any method failed use this to acquire details on error. + * @return error string. + */ + virtual string GetError( void ) = 0; + + /** + * Close binary. + * @return true if succesful. + */ + virtual bool Close( void ) = 0; + + /** + * Locate code line and file for given address. + * @result + * @return true if successful. + */ + virtual bool AddressToLine( CATMemoryAddress* result ) = 0; +}; +#endif \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/inc/stdafx.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/inc/stdafx.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2008 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: Include file for standard system include files, +* or project specific include files that are used frequently, but +* are changed infrequently. +* Version : %version: 1 % +* +*/ + + +#pragma once + +// MemoryLeak checking function. +// Note! Do not comming in svn with this flag enabled. +//#define MEM_LEAK_CHECK + +// Addr2line binary used. +//#define ADDR2LINE + +#ifdef MEM_LEAK_CHECK +#define _CRTDBG_MAP_ALLOC +#include <stdlib.h> +#include <crtdbg.h> +#endif + +#include <tchar.h> +#include <fstream> //ifstream,ofstream +#include <windows.h> +#include <string> //string +#include <vector> //string +#include <sstream> //stringstream +#include <iostream> // cout +#include <map> // map +#include <time.h> \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/install/addr2line.exe Binary file analyzetool/commandlineengine/install/addr2line.exe has changed diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/install/atool.exe Binary file analyzetool/commandlineengine/install/atool.exe has changed diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/install/binutils-2.19.1-src.zip Binary file analyzetool/commandlineengine/install/binutils-2.19.1-src.zip has changed diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/install/xerces-c_2_7.dll Binary file analyzetool/commandlineengine/install/xerces-c_2_7.dll has changed diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/lib/xerces-c_2.lib Binary file analyzetool/commandlineengine/lib/xerces-c_2.lib has changed diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/CATBase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/CATBase.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,1299 @@ +/* +* 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 CATBase. +* +*/ + + +#include "../inc/CATBase.h" +#include "../inc/CATParseXML.h" + +// ----------------------------------------------------------------------------- +// CATBase::CATBase +// Constructor. +// ----------------------------------------------------------------------------- +CATBase::CATBase(void) +{ + LOG_FUNC_ENTRY("CATBase::CATBase"); +} + +// ----------------------------------------------------------------------------- +// CATBase::~CATBase +// Destructor. +// ----------------------------------------------------------------------------- +CATBase::~CATBase(void) +{ + LOG_FUNC_ENTRY("CATBase::~CATBase"); +} + +// ----------------------------------------------------------------------------- +// CATBase::ChangeToLower +// Converts any uppercase letter to lowercase. +// ----------------------------------------------------------------------------- +void CATBase::ChangeToLower( string& sInput ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::ChangeToLower"); + int iLength = (int)sInput.size(); + for( int i = 0 ; i < iLength ; i++ ) + { + sInput[i] = (char)tolower( sInput[i] ); + } +} + +// ----------------------------------------------------------------------------- +// CATBase::ChangeToUpper +// Converts any uppercase letter to lowercase. +// ----------------------------------------------------------------------------- +void CATBase::ChangeToUpper( string& sInput ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::ChangeToUpper"); + int iLength = (int)sInput.size(); + for( int i = 0 ; i < iLength ; i++ ) + { + sInput[i] = (char)toupper( sInput[i] ); + } +} + +// ----------------------------------------------------------------------------- +// CATBase::TrimString +// Remove spaces and tabulatures from beginning and +// end of given string. +// ----------------------------------------------------------------------------- +void CATBase::TrimString( string& sInput ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::TrimString"); + if( sInput.empty() ) + return; + //Remove spaces and tabulatures from beginning of string + while( !sInput.empty() && ( sInput[0] == SPACE_CHAR_VALUE || sInput[0] == TAB_CHAR_VALUE ) ) + { + sInput.erase( 0, 1 ); + } + //Remove spaces and tabulatures from end of string + while( !sInput.empty() && ( sInput[sInput.size()-1] == SPACE_CHAR_VALUE || sInput[sInput.size()-1] == TAB_CHAR_VALUE ) ) + { + sInput.erase( sInput.size()-1, 1 ); + } +} + +// ----------------------------------------------------------------------------- +// CATBase::SearchFileWithExtension +// Searches files with given extension from path. +// ----------------------------------------------------------------------------- +bool CATBase::SearchFileWithExtension( const char* pPathAndExt, bool bPrintErrors, string& sErrorLog ) +{ + LOG_FUNC_ENTRY("CATBase::SearchFileWithExtension"); + WIN32_FIND_DATA FindFileData; + HANDLE hFind; + string sTemp( pPathAndExt ); + + //Find file + hFind = FindFirstFile( sTemp.c_str(), &FindFileData ); + if (hFind == INVALID_HANDLE_VALUE) + { + string sErrorString( "No " ); + //Get extension + string sExt( pPathAndExt ); + sExt.erase( 0, sExt.find_last_of( "." ) ); + + sErrorString.append( sExt ); + sErrorString.append( " files in directory: " ); + + string sWithoutExt( pPathAndExt ); + sWithoutExt.erase( sWithoutExt.find_last_of( "." )-1, string::npos ); + sErrorString.append( sWithoutExt ); + + if( bPrintErrors ) + { + //string sTemp( pPathAndExt ); + //printf( "Can not find: %s.\n", pPathAndExt ); + printf( sErrorString.c_str() ); + } + else + { + //Add line change if sErrorString not empty + if( !sErrorLog.empty() ) + sErrorString.insert( 0, "\n" ); + sErrorLog.append( sErrorString ); + } + return false; + } + else + { + FindClose(hFind); + return true; + } +} + +// ----------------------------------------------------------------------------- +// CATBase::GetPathOrFileName +// Returns path to file or file name. +// ----------------------------------------------------------------------------- +string CATBase::GetPathOrFileName( bool bFileName, string sInput ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::GetPathOrFileName"); + string sRet; + size_t iPos = sInput.size(); + + sInput = ChangeSlashToBackSlash( sInput ); + + //Find character '\' starting from end of string + while( iPos > 0 && sInput[iPos] != '\\' ) + { + iPos--; + } + if( iPos > 0 ) + { + //Return file name + if( bFileName ) + { + sInput.erase( 0, iPos+1 ); + sRet = sInput; + } + else //Return file path + { + sInput.erase( iPos+1, string::npos ); + sRet = sInput; + } + } + else + { + if( !bFileName ) + return sRet; + sRet = sInput; + } + return sRet; +} + +// ----------------------------------------------------------------------------- +// CATBase::GetFileNameUsingExt +// Searches files with given extension from path. +// ----------------------------------------------------------------------------- +string CATBase::GetFileNameUsingExt( const char* pPathAndExt ) +{ + LOG_FUNC_ENTRY("CATBase::GetFileNameUsingExt"); + WIN32_FIND_DATA FindFileData; + HANDLE hFind; + string sRet; + + //Find file + hFind = FindFirstFile( pPathAndExt, &FindFileData ); + if (hFind == INVALID_HANDLE_VALUE) + { + //if( bPrintErrors ) + printf( "Can not find: %s.\n", pPathAndExt ); + return sRet; + } + else + { + sRet.append( FindFileData.cFileName ); + FindClose(hFind); + return sRet; + } +} + +// ----------------------------------------------------------------------------- +// CATBase::GetStringUntilNextSpace +// Function returns string from begin of given string until next space, +// characters until next space are removed from sInput string. +// ----------------------------------------------------------------------------- +string CATBase::GetStringUntilNextSpace( string& sInput, bool bEraseFromInput ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::GetStringUntilNextSpace"); + string sTemp( sInput ); + size_t iSize = sTemp.find_first_of(' '); + if( iSize != string::npos ) + { + sTemp.resize( iSize ); + if( bEraseFromInput ) + sInput.erase( 0, (iSize+1) ); + } + else + { + if ( bEraseFromInput ) + sInput.clear(); + } + return sTemp; +} + +// ----------------------------------------------------------------------------- +// CATBase::ChangeSlashToBackSlash +// Function changes all BackSlash characters to Slash character from +// given string. +// ----------------------------------------------------------------------------- +string CATBase::ChangeSlashToBackSlash( string sInput ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::ChangeSlashToBackSlash"); + for( unsigned int i = 0 ; i < sInput.length() ; i++ ) + { + if( sInput[i] == '/' ) + { + sInput[i] = '\\'; + } + } + return sInput; +} + +// ----------------------------------------------------------------------------- +// CATBase::FileExists +// Check if given file exists. +// ----------------------------------------------------------------------------- +bool CATBase::FileExists( const char * pFilename ) +{ + LOG_FUNC_ENTRY("CATBase::FileExists"); + DWORD dwRet = GetFileAttributes( pFilename ); + if( dwRet == INVALID_FILE_ATTRIBUTES ) + { + return false; + } + else + { + //Is file directory? + if( dwRet & FILE_ATTRIBUTE_DIRECTORY ) + { + return false; + } + } + return true; +} + +bool CATBase::IsFileReadOnly( const char* pFilename ) +{ + LOG_FUNC_ENTRY("CATBase::IsFileReadOnly"); + DWORD dwRet = GetFileAttributes( pFilename ); + if( dwRet == INVALID_FILE_ATTRIBUTES ) + return false; + if( dwRet & FILE_ATTRIBUTE_READONLY ) + return true; + return false; +} + +bool CATBase::SetFileReadOnly( const char* pFileName ) +{ + LOG_FUNC_ENTRY("CATBase::SetFileReadOnly"); + DWORD dw = GetFileAttributes( pFileName ); + if( dw == INVALID_FILE_ATTRIBUTES ) + return false; + if( dw & FILE_ATTRIBUTE_READONLY ) + return true; + dw = dw | FILE_ATTRIBUTE_READONLY ; + if ( SetFileAttributes( pFileName, dw ) ) + return true; + return false; +} +bool CATBase::SetFileWritable( const char* pFileName ) +{ + LOG_FUNC_ENTRY("CATBase::SetFileWritable"); + DWORD dw = GetFileAttributes( pFileName ); + if( dw == INVALID_FILE_ATTRIBUTES ) + return false; + if( ! dw & FILE_ATTRIBUTE_READONLY ) + return true; + dw = dw ^ FILE_ATTRIBUTE_READONLY ; + if ( SetFileAttributes( pFileName, dw ) ) + return true; + return false; +} + +// ----------------------------------------------------------------------------- +// CATBase::FileCopyToPath +// Copies file to given path +// ----------------------------------------------------------------------------- +bool CATBase::FileCopyToPath(const string& sFile, const string& sToPath) +{ + LOG_FUNC_ENTRY("CATBase::FileCopyToPath"); + // Display message + cout << AT_MSG << "Copy " << sFile << AT_FILE_TO << sToPath << endl; + if ( sFile.empty() || sToPath.empty() ) + { + LOG_FUNC_EXIT("CATBase::FileCopyToPath Error, empty parameter"); + return false; + } + // Copy using windows api (seems not to work when relavite path .. + /* + // Full path where to copy + string sDestination = sToPath; + // Append '\' to string if not exists + if ( sDestination.length() > 1 ) + { + const char cLastChar = sDestination[ sDestination.length() -1 ]; + if ( cLastChar != DASH ) + sDestination.append("\\"); + } + int iRet = 0; + iRet = CopyFile( sFile.c_str(), sDestination.c_str(), false ); + if ( iRet != 0 ) + { + return false; + } + */ + string sCommand; + sCommand.append( "copy /Y \""); + sCommand.append( sFile ); + sCommand.append( "\" \"" ); + sCommand.append( sToPath ); + sCommand.append( "\" > nul 2>&1" ); + LOG_STRING( sCommand ); + int iRet = 0; + iRet = (int)system( sCommand.c_str() ); + if ( iRet != 0 ) + return false; + return true; +} + +// ----------------------------------------------------------------------------- +// CATBase::FileMoveToPath +// Copies file to given path +// ----------------------------------------------------------------------------- +bool CATBase::FileMoveToPath(const string& sFile, const string& sToPath) +{ + LOG_FUNC_ENTRY("CATBase::FileMoveToPath"); + // Display message + cout << AT_MSG << "Move " << sFile << AT_FILE_TO << sToPath << endl; + if ( sFile.empty() || sToPath.empty() ) + { + LOG_FUNC_EXIT("CATBase::FileMoveToPath Error, empty parameter"); + return false; + } + // Move (again windows api function does not support relative path .. in it + /* + // Get filename from sFile + string sFileName = GetPathOrFileName( true, sFile ); + // Full path where to copy + string sDestination = sToPath; + // Append '\' to string if not exists + if ( sDestination.length() > 1 ) + { + const char cLastChar = sDestination[ sDestination.length() -1 ]; + if ( cLastChar != DASH ) + sDestination.append("\\"); + } + int iRet = 0; + iRet = MoveFile( sFile.c_str(), sDestination.c_str()); + if ( iRet != 0 ) + { + return false; + } + */ + string sCommand; + sCommand.append( "move /Y \""); + sCommand.append( sFile ); + sCommand.append( "\" \"" ); + sCommand.append( sToPath ); + sCommand.append( "\" > nul 2>&1" ); + LOG_STRING( sCommand ); + int iRet = 0; + iRet = (int)system( sCommand.c_str() ); + if ( iRet != 0 ) + return false; + return true; +} +// ----------------------------------------------------------------------------- +// CATBase::CreateTempPath +// Creates temporary directory path for given mmp file +// ----------------------------------------------------------------------------- +string CATBase::CreateTempPath(const string& sMmpFileWithPath) +{ + LOG_FUNC_ENTRY("CATBase::CreateTempPath"); + string sTempPath = GetPathOrFileName( false, sMmpFileWithPath ); + sTempPath.append( AT_TEMP_DIR ); + sTempPath.append( "\\" ); + return sTempPath; +} + +// ----------------------------------------------------------------------------- +// CATBase::RemovePathAndExt +// Removes extension from file name and returns file name without extension. +// ----------------------------------------------------------------------------- +string CATBase::RemovePathAndExt( string sFileName, bool bReverseFindExt) +{ + LOG_LOW_FUNC_ENTRY("CATBase::RemovePathAndExt"); + string sRet; + sFileName = GetPathOrFileName( true, sFileName ); + if ( bReverseFindExt ) + { + // Remove extension from reverse + size_t iPos = sFileName.find_last_of('.'); + if( iPos != string::npos ) + { + sFileName.resize( sFileName.find_last_of('.') ); + sRet = sFileName; + } + } + else + { + // Remove extension finding first . + size_t iPos = sFileName.find_first_of('.'); + if( iPos != string::npos ) + { + sFileName.resize( sFileName.find_first_of('.') ); + sRet = sFileName; + } + } + return sRet; +} + +// ----------------------------------------------------------------------------- +// CATBase::IsTargetTypeSupported +// Checks from constant array is this target unsupported +// ----------------------------------------------------------------------------- +bool CATBase::IsTargetTypeSupported(string sTargetType) +{ + LOG_FUNC_ENTRY("CATBase::IsTargetTypeSupported"); + // compare to list + int iArraySize = sizeof( UNSUPPORTED_TARGET_TYPES ) / sizeof( string ); + for ( int i=0 ; i < iArraySize ; i++ ) + { + string sUnsupported = UNSUPPORTED_TARGET_TYPES[i]; + // lowercase both + ChangeToLower(sTargetType); + ChangeToLower(sUnsupported); + // compare + if ( sUnsupported.compare( sTargetType ) == 0 ) + { + return false; + } + } + return true; +} + +// ----------------------------------------------------------------------------- +// CATBase::IsTargetTypeKernelSide +// Checks from constant array is this target type kernel side +// ----------------------------------------------------------------------------- +bool CATBase::IsTargetTypeKernelSide(string sTargetType) +{ + LOG_FUNC_ENTRY("CATBase::IsTargetTypeKernelSide"); + // compare to list + int iArraySize = sizeof( KERNEL_SIDE_TARGET_TYPES ) / sizeof( string ); + for ( int i=0 ; i < iArraySize ; i++ ) + { + string sUnsupported = KERNEL_SIDE_TARGET_TYPES[i]; + // lowercase both + ChangeToLower(sTargetType); + ChangeToLower(sUnsupported); + // compare + if ( sUnsupported.compare( sTargetType ) == 0 ) + { + return true; + } + } + return false; +} + +bool CATBase::CheckVariant( const string& sEpocRoot, const string& sVariant ) +{ + LOG_FUNC_ENTRY("CATBase::CheckVariant"); + string sFileToCheck; + // Add epoc root + if( sEpocRoot.size() > 1 ) + sFileToCheck.append( sEpocRoot ); + // Add path + sFileToCheck.append( VARIANT_DIR ) ; + // Add variant + sFileToCheck.append( sVariant ); + // Add extension + sFileToCheck.append( VARIANT_FILE_EXTENSION ); + // check does FileExists + return FileExists( sFileToCheck.c_str() ); +} +bool CATBase::IsDefaultVariant( const string& sEpocRoot ) +{ + LOG_FUNC_ENTRY("CATBase::IsDefaultVariant"); + string sFileToCheck; + // Add epoc root + if( sEpocRoot.size() > 1 ) + sFileToCheck.append( sEpocRoot ); + // Add path + sFileToCheck.append( VARIANT_DIR ) ; + // Add variant + sFileToCheck.append( "DEFAULT" ); + // Add extension + sFileToCheck.append( VARIANT_FILE_EXTENSION ); + // check does FileExists + return FileExists( sFileToCheck.c_str() ); +} + +// ----------------------------------------------------------------------------- +// CATBase::FileDelete +// FileDelete +// ----------------------------------------------------------------------------- +bool CATBase::FileDelete(const string& sFile, bool bPrint ) +{ + LOG_FUNC_ENTRY("CATBase::FileDelete"); + // does file even exists + if ( !FileExists( sFile.c_str() ) ) + return false; + // delete file + int iRet = _unlink( sFile.c_str() ); + // if print on display error + if ( iRet && bPrint ) + { + cout << AT_MSG << "Error, deleting file " << sFile + << endl; + } + // if print on display message + else if ( !iRet && bPrint ) + { + cout << AT_MSG << "Delete " << sFile << endl; + } + // return + if ( iRet ) + return false; + return true; +} +// ----------------------------------------------------------------------------- +// CATBase::DirDelete +// Delelete directory +// ----------------------------------------------------------------------------- +bool CATBase::DirDelete(const string& sDir, bool bPrint ) +{ + LOG_FUNC_ENTRY("CATBase::DirDelete"); + if ( sDir.find( AT_TEMP_DIR) == string::npos ) + return false; + + if ( sDir.length() < 2 ) + return false; + + string sDir2; + if ( sDir.at(1) != ':' ) + { + char cDir[MAX_LINE_LENGTH]; + GetCurrentDirectory( MAX_LINE_LENGTH , cDir ); + sDir2.append( cDir ); + sDir2.append( "\\" ); + sDir2.append( sDir ); + } + else + sDir2.append( sDir ); + + // does directory exists + DWORD dwRet = GetFileAttributes( sDir2.c_str() ); + if ( dwRet == INVALID_FILE_ATTRIBUTES ) + return false; + else if ( ! (dwRet & FILE_ATTRIBUTE_DIRECTORY) ) + { + return false; + } + // Delete dir + string sCmd( "rmdir /S /Q " ); + sCmd.append( sDir2 ); + sCmd.append( " > nul 2>&1" ); + int iRet = (int)system( sCmd.c_str() ); + if ( iRet && bPrint) + { + cout << AT_MSG << "Error, deleting directory " << sDir2 << endl; + } + else if ( !iRet && bPrint ) + { + cout << AT_MSG << "Delete directory " << sDir2 << endl; + } + if ( iRet ) + return false; + return true; +} + +// ----------------------------------------------------------------------------- +// CATBase::DirCreate +// Create directory +// ----------------------------------------------------------------------------- +bool CATBase::DirCreate(const string& sDir, bool bPrint ) +{ + LOG_FUNC_ENTRY("CATBase::DirCreate"); + + if ( sDir.length() < 2 ) + return false; + + string sDir2; + if ( sDir.at(1) != ':' ) + { + char cDir[MAX_LINE_LENGTH]; + GetCurrentDirectory( MAX_LINE_LENGTH , cDir ); + sDir2.append( cDir ); + sDir2.append( "\\" ); + sDir2.append( sDir ); + } + else + sDir2.append( sDir ); + + // does directory exists + DWORD dwRet = GetFileAttributes( sDir2.c_str() ); + if ( dwRet != INVALID_FILE_ATTRIBUTES ) + { + if( dwRet & FILE_ATTRIBUTE_DIRECTORY ) + return false; + } + // Create dir + string sCmd( "mkdir " ); + sCmd.append( sDir2 ); + sCmd.append( " > nul 2>&1" ); + int iRet = (int)system( sCmd.c_str() ); + if ( iRet && bPrint) + { + cout << AT_MSG << "Error, creating directory " << sDir2 << endl; + } + else if ( !iRet && bPrint ) + { + cout << AT_MSG << "Directory " << sDir2 << " created" << endl; + } + if ( iRet ) + return false; + return true; +} + +// ----------------------------------------------------------------------------- +// CATBase::ConvertTCHARtoString +// Convert TCHAR* to std::string +// ----------------------------------------------------------------------------- +string CATBase::ConvertTCHARtoString(TCHAR* charArray) +{ + LOG_LOW_FUNC_ENTRY("CATBase::ConvertTCHARtoString"); + // Loop char array + stringstream ss; + int iIndex = 0; + char c = (char) charArray[iIndex]; + // until null termination + while ( c != '\0' ) + { + ss << c; + iIndex++; + c = (char) charArray[iIndex]; + } + // return string + return ss.str(); +} + +// ----------------------------------------------------------------------------- +// CATBase::ConvertTCHARtoString +// Get list of files in directory +// ----------------------------------------------------------------------------- +vector<string> CATBase::DirList(const string& sDirectory + , bool bListDirs, bool bAddPathToFile) +{ + LOG_FUNC_ENTRY("CATBase::DirList"); + // Create string to modify it + string sDir = sDirectory; + // Add if missing '\' & '*' to the sDirectory + if ( sDir.at( sDir.size()-1 ) != '\\' ) + sDir.append( "\\" ); + // Path to add to file string if specified + string sPath = sDir; + // Add * to for windows api to find all files + sDir.append( "*" ); + // convert directory string to LPCSTR + LPCSTR dir( sDir.c_str() ); + // vector to store file list + vector<string> vFileList; + // Using win32 api to find list of files in directory + // file data "container" + WIN32_FIND_DATA fileData; + // handle to directory + HANDLE hFinder = FindFirstFile( dir, &fileData ); + if ( hFinder == INVALID_HANDLE_VALUE ) + { + // no files found + return vFileList; + } + // loop files add to vector and return + while( FindNextFile(hFinder, &fileData ) ) + { + DWORD dw = fileData.dwFileAttributes; + // skip if its directory and bListDirs not specified + if ( dw & FILE_ATTRIBUTE_DIRECTORY && ! bListDirs) + continue; + // add files to vector + string sFile = ConvertTCHARtoString( fileData.cFileName ); + // Add given path to file string if specified + if ( bAddPathToFile ) + sFile.insert( 0, sPath ); + vFileList.push_back( sFile ); + } + // Close file find handler + FindClose( hFinder ); + return vFileList; +} + +// ----------------------------------------------------------------------------- +// CATBase::ParseRelativePathToString +// ParseRelative +// ----------------------------------------------------------------------------- +void CATBase::ParseRelativePathString(string& sPathString) +{ + LOG_LOW_FUNC_ENTRY("CATBase::ParseRelativePathString"); + string sParsed; + // find .. + size_t iDots = sPathString.find( ".." ); + while ( iDots != string::npos ) + { + RemoveRelativePath( sPathString, iDots ); + iDots = sPathString.find( ".." ); + } +} + +// ----------------------------------------------------------------------------- +// CATBase::RemoveRelativePath +// Remove relative path from string (using given index) +// ----------------------------------------------------------------------------- +void CATBase::RemoveRelativePath(string& sString, size_t iDots) +{ + LOG_LOW_FUNC_ENTRY("CATBase::RemoveRelativePath"); + // Chck if accidentally given wrong parameter + if ( iDots == string::npos + || iDots < 1 ) + return; + // Parsed string + string sParsed; + // Find position of last backslash before dots + size_t i = sString.rfind("\\", iDots-2 ); + // Pickup start part (depending is the backslash at last parts first char) + if ( sString.at(iDots+2) != '\\' ) + sParsed = sString.substr( 0, i+1 ) ; + else + sParsed = sString.substr( 0, i ); + // Pick up last part + sParsed.append( sString.substr( iDots+2, sString.size() ) ); + sString = sParsed; +} + +// ----------------------------------------------------------------------------- +// Get extension from given string +// ----------------------------------------------------------------------------- +string CATBase::GetExtension(const string& sString) +{ + LOG_LOW_FUNC_ENTRY("CATBase::GetExtension"); + // find last . + size_t iDot = sString.find_last_of( "." ); + // return string after . if found + if ( iDot != string::npos ) + return sString.substr(iDot+1, sString.length()-(iDot+1) ); + // otherwise return given string + return sString; +} + +// ----------------------------------------------------------------------------- +// CATBase::DirectoryExists +// Check if given directory exists. +// ----------------------------------------------------------------------------- +bool CATBase::DirectoryExists( const char* pDirname ) +{ + LOG_FUNC_ENTRY("CATBase::DirectoryExists"); + size_t iLenght = strlen( pDirname ); + + if ( iLenght < 2 ) + return false; + + string sDir; + if ( pDirname[1] != ':' ) + { + char cDir[MAX_LINE_LENGTH]; + GetCurrentDirectory( MAX_LINE_LENGTH , cDir ); + sDir.append( cDir ); + sDir.append( "\\" ); + sDir.append( pDirname ); + } + else + sDir.append( pDirname ); + + DWORD dwRet = GetFileAttributes( sDir.c_str() ); + if( dwRet == INVALID_FILE_ATTRIBUTES ) + { + return false; + } + else + { + //Is file directory? + if( dwRet & FILE_ATTRIBUTE_DIRECTORY ) + { + return true; + } + else + { + return false; + } + } +} + +// ----------------------------------------------------------------------------- +// CATBase::ConvertUnixPathToWin +// ----------------------------------------------------------------------------- +void CATBase::ConvertUnixPathToWin( string& sPath ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::ConvertUnixPathToWin"); + size_t iSpot = 0; + // convert '/' to '\' + iSpot = sPath.find( "/" ); + while( iSpot != string::npos ) + { + sPath.replace(iSpot,1, "\\"); + iSpot = sPath.find( "/", iSpot+1 ); + } + // convert '\\' to '\' + iSpot = sPath.find( "\\\\" ); + while( iSpot != string::npos ) + { + sPath.replace(iSpot,2,"\\"); + iSpot = sPath.find( "\\\\" ); + } +} + +// ----------------------------------------------------------------------------- +// CATBase::RemoveAllAfterDotIfTwoDots +// Removes all after first '.' +// if given string contains 2 '.' or more +// ----------------------------------------------------------------------------- +void CATBase::RemoveAllAfterDotIfTwoDots(string& sModName) +{ + LOG_LOW_FUNC_ENTRY("CATBase::RemoveAllAfterDotIfTwoDots"); + // did we find variable? + size_t found; + // Find first '.' + found = sModName.find("."); + if ( found != string::npos ) + { + // Try find second '.' + found = sModName.find(".", found+1); + if ( found != string::npos ) + { + // Remove all after first '.' + sModName = sModName.substr(0, sModName.find(".")+1 ); + } + } +} +// ----------------------------------------------------------------------------- +// CATBase::CreateTemporaryCpp +// ----------------------------------------------------------------------------- +bool CATBase::CreateTemporaryCpp( const string& sId, + const string& sPath + ,const string& sS60FileName + ,int iLogOption + ,int iIsDebug + ,int iAllocCallStackSize + ,int iFreeCallStackSize ) +{ + LOG_FUNC_ENTRY("CATBase::CreateTemporaryCpp"); + // Add slash to path if missing + string sTempCpp = sPath; + if( sTempCpp.at( sTempCpp.length() - 1 ) != '\\' ) + sTempCpp.append("\\"); + + // append temporary cpp name with id in middle + sTempCpp.append( AT_TEMP_CPP_LOWER_START ); + sTempCpp.append( sId ); + sTempCpp.append( AT_TEMP_CPP_LOWER_END ); + + //Open and truncate temporary cpp + ofstream out( sTempCpp.c_str() , ios::trunc ); + if ( ! out.good() ) + { + out.close(); + return false; + } + // Headers + out << "#include <e32base.h>"; + // Is debug + out << "\nconst TInt ATTempDebug(" << iIsDebug << ");"; + // Log option + out << "\nconst TInt ATTempLogOption(" << iLogOption << ");"; + // Alloc call stack + out << "\nconst TInt ATTempAllocCallStackSize(" << iAllocCallStackSize << ");"; + // Free call stack + out << "\nconst TInt ATTempFreeCallStackSize(" << iFreeCallStackSize << ");"; + // Log file name + out << "\n_LIT( ATTempLogFileName, \"" << sS60FileName << "\" );"; + // Version number + out << "\n_LIT( ATTempVersion, \"" << ATOOL_COMPATIBILITY_STRING << "\" );"; + // Variable functions use enumeration values that are defined in memoryhook (customuser.h) + // We use constants here so that we don't need to include the header file, wich + // might cause problems. +/* Enumeration copied to comment for notes + enum TATOptions + { + ELogFileName = 1, + EVersion = 2 , + ELogOption = 3, + EDebug = 4, + EAllocCallStackSize = 5, + EFreeCallStackSize = 6 + }; +*/ + out << "\nTInt GetInt( const TUint8 aType )"; + out << "\n{"; + out << "\nswitch( aType )"; + out << "\n{"; + out << "\ncase 4: return ATTempDebug; "; + out << "\ncase 3: return ATTempLogOption;"; + out << "\ncase 5: return ATTempAllocCallStackSize;"; + out << "\ncase 6: return ATTempFreeCallStackSize;"; + out << "\ndefault: return KErrArgument;"; + out << "\n}"; + out << "\n}"; + out << "\nTPtrC GetString( const TUint8 aType )"; + out << "\n{"; + out << "\nswitch( aType )"; + out << "\n{"; + out << "\ncase 1: return ATTempLogFileName();"; + out << "\ncase 2: return ATTempVersion();"; + out << "\ndefault: return KNullDesC();"; + out << "\n}"; + out << "\n}"; + + /** Todo: Old way of separate functions, these here for backup support and to ease testing. */ + /** Unnessesary in the future, so can be removed then (1.8.2). */ + + out << "\n_LIT( KFileName, \""; + out << sS60FileName; + out << "\" );\n"; + + // Hardcoded version number for support. + out << "\n/* The AnalyzeTool version number used. */"; + out << "\n_LIT( KAtoolVersion, \"1.7.5;1.9.1\" );\n"; + + out << "\nconst TFileName LogFileName()"; + out << "\n {"; + out << "\n return TFileName( KFileName() );"; + out << "\n }"; + + out << "\nTUint32 AllocCallStackSize()"; + out << "\n {"; + out << "\n return TUint32( "; + out << iAllocCallStackSize; + out << " );\n"; + out << "\n }"; + + out << "\nTUint32 FreeCallStackSize()"; + out << "\n {"; + out << "\n return TUint32( "; + out << iFreeCallStackSize; + out << " );\n"; + out << "\n }"; + + out << "\nconst TFileName AtoolVersion()"; + out << "\n {"; + out << "\n return TFileName( KAtoolVersion() );"; + out << "\n }"; + + out << "\nTUint32 LogOption()"; + out << "\n {"; + out << "\n return TUint32( "; + out << iLogOption; + out << " );"; + out << "\n }"; + + out << "\nTUint32 IsDebug()"; + out << "\n {"; + out << "\n return TUint32( "; + out << iIsDebug; + out << " );"; + out << "\n }"; + + // End of file and close + out << "\n\n// End of File\n"; + out.close(); + cout << AT_MSG << "Created " << sTempCpp << endl; + return true; +} + +// ----------------------------------------------------------------------------- +// CATBase::IsDataFile +// ----------------------------------------------------------------------------- +bool CATBase::IsDataFile( string sFile ) +{ + LOG_FUNC_ENTRY("CATBase::IsDataFile"); + // Check that sFile not empty + if ( sFile.empty() || sFile.length() < 1 ) + return false; + + // Temporary line char array. + char cLineFromFile[MAX_LINE_LENGTH]; + //Open file + ifstream in( sFile.c_str() ); + + //File open ok? + if( !in.good() ) + return false; + + //Read all lines + in.getline( cLineFromFile, MAX_LINE_LENGTH ); + + string sLineFromFile( cLineFromFile ); + in.close(); + if( sLineFromFile.find( "DATA_FILE_VERSION" ) != string::npos ) + return true; + else + return false; +} + + +// ----------------------------------------------------------------------------- +// CATBase::ParseStringToVector +// ----------------------------------------------------------------------------- +vector<string> CATBase::ParseStringToVector( const string& sInput, char separator ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::ParseStringToVector"); + string sString(sInput); + // Elements vector + vector<string> vStrings; + size_t iPos = sString.find( separator ); + // If can not find it return vector with just one element + if ( iPos == string::npos ) + { + // Don't add empty item into vector. + if ( sString.size() > 0 ) + vStrings.push_back( sString ); + return vStrings; + } + // Loop elements + while( iPos != string::npos ) + { + string sElement = sString.substr(0, iPos); + vStrings.push_back( sElement ); + sString.erase(0, iPos +1 ); + iPos = sString.find( separator ); + } + // Add last element if any + if ( sString.size() > 0 ) + vStrings.push_back( sString ); + // Return elements + return vStrings; +} + +// ----------------------------------------------------------------------------- +// CATBase::FilterString +// Filter string out of unwanted characters. The list of allowed +// characters is defined in CFILTERSTRING. +// ----------------------------------------------------------------------------- +string CATBase::FilterString( const string& sString ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::FilterString"); + string sFiltered; + for( size_t i = 0 ; i < sString.length() ; i++ ) + { + const char p = sString.at( i ); + if ( strchr( CFILTERSTRING, p ) != 0 ) + sFiltered.push_back( p ); + } + return sFiltered; +} + +// ----------------------------------------------------------------------------- +// CATBase::FilterExtraSpaces +// Replaces multiple continuous spaces with single. Won't leave +// spaces in start or end of string. +// ----------------------------------------------------------------------------- +void CATBase::FilterExtraSpaces( string& sString ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::FilterExtraSpaces"); + string sFiltered; + // Loop thru char array. + for( size_t i = 0 ; i < sString.length(); i++ ) + { + // Is char space? + if ( sString.at( i ) == ' ' ) + { + // Pick up space if filtered does not contain char as last. + if ( sFiltered.rbegin() == sFiltered.rend() ) + sFiltered.push_back( sString.at( i ) ); + else if ( * ( sFiltered.rbegin() ) != ' ' ) + sFiltered.push_back( sString.at( i ) ); + } + else + sFiltered.push_back( sString.at( i ) ); + } + + // Remove first and/or last character if it is space. + if ( sFiltered.begin() != sFiltered.end() ) + { + if( * ( sFiltered.begin() ) == ' ' ) + sFiltered.erase( 0, 1 ); + } + if ( sFiltered.rbegin() != sFiltered.rend() ) + { + if( * ( sFiltered.rbegin() ) == ' ' ) + sFiltered.resize( sFiltered.length()-1 ); + } + sString = sFiltered; +} + + +bool CATBase::hexToDec( string& sHex, unsigned int& iDec ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::hexToDec"); + istringstream ss( sHex ); + ss.setf( ios::hex, ios::basefield ); + if( ( ss >> iDec ) ) + return true; + return false; +} + +bool CATBase::hexToDec( string& sHex, int& iDec ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::hexToDec"); + istringstream ss( sHex ); + ss.setf( ios::hex, ios::basefield ); + if( ( ss >> iDec ) ) + return true; + return false; +} + +bool CATBase::hexToDec( string& sHex, unsigned long& ulDec ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::hexToDec"); + istringstream ss( sHex ); + ss.setf( ios::hex, ios::basefield ); + if( ( ss >> ulDec ) ) + return true; + return false; +} + +bool CATBase::hexToDec( string& sHex, unsigned long long& ullDec ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::hexToDec"); + istringstream ss( sHex ); + ss.setf( ios::hex, ios::basefield ); + if( ( ss >> ullDec ) ) + return true; + return false; +} + +/** +* Used to create array of integer & hex value pairs. +*/ +struct CHexMap +{ + char chr; + int value; +}; + +// ----------------------------------------------------------------------------- +// CATBase::_httoi +// ----------------------------------------------------------------------------- +unsigned long CATBase::_httoi(const char *value) +{ + LOG_LOW_FUNC_ENTRY("CATBase::_httoi"); + unsigned long l; + string s( value ); + if ( CATBase::hexToDec( s, l ) ) + return l; + return 0; +} + + +// ----------------------------------------------------------------------------- +// CATBase::NumberToHexString(int) +// ----------------------------------------------------------------------------- +string CATBase::NumberToHexString( unsigned int i ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::IntToHexString"); + stringstream ss; + ss << "0x" << hex << i; + string retval; retval = ss.str().c_str(); + return retval; +} +// ----------------------------------------------------------------------------- +// CATBase::NumberToHexString(long) +// ----------------------------------------------------------------------------- +string CATBase::NumberToHexString( unsigned long i ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::IntToHexString"); + stringstream ss; + ss << "0x" << hex << i; + string retval; retval = ss.str().c_str(); + return retval; +} + +// ----------------------------------------------------------------------------- +// CATBase::IsHexCharacter +// ----------------------------------------------------------------------------- +bool CATBase::IsHexCharacter(const TCHAR *value) +{ + LOG_LOW_FUNC_ENTRY("CATBase::IsHexCharacter"); + const int HexMapL = 22; + CHexMap HexMap[HexMapL] = + { + {'0', 0}, {'1', 1}, + {'2', 2}, {'3', 3}, + {'4', 4}, {'5', 5}, + {'6', 6}, {'7', 7}, + {'8', 8}, {'9', 9}, + {'A', 10}, {'B', 11}, + {'C', 12}, {'D', 13}, + {'E', 14}, {'F', 15}, + {'a', 10}, {'b', 11}, + {'c', 12}, {'d', 13}, + {'e', 14}, {'f', 15} + }; + bool found = false; + for (int i = 0; i < HexMapL; i++) + { + if(HexMap[i].chr == *value) + { + found = true; + break; + } + } + return found; +} + +// ----------------------------------------------------------------------------- +// CATBase::IsAscii(const char*,const unsigned int) +// ----------------------------------------------------------------------------- +bool CATBase::IsAscii( const char* pInput, const unsigned int iLength ) +{ + LOG_LOW_FUNC_ENTRY("CATBase::IsAscii"); + bool bRet = true; + const char* pPoint = pInput; + for( unsigned int i = 0 ; i < iLength ; i++) + { + if( !__isascii(*pPoint) ) + { + bRet = false; + break; + } + pPoint++; + } + return bRet; +} + +// ----------------------------------------------------------------------------- +// CATBase::GetEpocRoot( string& sEpocRoot ) +// ----------------------------------------------------------------------------- +bool CATBase::GetEpocRoot( string& sEpocRoot ) +{ + LOG_FUNC_ENTRY( "CATBase::GetEpocRoot" ); + bool bRet = true; + //Find EPOCROOT from environment variable + char* pEpocRoot = getenv ("EPOCROOT"); + if( pEpocRoot == NULL ) + { + const char pDevicesPath[] = "C:\\Program Files\\Common Files\\Symbian\\devices.xml"; + CATParseXML parser; + //Find EPOCROOT from devices + sEpocRoot = parser.GetEpocRootPathFromXML(pDevicesPath); + if( sEpocRoot.empty() ) + { + printf("EPOCROOT not set to environment variables.\n"); + bRet = false; + } + } + else + { + sEpocRoot.append( pEpocRoot ); + LOG_STRING( "EpocRoot :" << sEpocRoot ); + } + //Remove trailing slash + if ( sEpocRoot.size() > 1 && sEpocRoot[ sEpocRoot.length()-1 ] == '\\' ) + sEpocRoot.resize( sEpocRoot.length()-1 ); + return bRet; +} +//End of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/CATDatParser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/CATDatParser.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,1542 @@ +/* +* 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: Class responsible to parse data files +* +*/ + + +#include "../inc/CATDatParser.h" +#include "../inc/CATProject.h" +#include "../inc/CATModule2.h" +#include "../inc/CATMemoryAddress.h" +#include "../inc/catromsymbol.h" + +// ----------------------------------------------------------------------------- +// CATDatParser::CATDatParser +// Constructor only for testing! +// (No module vector defined so no locating codelines / call stacks) +// ----------------------------------------------------------------------------- +CATDatParser::CATDatParser() +{ + LOG_FUNC_ENTRY("CATDatParser::CATDatParser"); + Construct(); +} + +// ----------------------------------------------------------------------------- +// CATDatParser::CATDatParser +// Constructor +// ----------------------------------------------------------------------------- +CATDatParser::CATDatParser(vector<CATModule2*>* pModules ) +{ + LOG_FUNC_ENTRY("CATDatParser::CATDatParser"); + Construct(); + m_pModules = pModules; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::Construct +// "Real" constructor +// ----------------------------------------------------------------------------- +void CATDatParser::Construct() +{ + LOG_FUNC_ENTRY("CATDatParser::Construct"); + + m_iDataVersion = 1; // Default version of data. + m_bDllLoadFound = false; + m_bProcessStartFound = false; + m_bSubtestOnGoing = false; + + m_DataSaver.InitXML(); + + m_eBuildType = -2; + m_eProcess_state = not_started; + m_eProjectBuildType = -1; + + m_iCurrentProcessId = 0; + m_iLeakNumber = 0; + m_iLogLevel = 3; + m_iOffSet = 0; + + m_iPinPointedLeaks = 0; + m_iPinPointedSubTestLeaks = 0; + m_iSubtestStartHandleCount = 0; + m_iSuccesfullRuns = 0; + m_iTotalNumberOfLeaks = 0; + m_iTotalRuns = 0; + + m_pRomSymbol = 0; + m_pModules = 0; + + m_sCurrentProcessName = ""; + m_sInputFile = ""; + m_sInputFileTemp = ""; + m_sOutputFile = ""; + m_sProjectPlatform = ""; + m_vRomSymbolFiles.clear(); + m_vDllLoadModList.clear(); + m_vDllLoadModListSubTest.clear(); + m_vHandleLeaks.clear(); + m_vMemoryAddress.clear(); +} + +// ----------------------------------------------------------------------------- +// CATDatParser::~CATDatParser +// Destructor +// ----------------------------------------------------------------------------- +CATDatParser::~CATDatParser() +{ + LOG_FUNC_ENTRY("CATDatParser::~CATDatParser"); + + if ( m_In.is_open() ) + m_In.close(); + // Delete temporary input file if any + if ( !m_sInputFileTemp.empty() ) + { + if ( FileExists( m_sInputFileTemp.c_str() ) ) + FileDelete( m_sInputFileTemp, false ); + } + // Clean memory addresses if any + CleanMemoryAddresses(); + // Delete rom symbol. + if ( m_pRomSymbol ) + { + delete m_pRomSymbol; + m_pRomSymbol = NULL; + } +} + +// ----------------------------------------------------------------------------- +// CATDatParser::Analyze +// Analyze given data file +// ----------------------------------------------------------------------------- +int CATDatParser::Analyze() +{ + LOG_FUNC_ENTRY("CATDatParser::Analyze"); + // Return if input file not set + if ( m_sInputFile.empty() ) + return AT_RETURN_CODE::INVALID_DATA_FILE; + // If open close first + if ( m_In.is_open() ) + m_In.close(); + // Open file + m_In.open( m_sInputFile.c_str() ); + if ( ! m_In.good() ) + return AT_RETURN_CODE::INVALID_DATA_FILE; + try { + // If rom symbol file specified. + if ( ! m_vRomSymbolFiles.empty() ) + { + // Create new rom symbol file "parser". + m_pRomSymbol = new CATRomSymbol(); + m_pRomSymbol->m_bShowProgressMessages = true; + // Set symbol files. + if ( ! m_pRomSymbol->SetSymbols( m_vRomSymbolFiles ) ) + { + cout << AT_MSG << "Rom/Rofs symbols error: " << m_pRomSymbol->GetError() << endl; + // If file open fails we delete it and will not use it. + delete m_pRomSymbol; + m_pRomSymbol = NULL; + cout << AT_MSG << "Analyze aborted." << endl; + return AT_RETURN_CODE::SYMBOL_FILE_ERROR; + } + } + // Return code + int iRet = 0; + // Clear variables + ClearParsingVariables(); + // If output defined disable printing + if ( ! m_sOutputFile.empty() ) + m_DataSaver.SetPrintFlag( false ); + // Header + Header(); + // Parsing + iRet = Parse(); + // Footer + if ( iRet == AT_RETURN_CODE::OK ) + Footer(); + // If output defined save xml + if ( ! m_sOutputFile.empty() ) + m_DataSaver.SaveLinesToFile( m_sOutputFile.c_str(), XML_DATA ); + // Return + return iRet; + } catch ( int i ) + { + cout << AT_MSG << "Error, Analyze failed. : " << i << endl; + return AT_RETURN_CODE::UNHANDLED_EXCEPTION; + } +} +// ----------------------------------------------------------------------------- +// CATDatParser::Header +// Print header of report +// ----------------------------------------------------------------------------- +void CATDatParser::Header() +{ + LOG_FUNC_ENTRY("CATDatParser::Header"); + // Analyze report header + m_DataSaver.AddString( "Atool.exe v." ); + m_DataSaver.AddString( ATOOL_VERSION ); + m_DataSaver.AddString( "\n" ); + m_DataSaver.AddString( "Analyzing memory leaks..." ); + m_DataSaver.AddLineToLast(); +} + +// ----------------------------------------------------------------------------- +// CATDatParser::Footer +// Print footer of report +// ----------------------------------------------------------------------------- +void CATDatParser::Footer() +{ + LOG_FUNC_ENTRY("CATDatParser::Footer"); + m_DataSaver.AddString( "\nTotal Runs: " ); + m_DataSaver.AddInteger( m_iTotalRuns ); + m_DataSaver.AddLineToLast(); + + int iFailedRuns = m_iTotalRuns - m_iSuccesfullRuns; + m_DataSaver.AddString( "Failed Runs: " ); + m_DataSaver.AddInteger( iFailedRuns ); + m_DataSaver.AddLineToLast(); + + char cTemp[128]; + string sResult( itoa( m_iTotalRuns, cTemp, 10 ) ); + sResult.append( ";" ); + sResult.append( itoa( iFailedRuns, cTemp, 10 ) ); + sResult.append( ";" ); + + m_DataSaver.SaveXML( sResult, RESULT ); +} + +// ----------------------------------------------------------------------------- +// CATDatParser::ClearParsingVariables +// Clear/Reset all member variables related to parsing data file +// ----------------------------------------------------------------------------- +void CATDatParser::ClearParsingVariables() +{ + LOG_FUNC_ENTRY("CATDatParser::ClearParsingVariables"); + // Clear variables related to analyze + m_eProcess_state = not_started; + m_bProcessStartFound = false; + m_bDllLoadFound = false; + m_iTotalNumberOfLeaks = 0; + m_iPinPointedLeaks = 0; + m_iLeakNumber = 0; + m_iTotalRuns = 0; + m_iSuccesfullRuns = 0; + m_bSubtestOnGoing = false; + m_iSubtestStartHandleCount = 0; + CleanMemoryAddresses(); +} + +// ----------------------------------------------------------------------------- +// CATDatParser::Parse +// Parses data file. Note! header and footer of the report are done in +// separate functions. +// ----------------------------------------------------------------------------- +int CATDatParser::Parse() +{ + LOG_FUNC_ENTRY("CATDatParser::Parse"); + // Read all lines + char cLine[MAX_LINE_LENGTH]; + do + { + string sLine; + try { + m_In.getline( cLine, MAX_LINE_LENGTH ); + sLine = cLine ; + } catch(...) + { + LOG_STRING( AT_MSG << "Unexpected error, reading data file." ); + continue; + } + if( sLine.find( LABEL_DATA_FILE_VERSION ) != string::npos ) + { + // Check data file version + if( sLine.find( AT_DATA_FILE_VERSION ) == string::npos ) + { + return AT_RETURN_CODE::WRONG_DATA_FILE_VERSION; + } + } + else if( sLine.find( LABEL_PROCESS_START ) != string::npos ) + { + if ( ! ParseProcessStart( sLine ) ) + return AT_RETURN_CODE::ANALYZE_ERROR; + } + else if( sLine.find( LABEL_DLL_LOAD ) != string::npos ) + { + if ( ! ParseDllLoad( sLine ) ) + return AT_RETURN_CODE::ANALYZE_ERROR; + } + else if( sLine.find( LABEL_DLL_UNLOAD ) != string::npos ) + { + if ( ! ParseDllUnload( sLine ) ) + return AT_RETURN_CODE::ANALYZE_ERROR; + } + else if( sLine.find( LABEL_MEM_LEAK ) != string::npos) + { + if ( ! ParseMemLeak( sLine ) ) + return AT_RETURN_CODE::ANALYZE_ERROR; + } + else if( sLine.find( LABEL_PROCESS_END ) != string::npos ) + { + if ( ! ParseProcessEnd( sLine ) ) + return AT_RETURN_CODE::ANALYZE_ERROR; + } + else if( sLine.find( LABEL_ERROR_OCCURED ) != string::npos ) + { + if ( ! ParseErrorOccured( sLine ) ) + return AT_RETURN_CODE::ANALYZE_ERROR; + } + else if( sLine.find( LABEL_HANDLE_LEAK ) != string::npos ) + { + if ( ! ParseHandleLeak( sLine ) ) + return AT_RETURN_CODE::ANALYZE_ERROR; + } + else if( sLine.find( LABEL_TEST_START ) != string::npos ) + { + if ( ! ParseTestStart( sLine ) ) + return AT_RETURN_CODE::ANALYZE_ERROR; + } + else if( sLine.find( LABEL_TEST_END ) != string::npos ) + { + if ( ! ParseTestEnd( sLine ) ) + return AT_RETURN_CODE::ANALYZE_ERROR; + } + else if( sLine.find( LABEL_LOGGING_CANCELLED ) != string::npos ) + { + if ( ! ParseLoggingCancelled( sLine ) ) + return AT_RETURN_CODE::ANALYZE_ERROR; + } + } + while( m_In.good() ); + // Message of failed run if process start was last line in data. + if ( m_eProcess_state == ongoing ) + { + m_DataSaver.AddString( "Test run failed.\n" ); + m_DataSaver.AddLineToLast(); + } + return AT_RETURN_CODE::OK; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::ParseProcessStart +// ----------------------------------------------------------------------------- +bool CATDatParser::ParseProcessStart( string& sLine) +{ + LOG_FUNC_ENTRY("CATDatParser::ParseProcessStart"); + if ( m_eProcess_state == ongoing ) + { + m_DataSaver.AddString( "Test run failed.\n" ); + m_DataSaver.AddLineToLast(); + } + m_eProcess_state = ongoing; + m_bProcessStartFound = true; + + // Clear handle leaks + m_vHandleLeaks.clear(); + // Increment runs + m_iTotalRuns++; + // Clean leak count + m_iTotalNumberOfLeaks = 0; + // Clean pin pointed leaks count. + m_iPinPointedLeaks = 0; + // Clean leak number + m_iLeakNumber = 0; + + // Clean loaded mods + m_vDllLoadModList.clear(); + m_vDllLoadModListSubTest.clear(); + + // Skip text PROCESS_START + GetStringUntilNextSpace( sLine ); + // Get process name + m_sCurrentProcessName = GetStringUntilNextSpace( sLine ); + // Get Pid + string sPid = GetStringUntilNextSpace( sLine ); + m_iCurrentProcessId = _httoi( sPid.c_str() ); + + // Header for process tart + m_DataSaver.AddString( "\n--------------------------------\n" ); + m_DataSaver.AddString( "Test Run start (" ); + m_DataSaver.AddString( m_sCurrentProcessName.c_str() ); + m_DataSaver.AddString( "): " ); + + // Get start time + string sTime = GetStringUntilNextSpace( sLine ); + sTime = ConvertTimeToLocalTime( sTime ); + m_DataSaver.AddString( sTime.c_str() ); + + // Create data for xml + string sData( sTime ); + sData.append( ";" ); + + // Build mode UDEB/UREL. + string sBuildType = GetStringUntilNextSpace( sLine ); + + m_DataSaver.AddString( " Build target: " ); + if( sBuildType.compare( "0" ) == 0 ) + { + m_eBuildType = CATProject::UREL; + } + else if( sBuildType.compare( "1" ) == 0 ) + { + m_eBuildType = CATProject::UDEB; + } + m_DataSaver.AddString( CATProject::GetBuildTypeString( m_eBuildType ).c_str() ); + + // Version. + string sVersion = GetStringUntilNextSpace( sLine ); + unsigned int iVer = 0; + if ( hexToDec( sVersion, iVer ) && iVer != 0 ) + m_iDataVersion = iVer; + + // End line in data. + m_DataSaver.AddLineToLast(); + + // xml + sData.append( CATProject::GetBuildTypeString( m_eBuildType ) ); + sData.append( ";" ); + sData.append( m_sCurrentProcessName ); + m_DataSaver.SaveXML( sData, RUN ); + + // If projects platform defined check that it is same in data. (future feature). + if ( ! m_sProjectPlatform.empty() ) + { + // If platform info is added to data file do check here. + } + // If projects build type defined check that it is same in data. + if ( m_eProjectBuildType != -1 ) + { + if ( m_eBuildType != m_eProjectBuildType ) + { + string sError(AT_MSG); + sError.append( "Error, analyzed data has build type of " ); + sError.append( CATProject::GetBuildTypeString( m_eBuildType ) ); + sError.append( " and project has build type " ); + sError.append( CATProject::GetBuildTypeString( m_eProjectBuildType ) ); + sError.append( ". Pinpointed code lines are not valid." ); + m_DataSaver.AddString( sError.c_str(), false ); + m_DataSaver.AddLineToLast(); + } + } + return true; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::ParseProcessEnd +// ----------------------------------------------------------------------------- +bool CATDatParser::ParseProcessEnd( string& sLine ) +{ + LOG_FUNC_ENTRY("CATDatParser::ParseProcessEnd"); + GetStringUntilNextSpace( sLine ); + + // Get process id + string sProcessID = GetStringUntilNextSpace( sLine ); + unsigned long iProcessID = _httoi( sProcessID.c_str() ); + + // Get time + string sTime = GetStringUntilNextSpace( sLine ); + + // Convert leak time + sTime = ConvertTimeToLocalTime( sTime ); + + // Process started? + if( iProcessID == m_iCurrentProcessId ) + { + m_iSuccesfullRuns++; + m_DataSaver.AddLineToLast(); + m_DataSaver.AddString( "Test Run end (" ); + m_DataSaver.AddString( m_sCurrentProcessName.c_str() ); + m_DataSaver.AddString( "): " ); + m_DataSaver.AddString( sTime.c_str() ); + m_DataSaver.AddLineToLast(); + m_DataSaver.AddString( "Build target: " ); + m_DataSaver.AddString( CATProject::GetBuildTypeString( m_eBuildType ).c_str() ); + m_DataSaver.AddLineToLast(); + + m_eProcess_state = stopped; + // Number of leaks + if ( m_iLogLevel == 1 || m_iLogLevel == 2 ) + { + if ( m_iPinPointedLeaks > 0 ) + { + m_DataSaver.AddInteger( m_iPinPointedLeaks ); + m_DataSaver.AddString( " number of pinpointed memory leak(s)." ); + m_DataSaver.AddLineToLast(); + } + m_DataSaver.AddInteger( m_iLeakNumber ); + m_DataSaver.AddString( " total number of memory leak(s)." ); + m_DataSaver.AddLineToLast(); + } + else + { + m_DataSaver.AddInteger( m_iTotalNumberOfLeaks ); + m_DataSaver.AddString( " memory leak(s) found." ); + m_DataSaver.AddLineToLast(); + } + + // xml + char cTemp[128]; + m_DataSaver.SaveXML( itoa( m_iTotalNumberOfLeaks, cTemp, 10 ) , MEM_LEAKS ); + + // Print all modules which have leaks + for( size_t i = 0 ; i < m_vDllLoadModList.size() ; i++ ) + { + if( m_vDllLoadModList.at(i).iLeaks > 0 ) + { + m_DataSaver.AddInteger( m_vDllLoadModList.at(i).iLeaks ); + m_DataSaver.AddString( " memory leak(s) in module: " ); + m_DataSaver.AddString( m_vDllLoadModList.at(i).sModuleName.c_str() ); + m_DataSaver.AddLineToLast(); + + // xml + string sModuleNameAndLeaks( m_vDllLoadModList[i].sModuleName ); + sModuleNameAndLeaks.append(";"); + sModuleNameAndLeaks.append( itoa( m_vDllLoadModList[i].iLeaks, cTemp, 10 ) ); + m_DataSaver.SaveXML( sModuleNameAndLeaks , MEM_LEAK_MODULE ); + } + } + + if ( m_vHandleLeaks.size() > 0 ) + { + // We have handle leaks + bool bHandLeaksFound = false; + int iTotalNrOfLeaks = 0; + // Print handle leaks + for( size_t i = 0 ; i < m_vHandleLeaks.size() ; i++ ) + { + string sTempHandleLeak( m_vHandleLeaks[i] ); + // Name. + string sHandleLeakModule( GetStringUntilNextSpace( sTempHandleLeak ) ); + // Count. + string sNrOfLeaks( GetStringUntilNextSpace(sTempHandleLeak) ); + unsigned long iNrOfLeaks = _httoi( sNrOfLeaks.c_str() ); + iTotalNrOfLeaks += iNrOfLeaks; + if( iNrOfLeaks ) + { + if( !bHandLeaksFound ) + { + m_DataSaver.SaveXML( sNrOfLeaks , HANDLE_LEAKS ); + } + bHandLeaksFound = true; + m_DataSaver.AddInteger( iNrOfLeaks ); + // Just print out how many leaks found. + // Because its always unknown. + m_DataSaver.AddString( " handle leak(s) found." ); + m_DataSaver.AddLineToLast(); + + // xml + string sXMLInfo( sHandleLeakModule ); + sXMLInfo.append( ";" ); sXMLInfo.append( sNrOfLeaks ); + m_DataSaver.SaveXML( sXMLInfo , HANDLE_LEAK_MODULE ); + } + } + // Update number if handle leaks + m_DataSaver.SaveXML( itoa( iTotalNrOfLeaks, cTemp, 10 ) , HANDLE_LEAKS ); + if( !bHandLeaksFound ) + { + //m_DataSaver.AddLineToLast(); + m_DataSaver.AddString( TEXT_NO_HANDLE_LEAKS ); + m_DataSaver.AddLineToLast(); + } + } + else + { + // No handle leaks + m_DataSaver.AddLineToLast(); + m_DataSaver.AddString( TEXT_NO_HANDLE_LEAKS ); + m_DataSaver.AddLineToLast(); + } + + // Process end to xml + m_DataSaver.SaveXML( sTime, RUN_END ); + // Reset current process + m_iCurrentProcessId = 0; + } + + // If no dll load or process start found + if ( ! m_bProcessStartFound || !m_bDllLoadFound ) + { + m_DataSaver.AddLineToLast(); + m_DataSaver.AddString( AT_ANALYZE_INSUFFICIENT_LOGGING_DATA ); + m_DataSaver.AddLineToLast(); + } + + return true; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::ParseDllLoad +// ----------------------------------------------------------------------------- +bool CATDatParser::ParseDllLoad( string& sLine ) +{ + LOG_FUNC_ENTRY("CATDatParser::ParseDllLoad"); + //DLL_LOAD <DLL name> <Time stamp> <Memory start address> <Memory end address> + m_bDllLoadFound = true; + DLL_LOAD_INFO structDllInfo; + structDllInfo.iStartAddress = 0; + structDllInfo.iEndAddress = 0; + structDllInfo.iLeaks = 0; + + // Skip "DLL_LOAD " + GetStringUntilNextSpace( sLine ); + + // Get module name + structDllInfo.sModuleName = GetStringUntilNextSpace( sLine ); + ChangeToLower( structDllInfo.sModuleName ); + + // Create module from this if project platform emulator + if ( _stricmp( "winscw", m_sProjectPlatform.c_str() ) == 0 ) + CreateWinscwModule( structDllInfo.sModuleName ); + + if ( m_iDataVersion >= AT_DLL_TIMESTAMP_DATA_VERSION ) + { + // Pickup module loading time. + string sLoadTime = GetStringUntilNextSpace( sLine ); + unsigned long long ull; + if ( hexToDec( sLoadTime, ull ) ) + structDllInfo.iLoadTime = ull; + } + + // Get dll start memory string address from line + // Convert string address to real memory address + structDllInfo.iStartAddress = + _httoi( GetStringUntilNextSpace( sLine ).c_str() ); + + // Get dll end memory string address from line + // Convert string address to real memory address + structDllInfo.iEndAddress = + _httoi( + GetStringUntilNextSpace( sLine ).c_str() ); + + // Is module already loaded, if not add it to list. + bool bFound = false; + for( vector<DLL_LOAD_INFO>::iterator it = m_vDllLoadModList.begin(); + it != m_vDllLoadModList.end() ; it++ ) + { + if( (*it).sModuleName.compare( structDllInfo.sModuleName ) == 0 ) + { + bFound = true; + break; + } + } + if( ! bFound ) + m_vDllLoadModList.push_back( structDllInfo ); + + // Sub test module list. + bFound = false; + for( vector<DLL_LOAD_INFO>::iterator it = m_vDllLoadModListSubTest.begin(); + it != m_vDllLoadModListSubTest.end() ; it++ ) + { + if( (*it).sModuleName.compare( structDllInfo.sModuleName ) == 0 ) + { + bFound = true; + break; + } + } + if( ! bFound ) + m_vDllLoadModListSubTest.push_back( structDllInfo ); + + return true; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::ParseDllUnload +// ----------------------------------------------------------------------------- +bool CATDatParser::ParseDllUnload( string& sLine ) +{ + LOG_FUNC_ENTRY("CATDatParser::ParseDllUnload"); + + // Ignore unloads on older version because no timestamps. + if ( m_iDataVersion < AT_DLL_TIMESTAMP_DATA_VERSION ) + { + return true; + } + + // Skip "DLL_UNLOAD " + GetStringUntilNextSpace( sLine ); + + // Get module name + string sModuleName = GetStringUntilNextSpace( sLine ); + ChangeToLower( sModuleName ); + + // Unload time + unsigned long long ull; + string sUnload = GetStringUntilNextSpace( sLine ); + if ( ! hexToDec( sUnload, ull ) ) + return true; + + // Set module unload time. + vector<DLL_LOAD_INFO>::iterator it; + for( it = m_vDllLoadModList.begin() ; it != m_vDllLoadModList.end() ; it++ ) + { + if ( sModuleName.compare( it->sModuleName ) == 0 ) + { + (*it).iUnloadTime = ull; + break; + } + } + for( it = m_vDllLoadModListSubTest.begin() ; it != m_vDllLoadModListSubTest.end() ; it++ ) + { + if ( sModuleName.compare( it->sModuleName ) == 0 ) + { + (*it).iUnloadTime = ull; + break; + } + } + return true; +} +// ----------------------------------------------------------------------------- +// CATDatParser::ParseLoggingCancelled +// ----------------------------------------------------------------------------- +bool CATDatParser::ParseLoggingCancelled( string& sLine ) +{ + LOG_FUNC_ENTRY("CATDatParser::ParseLoggingCancelled"); + // Skip text "LOGGING_CANCELLED" + GetStringUntilNextSpace( sLine ); + + // Get time + string sTime( GetStringUntilNextSpace( sLine ) ); + sTime = ConvertTimeToLocalTime( sTime ); + m_DataSaver.AddString( "Logging Cancelled." ); + m_DataSaver.AddLineToLast(); + return true; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::ParseHandleLeak +// ----------------------------------------------------------------------------- +bool CATDatParser::ParseHandleLeak( string& sLine ) +{ + LOG_FUNC_ENTRY("CATDatParser::ParseHandleLeak"); + // Skip text "HANDLE_LEAK" + GetStringUntilNextSpace( sLine ); + m_vHandleLeaks.push_back( sLine ); + return true; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::ParseTestStart +// ----------------------------------------------------------------------------- +bool CATDatParser::ParseTestStart( string& sLine ) +{ + LOG_FUNC_ENTRY("CATDatParser::ParseTestStart"); + m_bSubtestOnGoing = true; + m_iLeakNumber = 0; + m_iPinPointedSubTestLeaks = 0; + + // Reset subtest leaked modules list + for( size_t i = 0 ; i < m_vDllLoadModListSubTest.size() ; i++ ) + { + m_vDllLoadModListSubTest.at(i).iLeaks = 0; + } + + // Skip text "TEST_START" + GetStringUntilNextSpace( sLine ); + // Time + string sTime( GetStringUntilNextSpace( sLine ) ); + sTime = ConvertTimeToLocalTime( sTime ); + // Name + string sSubTestName( GetStringUntilNextSpace( sLine ) ); + m_DataSaver.AddLineToLast(); + + // Get handle count in subtest start + string sSubTestStartHandleCount( GetStringUntilNextSpace( sLine ) ); + m_iSubtestStartHandleCount = atoi( sSubTestStartHandleCount.c_str() ); + + // Add start to report + m_DataSaver.AddString( "\nSub test (" ); + m_DataSaver.AddString( sSubTestName.c_str() ); + m_DataSaver.AddString( ") start: " ); + m_DataSaver.AddString( sTime.c_str() ); + + // m_DataSaver.AddLineToLast(); + + // Add start to xml + string sResult( sSubTestName ); + sResult.append( ";" ); + sResult.append( sTime ); + sResult.append( ";" ); + m_DataSaver.SaveXML( sResult, TEST_START ); + return true; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::ParseTestEnd +// ----------------------------------------------------------------------------- +bool CATDatParser::ParseTestEnd( string& sLine ) +{ + LOG_FUNC_ENTRY("CATDatParser::ParseTestEnd"); + // Skip text "TEST_END" + GetStringUntilNextSpace( sLine ); + + // Time + string sTime( GetStringUntilNextSpace( sLine ) ); + sTime = ConvertTimeToLocalTime( sTime ); + + // Name + string sSubTestName( GetStringUntilNextSpace( sLine ) ); + m_DataSaver.AddLineToLast(); + + // Add test end info to report + m_DataSaver.AddString( "Sub test (" ); + m_DataSaver.AddString( sSubTestName.c_str() ); + m_DataSaver.AddString( ") end: " ); + m_DataSaver.AddString( sTime.c_str() ); + m_DataSaver.AddLineToLast(); + + // Leak count to report in subtest + if( m_iLeakNumber > 0 ) + { + if ( m_iLogLevel == 1 || m_iLogLevel == 2 ) + { + m_DataSaver.AddInteger( m_iPinPointedSubTestLeaks ); + m_DataSaver.AddString( " number of pinpointed memory leaks." ); + m_DataSaver.AddLineToLast(); + m_DataSaver.AddInteger( m_iLeakNumber ); + m_DataSaver.AddString( " memory leaks found." ); + } + else + { + m_DataSaver.AddInteger( m_iLeakNumber ); + m_DataSaver.AddString( " memory leaks found." ); + } + } + else + { + m_DataSaver.AddString( "No memory leaks found." ); + } + m_DataSaver.AddLineToLast(); + + // Use sTime to store info to xml + sTime.append(";"); + char cTemp[128]; + // Print all modules whitch have leaks + for( unsigned int i = 0 ; i < m_vDllLoadModListSubTest.size() ; i++ ) + { + if( m_vDllLoadModListSubTest.at(i).iLeaks > 0 ) + { + // Normal report + m_DataSaver.AddInteger( m_vDllLoadModListSubTest[i].iLeaks ); + m_DataSaver.AddString( " memory leaks in module: " ); + m_DataSaver.AddString( m_vDllLoadModListSubTest.at(i).sModuleName.c_str() ); + m_DataSaver.AddLineToLast(); + // xml + string sModuleNameAndLeaks( m_vDllLoadModListSubTest.at(i).sModuleName ); + sModuleNameAndLeaks.append(";"); + sModuleNameAndLeaks.append( itoa( m_vDllLoadModListSubTest.at(i).iLeaks, cTemp, 10 ) ); + m_DataSaver.SaveXML( sModuleNameAndLeaks , SUBTEST_MEM_LEAK_MODULE ); + } + } + // Handle count + int iEndHandleCount = atoi( GetStringUntilNextSpace( sLine ).c_str() ); + // Is there handle leaks in subtest? + if( iEndHandleCount > m_iSubtestStartHandleCount ) + { + // Print normal report + m_DataSaver.AddInteger( iEndHandleCount - m_iSubtestStartHandleCount ); + m_DataSaver.AddString( " handle leaks in subtest: " ); + m_DataSaver.AddString( sSubTestName.c_str() ); + m_DataSaver.AddString( "." ); + m_DataSaver.AddLineToLast(); + + // Print handle leaks to XML + string sNrOfHandleLeaks( itoa( iEndHandleCount - m_iSubtestStartHandleCount, cTemp, 10 ) ); + sNrOfHandleLeaks.append( ";" ); + m_DataSaver.SaveXML( sNrOfHandleLeaks, SUBTEST_HANDLE_LEAKS ); + } + else + { + // No handle leaks + m_DataSaver.AddString( TEXT_NO_HANDLE_LEAKS ); + m_DataSaver.AddLineToLast(); + } + // Save xml + m_DataSaver.SaveXML( sTime, TEST_END ); + // Back to normal leaks + m_bSubtestOnGoing = false; + return true; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::ParseErrorOccured +// ----------------------------------------------------------------------------- +bool CATDatParser::ParseErrorOccured( string& sLine ) +{ + LOG_FUNC_ENTRY("CATDatParser::ParseErrorOccured"); + string sTime,sError; + + // Skip text "ERROR_OCCURED:" + GetStringUntilNextSpace( sLine ); + + // Get error + sError = GetStringUntilNextSpace( sLine ); + // Get and convert error time + sTime = GetStringUntilNextSpace( sLine ); + sTime = ConvertTimeToLocalTime( sTime ); + + // Print error line + m_DataSaver.AddLineToLast(); + m_DataSaver.AddString( "Error occured on: " ); + m_DataSaver.AddString( sTime.c_str() ); + m_DataSaver.AddString( ". " ); + m_DataSaver.AddString( "Symbian error code: " ); + m_DataSaver.AddString( sError.c_str() ); + m_DataSaver.AddString( "." ); + m_DataSaver.AddLineToLast(); + + return true; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::ParseMemLeak +// ----------------------------------------------------------------------------- +bool CATDatParser::ParseMemLeak( string& sLine ) +{ + LOG_FUNC_ENTRY("CATDatParser::ParseMemLeak"); + // Increment leak count + if ( ! m_bSubtestOnGoing ) + m_iTotalNumberOfLeaks++; + + // Increase leak number + m_iLeakNumber++; + + // Leak data variables + string sModuleName; + string sLeakSize; + string sTime; + unsigned long long iTime = 0; + string sLeakAddress; + + // Skip text "MEM_LEAK" + GetStringUntilNextSpace( sLine ); + // Get leak address + sLeakAddress = GetStringUntilNextSpace( sLine ); + // Get time + sTime = GetStringUntilNextSpace( sLine ); + // Convert time to decimal + hexToDec( sTime, iTime ); + // Get memory reserve size + sLeakSize = GetStringUntilNextSpace( sLine ); + // Convert leak time + sTime = ConvertTimeToLocalTime( sTime ); + + // Loop thru call stack and put memory addresses in vector + CleanMemoryAddresses(); // Clean memory address vector + CATMemoryAddress* pMemAddr = 0; + vector<string> vStrings = ParseStringToVector( sLine, ' ' ); + for( size_t i = 0; i < vStrings.size() ; i++ ) + { + pMemAddr = new CATMemoryAddress( vStrings.at(i), m_iOffSet ); + // Set address time + pMemAddr->SetTime( iTime ); + // Set address module name + if ( pMemAddr->FindSetModuleName( &m_vDllLoadModList ) ) + { + // Increment leaks in module once + if ( sModuleName.empty() ) + { + if ( m_bSubtestOnGoing ) + m_vDllLoadModListSubTest.at( pMemAddr->GetDllLoadInfoIndex() ).iLeaks++; + else + m_vDllLoadModList.at( pMemAddr->GetDllLoadInfoIndex() ).iLeaks++; + // Set leak's module where it was located. + sModuleName = pMemAddr->GetModuleName(); + } + } + // Add it to vector + m_vMemoryAddress.push_back( pMemAddr ); + } + // If logging level is 0 Skip printing / locating code lines for call stack items. + if ( m_iLogLevel == 0 ) + return true; + if ( m_pModules && vStrings.size() > 0 ) + { + // Have we successfully located code line for memory address + bool bSuccesfullAddressToLine = false; + for( size_t x = 0; x < m_vMemoryAddress.size(); x++ ) + { + int iIndexInDll = m_vMemoryAddress.at( x )->GetDllLoadInfoIndex(); + if ( iIndexInDll != -1 ) + { + // Dll module name from data file + string sDllName = m_vDllLoadModList.at( iIndexInDll ).sModuleName; + // Find module from project. These are read from makefiles. + for ( size_t y = 0; y < m_pModules->size() ; y++ ) + { + // Module name from project data (makefiles) + string sModuleName = m_pModules->at( y )->GetBinaryName(); + // If we find module from project ones, use it to located code line for memory address + // Note! dll names can be pretty messy i.e. DLL_LOAD 10281fc6.dll{000a0000}[10281fc6] 81d57b88 81e60a90 + if ( sDllName.find( sModuleName ) != string::npos ) + { + m_pModules->at( y )->AddressToLine( m_vMemoryAddress.at( x ) ); + if ( ! bSuccesfullAddressToLine ) + { + int iPPState = m_vMemoryAddress.at( x )->GetAddressToLineState(); + if ( iPPState == CATMemoryAddress::EXACT || iPPState == CATMemoryAddress::FUNCTION ) + { + bSuccesfullAddressToLine = true; + if ( m_bSubtestOnGoing ) + m_iPinPointedSubTestLeaks++; + else + m_iPinPointedLeaks++; + } + } + } + } + } + } + // If rom/rofs specified we use it to try get binary and function names + // for addresses currently out of process range. + if ( m_pRomSymbol ) + { + for( size_t x = 0; x < m_vMemoryAddress.size(); x++ ) + { + if ( m_vMemoryAddress.at(x)->GetAddressToLineState() == CATMemoryAddress::OUT_OF_PROCESS + || m_vMemoryAddress.at(x)->GetAddressToLineState() == CATMemoryAddress::OUT_OF_RANGE ) + { + m_pRomSymbol->AddressToLine( m_vMemoryAddress.at(x) ); + } + } + } + } + // Print leak + PrintMemLeak( sTime, sLeakSize, sLeakAddress, sModuleName); + return true; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::PrintMemLeak +// ----------------------------------------------------------------------------- +void CATDatParser::PrintMemLeak(const string& sTime, + const string& sLeakSize, + const string& sLeakAddr, + const string& sModuleName) +{ + LOG_FUNC_ENTRY("CATDatParser::PrintMemLeak"); + // Print header data of leak + m_DataSaver.AddString("\nMemory leak "); + m_DataSaver.AddInteger( m_iLeakNumber, true); + + // Leak size + m_DataSaver.AddString( " (" ); + m_DataSaver.AddInteger( _httoi( sLeakSize.c_str() ), true ); + m_DataSaver.AddString( " bytes) " ); + + // Leak address + m_DataSaver.AddString("(0x"); + m_DataSaver.AddString( sLeakAddr.c_str(), true ); + m_DataSaver.AddString( ") " ); + + // Time + m_DataSaver.AddString( sTime.c_str(), true ); + m_DataSaver.AddString( " " ); + + // Module name + m_DataSaver.AddString( sModuleName.c_str(), true ); + m_DataSaver.SaveCarbideDataHeader(); + + // Add header line + m_DataSaver.AddLineToLast(); + + // Print the call stack items + for( size_t i = 0 ; i < m_vMemoryAddress.size() ; i++ ) + { + // On log levels 1 & 2 we only print located code lines. + #ifndef ADDR2LINE + if( + ( m_iLogLevel == 1 || m_iLogLevel == 2 ) + && + ( m_vMemoryAddress.at(i)->GetAddressToLineState() != CATMemoryAddress::EXACT + && m_vMemoryAddress.at(i)->GetAddressToLineState() != CATMemoryAddress::FUNCTION ) + ) + { + // Skips to next + continue; + } + #endif + #ifdef ADDR2LINE + if( ( m_iLogLevel == 1 || m_iLogLevel == 2 ) + && m_vMemoryAddress.at(i)->GetAddressToLineState() != CATMemoryAddress::EXACT ) + { + // Skips to next + continue; + } + #endif + else if ( m_vMemoryAddress.at(i)->GetAddressToLineState() == CATMemoryAddress::OUT_OF_PROCESS ) + { + // Is memory address out of modules range + string sTemp; + sTemp.append( m_vMemoryAddress.at(i)->GetAddressString() ); + sTemp.append( " Address out of process memory."); + m_DataSaver.AddString( sTemp.c_str(), true ); + m_DataSaver.AddLineToLast(); + continue; + } + + // Print memory address + m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetAddressString().c_str(), true ); + + // Space (only for console output) + m_DataSaver.AddString( " " ); + + m_DataSaver.AddCarbideData( + NumberToHexString( m_vMemoryAddress.at(i)->GetOffSetFromModuleStart() ) ); + + // Module name + m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetModuleName().c_str(), true ); + + // Print call stack memory address details depending on state of memory address + switch( m_vMemoryAddress.at(i)->GetAddressToLineState() ) + { + // Address outside of known processes + case CATMemoryAddress::OUT_OF_PROCESS: + m_DataSaver.AddLineToLast(); + break; + // Address located outside of known modules symbols + case CATMemoryAddress::OUT_OF_RANGE: + m_DataSaver.AddString( " " ); + m_DataSaver.AddString( "???", true ); + m_DataSaver.AddLineToLast(); + break; + // Symbol state is currently used when using rom symbol file. + // From it we get module name & function name. + case CATMemoryAddress::SYMBOL: + m_DataSaver.AddString( " " ); + m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFunctionName().c_str(), true ); + if ( ! m_vMemoryAddress.at( i )->GetFileName().empty() ) + { + m_DataSaver.AddString( " (" ); + m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFileName().c_str(), true ); + m_DataSaver.AddString( ")" ); + } + m_DataSaver.AddLineToLast(); + break; + // Lst & Map implementation + #ifndef ADDR2LINE + case CATMemoryAddress::FUNCTION: + case CATMemoryAddress::EXACT: + m_DataSaver.AddString( " " ); + m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFunctionName().c_str(), true ); + // Small difference displaying details depending on build urel/udeb + if ( m_eBuildType == CATProject::UREL ) + { + // UREL + // Set build info to data saver + m_DataSaver.SetBuild( false ); + // urel = functionname: linenumber (filename) + m_DataSaver.AddString( ": " ); + if ( m_vMemoryAddress.at(i)->GetFunctionLineNumber() != -1 ) + m_DataSaver.AddInteger( m_vMemoryAddress.at(i)->GetFunctionLineNumber(), true ); + else if ( m_vMemoryAddress.at(i)->GetExactLineNumber() != -1 ) + m_DataSaver.AddInteger( m_vMemoryAddress.at(i)->GetExactLineNumber(), true ); + m_DataSaver.AddString( " (" ); + m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFileName().c_str(), true ); + m_DataSaver.AddString( ")" ); + m_DataSaver.AddLineToLast(); + } + else + { + // UDEB + // udeb = functionname: (filename:linenumber) + m_DataSaver.AddString( " (" ); + m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFileName().c_str(), true ); + m_DataSaver.AddString( ":" ); + if( m_vMemoryAddress.at(i)->GetExactLineNumber() != -1 ) + m_DataSaver.AddInteger( m_vMemoryAddress.at(i)->GetExactLineNumber(), true ); + else + m_DataSaver.AddString( "???", true ); + m_DataSaver.AddString( ")" ); + m_DataSaver.AddLineToLast(); + } + break; + #endif + // addr2line implementation (new). + #ifdef ADDR2LINE + case CATMemoryAddress::FUNCTION: + m_DataSaver.AddString( " " ); + m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFunctionName().c_str(), true ); + m_DataSaver.AddString( " (" ); + m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFileName().c_str(), true ); + m_DataSaver.AddString( ":" ); + if( m_vMemoryAddress.at(i)->GetExactLineNumber() != -1 ) + m_DataSaver.AddInteger( m_vMemoryAddress.at(i)->GetFunctionLineNumber(), true ); + else + m_DataSaver.AddString( "???", true ); + m_DataSaver.AddString( ")" ); + m_DataSaver.AddLineToLast(); + break; + case CATMemoryAddress::EXACT: + m_DataSaver.AddString( " " ); + m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFunctionName().c_str(), true ); + m_DataSaver.AddString( " (" ); + m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFileName().c_str(), true ); + m_DataSaver.AddString( ":" ); + if( m_vMemoryAddress.at(i)->GetExactLineNumber() != -1 ) + m_DataSaver.AddInteger( m_vMemoryAddress.at(i)->GetExactLineNumber(), true ); + else + m_DataSaver.AddString( "???", true ); + m_DataSaver.AddString( ")" ); + m_DataSaver.AddLineToLast(); + break; + #endif + } // End switch + // On logging level 1 we only print one located code line + #ifndef ADDR2LINE + if ( m_iLogLevel == 1 && ( m_vMemoryAddress.at(i)->GetAddressToLineState() == CATMemoryAddress::EXACT || + m_vMemoryAddress.at(i)->GetAddressToLineState() == CATMemoryAddress::FUNCTION ) ) + break; + #endif + #ifdef ADDR2LINE + if ( m_iLogLevel == 1 && m_vMemoryAddress.at(i)->GetAddressToLineState() == CATMemoryAddress::EXACT ) + break; + #endif + } // End call stack items loop +} + +// ----------------------------------------------------------------------------- +// CATDatParser::SetInputFile +// ----------------------------------------------------------------------------- +void CATDatParser::SetInputFile(const string& sInputFile) +{ + LOG_FUNC_ENTRY("CATDatParser::SetInputFile"); + m_sInputFile = sInputFile; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::SetOutputFile +// ----------------------------------------------------------------------------- +void CATDatParser::SetOutputFile(const string& sOutpuFile) +{ + LOG_FUNC_ENTRY("CATDatParser::SetOutputFile"); + m_sOutputFile = sOutpuFile; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::SetRomSymbolFiles +// ----------------------------------------------------------------------------- +void CATDatParser::SetRomSymbolFiles(const vector<string>& vRomSymbolFiles) +{ + LOG_FUNC_ENTRY("CATDatParser::SetRomSymbolFiles"); + m_vRomSymbolFiles = vRomSymbolFiles; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::SetLogLevel +// ----------------------------------------------------------------------------- +void CATDatParser::SetLogLevel(int iLogLevel) +{ + LOG_FUNC_ENTRY("CATDatParser::SetLogLevel"); + m_iLogLevel = iLogLevel; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::GetLogLevel +// ----------------------------------------------------------------------------- +int CATDatParser::GetLogLevel() const +{ + LOG_LOW_FUNC_ENTRY("CATDatParser::GetLogLevel"); + return m_iLogLevel; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::CleanMemoryAddresses +// ----------------------------------------------------------------------------- +void CATDatParser::CleanMemoryAddresses() +{ + LOG_LOW_FUNC_ENTRY("CATDatParser::CleanMemoryAddresses"); + // Cleanup memory addressses. + for( vector<CATMemoryAddress*>::iterator it = m_vMemoryAddress.begin(); it != m_vMemoryAddress.end(); it++ ) + { + delete *it; + } + m_vMemoryAddress.clear(); +} + +// ----------------------------------------------------------------------------- +// CATDatParser::ConvertTimeToLocalTime +// ----------------------------------------------------------------------------- +string CATDatParser::ConvertTimeToLocalTime( string sInputTime ) +{ + LOG_LOW_FUNC_ENTRY("CATDatParser::ConvertTimeToLocalTime"); + //Is process end abnormal? + if( sInputTime.compare( LABEL_ABNORMAL ) == 0 ) + { + return string( AT_ANALYZE_ABNORMAL_EXIT ); + } + else + // Check that input time is at least 32-bit + if( sInputTime.length() <= 8 ) + { + sInputTime.clear(); + return sInputTime; + } + + string sTemp = sInputTime; + const char* pTemp = sTemp.c_str(); + + // Are all characters hex + for( unsigned int i = 0 ; i < sTemp.size() ; i++ ) + { + if( !IsHexCharacter( (pTemp + i) ) ) + { + return sInputTime; + } + } + + // Get LSB bits + string sLsb; + sLsb.append( sInputTime.substr( sInputTime.length()-8, sInputTime.length() ) ); + unsigned int iLsbTime = (unsigned int)_httoi( sLsb.c_str() ); + + // Get MSB bits + string sMsb; + sMsb.append( sInputTime.substr( 0, sInputTime.length()-8 ) ); + unsigned int iMsbTime = (unsigned int)_httoi( sMsb.c_str() ); + + // Get time in microsecods + long long sdf = iMsbTime * 0x100000000 + iLsbTime; + + // Get original time (starting at year 1970 ) + long long llOrigTime = sdf; + + // Get seconds + sdf = ( sdf )/1000000; + + // Check that sdf contains some time value + if( sdf <= 0) + { + // Error in time calculation + // Return empty string + sInputTime.clear(); + return sInputTime; + } + + // Original time after year 1970 in seconds + long long llOrignTimeInSeconds = sdf; + + // Calculate new time which does not include millisecods + long long llDiffTime = (llOrignTimeInSeconds * 1000000); + + // Calculate time difference in milliseconds + int llDiffTimeInMilliSecods = (int)( llOrigTime - llDiffTime )/1000; + + // Convert difference time to char + char cDiffInMilliSeconds[20]; + _itoa( llDiffTimeInMilliSecods, cDiffInMilliSeconds, 10 ); + + // Time info structure + struct tm *timeinfo; + + // Get local time + timeinfo = localtime ( (time_t*) &sdf ); + + // Create string and append memory leak time to it + string sTime; + sTime.append( asctime( timeinfo ) ); + + // Remove last char of locale time string which is \n + sTime.resize( (int)sTime.length()-1 ); + + // Get last space index + int iLastSpace = (int)sTime.find_last_of(" "); + + // If last space index is valid + if( iLastSpace <= (int)sTime.length() && iLastSpace > 0) + { + string sTempTime; + // Append first part of original time string + sTempTime.append( sTime.substr( 0, iLastSpace ) ); + + // Append millisecods + sTempTime.append( "." ); + sTempTime.append( cDiffInMilliSeconds ); + + // Append the rest of the original time string part + sTempTime.append( sTime.substr( iLastSpace, sTime.length())); + + // Clear original and append new time string which includes millisecods + sTime.clear(); + sTime.append( sTempTime ); + } + + // Return memory leak time + return sTime.c_str(); +} + +bool CATDatParser::CreateWinscwModule( const string& sBinaryName ) +{ + LOG_FUNC_ENTRY( "CATDatParser::CreateWinscwModule" ); + // Is module already created? + for( vector<CATModule2*>::iterator it = m_pModules->begin(); it != m_pModules->end(); it++ ) + { + if ( _stricmp( sBinaryName.c_str(), (*it)->GetBinaryName().c_str() ) == 0 ) + return true; + } + // No create new one and set its values. + CATModule2* mod = new CATModule2(); + mod->SetTarget( RemovePathAndExt( sBinaryName, true ) ); + mod->SetRequestedTargetExt( GetExtension( sBinaryName ) ); + mod->SetReleasePath( string( "\\epoc32\\release" ) ); + if ( m_eBuildType == CATProject::UDEB ) + mod->SetFullVariantPath( string( "winscw\\udeb" ) ); + else + mod->SetFullVariantPath( string( "winscw\\urel" ) ); + mod->SetVariantPlatform( string( "winscw" ) ); + m_pModules->push_back( mod ); + return true; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::FindModuleUsingAddress +// Function finds module using given address. +// ----------------------------------------------------------------------------- +int CATDatParser::FindModuleUsingAddress( unsigned long iAddress ) const +{ + LOG_LOW_FUNC_ENTRY("CATDatParser::FindModuleUsingAddress"); + int iRet = -1; + for( unsigned int i = 0 ; i < m_vDllLoadModList.size() ; i++ ) + { + // Is address between start and end address? + if( iAddress > m_vDllLoadModList[i].iStartAddress && iAddress < m_vDllLoadModList[i].iEndAddress ) + { + iRet = i; + break; + } + } + return iRet; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::FindModuleUsingPID +// Function finds module using module id. +// ----------------------------------------------------------------------------- +/* +int CATDatParser::FindModuleUsingPID( unsigned long iPID ) const +{ + LOG_FUNC_ENTRY("CATDatParser::FindModuleUsingPID"); + + int iRet = -1; + + // Change module name characters to lowercase + for( unsigned int i = 0 ; i < m_vDllLoadModList.size() ; i++ ) + { + if( m_vDllLoadModList[i].iPID == iPID ) + { + iRet = i; + break; + } + } + return iRet; +} +*/ +// ----------------------------------------------------------------------------- +// CATDatParser::FindModuleUsingName +// Function finds module using module name. +// ----------------------------------------------------------------------------- +int CATDatParser::FindModuleUsingName( const char* pModName ) +{ + LOG_LOW_FUNC_ENTRY("CATDatParser::FindModuleUsingName"); + + // Mod name empty? + if( pModName == NULL || *pModName == 0 ) + return -1; + + int iRet = -1; + string sModName( pModName ); + // Change module name characters to lowercase + ChangeToLower( sModName ); + // Remove variant marks (dots) + RemoveAllAfterDotIfTwoDots( sModName); + for( unsigned int i = 0 ; i < m_vDllLoadModList.size() ; i++ ) + { + string sTemp( m_vDllLoadModList[i].sModuleName ); + ChangeToLower( sTemp ); + // Remove variant marks (dots) + RemoveAllAfterDotIfTwoDots( sTemp ); + if( sTemp.find( sModName ) != string::npos ) + { + iRet = i; + break; + } + } + return iRet; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::SetPrintFlag +// ----------------------------------------------------------------------------- +void CATDatParser::SetPringFlag( bool bPrintFlag ) +{ + LOG_FUNC_ENTRY("CATDatParser::SetPringFlag"); + m_DataSaver.SetPrintFlag( bPrintFlag ); +} +// ----------------------------------------------------------------------------- +// CATDatParser::SetOffSet +// ----------------------------------------------------------------------------- +void CATDatParser::SetOffSet( int iOffSet ) +{ + LOG_FUNC_ENTRY("CATDatParser::SetOffSet"); + m_iOffSet = iOffSet; +} + +// ----------------------------------------------------------------------------- +// CATDatParser::GetOffSet +// ----------------------------------------------------------------------------- +int CATDatParser::GetOffSet( ) const +{ + LOG_LOW_FUNC_ENTRY("CATDatParser::GetOffSet"); + return m_iOffSet; +} + +// ----------------------------------------------------------------------------- +// Set project platform. +// ----------------------------------------------------------------------------- +void CATDatParser::SetProjectPlatform( const string& sPlatform ) +{ + LOG_FUNC_ENTRY("CATDatParser::SetProjectPlatform"); + m_sProjectPlatform = sPlatform; + + // Check that platform not empty before determing platform from it. + if ( sPlatform.empty() ) + return; + + // Set functions offset in mapfiles correct (depending on platform). + if ( _stricmp( sPlatform.c_str(), "armv5" ) == 0 ) + { + m_iOffSet = FUNCTIONS_OFFSET_IN_MAP_FILE_ARMV5; + } + else if ( _stricmp( sPlatform.c_str(), "winscw" ) == 0 ) + { + m_iOffSet = FUNCTIONS_OFFSET_IN_MAP_FILE_WINSCW; + } + else if ( _stricmp( sPlatform.c_str(), "gcce" ) == 0 ) + { + m_iOffSet = FUNCTIONS_OFFSET_IN_GCCE; + } + else + { + LOG_STRING( AT_MSG << "Error, cannot set function's offset in map file, invalid platform: " << sPlatform ); + } +} + +// ----------------------------------------------------------------------------- +// Set projects build type. Use enumeration defined in CATProject. +// ----------------------------------------------------------------------------- +void CATDatParser::SetProjectBuildType( int eBuildType ) +{ + LOG_FUNC_ENTRY("CATDatParser::SetProjectBuildType"); + m_eProjectBuildType = eBuildType; +} + +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/CATDataSaver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/CATDataSaver.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,873 @@ +/* +* 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 CATDataSaver. +* +*/ + + +#include "../inc/catdatasaver.h" + +#include <xercesc/util/OutOfMemoryException.hpp> + +#if defined(XERCES_NEW_IOSTREAMS) +#include <iostream> +#else +#include <iostream.h> +#endif + +// Line feed char sequence used in XML report +wchar_t AT_XML_LINEFEEDS[3] = L"\r\n"; + +// ----------------------------------------------------------------------------- +// CATDataSaver::CATDataSaver +// Constructor. +// ----------------------------------------------------------------------------- +CATDataSaver::CATDataSaver( void ) +{ + LOG_FUNC_ENTRY("CATDataSaver::CATDataSaver"); + m_iLoggingLevel = DEFAULT_LOGGING_LEVEL; + m_bPrintImmediately = true; + m_bXMLInitOk = false; + m_bUdebBuild = true; + + m_iRunNumber = 1; + + m_pDomDoc = NULL; + m_pRootElem = NULL; + m_Serializer = NULL; + m_pCurrentLeakElem = NULL; + m_pRunElement = NULL; + m_pMemoryLeaks = NULL; + m_pHandleLeaks = NULL; + m_pCurrentSubTestElem = NULL; + m_pSubtestMemoryLeaks = NULL; +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::~CATDataSaver +// Destructor. +// ----------------------------------------------------------------------------- +CATDataSaver::~CATDataSaver(void) +{ + LOG_FUNC_ENTRY("CATDataSaver::~CATDataSaver"); + if( m_bXMLInitOk ) + { + if( m_Serializer ) + delete m_Serializer; + + m_pDomDoc->release(); + xercesc::XMLPlatformUtils::Terminate(); + } +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::SaveLinesToFile +// Gets logging level. +// ----------------------------------------------------------------------------- +void CATDataSaver::SaveLinesToFile( const char* pFileName, int iDataToSave ) +{ + LOG_FUNC_ENTRY("CATDataSaver::SaveLinesToFile"); + + // Nothing to print? + if( m_vLines.empty() ) + { + printf( "No output data." ); + return; + } + if( iDataToSave != XML_DATA ) + { + ofstream out( pFileName ); + + if( !out.good() ) + { + printf( "Can not open file: %s\n", pFileName ); + return; + } + switch( iDataToSave ) + { + case TEXT_DATA: + for( int i = 0 ; i < (int)m_vLines.size() ; i++ ) + { + out << m_vLines[i].c_str(); + } + break; + } + out.close(); + } + else + { + if( m_bXMLInitOk ) + { + xercesc::XMLFormatTarget* myFormTarget = NULL; + try + { + // Create format + myFormTarget = new xercesc::LocalFileFormatTarget( pFileName ); + + // Set line-feeds to dom writer + m_Serializer->setNewLine( AT_XML_LINEFEEDS ); + + // Set human-readable property. Note! Api already changed in >2.7 + // so this will cause error/problems if linked to newer library. + m_Serializer->setFeature( xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true ); + + // Write document + m_Serializer->writeNode(myFormTarget, *m_pDomDoc); + } + catch(...) + { + printf( "Can not save output file: %s.", pFileName ); + } + if( myFormTarget ) + delete myFormTarget; //lint !e118 + } + } +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::PrintLinesToScreen +// Prints all saved lines to screen. +// ----------------------------------------------------------------------------- +void CATDataSaver::PrintLinesToScreen( void ) +{ + LOG_FUNC_ENTRY("CATDataSaver::PrintLinesToScreen"); + // Nothing to print? + if( m_vLines.empty() ) + { + printf( "No output data." ); + return; + } + for( int i = 0 ; i < (int)m_vLines.size() ; i++ ) + { + printf( m_vLines[i].c_str() ); + } +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::AddLineToFirst +// Adds saved line to first in database. +// ----------------------------------------------------------------------------- +void CATDataSaver::AddLineToFirst( void ) +{ + LOG_LOW_FUNC_ENTRY("CATDataSaver::AddLineToFirst"); + m_sLine.append( "\n" ); + m_vLines.insert( m_vLines.begin(), m_sLine ); + m_sLine.clear(); +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::AddLineToLast +// Adds saved line to last in database. +// ----------------------------------------------------------------------------- +void CATDataSaver::AddLineToLast() +{ + LOG_LOW_FUNC_ENTRY("CATDataSaver::AddLineToLast"); + m_sLine.append( "\n" ); + + string sTempDataLine; + + m_vLines.push_back( m_sLine ); + + SaveXML( m_sCarbideDataLine, ITEM ); + + if( m_bPrintImmediately ) + { + printf( m_sLine.c_str() ); + } + + m_sCarbideDataLine.clear(); + m_sLine.clear(); +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::AddString +// Adds string to current line. +// ----------------------------------------------------------------------------- +void CATDataSaver::AddString( const char* pData, bool bSaveCarbideData ) +{ + LOG_LOW_FUNC_ENTRY("CATDataSaver::AddString"); + m_sLine.append( pData ); + + if( bSaveCarbideData ) + { + m_sCarbideDataLine.append( pData ); + m_sCarbideDataLine.append(";"); + } +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::AddInteger +// Converts integer to string and adds it to current line. +// ----------------------------------------------------------------------------- +void CATDataSaver::AddInteger( int iValue, bool bSaveCarbideData ) +{ + LOG_LOW_FUNC_ENTRY("CATDataSaver::AddInteger"); + char cTemp[128]; + string sValue( itoa( iValue, cTemp, 10 ) ); + m_sLine.append( sValue ); + + if( bSaveCarbideData ) + { + m_sCarbideDataLine.append( sValue ); + m_sCarbideDataLine.append(";"); + } +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::SetLoggingLevel +// Sets logging level. +// ----------------------------------------------------------------------------- +void CATDataSaver::SetLoggingLevel( int iLoggingLevel ) +{ + LOG_FUNC_ENTRY("CATDataSaver::SetLoggingLevel"); + // Check that new logging level is valid + // Acceptable values are between MIN_LOGGING_LEVEL and + // MAX_LOGGING_LEVEL including them + if( iLoggingLevel >= MIN_LOGGING_LEVEL && iLoggingLevel <= MAX_LOGGING_LEVEL ) + { + m_iLoggingLevel = iLoggingLevel; + } + else + { + // New logging level value is invalid => set default logging level + m_iLoggingLevel = DEFAULT_LOGGING_LEVEL; + } +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::GetLoggingLevel +// Gets logging level. +// ----------------------------------------------------------------------------- +int CATDataSaver::GetLoggingLevel( void ) +{ + LOG_LOW_FUNC_ENTRY("CATDataSaver::GetLoggingLevel"); + return m_iLoggingLevel; +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::SetPrintFlag +// Sets print immediately flag. +// ----------------------------------------------------------------------------- +void CATDataSaver::SetPrintFlag( bool bPrintImmediately ) +{ + LOG_FUNC_ENTRY("CATDataSaver::SetPrintFlag"); + m_bPrintImmediately = bPrintImmediately; +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::SaveCarbideDataHeader +// Sets data header for Carbide data. +// ----------------------------------------------------------------------------- +void CATDataSaver::SaveCarbideDataHeader( void ) +{ + LOG_FUNC_ENTRY("CATDataSaver::SaveCarbideDataHeader"); + SaveXML( m_sCarbideDataLine, LEAK ); + m_sCarbideDataLine.clear(); +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::InitXML +// Initializes xerces xml parser. +// ----------------------------------------------------------------------------- +bool CATDataSaver::InitXML( void ) +{ + LOG_FUNC_ENTRY("CATDataSaver::InitXML"); + try + { + xercesc::XMLPlatformUtils::Initialize(); + } + catch ( ... )//(const XMLException& toCatch) + { + // Do your failure processing here + printf("XML initialization failed.\n"); + return false; + } + // Error code. + int errorCode = 0; + // getDomIMplementation returns null if source has none. + xercesc::DOMImplementation* impl = xercesc::DOMImplementationRegistry::getDOMImplementation(L"Core"); + if (impl != NULL) + { + // Create new DOMWriter. + m_Serializer = ((xercesc::DOMImplementationLS*)impl)->createDOMWriter(); + // New document. + try + { + m_pDomDoc = impl->createDocument( + 0, // Root element namespace URI. + L"results", // Root element name + 0); // Document type object (DTD). + + m_pRootElem = m_pDomDoc->getDocumentElement(); + } + catch (const xercesc::OutOfMemoryException&) + { + XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER endl; + errorCode = 5; + } + catch (const xercesc::DOMException& e) + { + XERCES_STD_QUALIFIER cerr << "DOMException code is: " << e.code << XERCES_STD_QUALIFIER endl; + errorCode = 2; + } + catch (...) + { + XERCES_STD_QUALIFIER cerr << "An error occurred creating the document" << XERCES_STD_QUALIFIER endl; + errorCode = 3; + } + } // (inpl != NULL) + else + { + XERCES_STD_QUALIFIER cerr << "Requested implementation is not supported" << XERCES_STD_QUALIFIER endl; + errorCode = 4; + } + if( !errorCode ) + { + m_bXMLInitOk = true; + return true; + } + else + { + return false; + } +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::WCharToChar +// Converts wchar_t* -> char*. +// ----------------------------------------------------------------------------- +void CATDataSaver::WCharToChar( string& sInput, const WCHAR* Source ) +{ + LOG_LOW_FUNC_ENTRY("CATDataSaver::WCharToChar"); + if( !Source ) + return; + int i = 0; + + while( Source[i] != '\0' ) + { + char c = (CHAR)Source[i]; + sInput.append( &c, 1 ); + ++i; + } +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::CharToWChar +// Converts char* -> wchar_t*. +// ----------------------------------------------------------------------------- +LPWSTR CATDataSaver::CharToWChar( const char* str ) +{ + LOG_LOW_FUNC_ENTRY("CATDataSaver::CharToWChar"); + LPWSTR out = NULL; + if( str != NULL ) + { + int in_len = (int)strlen( str ); + int out_len = MultiByteToWideChar(CP_ACP, 0, str, in_len, NULL, 0) + 2; + out = new WCHAR[out_len]; + + if (out) + { + memset(out, 0x00, sizeof(WCHAR)*out_len); + MultiByteToWideChar(CP_ACP, 0, str, in_len, out, in_len); + } + } + return out; +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::SaveXML +// Writes data to xml tree. +// ----------------------------------------------------------------------------- +void CATDataSaver::SaveXML( string sInput, int iElementType ) +{ + LOG_FUNC_ENTRY("CATDataSaver::SaveXML"); + // Variables ok? + if( sInput.empty() || m_pDomDoc == NULL ) + { + return; + } + try + { + switch( iElementType ) + { + case RESULT: + { + // Print number of runs + string sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + LPWSTR wTemp = CharToWChar( sTemp.c_str() ); + m_pRootElem->setAttribute( L"runs", (const LPWSTR)wTemp ); + + // Print failed runs + sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + if( wTemp ) + delete[] wTemp; + wTemp = CharToWChar( sTemp.c_str() ); + m_pRootElem->setAttribute( L"failed", (const LPWSTR)wTemp ); + if( wTemp ) + delete[] wTemp; + } + break; + case RUN: + { + if( m_pRootElem == NULL ) + return; + xercesc::DOMElement* runElem = m_pDomDoc->createElement( L"run" ); + m_pRootElem->appendChild( runElem ); + + // Reset handle leaks. + m_pHandleLeaks = NULL; + + // Print start time + string sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + LPWSTR wTemp = CharToWChar( sTemp.c_str() ); + runElem->setAttribute( L"start_time", (const LPWSTR)wTemp ); + runElem->setAttribute( L"end_time", NULL ); + if( wTemp ) + delete[] wTemp; + + // Print build target + sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + wTemp = CharToWChar( sTemp.c_str() ); + runElem->setAttribute( L"build_target", (const LPWSTR)wTemp ); + if( wTemp ) + delete[] wTemp; + + // Print process name + wTemp = CharToWChar( sInput.c_str() ); + runElem->setAttribute( L"process_name", (const LPWSTR)wTemp ); + + m_pRunElement = runElem; + + char cTemp[128]; + if( wTemp ) + delete[] wTemp; + wTemp = CharToWChar( itoa( m_iRunNumber, cTemp, 10 ) ); + runElem->setAttribute( L"id", (const LPWSTR)wTemp ); + m_iRunNumber++; + if( wTemp ) + delete[] wTemp; + } + break; + case LEAK: + { + m_pCurrentLeakElem = m_pDomDoc->createElement( L"leak" ); + + + if( m_pCurrentLeakElem == NULL || m_pRunElement == NULL ) + return; + + // Sub test? + if( m_pCurrentSubTestElem ) + m_pCurrentSubTestElem->appendChild( m_pCurrentLeakElem ); + else + m_pRunElement->appendChild( m_pCurrentLeakElem ); + + // Print leak ID + string sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + LPWSTR wTemp = CharToWChar( sTemp.c_str() ); + m_pCurrentLeakElem->setAttribute( L"id", (const LPWSTR)wTemp ); + + // Print leak size + sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + if( wTemp ) + delete[] wTemp; + wTemp = CharToWChar( sTemp.c_str() ); + m_pCurrentLeakElem->setAttribute( L"size", (const LPWSTR)wTemp ); + + // Print leak address + sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + if( wTemp ) + delete[] wTemp; + wTemp = CharToWChar( sTemp.c_str() ); + m_pCurrentLeakElem->setAttribute( L"memaddress", (const LPWSTR)wTemp ); + + // Print leak time + sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + if( wTemp ) + delete[] wTemp; + wTemp = CharToWChar( sTemp.c_str() ); + m_pCurrentLeakElem->setAttribute( L"time", (const LPWSTR)wTemp ); + + // Print leak module + sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + if( wTemp ) + delete[] wTemp; + wTemp = CharToWChar( sTemp.c_str() ); + m_pCurrentLeakElem->setAttribute( L"module", (const LPWSTR)wTemp ); + if( wTemp ) + delete[] wTemp; + } + break; + case ITEM: + { + xercesc::DOMNode* callstackNode = NULL; + + xercesc::DOMElement* callstackElem = NULL; + + if( m_pCurrentLeakElem == NULL ) + return; + + // Print module name + if( !m_pCurrentLeakElem->hasChildNodes() ) + { + callstackElem = m_pDomDoc->createElement( L"callstack" ); + m_pCurrentLeakElem->appendChild( callstackElem ); + callstackNode = callstackElem; + } + else + { + callstackNode = m_pCurrentLeakElem->getFirstChild(); + } + + // Add callstack item + xercesc::DOMElement* itemElem = m_pDomDoc->createElement( L"item" ); + callstackNode->appendChild( itemElem ); + + // Print memory address name + string sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + LPWSTR wTemp = CharToWChar( sTemp.c_str() ); + + itemElem->setAttribute( L"memaddress", (const LPWSTR)wTemp ); + + // Print calculated memory address + sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + if( wTemp ) + delete[] wTemp; + wTemp = CharToWChar( sTemp.c_str() ); + + itemElem->setAttribute( L"calc_addr", (const LPWSTR)wTemp ); + + // Print module name + sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + if( wTemp ) + delete[] wTemp; + wTemp = CharToWChar( sTemp.c_str() ); + + itemElem->setAttribute( L"module", (const LPWSTR)wTemp ); + + // Print function name + sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + if( wTemp ) + delete[] wTemp; + wTemp = CharToWChar( sTemp.c_str() ); + + itemElem->setAttribute( L"function", (const LPWSTR)wTemp ); + + sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + + // Print function line from urel build + if( !m_bUdebBuild ) + { + if( wTemp ) + delete[] wTemp; + wTemp = CharToWChar( sTemp.c_str() ); + itemElem->setAttribute( L"function_line", (const LPWSTR)wTemp ); + sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + } + + // Print file name + if( wTemp ) + delete[] wTemp; + // Erase if path found from sTemp. + if ( sTemp.rfind( "/" ) != string::npos ) + { + sTemp.erase(0, sTemp.rfind( "/" )+1 ); + } + if ( sTemp.rfind( "\\" ) != string::npos ) + { + sTemp.erase(0, sTemp.rfind( "\\" )+1 ); + } + wTemp = CharToWChar( sTemp.c_str() ); + + itemElem->setAttribute( L"file", (const LPWSTR)wTemp ); + + // Print line of file + sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + if( wTemp ) + delete[] wTemp; + wTemp = CharToWChar( sTemp.c_str() ); + + if( m_bUdebBuild ) + itemElem->setAttribute( L"line", (const LPWSTR)wTemp ); + if( wTemp ) + delete[] wTemp; + } + break; + case RUN_END: + { + if( m_pRunElement == NULL ) + return; + const LPWSTR wTemp = CharToWChar( sInput.c_str() ); + m_pRunElement->setAttribute( L"end_time", wTemp ); + if( wTemp ) + delete[] wTemp; + } + break; + case ERROR_IN_RUN: + { + if( m_pRunElement == NULL ) + return; + // Add error item + xercesc::DOMElement* errorElem = m_pDomDoc->createElement( L"error" ); + m_pRunElement->appendChild( errorElem ); + + // Print error code + string sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + LPWSTR wTemp = CharToWChar( sTemp.c_str() ); + errorElem->setAttribute( L"code", (const LPWSTR)wTemp ); + + // Print error time + sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + if( wTemp ) + delete[] wTemp; + wTemp = CharToWChar( sTemp.c_str() ); + errorElem->setAttribute( L"time", (const LPWSTR)wTemp ); + if( wTemp ) + delete[] wTemp; + } + break; + case MEM_LEAKS: + { + if( m_pRunElement == NULL ) + return; + xercesc::DOMElement* memoryLeaksElement = m_pDomDoc->createElement( L"mem_leaks" ); + m_pRunElement->appendChild( memoryLeaksElement ); + m_pMemoryLeaks = memoryLeaksElement; + + // Print number of leaks + LPWSTR wTemp = CharToWChar( sInput.c_str() ); + memoryLeaksElement->setAttribute( L"count", (const LPWSTR)wTemp ); + if( wTemp ) + delete[] wTemp; + } + break; + case MEM_LEAK_MODULE: + { + if( m_pMemoryLeaks == NULL ) + return; + xercesc::DOMElement* moduleElement = m_pDomDoc->createElement( L"module" ); + m_pMemoryLeaks->appendChild( moduleElement ); + + // Print module name + string sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + LPWSTR wTemp = CharToWChar( sTemp.c_str() ); + moduleElement->setAttribute( L"name", (const LPWSTR)wTemp ); + + if( wTemp ) + delete[] wTemp; + // Print number of memory leaks + wTemp = CharToWChar( sInput.c_str() ); + moduleElement->setAttribute( L"leaks", (const LPWSTR)wTemp ); + if( wTemp ) + delete[] wTemp; + } + break; + case HANDLE_LEAKS: + { + if( m_pRunElement == NULL ) + return; + if( m_pHandleLeaks ) + { + // Update number of leaks + LPWSTR wTemp = CharToWChar( sInput.c_str() ); + m_pHandleLeaks->setAttribute( L"count", (const LPWSTR)wTemp ); + if( wTemp ) + delete[] wTemp; + } + else + { + xercesc::DOMElement* handleLeaksElement = m_pDomDoc->createElement( L"handle_leaks" ); + m_pRunElement->appendChild( handleLeaksElement ); + m_pHandleLeaks = handleLeaksElement; + + // Print number of leaks + LPWSTR wTemp = CharToWChar( sInput.c_str() ); + handleLeaksElement->setAttribute( L"count", (const LPWSTR)wTemp ); + if( wTemp ) + delete[] wTemp; + } + } + break; + case HANDLE_LEAK_MODULE: + { + if( m_pHandleLeaks == NULL ) + return; + xercesc::DOMElement* moduleElement = m_pDomDoc->createElement( L"module" ); + m_pHandleLeaks->appendChild( moduleElement ); + + // Print module name + string sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + LPWSTR wTemp = CharToWChar( sTemp.c_str() ); + moduleElement->setAttribute( L"name", (const LPWSTR)wTemp ); + if( wTemp ) + delete[] wTemp; + + // Print number of memory leaks + wTemp = CharToWChar( sInput.c_str() ); + moduleElement->setAttribute( L"leaks", (const LPWSTR)wTemp ); + if( wTemp ) + delete[] wTemp; + } + break; + case TEST_START: + { + m_pCurrentSubTestElem = m_pDomDoc->createElement( L"subtest" ); + + if( m_pCurrentSubTestElem == NULL || m_pRunElement == NULL ) + return; + + m_pRunElement->appendChild( m_pCurrentSubTestElem ); + + // Print sub test name + string sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + LPWSTR wTemp = CharToWChar( sTemp.c_str() ); + m_pCurrentSubTestElem->setAttribute( L"name", (const LPWSTR)wTemp ); + if( wTemp ) + { + delete[] wTemp; + wTemp = NULL; + } + + // Print sub test time + sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + wTemp = CharToWChar( sTemp.c_str() ); + m_pCurrentSubTestElem->setAttribute( L"start_time", (const LPWSTR)wTemp ); + if( wTemp ) + delete[] wTemp; + break; + } + case TEST_END: + { + if( m_pCurrentSubTestElem == NULL ) + return; + // Print end time + string sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + LPWSTR wTemp = CharToWChar( sTemp.c_str() ); + m_pCurrentSubTestElem->setAttribute( L"end_time", (const LPWSTR)wTemp ); + m_pCurrentSubTestElem = NULL; + if( wTemp ) + delete[] wTemp; + break; + } + case SUBTEST_MEM_LEAKS: + { + if( m_pCurrentSubTestElem == NULL ) + return; + xercesc::DOMElement* memoryLeaksElement = m_pDomDoc->createElement( L"mem_leaks" ); + m_pCurrentSubTestElem->appendChild( memoryLeaksElement ); + m_pSubtestMemoryLeaks = memoryLeaksElement; + + // Print number of leaks + LPWSTR wTemp = CharToWChar( sInput.c_str() ); + memoryLeaksElement->setAttribute( L"count", (const LPWSTR)wTemp ); + if( wTemp ) + delete[] wTemp; + break; + } + case SUBTEST_MEM_LEAK_MODULE: + { + if( m_pSubtestMemoryLeaks == NULL ) + return; + xercesc::DOMElement* moduleElement = m_pDomDoc->createElement( L"module" ); + m_pSubtestMemoryLeaks->appendChild( moduleElement ); + + // Print module name + string sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + LPWSTR wTemp = CharToWChar( sTemp.c_str() ); + moduleElement->setAttribute( L"name", (const LPWSTR)wTemp ); + + if( wTemp ) + delete[] wTemp; + // Print number of memory leaks + wTemp = CharToWChar( sInput.c_str() ); + moduleElement->setAttribute( L"leaks", (const LPWSTR)wTemp ); + if( wTemp ) + delete[] wTemp; + break; + } + case SUBTEST_HANDLE_LEAKS: + { + if( m_pCurrentSubTestElem == NULL ) + return; + xercesc::DOMElement* handleLeaksElement = m_pDomDoc->createElement( L"handle_leaks" ); + m_pCurrentSubTestElem->appendChild( handleLeaksElement ); + + //Print number of handle leaks + string sTemp = GetStringUntilNextGivenChar( sInput, ';' ); + LPWSTR wTemp = CharToWChar( sTemp.c_str() ); + handleLeaksElement->setAttribute( L"count", (const LPWSTR)wTemp ); + if( wTemp ) + delete[] wTemp; + break; + } + default: + break; + } + } + catch( ... ) + { + printf( "Error when writing data to XML file." ); + } +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::GetStringUntilNextGivenChar +// Function returns string from begin of given string until next given char, +// characters until given char are removed from sInput string. +// ----------------------------------------------------------------------------- +string CATDataSaver::GetStringUntilNextGivenChar( string& sInput, char cCharacter ) +{ + LOG_LOW_FUNC_ENTRY("CATDataSaver::GetStringUntilNextGivenChar"); + string sRet; + size_t iPos = sInput.find( cCharacter ); + if( sInput.size() > 1 && iPos != string::npos ) + { + sRet = sInput.substr( 0, iPos ); + sInput.erase( 0, (iPos + 1) ); + } + return sRet; +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::SetBuild +// Function sets build target info. +// ----------------------------------------------------------------------------- +void CATDataSaver::SetBuild( bool bUdebBuild ) +{ + LOG_FUNC_ENTRY("CATDataSaver::SetBuild"); + m_bUdebBuild = bUdebBuild; +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::AddCarbideData +// Function adds string to Carbide data. +// ----------------------------------------------------------------------------- +void CATDataSaver::AddCarbideData( const string& sInput ) +{ + LOG_LOW_FUNC_ENTRY("CATDataSaver::AddCarbideData"); + m_sCarbideDataLine.append( sInput ); + m_sCarbideDataLine.append(";"); +} + +// ----------------------------------------------------------------------------- +// CATDataSaver::IntegerToString +// Converts integer to string. +// ----------------------------------------------------------------------------- +string CATDataSaver::IntegerToString( int iValueToConvert ) +{ + LOG_LOW_FUNC_ENTRY("CATDataSaver::IntegerToString"); + char cTemp[128]; + string sValue( itoa( iValueToConvert, cTemp, 10 ) ); + return sValue; +} diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/CATMemoryAddress.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/CATMemoryAddress.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,307 @@ +/* +* 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: Class representing a memory address and its details. +* +*/ + + +#include "../inc/CATMemoryAddress.h" +#include "../inc/CATBase.h" + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::CATMemoryAddress +// Constructor +// ----------------------------------------------------------------------------- +CATMemoryAddress::CATMemoryAddress(string& sAddress, unsigned long iOffSet) +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::CATMemoryAddress"); + m_sAddress = sAddress; + m_sFileName = ""; + m_sFunctionName = ""; + m_sModuleName = ""; + m_iAddress = CATBase::_httoi( sAddress.c_str() ); + m_iDllLoadinfoIndex = -1; + m_iModuleStartAddress = 0; + m_iOffSetFromModuleStart = 0; + m_iExactLineNumber = -1; + m_iFunctionLineNumber = -1; + m_ePinPointState = OUT_OF_PROCESS; + m_iOffSet = iOffSet; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::~CATMemoryAddress +// Destructor. +// ----------------------------------------------------------------------------- +CATMemoryAddress::~CATMemoryAddress() +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::~CATMemoryAddress"); +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::FindSetModuleName +// Find which binary this address belongs to. +// Sets also the offsetfrommodulestart. +// ----------------------------------------------------------------------------- +bool CATMemoryAddress::FindSetModuleName(vector<DLL_LOAD_INFO>* vDlls) +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::FindSetModuleName"); + vector<DLL_LOAD_INFO>::iterator it; + for ( it = vDlls->begin() ; + it != vDlls->end(); it++ ) + { + // Is modules load time defined? + if ( (*it).iLoadTime > 0 ) + { + // Check that load time is earlier or same as allocation + if ( m_iTime >= (*it).iLoadTime + && m_iAddress >= (*it).iStartAddress + && m_iAddress < (*it).iEndAddress ) + { + // Module is loaded until process end. + if ( (*it).iUnloadTime == 0 ) + break; + // Check is allocation done before module was unloaded. + else if ( (*it).iUnloadTime >= m_iTime ) + break; + } + } + // Module has no time defined use only code segments. + else + { + if ( m_iAddress >= (*it).iStartAddress + && m_iAddress < (*it).iEndAddress ) + break; + } + } + + // Did we not find module where address is? + if ( it == vDlls->end() ) + return false; + + m_ePinPointState = OUT_OF_RANGE; + m_sModuleName = (*it).sModuleName; + m_iModuleStartAddress = (*it).iStartAddress; + m_iOffSetFromModuleStart = m_iAddress - m_iModuleStartAddress; + m_iOffSetFromModuleStart += m_iOffSet; + m_iDllLoadinfoIndex = distance( vDlls->begin(), it ) ; + return true; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::SetModuleStartAddress +// Set start address of the binary in which address resides. +// Note, this also sets the offset from start value. +// ----------------------------------------------------------------------------- +void CATMemoryAddress::SetModuleStartAddress(unsigned long iAddress) +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::SetModuleStartAddress"); + m_iModuleStartAddress = iAddress; + m_iOffSetFromModuleStart = m_iAddress - m_iModuleStartAddress; + m_iOffSetFromModuleStart += m_iOffSet; +} + + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::GetOffSetFromModuleStart +// Note return value includes the set offset. +// So this value is not binary start - address. +// Instead it is. +// memory address - binary start address + offset +// ----------------------------------------------------------------------------- +unsigned long CATMemoryAddress::GetOffSetFromModuleStart() +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::GetOffSetFromModuleStart"); + return m_iOffSetFromModuleStart; +} + +int CATMemoryAddress::GetDllLoadInfoIndex() +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::GetDllLoadInfo"); + return m_iDllLoadinfoIndex; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::SetTime +// ----------------------------------------------------------------------------- +void CATMemoryAddress::SetTime( unsigned long long& ullTime ) +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::SetTime"); + m_iTime = ullTime; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::GetTIme +// ----------------------------------------------------------------------------- +unsigned long long CATMemoryAddress::GetTime() +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::GetTime"); + return m_iTime; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::SetAddress +// ----------------------------------------------------------------------------- +void CATMemoryAddress::SetAddress(string& sAddress) +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::SetAddress"); + m_sAddress = sAddress; + m_iAddress = CATBase::_httoi( sAddress.c_str() ); +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::GetAddressString +// ----------------------------------------------------------------------------- +string CATMemoryAddress::GetAddressString() +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::GetAddressString"); + return m_sAddress; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::SetAddress +// ----------------------------------------------------------------------------- +void CATMemoryAddress::SetAddress(unsigned long iAddress) +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::SetAddress"); + m_iAddress = iAddress; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::GetAddress +// ----------------------------------------------------------------------------- +unsigned long CATMemoryAddress::GetAddress() +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::GetAddress"); + return m_iAddress; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::SetModuleName +// ----------------------------------------------------------------------------- +void CATMemoryAddress::SetModuleName(string& sModuleName) +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::SetModuleName"); + m_sModuleName = sModuleName; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::GetModuleName +// ----------------------------------------------------------------------------- +string CATMemoryAddress::GetModuleName() +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::GetModuleName"); + return m_sModuleName; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::SetAddressToLineState +// ----------------------------------------------------------------------------- +void CATMemoryAddress::SetAddressToLineState( ADDRESS_TO_LINE_STATE eState ) +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::SetAddressToLineState"); + m_ePinPointState = eState; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::GetAddressToLineState +// ----------------------------------------------------------------------------- +int CATMemoryAddress::GetAddressToLineState() +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::GetAddressToLineState"); + return m_ePinPointState; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::SetFileName +// ----------------------------------------------------------------------------- +void CATMemoryAddress::SetFileName(string& sFileName) +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::SetFileName"); + m_sFileName = sFileName; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::GetFileName +// ----------------------------------------------------------------------------- +string CATMemoryAddress::GetFileName() +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::GetFileName"); + return m_sFileName; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::SetFunctionName +// ----------------------------------------------------------------------------- +void CATMemoryAddress::SetFunctionName(string& sFunctionName) +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::SetFunctionName"); + m_sFunctionName = sFunctionName; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::GetFunctionName +// ----------------------------------------------------------------------------- +string CATMemoryAddress::GetFunctionName() +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::GetFunctionName"); + return m_sFunctionName; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::SetFunctionLineNumber +// ----------------------------------------------------------------------------- +void CATMemoryAddress::SetFunctionLineNumber(int iFunctionLineNumber) +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::SetFunctionLineNumber"); + m_iFunctionLineNumber = iFunctionLineNumber; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::GetFunctionLineNumber +// ----------------------------------------------------------------------------- +int CATMemoryAddress::GetFunctionLineNumber() +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::GetFunctionLineNumber"); + return m_iFunctionLineNumber; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::SetExactLineNumber +// ----------------------------------------------------------------------------- +void CATMemoryAddress::SetExactLineNumber(int iExactLineNumber) +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::SetExactLineNumber"); + m_iExactLineNumber = iExactLineNumber; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::GetExactLineNumber +// ----------------------------------------------------------------------------- +int CATMemoryAddress::GetExactLineNumber() +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::GetExactLineNumber"); + return m_iExactLineNumber; +} + +// ----------------------------------------------------------------------------- +// CATMemoryAddress::GetModuleStartAddress +// ----------------------------------------------------------------------------- +unsigned long CATMemoryAddress::GetModuleStartAddress() const +{ + LOG_LOW_FUNC_ENTRY("CATMemoryAddress::GetModuleStartAddress"); + return m_iModuleStartAddress; +} + +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/CATMmp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/CATMmp.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,396 @@ +/* +* 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: Class responsible of handling mmp files. +* +*/ + + +#include "../inc/CATMmp.h" + +CATMmp::CATMmp() +{ + LOG_FUNC_ENTRY("CATMmp::CATMmp"); +} + +CATMmp::~CATMmp() +{ + LOG_FUNC_ENTRY("CATMmp::~CATMmp"); +} + +// ----------------------------------------------------------------------------- +// CATMmp::IsMmpEdited +// Checks is the file edited by AT +// ----------------------------------------------------------------------------- +bool CATMmp::IsMmpEdited( bool bBackup) +{ + LOG_FUNC_ENTRY("CATMmp::IsMmpEdited"); + // Stream to read file + ifstream in; + // Temp char array to read line + char cTemp[MAX_LINE_LENGTH]; + // Open file + if ( bBackup ) + in.open( CreateMmpBackupPath().c_str() ); + else + in.open( m_sMmpFile.c_str() ); + // Is file open ok + if( ! in.good() ) + { + cout << AT_MSG << "Error, can not open file " + << m_sMmpFile << endl; + in.close(); + return false; + } + // Search edit start line + bool bEdited=false; + const char* cFind = MMPFILECHANGES[0].c_str(); + while( ! bEdited && in.good() ) + { + // Get line + in.getline( cTemp, MAX_LINE_LENGTH ); + // Compare to first line in changes + if ( strstr( cTemp, cFind) ) + { + bEdited = true; + // Stop looking any further + break; + } + } + // Close file and return result + in.close(); + return bEdited; +} + +// ----------------------------------------------------------------------------- +// CATMmp::EditMmpFile +// Makes AnalyzeTool changes to given mmp file +// ----------------------------------------------------------------------------- +bool CATMmp::EditMmpFile(const string& sTargetType, const string& sId) +{ + LOG_FUNC_ENTRY("CATMmp::EditMmpFile"); + + if ( ! RemoveWriteProtections() ) + return false; + + // Stream where to add changes + ofstream out; + + // Open mmp file for editing (append changes to the end) + out.open( m_sMmpFile.c_str(), ios::out | ios::app ); + + // File open ok? + if( !out.good() ) + { + cout << AT_MSG << "Error, can not open file " + << m_sMmpFile; + out.close(); + return false; + } + + // Write lines to mmp file + if ( sTargetType.compare( "dll" ) == 0 || sTargetType.compare( "lib" ) == 0 ) + { + // DLL changes + int size = sizeof( MMPFILECHANGES_DLL ) / sizeof( string ); + for( int i = 0; i < size; i++ ) + { + out << endl << MMPFILECHANGES_DLL[i]; + } + out << endl; + } + else + { + // Other than DLL changes + int size = sizeof( MMPFILECHANGES ) / sizeof( string ); + for( int i = 0; i < size; i++ ) + { + // After second line of changes add also source statement + out << endl << MMPFILECHANGES[i]; + if ( i == 1 ) + { + out << endl + << "SOURCE " + << AT_TEMP_CPP_LOWER_START + << sId + << AT_TEMP_CPP_LOWER_END; + } + } + out << endl; + } + // Close stream + out.close(); + + cout << AT_MSG << "Mmp file : " << m_sMmpFile << " edited." << endl; + + return true; +} + +// ----------------------------------------------------------------------------- +// CATMmp::BackupMmpFile +// Backups the mmp file to path/atool_temp/filename.mmp.tmp +// Calling this function results always to +// - none edited mmp +// - none edited backup +// - If mmp is write protected. Create writable copy from it. Backup the write +// procted one. +// ----------------------------------------------------------------------------- +bool CATMmp::BackupMmpFile( ) +{ + LOG_FUNC_ENTRY("CATMmp::BackupMmpFile"); + + if ( ! RemoveWriteProtections() ) + return false; + + // Backup path+filename + string sBackup = CreateMmpBackupPath(); + + // Backup mmp. + if ( CopyFile( m_sMmpFile.c_str() , sBackup.c_str(), false ) == 0 ) + { + // Log and return false if failed to copy file + LOG_STRING( "error copyfile " << m_sMmpFile << " to " << sBackup ); + return false; + } + + // If backup now edited remove changes from it. + if ( IsMmpEdited( true ) ) + { + if ( ! RemoveMmpFileChanges( true ) ) + return false; + } + + return true; +} +// ----------------------------------------------------------------------------- +// CATMmp::RestoreMmpFile +// Restores the mmp file from backup +// ----------------------------------------------------------------------------- +bool CATMmp::RestoreMmpFile() +{ + LOG_FUNC_ENTRY("CATMmp::RestoreMmpFile"); + + if ( ! RemoveWriteProtections() ) + return false; + + if ( CopyFile( CreateMmpBackupPath().c_str() , m_sMmpFile.c_str(), false ) == 0 ) + { + // Log and return false if failed to copy file + LOG_STRING("error copyfile " << CreateMmpBackupPath() << " to " << m_sMmpFile ); + return false; + } + else + cout << AT_MSG << "Mmp file : " << m_sMmpFile << " restored." << endl; + return true; +} + +// ----------------------------------------------------------------------------- +// CATMmp::RemoveMmpFileChanges +// Removes AT changes from given mmp file +// ----------------------------------------------------------------------------- +bool CATMmp::RemoveMmpFileChanges(bool bBackup) +{ + LOG_FUNC_ENTRY("CATMmp::RemoveMmpFileChanges"); + + if ( ! RemoveWriteProtections() ) + return false; + + // File reading stream + ifstream in; + // Vector to hold file data + vector<string> vLines; + // Open file + if ( bBackup ) + in.open( CreateMmpBackupPath().c_str(), ios::in ); + else + in.open( m_sMmpFile.c_str(), ios::in ); + // Check file open ok + if ( ! in.good() ) + { + cout << AT_MSG << "Error, opening file"; + if ( bBackup ) + cout << CreateMmpBackupPath(); + else + cout << m_sMmpFile; + cout << endl; + return false; + } + // Read file to temporary stream except AT changes + char cLine[MAX_LINE_LENGTH]; + // Boolean to know read or not + bool bRead = true; + // Integer to confirm that AT changes were succefully found and + // not read even if they are found multiple times + int iSuccessfull = 0; + // Number of 'lines' in mmp changes + int iChangesSize = sizeof( MMPFILECHANGES ) / sizeof( string ); + // First mmp changes line + string sFirstLine = MMPFILECHANGES[0]; + // Last mmp changes line + string sLastLine = MMPFILECHANGES[iChangesSize-1]; + while( in.good() ) + { + in.getline( cLine, MAX_LINE_LENGTH ); + // Check start of AT changes + if( strstr( cLine, sFirstLine.c_str() ) != 0 ) + { + // Remove last linefeed + vector<string>::iterator it = vLines.end(); + it--; + if ( it->size() == 0 ) + vLines.erase( vLines.end()-1, vLines.end() ); + // Stop reading + bRead = false; + iSuccessfull+=3; + } + // Read lines outside AT changes + if ( bRead ) + { + // Gather all other lines except the AT edits + vLines.push_back( string(cLine) ); + } + // Check end of AT changes + if( strstr( cLine, sLastLine.c_str() ) != 0 ) + { + // Get empty line + in.getline( cLine, MAX_LINE_LENGTH ); + // Continue reading + bRead = true; + iSuccessfull-=1; + } + } + // Close reading file stream + in.close(); + // To check all went ok iSuccesfull%2 = 0 + if ( iSuccessfull%2 != 0 && iSuccessfull >= 2 ) + { + cout << AT_MSG << "Error, removing mmp changes from "; + if ( bBackup ) + cout << CreateMmpBackupPath(); + else + cout << m_sMmpFile; + cout << endl; + return false; + } + // Overwrite current mmp file + ofstream out; + // Open file (truncates old data) + if ( bBackup ) + out.open( CreateMmpBackupPath().c_str(), ios::trunc ); + else + out.open( m_sMmpFile.c_str(), ios::trunc ); + // Is open ok + if( ! out.good() ) + { + cout << AT_MSG << "Error, opening file "; + if ( bBackup ) + cout << CreateMmpBackupPath(); + else + cout << m_sMmpFile; + cout << endl; + } + // Write lines to file + for( vector<string>::iterator it = vLines.begin() ; it != vLines.end() ; it++ ) + { + out << *it << endl; + } + // Close + out.close(); + // Return true + return true; +} +// ----------------------------------------------------------------------------- +// CATMmp::VerifyAndRecover +// Wont change mmp if it is not edited +// Replaces mmp file using backup if it exists and it is +// not edited otherwise removes changes from mmp file. +// ----------------------------------------------------------------------------- +bool CATMmp::VerifyAndRecover() +{ + LOG_FUNC_ENTRY("CATMmp::VerifyAndRecover"); + // Is it edited + if ( IsMmpEdited() ) + { + string sBackup = CreateMmpBackupPath(); + if ( FileExists( sBackup.c_str() ) ) + { + // Is backup edited + if ( ! IsMmpEdited( true ) ) + { + // Replace original with backup + return RestoreMmpFile(); + } + } + // Remove changes from original + return RemoveMmpFileChanges(); + } + // Non edited original + return true; +} + +// ----------------------------------------------------------------------------- +// CATMmp::CreateMmpBackupPath +// Creates string containing full path to backup mmp file +// ----------------------------------------------------------------------------- +string CATMmp::CreateMmpBackupPath() +{ + LOG_FUNC_ENTRY("CATMmp::CreateMmpBackupPath"); + // backup path+filename + string sBackup; + sBackup.append( GetPathOrFileName( false, m_sMmpFile ) ); + sBackup.append( AT_TEMP_DIR ); + sBackup.append( "\\" ); + // Add mmp file name to it and .tmp + sBackup.append( GetPathOrFileName( true, m_sMmpFile ) ); + // Add .tmp + sBackup.append( ".tmp" ); + // Return it + return sBackup; +} + +// ----------------------------------------------------------------------------- +// CATMmp::RemoveWriteProtections +// Removes write protection of mmp file and backup if exists. +// ----------------------------------------------------------------------------- +bool CATMmp::RemoveWriteProtections() +{ + LOG_LOW_FUNC_ENTRY("CATMmp::RemoveWriteProtections"); + + // Backup path+filename + string sBackup = CreateMmpBackupPath(); + + // Check is mmp read-only + if ( IsFileReadOnly( m_sMmpFile.c_str() ) ) + { + if( ! SetFileWritable( m_sMmpFile.c_str() ) ) + { + LOG_STRING( "error setting mmp file writable" << m_sMmpFile ); + return false; + } + } + + // Check is there a backup if is remove any write protection from it. + if ( FileExists( sBackup.c_str() ) ) + { + if ( IsFileReadOnly( sBackup.c_str() ) ) + { + if( ! SetFileWritable( sBackup.c_str() ) ) + { + LOG_STRING( "error setting mmp file writable" << sBackup ); + return false; + } + } + } + return true; +} +// End of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/CATModule2.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/CATModule2.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,1634 @@ +/* +* 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: Class representing a module in project (sbs2) +* +*/ + + +#include "../inc/CATModule2.h" +#include "../inc/CATProject.h" +#include "../inc/CATDatParser.h" +#include "../inc/CATMemoryAddress.h" +#include "../inc/catdbghelper.h" +#include "../inc/cataddr2line.h" + +CATModule2::CATModule2(void) +{ + LOG_FUNC_ENTRY("CATModule2::CATModule2"); + m_bAddressToLineInitialized = false; + m_pAddressToLine = 0; + m_sErrors = ""; + m_sMakeFile = ""; + m_eBuildSystem = CATProject::SBS_V1; + m_sCompileInfoText = ""; +} + +CATModule2::~CATModule2(void) +{ + LOG_FUNC_ENTRY("CATModule2::~CATModule2"); + if ( m_pAddressToLine ) + m_pAddressToLine->Close(); + delete m_pAddressToLine; +} + +bool CATModule2::AddressToLine( CATMemoryAddress* pMemoryAddress ) +{ + LOG_FUNC_ENTRY("CATModule2::AddressToLine"); + if ( _stricmp( m_sVariantPlatform.c_str(), "winscw" ) == 0 ) + { + return AddressToLineWinscw( pMemoryAddress ); + } + else if ( _stricmp( m_sVariantPlatform.c_str(), "armv5" ) == 0 ) + { + // addr2line exe. + #ifdef ADDR2LINE + return AddressToLineAddr2lineExe( pMemoryAddress ); + #endif + // lst and map files. + #ifndef ADDR2LINE + return AddressToLineArmv5( pMemoryAddress ); + #endif + } + else if ( _stricmp( m_sVariantPlatform.c_str(), "gcce" ) == 0 ) + { + return AddressToLineAddr2lineExe( pMemoryAddress ); + } + return false; +} + +bool CATModule2::AddressToLineWinscw( CATMemoryAddress* pMemoryAddress ) +{ + LOG_FUNC_ENTRY("CATModule2::AddressToLineWinscw( CATMemoryAddress* pMemoryAddress )"); + if ( m_pAddressToLine == 0 && ! m_bAddressToLineInitialized ) + { + // Use debug helper to locate codelines on winscw platform. + m_pAddressToLine = new CATDbgHelper(); + + // Create full path to binary which we open using CATDbgHelper. + string sFullPathToBinary = GetBinaryFile(); + + // If opening of binary not succesfull set return value to false. + if ( ! m_pAddressToLine->Open( sFullPathToBinary, pMemoryAddress->GetModuleStartAddress() ) ) + { + LOG_STRING("Error, m_pAddressToLine->Open()"); + return false; + } + m_bAddressToLineInitialized = true; + } + // Check pointer before calling. + if ( m_pAddressToLine == 0 ) + return false; + m_pAddressToLine->AddressToLine( pMemoryAddress ); + return true; +} + +bool CATModule2::AddressToLineArmv5( CATMemoryAddress* pMemoryAddress ) +{ + LOG_FUNC_ENTRY("CATModule2::AddressToLine( CATMemoryAddress* pMemoryAddress )"); + if ( ! m_bAddressToLineInitialized ) + return false; + // Find from map file + int iMapIndex = GetSymbolIndexUsingAddress( pMemoryAddress->GetOffSetFromModuleStart() ); + if ( iMapIndex == -1 ) + { + pMemoryAddress->SetAddressToLineState( CATMemoryAddress::OUT_OF_RANGE ); + return true; + } + // Set symbol name + string sSymbolName = m_vMapFileFuncList.at( iMapIndex ).sFunctionName; + + // Remove (... from symbol name + string sSymbolNameRefined( sSymbolName ); + size_t iPos = sSymbolNameRefined.find( "(" ); + if ( iPos != string::npos ) + sSymbolNameRefined.resize( iPos ); + + // Set symbol name as function name for memory address + pMemoryAddress->SetFunctionName( sSymbolNameRefined ); + + // Set state to symbol + pMemoryAddress->SetAddressToLineState( CATMemoryAddress::SYMBOL ); + + // Offset from function start addr + int iOffSetFromFuncStart = pMemoryAddress->GetOffSetFromModuleStart() + - m_vMapFileFuncList.at( iMapIndex ).iAddress; + + // Find from lst list + int iLstIndex = GetLineInFileIndexUsingSymbolName( sSymbolName ); + if ( iLstIndex == -1 ) + return true; + + // Set pinpointing + int iFuncLineNumber = m_vLineInFile.at( iLstIndex ).iLine; + string sFileName = m_vLineInFile.at( iLstIndex ).sFileName; + string sLstFileName = m_vLineInFile.at( iLstIndex ).sLstName; + + pMemoryAddress->SetFunctionLineNumber( iFuncLineNumber ); + pMemoryAddress->SetFileName( sFileName ); + + pMemoryAddress->SetAddressToLineState( CATMemoryAddress::FUNCTION ); + + // In urel mode don't get exact code line + if ( ! IsUDEB() ) + return true; + + // Next calculate the code line inside function + int iExactLineNumber = FindLeakCodeLine( sLstFileName, iFuncLineNumber, iOffSetFromFuncStart ); + pMemoryAddress->SetExactLineNumber( iExactLineNumber ); + + // State is now exact + pMemoryAddress->SetAddressToLineState( CATMemoryAddress::EXACT ); + return true; +} + +bool CATModule2::AddressToLineAddr2lineExe( CATMemoryAddress* pMemoryAddress ) +{ + LOG_FUNC_ENTRY("CATModule2::AddressToLineAddr2lineExe( CATMemoryAddress* pMemoryAddress )"); + if ( m_pAddressToLine == 0 && ! m_bAddressToLineInitialized ) + { + // Use addr2line.exe to locate codelines on armv5 and gcce platform. + m_pAddressToLine = new CATAddr2line(); + + // Create full path to binary .sym file which we open using addr2line.exe. + string sFullPathToBinary = GetBinaryFile(); + + // If opening of binary not succesfull set return value to false. + if ( ! m_pAddressToLine->Open( sFullPathToBinary, pMemoryAddress->GetModuleStartAddress() ) ) + { + LOG_STRING("Error, m_pAddressToLine->Open()"); + return false; + } + m_bAddressToLineInitialized = true; + } + // Check pointer before calling. + if ( m_pAddressToLine == 0 ) + return false; + + m_pAddressToLine->AddressToLine( pMemoryAddress ); + return true; +} + +// Find symbol of given address +int CATModule2::GetSymbolIndexUsingAddress( unsigned long iAddress ) const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetSymbolIndexUsingAddress"); + for( size_t i = 0; i < m_vMapFileFuncList.size(); i++ ) + { + unsigned long iStart = m_vMapFileFuncList.at( i ).iAddress; + unsigned long iEnd = ( m_vMapFileFuncList.at( i ).iAddress + + m_vMapFileFuncList.at( i ).iFuncLength ); + + if ( iAddress >= iStart && iAddress < iEnd ) + return (int) i; + } + return -1; +} + +// Find index of function line in file vector of given symbolname +int CATModule2::GetLineInFileIndexUsingSymbolName( const string& sSymbolName ) const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetLineInFileIndexUsingSymbolName"); + for( size_t i = 0; i < m_vLineInFile.size(); i++ ) + { + string sLineInFileName = m_vLineInFile.at( i ).sFunction; + if( sLineInFileName.find( sSymbolName ) != string::npos ) + { + return (int) i; + } + } + return -1; +} + + +// Check does modules symbol file(s) exist. +bool CATModule2::SymbolFileExist( void ) +{ + LOG_FUNC_ENTRY("CATModule2::SymbolFileExist"); + string sFullPathToSym = GetSymbolFile(); + if ( !FileExists( sFullPathToSym.c_str() ) ) + { + // Add missing symbol file to error string. + m_sErrors.append( "Missing symbol file: " ); + m_sErrors.append( sFullPathToSym ); + m_sErrors.append( "\n" ); + return false; + } + return true; +} + +// Check does modules map file(s) exists. +bool CATModule2::MapFileExist( void ) +{ + LOG_FUNC_ENTRY("CATModule2::MapFileExist"); + string sFullPathToMap = GetMapFile(); + if ( !FileExists( sFullPathToMap.c_str() ) ) + { + // Add missing symbol file to error string. + m_sErrors.append( "Missing map file: " ); + m_sErrors.append( sFullPathToMap ); + m_sErrors.append( "\n" ); + return false; + } + return true; +} + +//Check does modules binary file(s) exist. +bool CATModule2::BinaryFileExist( void ) +{ + LOG_FUNC_ENTRY("CATModule2::BinaryFileExist"); + string sFullPathToBinary = GetBinaryFile(); + if ( ! FileExists( sFullPathToBinary.c_str() ) ) + { + // Add missing binary to error string. + m_sErrors.append( "Missing binary file: " ); + m_sErrors.append( sFullPathToBinary ); + m_sErrors.append( "\n" ); + return false; + } + return true; +} + +void CATModule2::AddSource(const string &sSourceFile, const string& sLstFile) +{ + LOG_LOW_FUNC_ENTRY("CATModule2::AddSource"); + // Parse sources which are separated by spaces + if( sSourceFile.length() < 1 || sLstFile.length() < 1 ) + return; + + // Skip if its temporary cpp. + if ( sSourceFile.find( AT_TEMP_CPP_LOWER_START) != string::npos ) + return; + + // Source structure + SOURCE sNew; + sNew.sCpp = sSourceFile; + sNew.sLst = sLstFile; + + // Verify paths. + ConvertUnixPathToWin( sNew.sCpp ); + ConvertUnixPathToWin( sNew.sLst ); + + // Lower case them. + ChangeToLower( sNew.sCpp ); + ChangeToLower( sNew.sLst ); + + // Add it + m_vSources.push_back( sNew ); +} + +void CATModule2::AddSources(string& sSource) +{ + LOG_LOW_FUNC_ENTRY("CATModule2::AddSources"); + // Parse sources which are separated by spaces + if( sSource.length() < 1 ) + return; + // Source structure + SOURCE sNew; + size_t iSpot = string::npos; + iSpot = sSource.find( " " ); + while( iSpot != string::npos ) + { + // Pickup source + sNew.sCpp = sSource.substr(0, iSpot); + // Convert path from Unix to Win + ConvertUnixPathToWin( sNew.sCpp ); + // Lowercase it + ChangeToLower( sNew.sCpp ); + // If its temp skip this + if ( sNew.sCpp.find( AT_TEMP_CPP_LOWER_START ) == string::npos ) + { + // Get corresponding lst file for source + sNew.sLst = GetLstNameOfSource( sNew.sCpp ); + m_vSources.push_back( sNew ); + // Remove it from sSource + sSource.erase(0,iSpot+1); + // Find new one + } + iSpot = sSource.find( " " ); + } + // Pickup last or only one source + sNew.sCpp = sSource; + // Convert path from unix to win + ConvertUnixPathToWin( sNew.sCpp ); + // Lowercase it + ChangeToLower( sNew.sCpp ); + // Lst name + sNew.sLst = GetLstNameOfSource( sNew.sCpp ); + if ( sNew.sCpp.find( AT_TEMP_CPP_LOWER_START ) == string::npos ) + { + // Get corresponding lst file for source + sNew.sLst = GetLstNameOfSource( sNew.sCpp ); + m_vSources.push_back( sNew ); + } +} +bool CATModule2::CreateTempCpp(const string& sS60FileName + , int eLoggingMode + , int eBuildType + , int iAllocCallStackSize + , int iFreeCallStackSize ) +{ + LOG_FUNC_ENTRY("CATModule2::CreateTemporaryCpp"); + // S60 filename + m_sS60FileName = sS60FileName; + // Make s60 filename target.type.dat if its empty and logging mode is file + if ( eLoggingMode == CATProject::FILE + && m_sS60FileName.empty() ) + { + m_sS60FileName = m_sTarget; + m_sS60FileName.append("."); + m_sS60FileName.append( m_sTargetType ); + m_sS60FileName.append(".dat"); + } + return CreateTemporaryCpp( GetUniqueId(), m_sTempPath, + m_sS60FileName, eLoggingMode, eBuildType, iAllocCallStackSize, iFreeCallStackSize ); +} + +bool CATModule2::ModifyMmp() +{ + LOG_FUNC_ENTRY("CATModule2::ModifyMmp"); + // Create backup + if ( ! m_Mmp.BackupMmpFile() ) + return false; + // Hook + return m_Mmp.EditMmpFile( m_sTargetType, GetUniqueId() ); +} + +bool CATModule2::RestoreMmp() +{ + LOG_FUNC_ENTRY("CATModule2::RestoreMmp"); + // Restore mmp from backup + return m_Mmp.RestoreMmpFile(); +} + +bool CATModule2::VerifyAndRecoverMmp() +{ + LOG_FUNC_ENTRY("CATModule2::VerifyAndRecoverMmp"); + // Verify mmp + return m_Mmp.VerifyAndRecover(); +} + +// ---------------------------------------------------------------------------- +// Releasables Handling methos +// ---------------------------------------------------------------------------- +bool CATModule2::CopyReleasables() +{ + LOG_FUNC_ENTRY("CATModule2::CopyReleasables"); + bool bRet = true; + if ( ! CopyLstFilesToTemp() ) + bRet = false; + if ( ! CopyMapFileToTemp() ) + bRet = false; + return bRet; +} + +bool CATModule2::CopyLstFilesToDir( const string& sDir ) +{ + LOG_FUNC_ENTRY("CATModule2::CopyLstFilesToDir"); + bool bRet = true; + // Copy lst files to given directory. + vector<SOURCE>::const_iterator source; + for( source = m_vSources.begin(); source != m_vSources.end() ; source++ ) + { + if ( ! FileCopyToPath( source->sLst, sDir ) ) + { + if ( !FileExists( source->sLst.c_str() ) ) + { + m_sErrors.append( "Missing listing file: " ); + m_sErrors.append( source->sLst ); + m_sErrors.append( "\n" ); + } + if ( !DirectoryExists( sDir.c_str() ) ) + { + m_sErrors.append( "Missing folder: " ); + m_sErrors.append( sDir ); + m_sErrors.append( "\n" ); + } + bRet = false; + } + } + // Return. + return bRet; +} + +bool CATModule2::CopyLstFilesToTemp() +{ + LOG_FUNC_ENTRY("CATModule2::CopyLstFilesToTemp"); + // Return boolean + bool bRet = true; + // Move all lst files except tmp cpp + vector<SOURCE>::iterator it = m_vSources.begin(); + while ( it != m_vSources.end() ) + { + if ( !FileCopyToPath( it->sLst, m_sTempPath ) ) + { + if ( !FileExists( it->sLst.c_str() ) ) + { + m_sErrors.append( "Missing listing file: " ); + m_sErrors.append( it->sLst ); + m_sErrors.append( "\n" ); + } + if ( !DirectoryExists( m_sTempPath.c_str() ) ) + { + m_sErrors.append( "Missing folder: " ); + m_sErrors.append( m_sTempPath ); + m_sErrors.append( "\n" ); + } + bRet = false; + } + it++; + } + return bRet; +} + +bool CATModule2::DeleteLstFilesFromSrc( void ) +{ + LOG_FUNC_ENTRY("CATModule2::DeleteLstFilesFromSrc"); + vector<SOURCE>::iterator it = m_vSources.begin(); + bool bRet = true; + // Delete lst files + while ( it != m_vSources.end() ) + { + if ( ! FileDelete( it->sLst, true ) ) + bRet = false; + it++; + } + return bRet; +} + +bool CATModule2::CopyMapFileToTemp() +{ + LOG_FUNC_ENTRY("CATModule2::CopyMapFileToTemp"); + // Return boolean + bool bRet = true; + // Map File to copy + string sMapFile = GetMapFile(); + if ( !FileCopyToPath( sMapFile, m_sTempPath ) ) + { + bRet = false; + if ( !FileExists( sMapFile.c_str() ) ) + { + // Add missing map file to error string. + m_sErrors.append( "Missing map file: " ); + m_sErrors.append( sMapFile ); + m_sErrors.append( "\n" ); + } + if ( !DirectoryExists( m_sTempPath.c_str() ) ) + { + // Add missing temporary folder + m_sErrors.append( "Missing folder: " ); + m_sErrors.append( m_sTempPath ); + m_sErrors.append( "\n" ); + } + } + return bRet; +} + +bool CATModule2::CleanTemporaryDir() +{ + LOG_FUNC_ENTRY("CATModule2::CleanTemporaryDir"); + bool bRet = true; + // Verify mmp + if ( ! m_Mmp.VerifyAndRecover() ) + bRet = false; + // Clean temporary dir + vector<string> vFileList = DirList( m_sTempPath, false , true ); + vector<string>::iterator it = vFileList.begin(); + // Size of constant table + int iCount = sizeof( TEMP_EXTENSION_NO_DELETE ) / sizeof( string ); + while ( it != vFileList.end() ) + { + // Get extension and compare it to list + bool bDelete = true; + string sExtension = GetExtension( *it ); + ChangeToLower( sExtension ); + for ( int i = 0 ; i < iCount ; i++ ) + { + if( sExtension.compare( TEMP_EXTENSION_NO_DELETE[i] ) == 0 ) + { + bDelete = false; + break; + } + } + if ( bDelete ) + { + // Delete file + if ( ! FileDelete( *it, true ) ) + bRet = false; + } + // Increment + it++; + } + return bRet; +} + +bool CATModule2::DeleteTemporaryDir() +{ + LOG_FUNC_ENTRY("CATModule2::DeleteTemporaryDir"); + bool bRet = true; + // Verify mmp + if ( ! m_Mmp.VerifyAndRecover() ) + bRet = false; + // Delete temp dir + if ( !DirDelete( m_sTempPath, true ) ) + bRet = false; + return bRet; +} + +bool CATModule2::IsUDEB() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::IsUDEB"); + // Determine from variant is this udeb + if ( m_sVariantType.find( "udeb" ) != string::npos ) + return true; + return false; +} +// ---------------------------------------------------------------------------- +// Private AddressToLine related methods +// ---------------------------------------------------------------------------- +bool CATModule2::InitializeAddressToLine() +{ + LOG_FUNC_ENTRY("CATModule2::InitializeAddressToLine"); + bool bRet = true; + // Read in different way depending on platform + if ( m_sVariantPlatform.compare("armv5") == 0 ) + { + // Add static library lst files to source vector, + // before reading them. + vector<string> vFiles = DirList( AT_TEMP_LST_DIR, false, true ); + for(vector<string>::iterator it = vFiles.begin() ; it != vFiles.end() ; it ++ ) + { + SOURCE source; + source.bStatic = true; + source.sLst = *it; + source.sCpp = *it; + source.sCpp = CATBase::RemovePathAndExt( source.sCpp, false ); + source.sCpp.append( ".cpp" ); + m_vSources.push_back( source ); + } + + if ( ! ReadListingFilesArmv5() ) + bRet = false; + if ( ! ReadMapFileArmv5() ) + bRet = false; + + if ( bRet ) + m_bAddressToLineInitialized = true; + } + return bRet; +} + + +bool CATModule2::ReadListingFilesArmv5() +{ + LOG_FUNC_ENTRY("CATModule2::ReadListingFilesArmv5"); + char cTemp[MAX_LINE_LENGTH]; + vector<SOURCE>::iterator viFileIter = m_vSources.begin(); + int iNumberOfLstFiles = (int)m_vSources.size(); + vector<string> vTempLines; + string sFileName; + + // Open all .lst files + while( iNumberOfLstFiles > 0 ) + { + // Make .lst file name + sFileName.clear(); + + // If lst file is not from static library make path to modules temporary directory. + if ( viFileIter->bStatic != true ) + { + // Remove path + if( viFileIter->sLst.find("\\") != string::npos ) + sFileName.append( + viFileIter->sLst.substr( viFileIter->sLst.find_last_of( "\\" ) + 1 + , viFileIter->sLst.size() ) ); + else + sFileName.append( viFileIter->sLst ); + + // Add temporary dir + sFileName.insert( 0, m_sTempPath ); + } + else + { + // Lst from static library don't change path. + sFileName = viFileIter->sLst; + } + // Open lst file + ifstream in( sFileName.c_str() ); + + // If file can not be opened, try to open next file + if( !in.good() ) + { + viFileIter++; + iNumberOfLstFiles--; + continue; + } + + string sTemp; + // Clear temporary lines + vTempLines.clear(); + // Add all lines to temp list + do + { + in.getline( cTemp, MAX_LINE_LENGTH ); + sTemp.clear(); + sTemp.append( cTemp ); + vTempLines.push_back( sTemp ); + } + while( in.good() ); + + LINE_IN_FILE structLineInFile; + + bool bFindENDP = false; + vector<string>::iterator viLinesIter = vTempLines.begin(); + + // Loop throw all lines in .lst file + while( viLinesIter != vTempLines.end() ) + { + // Find ";;;" + if( !bFindENDP && strstr(viLinesIter->c_str(), ";;;") != NULL ) + { + bFindENDP = true; + + vector<string>::iterator viLineTempIter = viLinesIter; + + // Find top line of function definition + while( viLineTempIter->size() > 0 ) + { + viLineTempIter--; + } + viLineTempIter++; + structLineInFile.sFunction.clear(); + structLineInFile.sFunction.append( viLineTempIter->c_str() ); + + viLinesIter++; + // Get Line + sTemp.clear(); + sTemp.append( viLinesIter->c_str() ); + sTemp.erase(0,3); + size_t iSize = sTemp.find_first_of(' '); + if( iSize != string::npos ) + sTemp.resize(iSize); + structLineInFile.iLine = atoi( sTemp.c_str() ); + + structLineInFile.sFileName.clear(); + structLineInFile.sFileName.append( viFileIter->sCpp.c_str() ); + structLineInFile.sLstName = sFileName; + m_vLineInFile.push_back( structLineInFile ); + } + else if( strstr(viLinesIter->c_str(), "ENDP") != NULL ) + bFindENDP = false; + viLinesIter++; + } + viFileIter++; + iNumberOfLstFiles--; + } + if( m_vLineInFile.size() > 0 ) + return true; + return false; +} + +bool CATModule2::ReadMapFileArmv5() +{ + LOG_FUNC_ENTRY("CATModule2::ReadMapFileArmv5"); + // Map file name + string sMapFileName = GetMapFile(); + // Remove path + if ( sMapFileName.find("\\") != string::npos ) + sMapFileName.erase(0, sMapFileName.find_last_of('\\')+1 ); + // Add temp path + sMapFileName.insert(0, m_sTempPath ); + + // Open .map file + ifstream in( sMapFileName.c_str() ); + + // File open ok? + if( ! in.good() ) + { + in.close(); + return false; + } + char cTemp[MAX_LINE_LENGTH]; + bool bFirstFuncFound = false; + // Get all lines where is "Thumb" + do + { + // Load one line from .map file + in.getline( cTemp, MAX_LINE_LENGTH ); + // Find _E32Startup + if( !bFirstFuncFound && ( strstr( cTemp, "_E32Startup" ) != NULL) ) + { + bFirstFuncFound = true; + } + else if( !bFirstFuncFound && ( strstr( cTemp, "_E32Dll" ) != NULL) ) + { + bFirstFuncFound = true; + } + else if( !bFirstFuncFound ) + // Skip if _E32Startup not found + continue; + + if( strstr( cTemp, "Thumb Code" ) != NULL || strstr( cTemp, "ARM Code" ) != NULL) + { + MAP_FUNC_INFO structMapFileLineInfo; + structMapFileLineInfo.sWholeLine.append( cTemp ); + + // Get memory string address from line + char* pStart = strstr( cTemp, "0x" ); + // Check did strstr return null. + if( pStart == NULL ) + continue; + char* pTemp = pStart; + char TempString[MAX_LINE_LENGTH]; + TempString[0] = 0; + size_t iLength = 0; + while( *pTemp != ' ' ) + { + TempString[iLength] = *pTemp; + pTemp++; + iLength++; + } + TempString[iLength] = 0; + + structMapFileLineInfo.iAddress = CATDatParser::_httoi( TempString ); + + pTemp = cTemp; + TempString[0] = 0; + + // Get function name + + // Skip spaces + while( *pTemp == ' ' ) + { + pTemp++; + } + iLength = 0; + // Find end of function name + string sTemp( pTemp ); + + // Location of character ')' + iLength = sTemp.find_first_of(')'); + + // Location of character ' ' + size_t iLength2 = sTemp.find_first_of(' '); + + // If ')' character is the last char and + // character ' ' is closer than ')' use location of ' ' + if( ( iLength + 1 ) == sTemp.length() && iLength2 < iLength ) + iLength = iLength2 - 1; + + if( iLength != string::npos ) + sTemp.resize( (iLength + 1) ); + + structMapFileLineInfo.sFunctionName.append( sTemp.c_str() ); + + bool bARM = false; + // Find function length + pStart = strstr( cTemp, "Thumb Code" ); + if( pStart == NULL ) + { + pStart = strstr( cTemp, "ARM Code" ); + bARM = true; + } + if( pStart != NULL ) + { + if( bARM ) + pStart += 8; + else + pStart += 10; + while(*pStart == ' ') + { + pStart++; + } + sTemp.clear(); + sTemp.append( pStart ); + size_t iSize = sTemp.find_first_of(' '); + if( iSize != string::npos ) + sTemp.resize( iSize ); + } + + structMapFileLineInfo.iFuncLength = atoi( sTemp.c_str() ); + if( bFirstFuncFound && structMapFileLineInfo.iFuncLength > 0 ) + // Save to list + m_vMapFileFuncList.push_back( structMapFileLineInfo ); + } + } + while( in.good() ); + in.close(); + return true; +} + +int CATModule2::FindLeakCodeLine( string& sFileName, int iLine, unsigned long iFromFuncAddress ) const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::FindLeakCodeLine"); + if ( sFileName.empty() ) + return -1; + char cLineFromFile[MAX_LINE_LENGTH]; + vector<string> vTempLines; + string sTemp; + char* pTemp = NULL; + char* pTempEnd = NULL; + int iFoundLine = -1; + int iRet = -1; + + // Open lst file + ifstream in( sFileName.c_str() ); + + bool bLineFound = false; + bool bFirstAddressInFuncFound = false; + unsigned long iFirstAddressInFunc = 0; + while( in.good() ) + { + in.getline( cLineFromFile, MAX_LINE_LENGTH ); + + if( bLineFound ) + { + vTempLines.push_back( cLineFromFile ); + // Is first character digit + if( isdigit( cLineFromFile[0] ) ) + { + if( !bFirstAddressInFuncFound ) + { + bFirstAddressInFuncFound = true; + sTemp.clear(); + sTemp.append( cLineFromFile ); + // Get value until next space + sTemp.resize( sTemp.find_first_of(' ') ); + + iFirstAddressInFunc = CATDatParser::_httoi( sTemp.c_str() ); + + // Return function start line if margin 0 + if( iFromFuncAddress == 0 ) + { + iRet = iLine; + return iRet; + } + } + else + { + // Find correct line using iFromFuncAddress variable + sTemp.clear(); + sTemp.append( cLineFromFile ); + // Get value until next space + sTemp.resize( sTemp.find_first_of(' ') ); + + unsigned long iValue = CATDatParser::_httoi( sTemp.c_str() ); + + if( ( iValue - iFirstAddressInFunc ) >= iFromFuncAddress ) + { + // If there is data in function, code line can not be found + if( strstr( cLineFromFile , "DCB" ) != NULL ) + { + iRet = -1; + return iRet; + } + pTemp = strstr( cLineFromFile, ";" ); + // Get line number + bool bStringNumber = true; + if( pTemp != NULL ) + { + string sTempLine( pTemp + 1 ); + // Are all characters numbers? + for( unsigned int i = 0 ; i < sTempLine .size() ; i++ ) + { + if( !isdigit(sTempLine[i]) ) + { + bStringNumber = false; + break; + } + } + } + else + bStringNumber = false; + if( bStringNumber ) + { + pTemp++; + // Get line number + iRet = atoi( pTemp ); + } + else + { + vector<string>::iterator sTempIter = vTempLines.end(); + + sTempIter--; + + // Find last code line + while( sTempIter != vTempLines.begin() ) + { + if( strstr( sTempIter->c_str() , "DCB" ) != NULL ) + { + iRet = -1; + return iRet; + } + if( strstr( sTempIter->c_str() , ";;;" ) == NULL ) + sTempIter--; + else + break; + } + if(sTempIter == vTempLines.begin() && strstr( sTempIter->c_str() , ";;;" ) == NULL) + { + iRet = -1; + return iRet; + } + sTempIter->erase( 0, 3 ); + sTempIter->resize( sTempIter->find(' ') ); + + // Leak line + iRet = atoi( sTempIter->c_str() ); + } + return iRet; + } + } + } + } + else // Line in file not found + { + // Find line of function + if( strstr( cLineFromFile, ";;;" ) != NULL ) + { + pTemp = &cLineFromFile[0]; + // Skip characters ";;;" + pTemp += 3; + pTempEnd = pTemp; + // Find end of line number + while( *pTempEnd != ' ' ) + { + pTempEnd++; + } + *pTempEnd = 0; + iFoundLine = atoi( pTemp ); + *pTempEnd = ' '; + if( iLine == iFoundLine ) + { + bLineFound = true; + } + } + } + } + return iRet; +} + +bool CATModule2::IsMakeSuccessfull() +{ + LOG_FUNC_ENTRY("CATModule2::IsMakeSuccessfull"); + m_sErrors.clear(); + + string sSearch; + bool bMakeSuccess = true; + + // Lst files checked only with armv5 platform. + if ( IsPlatformArmv5() ) + { + sSearch.append( m_sTempPath ); + sSearch.append( "*.lst" ); + if( !SearchFileWithExtension( sSearch.c_str(), false, m_sErrors ) ) + bMakeSuccess = false; + + // Map + sSearch.clear(); + sSearch.append( m_sTempPath ); + sSearch.append( "*.map" ); + if( !SearchFileWithExtension( sSearch.c_str(), false, m_sErrors ) ) + bMakeSuccess = false; + } + + // .tmp + sSearch.clear(); + sSearch.append( m_sTempPath ); + sSearch.append( "*.tmp" ); + if( !SearchFileWithExtension( sSearch.c_str(), false, m_sErrors ) ) + bMakeSuccess = false; + + return bMakeSuccess; +} + +bool CATModule2::CreateBuildCompleteFile() +{ + LOG_FUNC_ENTRY("CATModule2::CreateBuildCompleteFile"); + // Don't create file if temp path not set cause might be anywhere + if ( m_sTempPath.empty() ) + return false; + // Create empty file indicating this module is build + string sFile = m_sTempPath; + if( sFile.at( sFile.length() - 1 ) != '\\' ) + sFile.append("\\"); + sFile.append( "BuildComplete" ); + ofstream out( sFile.c_str() ); + out << m_sVariantPlatform << endl; + out << m_sVariantType << endl; + out.close(); + return true; +} + +bool CATModule2::ReadMakeFileFromTemp() +{ + LOG_FUNC_ENTRY("CATModule2::ReadMakeFileFromTemp"); + // Set makefile to point to temporary directory. + string sMakeFile = m_sTempPath; + sMakeFile.append( RemovePathAndExt( m_Mmp.m_sMmpFile, true ) ); + sMakeFile.append( "." ); + sMakeFile.append( AT_LEVEL_2_MAKEFILE_EXT ); + m_sMakeFile = sMakeFile; + return ReadMakeFilePrivate(); +} + +bool CATModule2::ReadMakeFile() +{ + LOG_FUNC_ENTRY("CATModule2::ReadMakeFile"); + // Read makefile + if ( ReadMakeFilePrivate() ) + { + // Copy makefile to temporary directory. + string sMakeFile = m_sTempPath; + sMakeFile.append( RemovePathAndExt( m_Mmp.m_sMmpFile, true ) ); + sMakeFile.append( "." ); + sMakeFile.append( AT_LEVEL_2_MAKEFILE_EXT ); + FileCopyToPath( m_sMakeFile, sMakeFile ); + return true; + } + return false; +} + +bool CATModule2::ReadMakeFilePrivate() +{ + LOG_FUNC_ENTRY("CATModule2::ReadMakeFilePrivate"); + + if ( m_sMakeFile.empty() ) + return false; + + LOG_STRING( "using makefile :" << m_sMakeFile ); + + // Stream object to read files + ifstream in; + // Char array to read line from file + char cLine[MAX_LINE_LENGTH]; + // String to use as buffer from file + string sLine; + // Open file + in.open( m_sMakeFile.c_str(), ios_base::in ); + // Check that its open + if ( ! in.good() ) + { + // Cannot open file + cout << AT_MSG << "Error, can not open file: " << m_sMakeFile << endl; + return false; + } + // Check is it wrapper makefile (starts with "%:") + in.getline( cLine, MAX_LINE_LENGTH ); + if ( cLine[0] == '%' && cLine[1] == ':' ) + { + LOG_STRING("Found wrapper makefile"); + in.close(); + // Use ".default" makefile + string sDefaultMakeFile = m_sMakeFile.substr( 0, m_sMakeFile.find_last_of( "." ) ); + sDefaultMakeFile.append( ".DEFAULT" ); + LOG_STRING( "using makefile :" << m_sMakeFile ); + // Does default exists. If not we need to run "wrapper make" + if ( ! FileExists( sDefaultMakeFile.c_str() ) ) + { + // Run the wrapper make to create "real" makefile + string sMakeFileCmd; + sMakeFileCmd.append("make -f \""); + sMakeFileCmd.append( m_sMakeFile ); + sMakeFileCmd.append( "\"" ); + LOG_STRING( "using makefile :" << m_sMakeFile ); + cout << AT_MSG_SYSTEM_CALL << sMakeFileCmd << endl; + int iRet = (int)system( sMakeFileCmd.c_str() ); + if ( iRet ) + { + cout << MAKE_ERROR; + return false; + } + } + m_sMakeFile = sDefaultMakeFile; + // Open new file + in.open( m_sMakeFile.c_str(), ios_base::in ); + // Check that it's open + if ( ! in.good() ) + { + // Cannot open file + cout << AT_MSG << "Error, can not open makefile: " << m_sMakeFile << endl; + return false; + } + } + in.seekg( ios_base::beg ); + + // Number of lines to read at max for basic module information. + int iReadLineCount = 20; + // Extension from target line. to be compared with targettype. + string sTargetExtension; + // Read line at a time. Loop until we find it or eof + do { + // Read line from file to array + in.getline( cLine, MAX_LINE_LENGTH ); + iReadLineCount--; + + sLine.clear(); + // Put that to string + sLine.append( cLine ); + // Search target + if ( sLine.find( MAKEFILE_TARGET_STRING ) != string::npos ) + { + // Found it. Now remove other than type from line + sLine.erase( 0, strlen( MAKEFILE_TARGET_STRING ) ); + ChangeToLower( sLine ); + sTargetExtension.clear(); + sTargetExtension = GetExtension( sLine ); + m_sTarget = RemovePathAndExt( sLine, true); + LOG_STRING("found target: " << sLine ); + } + // Search targettype + else if ( sLine.find( MAKEFILE_TARGETTYPE_STRING ) != string::npos ) + { + // Found it. Now remove other than type from line + sLine.erase( 0, strlen( MAKEFILE_TARGETTYPE_STRING ) ); + ChangeToLower( sLine ); + m_sTargetType = sLine; + LOG_STRING("found target type: " << m_sTargetType ); + } + else if ( sLine.find( MAKEFILE_BASIC_TARGETTYPE_STRING ) != string::npos ) + { + sLine.erase( 0, strlen( MAKEFILE_BASIC_TARGETTYPE_STRING ) ); + ChangeToLower( sLine ); + m_sRequestedTargetExt = sLine; + // Compare with the extension in target line if not same use target lines if its "valid". + if ( m_sRequestedTargetExt.compare( sTargetExtension ) != 0 && sTargetExtension.size() > 0 ) + m_sRequestedTargetExt = sTargetExtension; + LOG_STRING("found requested target extension: " << m_sTargetType ); + } + // Feature variant details + else if ( sLine.find( MAKEFILE_FEATURE_VARIANT_NAME ) != string::npos ) + { + sLine.erase( 0, strlen( MAKEFILE_FEATURE_VARIANT_NAME ) ); + m_sFeatureVariantName = sLine; + LOG_STRING("found feature variant name: " << sLine ); + } + else if ( sLine.find( MAKEFILE_FEATURE_VARIANT_UREL_LABEL ) != string::npos ) + { + sLine.erase( 0, strlen( MAKEFILE_FEATURE_VARIANT_UREL_LABEL ) ); + LOG_STRING("found feature variant urel label: " << sLine ); + if ( sLine.compare("INVARIANT") != 0 ) + m_sFeatureVariantURELLabel = sLine; + } + else if ( sLine.find( MAKEFILE_FEATURE_VARIANT_UDEB_LABEL ) != string::npos ) + { + sLine.erase( 0, strlen( MAKEFILE_FEATURE_VARIANT_UDEB_LABEL ) ); + LOG_STRING("found feature variant udeb label: " << sLine ); + if ( sLine.compare("INVARIANT") != 0 ) + m_sFeatureVariantUDEBLabel = sLine; + } + } while( in.good() && iReadLineCount > 0 ); + + // Search compile definitions + // CWDEFS CCDEFS ARMCCDEFS + do + { + in.getline( cLine, MAX_LINE_LENGTH ); + sLine.clear(); + sLine.append( cLine ); + if ( sLine.substr( 0 , 6 ).compare( string("CWDEFS") ) == 0 + || sLine.substr( 0 , 6 ).compare( string("CCDEFS") ) == 0 ) + { + sLine.erase( 0, 8 ); + m_sCompileDefinitions = sLine; + break; + } + else if( sLine.substr( 0 , 9 ).compare( string("ARMCCDEFS") ) == 0 ) + { + sLine.erase( 0, 11 ); + m_sCompileDefinitions = sLine; + break; + } + } while( in.good() ); + // Move reading back to start if we could not find compile flags. + in.seekg( ios_base::beg ); + + // Search listing information (modules source files). + int iFindItem = 1; //1 = Source, 2 = LISTINGUDEB/UREL, 3 = lst file + string sCdefs; + string sSource; + string sLst; + do + { + in.getline( cLine, MAX_LINE_LENGTH ); + sLine.clear(); + sLine.append( cLine ); + + switch( iFindItem ) + { + case 1: + if( sLine.find( "# Source " ) != string::npos ) + { + iFindItem = 2; + // Remove text "# Source " + sLine.erase( 0, 9 ); + sSource = sLine; + } + break; + case 2: + if( IsUDEB() ) + { + if( sLine.find( "LISTINGUDEB" ) != string::npos ) + { + iFindItem = 3; + } + } + else + { + if( sLine.find( "LISTINGUREL" ) != string::npos ) + { + iFindItem = 3; + } + } + break; + case 3: + if( sLine.find( "perl -S ecopyfile.pl" ) != string::npos ) + { + // Save lst file to list + sLine.erase( 0, ( sLine.find_first_of( "\\" ) ) ); + // remove last char if '"' + if ( sLine.at( sLine.size()-1 ) == '"' ) + sLine.erase( sLine.size()-1, sLine.size() ); + sLst = sLine; + AddSource( sSource, sLst ); + iFindItem = 1; + sSource.clear(); sLst.clear(); + + } + break; + } + } + while( in.good() ); + // close and return + in.close(); + return true; +} + +// ---------------------------------------------------------------------------- +// Get & Sets +// ---------------------------------------------------------------------------- +string CATModule2::GetErrors() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetErrors"); + return m_sErrors; +} + +string CATModule2::GetS60FileName() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetS60FileName"); + if ( m_sS60FileName.empty() ) + { + string sGeneratedDatName = m_sTarget; + sGeneratedDatName.append("."); + sGeneratedDatName.append( m_sTargetType ); + sGeneratedDatName.append(".dat"); + return sGeneratedDatName; + } + return m_sS60FileName; +} + +string CATModule2::GetLstNameOfSource(string sSource) const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetLstNameOfSource"); + // Find . before xtension + size_t iSpot = sSource.find_last_of( "." ); + // Get sub string to there + string sLst = sSource.substr(0, iSpot+1); + if ( m_sVariantPlatform.compare( "winscw" ) != 0 ) + { + // Add variant platform (i.e. armv5) + sLst.append( m_sVariantPlatform ); + sLst.append( "." ); + // Add variant type (i.e. build type liek urel) + sLst.append( m_sVariantType ); + sLst.append( "." ); + // Add target binary name + sLst.append( m_sTarget ); + sLst.append( "." ); + // Add target requested binary extension + sLst.append( m_sRequestedTargetExt ); + sLst.append( "." ); + // Add lst extension + sLst.append( "lst" ); + } + else + { + sLst.append( "WINSCW.lst" ); + } + return sLst; +} + +bool CATModule2::IsPlatformArmv5() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::IsPlatformArmv5"); + if ( _stricmp( m_sVariantPlatform.c_str(), "armv5" ) == 0 ) + return true; + return false; +} + +string CATModule2::GetMapFile() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetMapFile"); + // Map file with path using variables + string sMapFile( m_sReleasePath ); + if ( ! sMapFile.empty() ) + sMapFile.append( "\\" ); + sMapFile.append( m_sFullVariantPath ); + if ( ! m_sFullVariantPath.empty() ) + sMapFile.append( "\\" ); + sMapFile.append( m_sTarget ); + sMapFile.append( "." ); + // Possible feature variant. Note debug might not be defined + // when release has got one. + if ( IsUDEB() && !m_sFeatureVariantUDEBLabel.empty() ) + { + sMapFile.append( m_sFeatureVariantUDEBLabel ); + sMapFile.append( "." ); + } + + if ( !IsUDEB() && !m_sFeatureVariantURELLabel.empty() ) + { + sMapFile.append( m_sFeatureVariantURELLabel ); + sMapFile.append( "." ); + } + sMapFile.append( m_sRequestedTargetExt ); + sMapFile.append( ".map" ); + return sMapFile; +} + +string CATModule2::GetSymbolFile() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetSymbolFile"); + // Symbol file with path using variables + string sSymbolFile( m_sReleasePath ); + sSymbolFile.append( "\\" ); + sSymbolFile.append( m_sFullVariantPath ); + sSymbolFile.append( "\\" ); + sSymbolFile.append( m_sTarget ); + sSymbolFile.append( "." ); + // Possible feature variant. + if ( ! m_sFeatureVariantUDEBLabel.empty() || ! m_sFeatureVariantURELLabel.empty() ) + { + if ( IsUDEB() ) + sSymbolFile.append( m_sFeatureVariantUDEBLabel ); + else + sSymbolFile.append( m_sFeatureVariantURELLabel ); + sSymbolFile.append( "." ); + } + + if ( m_eBuildSystem == CATProject::SBS_V1 ) + { + sSymbolFile.append( "sym" ); + return sSymbolFile; + } + sSymbolFile.append( m_sRequestedTargetExt ); + sSymbolFile.append( ".sym" ); + return sSymbolFile; +} + +string CATModule2::GetBinaryFile() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetBinaryFile"); + // Binary file with path using variables + string sBinaryFile( m_sReleasePath ); + if ( ! sBinaryFile.empty() ) + sBinaryFile.append( "\\" ); + sBinaryFile.append( m_sFullVariantPath ); + if ( ! m_sFullVariantPath.empty() ) + sBinaryFile.append( "\\" ); + sBinaryFile.append( m_sTarget ); + sBinaryFile.append( "." ); + // Possible feature variant. + if ( ! m_sFeatureVariantUDEBLabel.empty() || ! m_sFeatureVariantURELLabel.empty() ) + { + if ( IsUDEB() ) + sBinaryFile.append( m_sFeatureVariantUDEBLabel ); + else + sBinaryFile.append( m_sFeatureVariantURELLabel ); + sBinaryFile.append( "." ); + } + sBinaryFile.append( m_sRequestedTargetExt ); + return sBinaryFile; +} + +bool CATModule2::SetMmpFile(const string& sMmpFile) +{ + LOG_FUNC_ENTRY("CATModule2::SetMmpFile"); + // Set mmp file + m_Mmp.m_sMmpFile = sMmpFile; + // Change to lower + ChangeToLower( m_Mmp.m_sMmpFile ); + // Convert + ConvertUnixPathToWin( m_Mmp.m_sMmpFile ); + // Set the temporary path. + m_sTempPath.clear(); + m_sTempPath = CreateTempPath( m_Mmp.m_sMmpFile ); + return true; +} + +bool CATModule2::CreateTemporaryDirectory() +{ + LOG_FUNC_ENTRY("CATModule2::CreateTemporaryDirectory"); + if ( m_sTempPath.empty() ) + { + LOG_STRING("Temporary path is not set."); + return false; + } + // Create temp dir if not exists + if ( ! DirectoryExists( m_sTempPath.c_str() ) ) + { + if ( !CreateDirectory( m_sTempPath.c_str(), NULL ) ) + { + cout << AT_MSG << "Error, can not create directory: " + << m_sTempPath << endl; + return false; + } + cout << AT_MSG << "Directory created: " << m_sTempPath << endl; + } + return true; +} + +void CATModule2::SetMakeFile( const string& sMakeFile ) +{ + LOG_FUNC_ENTRY("CATModule2::SetMakeFile"); + m_sMakeFile = sMakeFile; +} +string CATModule2::GetMakeFile() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetMakeFile"); + return m_sMakeFile; +} +string CATModule2::GetMmpFile() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetMmpFile"); + return m_Mmp.m_sMmpFile; +} +string CATModule2::GetTempPath() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetTempPath"); + return m_sTempPath; +} +void CATModule2::SetTarget(const string& sTarget) +{ + LOG_FUNC_ENTRY("CATModule2::SetTarget"); + m_sTarget = sTarget; + ChangeToLower( m_sTarget ); +} +string CATModule2::GetTarget() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetTarget"); + return m_sTarget; +} +string CATModule2::GetBinaryName() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetBinaryName"); + string sBinaryName; + sBinaryName.append( m_sTarget ); + sBinaryName.append( "." ); + sBinaryName.append( m_sRequestedTargetExt ); + return sBinaryName; +} + +void CATModule2::SetTargetType(const string& sTargetType) +{ + LOG_FUNC_ENTRY("CATModule2::SetTargetType"); + m_sTargetType = sTargetType; + ChangeToLower( m_sTargetType ); +} +string CATModule2::GetTargetType() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetTargetType"); + return m_sTargetType; +} +void CATModule2::SetRequestedTargetExt( const string& sRequestedTargetExt ) +{ + LOG_FUNC_ENTRY("CATModule2::SetRequestedTargetExt"); + m_sRequestedTargetExt = sRequestedTargetExt; + ChangeToLower( m_sRequestedTargetExt ); +} + +string CATModule2::GetRequestedTargetExt() const +{ + LOG_LOW_FUNC_ENTRY("CATmodule2::GetRequestedTargetExt"); + return m_sRequestedTargetExt; +} + +void CATModule2::SetVariantPlatform(const string& sVariantPlatform) +{ + LOG_FUNC_ENTRY("CATModule2::SetVariantPlatform"); + m_sVariantPlatform = sVariantPlatform; + ChangeToLower( m_sVariantPlatform ); +} +string CATModule2::GetVariantPlatform() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetVariantPlatform"); + return m_sVariantPlatform; +} +void CATModule2::SetVariantType(const string& sVariantType) +{ + LOG_FUNC_ENTRY("CATModule2::SetVariantType"); + m_sVariantType = sVariantType; + ChangeToLower( m_sVariantType ); +} +string CATModule2::GetVariantType() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetVariantType"); + return m_sVariantType; +} +void CATModule2::SetFeatureVariant(const string& sFeatureVariant) +{ + LOG_FUNC_ENTRY("CATModule2::SetFeatureVariant"); + m_sFeatureVariant = sFeatureVariant; + ChangeToLower( m_sFeatureVariant ); +} +string CATModule2::GetFeatureVariant() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetFeatureVariant"); + return m_sFeatureVariant; +} +void CATModule2::SetFeatureVariantName(const string& sFeatureVariantName) +{ + LOG_FUNC_ENTRY("CATModule2::SetFeatureVariantName"); + m_sFeatureVariantName = sFeatureVariantName; + ChangeToLower( m_sFeatureVariantName ); +} +string CATModule2::GetFeatureVariantName() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetFeatureVariantName"); + return m_sFeatureVariantName; +} +void CATModule2::SetReleasePath(const string& sReleasePath) +{ + LOG_FUNC_ENTRY("CATModule2::SetReleasePath"); + m_sReleasePath = sReleasePath; + ChangeToLower( m_sReleasePath ); + ConvertUnixPathToWin( m_sReleasePath ); + +} +string CATModule2::GetReleasePath() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetReleasePath"); + return m_sReleasePath; +} +void CATModule2::SetFullVariantPath(const string& sFullVariantPath) +{ + LOG_FUNC_ENTRY("CATModule2::SetFullVariantPath"); + m_sFullVariantPath = sFullVariantPath; + ChangeToLower( m_sFullVariantPath ); + ConvertUnixPathToWin( m_sFullVariantPath ); +} +string CATModule2::GetFullVariantPath() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetFullVariantPath"); + return m_sFullVariantPath; +} +string CATModule2::GetUniqueId() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetUniqueId"); + return FilterString( m_sTarget ); +} +void CATModule2::SetBuildSystem( int eBuildSystem ) +{ + LOG_FUNC_ENTRY("CATModule2::SetBuildSystem"); + m_eBuildSystem = eBuildSystem; +} + +int CATModule2::GetBuildSystem() const +{ + LOG_LOW_FUNC_ENTRY("CATModule2::GetBuildSystem"); + return m_eBuildSystem; +} + +void CATModule2::SetCompileDefinitions( const string& sCompileDefinitions ) +{ + LOG_LOW_FUNC_ENTRY( "CATModule2::SetCompileDefinitions" ); + m_sCompileDefinitions = sCompileDefinitions; +} + +string CATModule2::GetCompileDefinitions() const +{ + LOG_LOW_FUNC_ENTRY( "CATModule2::GetCompileDefinitions" ); + return m_sCompileDefinitions; +} + +void CATModule2::SetCompileInfoText( string sCompileInfoText ) +{ + LOG_LOW_FUNC_ENTRY( "CATModule2::SetCompileInfoText" ); + m_sCompileInfoText = sCompileInfoText; +} +string CATModule2::GetCompileInfoText() const +{ + LOG_LOW_FUNC_ENTRY( "CATModule2::GetCompileInfoText" ); + return m_sCompileInfoText; +} +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/CATParseTraceFile.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/CATParseTraceFile.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,585 @@ +/* +* 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 CATParseTraceFile. +* +*/ + + +#include "../inc/ATCommonDefines.h" +#include "../inc/CATParseTraceFile.h" +#include "../inc/catdatasaver.h" +#include "../inc/CATDatParser.h" + +#include <time.h> + +#define MAIN_ID "PCSS" +#define ALLOC_ID "ALLOC" // < V.1.6 allocation. +#define ALLOCH_ID "ALLOCH" // Header of multi message allocation. +#define ALLOCF_ID "ALLOCF" // Fragment of multi message allocation. +#define FREE_ID "FREE" +#define FREEH_ID "FREEH" // Header of multi message free. +#define FREEF_ID "FREEF" // Fragment of multi message free. +#define HANDLE_LEAK_ID "HANDLE_LEAK" + +const string ERROR_OCCURED = "ERROR_OCCURED"; // Error messages. +const string INCORRECT_ATOOL_VERSION = "INCORRECT_ATOOL_VERSION"; +/** +* Invalid characters in trace file line content. +* These will be filtered out before actuall parsing of line. +10 = LF +13 = CR +124 = | +*/ +const char cINVALID_TRACE_FILE_CHARS[] = { 10, 13, 124 }; + +// ----------------------------------------------------------------------------- +// CATParseTraceFile::CATParseTraceFile +// Constructor. +// ----------------------------------------------------------------------------- +CATParseTraceFile::CATParseTraceFile() +{ + LOG_FUNC_ENTRY("CATParseTraceFile::CATParseTraceFile"); + m_DataSaver.SetPrintFlag( false ); +} + +// ----------------------------------------------------------------------------- +// CATParseTraceFile::StartParse +// Main function to start trace parsing. +// ----------------------------------------------------------------------------- +bool CATParseTraceFile::StartParse( const char* pFileName, const char* pOutputFileName ) +{ + LOG_FUNC_ENTRY("CATParseTraceFile::StartParse"); + + // Return value, will be changed to true if process start found. + bool bRet = false; + + // Check pointers + if ( pFileName == NULL ) + return bRet; + + if( pOutputFileName == NULL ) + return bRet; + + if ( ! FileExists( pFileName ) ) + { + cout << AT_MSG << "Error, input file \"" + << pFileName + << "\" does not exist." << endl; + return bRet; + } + + // Open data file + ifstream in( pFileName ); + + // Check file opened ok + if ( !in.good() ) + return false; + + // Get stream size + size_t streamPos = in.tellg(); + in.seekg( 0, ios::end); + size_t streamEnd = in.tellg(); + in.seekg( 0, ios::beg); + + //Origianl characters (not filtered). + char cOriginalLineFromFile[MAX_LINE_LENGTH]; + + vector<CProcessData> vProcessList; + int iProcessIDinList = -1; + + bool bFileVersionSaved = false; + // Read lines + while( streamPos < streamEnd ) + { + // Get one line. Don't use stream flags to determinate end of file + // it can be found too early because trace can contain "anything". + in.getline( cOriginalLineFromFile, MAX_LINE_LENGTH ); + + // Refresh position + streamPos = in.tellg(); + + // Check has bad bit flag raised. (i.e. device problems reading data) + if( in.bad() ) + { + cout << AT_MSG << "Integrity error reading the trace file, reading aborted." << endl; + return false; + } + //Filtered characters. + char cLineFromFile[MAX_LINE_LENGTH]; + char* pFiltered = cLineFromFile; + + //Loop thru all characters in original line. + for( size_t i = 0 ; cOriginalLineFromFile[i] != 0 ; i++ ) + { + //If character in line is not in invalid character array append it + //to filtered line. + if ( strchr( cINVALID_TRACE_FILE_CHARS, cOriginalLineFromFile[i] ) == 0 ) + *pFiltered++ = cOriginalLineFromFile[i]; + } + *pFiltered++ = 0; //Add null termination to filtered line. + + if( !bFileVersionSaved && *cLineFromFile != 0 ) + { + bFileVersionSaved = true; + m_DataSaver.AddString( AT_DATA_FILE_VERSION ); + m_DataSaver.AddLineToLast(); + } + + // Is there main ID? + if( strstr( cLineFromFile, MAIN_ID ) != NULL ) + { + string sRestOfLine( cLineFromFile ); + string sTemp; + + // Delete all characters before main ID + sRestOfLine.erase( 0, sRestOfLine.find( MAIN_ID ) ); + + // Get main ID + sTemp = GetStringUntilNextSpace( sRestOfLine ); + + // Is there more data in line? + if( sRestOfLine.empty() ) + { + continue; + } + + // Get next argument + sTemp = GetStringUntilNextSpace( sRestOfLine ); + // This might be process id or error message + if ( sTemp.compare( ERROR_OCCURED ) == 0 ) + { + // Api mismatch between s60 side and atool.exe + if ( sRestOfLine.find( INCORRECT_ATOOL_VERSION ) != string::npos ) + { + cout << "Test run failed because version conflict between device binaries\nand the atool.exe version used to build the application." << endl; + size_t pS = sRestOfLine.find_first_of('['); + size_t pE = sRestOfLine.find_first_of(']'); + size_t pSL = sRestOfLine.find_last_of('['); + size_t pEL = sRestOfLine.find_last_of(']'); + if ( pS != string::npos && pE != string::npos && pSL != string::npos && pEL != string::npos ) + { + string deviceVer = sRestOfLine.substr( pS+1, pE-pS-1 ); + string atoolVer = sRestOfLine.substr( pSL+1, pEL-pSL-1 ); + cout << "\tdevice: " << deviceVer << endl + << "\tatool.exe: " << atoolVer << endl; + } + } + else + cout << sRestOfLine << endl; + continue; + } + unsigned long iProcessID = _httoi( sTemp.c_str() ); + + iProcessIDinList = -1; + // Find process from list + for( unsigned int i = 0 ; i < vProcessList.size() ; i++ ) + { + if( vProcessList[i].iProcessID == iProcessID ) + { + iProcessIDinList = i; + break; + } + } + // Is Process ID found from list? + if( iProcessIDinList == -1 ) + { + CProcessData ProcessData; + ProcessData.bProcessOnGoing = false; + ProcessData.iProcessID = iProcessID; + vProcessList.push_back( ProcessData ); + iProcessIDinList = (int)vProcessList.size() - 1; + } + + // Remove spaces from end of line + while( sRestOfLine[sRestOfLine.size()-1] == ' ' ) + { + sRestOfLine.resize( sRestOfLine.size()-1 ); + } + + string sWholeTempLine( sRestOfLine ); + + // Get command + sTemp = GetStringUntilNextSpace( sRestOfLine ); + + // Use c style string for easy comparisong of command. + const char* pCommand = sTemp.c_str(); + + // Process start. + if( ! _stricmp( pCommand, LABEL_PROCESS_START ) ) + { + bRet = true; // Set return value true we found start. + vProcessList[iProcessIDinList].vData.push_back( sWholeTempLine ); + vProcessList[iProcessIDinList].bProcessOnGoing = true; + continue; + } + + // Check is process ongoing if not skip other tags. + if( vProcessList[iProcessIDinList].bProcessOnGoing == false ) + continue; + + // "Old style" allocation (< v.1.6) + if( ! _stricmp( pCommand, ALLOC_ID ) ) + { + // Add alloc + vProcessList[iProcessIDinList].Alloc( sRestOfLine ); + + // Subtests running? + vector<CSubTestData>::iterator viSubTestIter = vProcessList[iProcessIDinList].vSubTests.begin(); + while( viSubTestIter != vProcessList[iProcessIDinList].vSubTests.end() ) + { + if( viSubTestIter->bRunning ) + { + // Save alloc also to sub test + viSubTestIter->Alloc( sRestOfLine ); + } + viSubTestIter++; + } + } + else if ( ! _stricmp( pCommand, ALLOCH_ID ) ) + { + // Add alloc + vProcessList[iProcessIDinList].AllocH( sRestOfLine ); + + // Subtests running? + vector<CSubTestData>::iterator viSubTestIter = vProcessList[iProcessIDinList].vSubTests.begin(); + while( viSubTestIter != vProcessList[iProcessIDinList].vSubTests.end() ) + { + if( viSubTestIter->bRunning ) + { + // Save alloc also to sub test + viSubTestIter->AllocH( sRestOfLine ); + } + viSubTestIter++; + } + } + // Allocation fragment (call stack). + else if ( ! _stricmp( pCommand, ALLOCF_ID ) ) + { + // Add alloc fragment + vProcessList[iProcessIDinList].AllocF( sRestOfLine ); + + // Subtests running? + vector<CSubTestData>::iterator viSubTestIter = vProcessList[iProcessIDinList].vSubTests.begin(); + while( viSubTestIter != vProcessList[iProcessIDinList].vSubTests.end() ) + { + if( viSubTestIter->bRunning ) + { + // Save alloc fragment also to sub test + viSubTestIter->AllocF( sRestOfLine ); + } + viSubTestIter++; + } + } + // Command free + else if( ! _stricmp( pCommand, FREE_ID ) ) + { + // Send free + vProcessList[iProcessIDinList].Free( sRestOfLine ); + + // Subtests running? + vector<CSubTestData>::iterator viSubTestIter = vProcessList[iProcessIDinList].vSubTests.begin(); + while( viSubTestIter != vProcessList[iProcessIDinList].vSubTests.end() ) + { + if( viSubTestIter->bRunning ) + { + // Send free to subtest + viSubTestIter->Free( sRestOfLine ); + } + viSubTestIter++; + } + } + // Header free. + else if( ! _stricmp( pCommand, FREEH_ID ) ) + { + // Send free + vProcessList[iProcessIDinList].FreeH( sRestOfLine ); + + // Subtests running? + vector<CSubTestData>::iterator viSubTestIter = vProcessList[iProcessIDinList].vSubTests.begin(); + while( viSubTestIter != vProcessList[iProcessIDinList].vSubTests.end() ) + { + if( viSubTestIter->bRunning ) + { + // Send free to subtest + viSubTestIter->FreeH( sRestOfLine ); + } + viSubTestIter++; + } + + } + else if( ! _stricmp( pCommand, FREEF_ID ) ) + { + // Not used currently. + } + // Command process end + else if( ! _stricmp( pCommand, LABEL_PROCESS_END ) ) + { + // Set process has ended. + vProcessList[iProcessIDinList].bProcessOnGoing = false; + + // Save leaks + vector<string> vLeaks; + vector<string>::iterator viLeaks; + vProcessList[iProcessIDinList].GetLeakList( vLeaks ); + for ( viLeaks = vLeaks.begin(); viLeaks != vLeaks.end(); viLeaks++ ) + { + sTemp.clear(); + sTemp.append( LABEL_MEM_LEAK ); + sTemp.append( " " ); + sTemp.append( *viLeaks ); + vProcessList[iProcessIDinList].vData.push_back( sTemp ); + } + vProcessList[iProcessIDinList].ClearAllocs(); + + vector<string>::iterator viHandleIter = vProcessList[iProcessIDinList].vHandleLeaks.begin(); + // Print handle leaks + while( viHandleIter != vProcessList[iProcessIDinList].vHandleLeaks.end() ) + { + sTemp.clear(); + sTemp.append( viHandleIter->c_str() ); + vProcessList[iProcessIDinList].vData.push_back( sTemp ); + viHandleIter++; + } + // Clear handle leaks from list + vProcessList[iProcessIDinList].vHandleLeaks.clear(); + + vector<CSubTestData>::iterator viSubTestIter = vProcessList[iProcessIDinList].vSubTests.begin(); + // Print sub test leaks + while( viSubTestIter != vProcessList[iProcessIDinList].vSubTests.end() ) + { + // Print sub test start + string sLine( LABEL_TEST_START ); sLine.append( " " ); + sLine.append( viSubTestIter->sStartTime ); sLine.append( " " ); + sLine.append( viSubTestIter->sSubTestName ); sLine.append( " " ); + sLine.append( viSubTestIter->sSubTestStartHandleCount ); + vProcessList[iProcessIDinList].vData.push_back( sLine ); + sLine.clear(); + + // DLL Loads. + for( vector<string>::iterator it = viSubTestIter->vData.begin(); + it != viSubTestIter->vData.end(); it++ ) + { + vProcessList[iProcessIDinList].vData.push_back( (*it) ); + } + + // Subtest leaks. + vector<string> vSubLeaks; + vector<string>::iterator viSubLeaks; + viSubTestIter->GetLeakList( vSubLeaks ); + for ( viSubLeaks = vSubLeaks.begin(); viSubLeaks != vSubLeaks.end(); viSubLeaks++ ) + { + sLine.append( LABEL_MEM_LEAK ); + sLine.append( " " ); + sLine.append( *viSubLeaks ); + vProcessList[iProcessIDinList].vData.push_back( sLine ); + sLine.clear(); + } + viSubTestIter->ClearAllocs(); + + if( !viSubTestIter->sEndTime.empty() ) + { + // Print sub test end + sLine.append( LABEL_TEST_END ); sLine.append( " " ); + sLine.append( viSubTestIter->sEndTime ); sLine.append( " " ); + sLine.append( viSubTestIter->sSubTestName ); sLine.append( " " ); + sLine.append( viSubTestIter->sSubTestEndHandleCount ); + vProcessList[iProcessIDinList].vData.push_back( sLine ); + } + viSubTestIter++; + } + + // Clear sub tests from list + vProcessList[iProcessIDinList].vSubTests.clear(); + vProcessList[iProcessIDinList].vData.push_back( sWholeTempLine ); + } + else if( ! _stricmp( pCommand, LABEL_HANDLE_LEAK ) ) + { + // Make whole line + sTemp.append( " " ); + sTemp.append( sRestOfLine ); + vProcessList[iProcessIDinList].vHandleLeaks.push_back( sTemp ); + } + else if( ! _stricmp( pCommand, LABEL_DLL_LOAD ) ) + { + // Add module load to process data. + vProcessList[iProcessIDinList].vData.push_back( sWholeTempLine ); + // Add module load to subtest data if test running. + for( vector<CSubTestData>::iterator it = vProcessList[iProcessIDinList].vSubTests.begin(); + it != vProcessList[iProcessIDinList].vSubTests.end(); it++ ) + { + if( it->bRunning ) + it->vData.push_back( sWholeTempLine ); + } + + } + else if( ! _stricmp( pCommand, LABEL_DLL_UNLOAD ) ) + { + // Add module load to process data. + vProcessList[iProcessIDinList].vData.push_back( sWholeTempLine ); + // Add module unload to subtest data if test running. + for( vector<CSubTestData>::iterator it = vProcessList[iProcessIDinList].vSubTests.begin(); + it != vProcessList[iProcessIDinList].vSubTests.end(); it++ ) + { + if( it->bRunning ) + it->vData.push_back( sWholeTempLine ); + } + } + else if( sTemp.find( LABEL_LOGGING_CANCELLED ) != string::npos || + sTemp.find( LABEL_PROCESS_END ) != string::npos || sTemp.find( LABEL_ERROR_OCCURED ) != string::npos || + sTemp.find( LABEL_HANDLE_LEAK ) != string::npos ) + { + vProcessList[iProcessIDinList].vData.push_back( sWholeTempLine ); + } + else if( ! _stricmp( pCommand, LABEL_TEST_START ) ) + { + bRet = true; // Set return value true we found start. + // Get sub test time + string sSubTestTime = GetStringUntilNextSpace( sRestOfLine ); + // Get sub test name + string sSubTestName = GetStringUntilNextSpace( sRestOfLine ); + // Get sub test start handle count + string sSubTestStartHandleCount = GetStringUntilNextSpace( sRestOfLine ); + + CSubTestData SubTestData; + SubTestData.bRunning = true; + SubTestData.sStartTime = sSubTestTime; + SubTestData.sSubTestName = sSubTestName; + SubTestData.sSubTestStartHandleCount = sSubTestStartHandleCount.c_str(); + + vProcessList[iProcessIDinList].vSubTests.push_back( SubTestData ); + } + else if( ! _stricmp( pCommand, LABEL_TEST_END ) ) + { + // Get sub test time + string sSubTestEnd = GetStringUntilNextSpace( sRestOfLine ); + // Get sub test name + string sSubTestName = GetStringUntilNextSpace( sRestOfLine ); + // Get sub test end handle count + string sSubTestEndHandleCount = GetStringUntilNextSpace( sRestOfLine ); + + // Find subtest + vector<CSubTestData>::iterator viSubTestIter = vProcessList[iProcessIDinList].vSubTests.begin(); + while( viSubTestIter != vProcessList[iProcessIDinList].vSubTests.end() ) + { + if( viSubTestIter->sSubTestName == sSubTestName && viSubTestIter->sEndTime.empty() ) + { + viSubTestIter->sEndTime = sSubTestEnd; + viSubTestIter->bRunning = false; + viSubTestIter->sSubTestEndHandleCount = sSubTestEndHandleCount.c_str(); + } + viSubTestIter++; + } + } + } + } + + // Print all saved data from processes + for( unsigned int i = 0 ; i < vProcessList.size() ; i++ ) + { + // Print saved lines + for( unsigned int iDataCounter = 0 ; iDataCounter < vProcessList[i].vData.size() ; iDataCounter++ ) + { + m_DataSaver.AddString( vProcessList[i].vData[iDataCounter].c_str() ); + m_DataSaver.AddLineToLast(); + } + + string sTemp; + + // Save leaks + vector<string> vLeaks; + vector<string>::iterator viLeaks; + vProcessList[i].GetLeakList( vLeaks ); + for ( viLeaks = vLeaks.begin(); viLeaks != vLeaks.end(); viLeaks++ ) + { + sTemp.clear(); + sTemp.append( LABEL_MEM_LEAK ); + sTemp.append( " " ); + sTemp.append( *viLeaks ); + m_DataSaver.AddString( sTemp.c_str() ); + m_DataSaver.AddLineToLast(); + } + + vector<string>::iterator viHandleIter = vProcessList[i].vHandleLeaks.begin(); + // Print handle leaks, if there is data left, there was no process end. + while( viHandleIter != vProcessList[i].vHandleLeaks.end() ) + { + sTemp.clear(); + sTemp.append( viHandleIter->c_str() ); + m_DataSaver.AddString( sTemp.c_str() ); + m_DataSaver.AddLineToLast(); + viHandleIter++; + } + vector<CSubTestData>::iterator viSubTestIter = vProcessList[i].vSubTests.begin(); + // Print sub test data, if there is data left, there was no process end. + while( viSubTestIter != vProcessList[i].vSubTests.end() ) + { + // Print sub test start + string sLine( LABEL_TEST_START ); sLine.append( " " ); + sLine.append( viSubTestIter->sStartTime ); sLine.append( " " ); + sLine.append( viSubTestIter->sSubTestName ); sLine.append( " " ); + sLine.append( viSubTestIter->sSubTestStartHandleCount ); + m_DataSaver.AddString( sLine.c_str() ); + m_DataSaver.AddLineToLast(); + sLine.clear(); + + // DLL Loads. + for( vector<string>::iterator it = viSubTestIter->vData.begin(); + it != viSubTestIter->vData.end(); it++ ) + { + m_DataSaver.AddString( (*it).c_str() ); + m_DataSaver.AddLineToLast(); + } + + // Subtest leaks. + vector<string> vSubLeaks; + vector<string>::iterator viSubLeaks; + viSubTestIter->GetLeakList( vSubLeaks ); + for ( viSubLeaks = vSubLeaks.begin(); viSubLeaks != vSubLeaks.end(); viSubLeaks++ ) + { + sLine.append( LABEL_MEM_LEAK ); + sLine.append( " " ); + sLine.append( *viSubLeaks ); + m_DataSaver.AddString( sLine.c_str() ); + m_DataSaver.AddLineToLast(); + sLine.clear(); + } + + // Print sub test end + sLine.append( LABEL_TEST_END ); sLine.append( " " ); + sLine.append( viSubTestIter->sEndTime ); sLine.append( " " ); + sLine.append( viSubTestIter->sSubTestName ); sLine.append( " " ); + sLine.append( viSubTestIter->sSubTestEndHandleCount ); + m_DataSaver.AddString( sLine.c_str() ); + m_DataSaver.AddLineToLast(); + + viSubTestIter++; + } + } + // Save lines to file. + m_DataSaver.SaveLinesToFile( pOutputFileName, TEXT_DATA ); + // Close file. + in.close(); + return bRet; +} + +// ----------------------------------------------------------------------------- +// CATParseTraceFile::GetDataSaver +// Gets data saver object. +// ----------------------------------------------------------------------------- +CATDataSaver* CATParseTraceFile::GetDataSaver(void) +{ + LOG_LOW_FUNC_ENTRY("CATParseTraceFile::GetDataSaver"); + return &m_DataSaver; +} +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/CATParseXML.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/CATParseXML.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,148 @@ +/* +* 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 CATParseXML. +* +*/ + + +#include "../inc/CATParseXML.h" +#include "../inc/catdatasaver.h" +#include "../inc/CATBase.h" + +#include <xercesc/parsers/XercesDOMParser.hpp> + +const char cCanNotFindEpocroot[] = "Can not find EPOCROOT from devices.xml.\n"; +const char cErrorInDeviceXml[] = "Error in devices.xml!\n"; +const char cCanNotFind[] = "Can not find file: %s.\n"; + +CATParseXML::CATParseXML(void) +{ + LOG_FUNC_ENTRY("CATParseXML::CATParseXML"); + try + { + xercesc::XMLPlatformUtils::Initialize(); + } + catch ( ... ) + { + //Print error + printf("XML initialization failed.\n"); + } +} + +CATParseXML::~CATParseXML(void) +{ + LOG_FUNC_ENTRY("CATParseXML::~CATParseXML"); +} + +// ----------------------------------------------------------------------------- +// CATParseXML::GetEpocRootPathFromXML +// Find epocroot path in xml file +// ----------------------------------------------------------------------------- +string CATParseXML::GetEpocRootPathFromXML(const char* pSourcePath) +{ + LOG_FUNC_ENTRY("CATParseXML::GetEpocRootPathFromXML"); + string sEpocRootPath; + // Check that source exists + if ( ! CATBase::FileExists( pSourcePath ) ) + { + LOG_STRING( "Source xml not found." ); + return sEpocRootPath; + } + try + { + xercesc::XercesDOMParser* parser = new xercesc::XercesDOMParser(); + xercesc::DOMDocument* pDomDoc; + + // Get devices.xml document + parser->parse( pSourcePath ); + pDomDoc = parser->getDocument(); + + // Get root element + xercesc::DOMElement* pRootElem = pDomDoc->getDocumentElement(); + + if( pRootElem ) + { + // Get all "device" elements + LPWSTR wTemp = CATDataSaver::CharToWChar( "device" ); + xercesc::DOMNodeList* pDeviceNodeList = pRootElem->getElementsByTagName( wTemp ); + if( wTemp ) + delete[] wTemp; + + // Find default SDK + + bool bEpocRootFound = false; + int iLength = pDeviceNodeList->getLength(); + for( int i = 0 ; i < iLength ; i++ ) + { + xercesc::DOMNode* pDeviceNode = pDeviceNodeList->item(i); + + xercesc::DOMNamedNodeMap* pAttributeList = pDeviceNode->getAttributes(); + + // Find attribute "default" + + int iAttribListLength = pAttributeList->getLength(); + for( int x = 0 ; x < iAttribListLength ; x++ ) + { + xercesc::DOMNode* pAttribNode = pAttributeList->item(x); + const LPWSTR pNodeName = (const LPWSTR)pAttribNode->getNodeName(); + + if( wcscmp( pNodeName, L"default" ) == 0 ) + { + const LPWSTR pNodeValue = (const LPWSTR)pAttribNode->getNodeValue(); + + // Find node value 'yes' + if( wcscmp( pNodeValue, L"yes" ) == 0 ) + { + // Find <epocroot> node + xercesc::DOMNode* pChildNode = pDeviceNode->getFirstChild(); + if( !pChildNode ) + break; + while( !bEpocRootFound ) + { + if( wcscmp( pChildNode->getNodeName() , L"epocroot" ) == 0 ) + { + bEpocRootFound = true; + + // Node value is child text node + xercesc::DOMNode* pTempTextNode = pChildNode->getFirstChild(); + const LPWSTR pPathNodeValue = (const LPWSTR)pTempTextNode->getNodeValue(); + + CATDataSaver::WCharToChar( sEpocRootPath, pPathNodeValue ); + + break; + } + pChildNode = pChildNode->getNextSibling(); + if( !pChildNode ) + break; + } + } // If node value yes + } // If node name default + if( bEpocRootFound ) + break; + } // for x + if( bEpocRootFound ) + break; + } // for i + } + if(parser) + delete parser; //lint !e118 + xercesc::XMLPlatformUtils::Terminate(); + } + catch (...) + { + printf("XML parsing failed."); + } + return sEpocRootPath; +} +// End of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/CATProject.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/CATProject.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,2413 @@ +/* +* 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: Class representing a project. +* +*/ + + +#include "../inc/CATProject.h" +#include "../inc/CATModule2.h" +#include "../inc/CATParseTraceFile.h" +#include "../inc/CATDatParser.h" + +//dbghelp.dll version function. +extern int showDbgHelpVersionInfo( bool showVersion ); + +// ---------------------------------------------------------------------------- +// CATProject::CATProject() +// ---------------------------------------------------------------------------- +CATProject::CATProject() +{ + LOG_FUNC_ENTRY("CATProject::CATProject"); + + m_bUninstrumented = true; + m_bAbldTest = false; + + // Use windows api to acquire current directory info. + GetCurrentDirectory( MAX_LINE_LENGTH, m_cCurrentDir ); + + m_eBuildSystem = SBS_V1; + m_eBuildType = UDEB; + m_eLoggingMode = TRACE; + m_eMode = NOT_DEFINED; + + m_iLoggingLevel = 3; + + m_pAnalyzer = 0; + + m_sBinaryTarget = ""; + m_sBuildCommand = ""; + m_sDataFile = ""; + m_sDataFileOutput = ""; + m_sDataFileTemp = ""; + m_sEpocRoot = "\\"; + m_sMakeFile = ""; + m_sPlatform = ""; + m_sS60FileName = ""; + m_sTargetModule = ""; + m_sVariant = ""; + + m_vRomSymbolFiles.clear(); + m_vModules.clear(); + m_vStaticLibraries.clear(); + m_vTargetModules.clear(); + m_vUnsupportedModules.clear(); +} + +// ---------------------------------------------------------------------------- +// CATProject::~CATProject() +// ---------------------------------------------------------------------------- +CATProject::~CATProject() +{ + LOG_FUNC_ENTRY("CATProject::~CATProject"); + + CleanModuleVectors(); + + // Delete analyzer + if ( m_pAnalyzer ) + delete m_pAnalyzer; + + // Temporary datafile + if ( !m_sDataFileTemp.empty() ) + { + if ( FileExists( m_sDataFileTemp.c_str() ) ) + FileDelete( m_sDataFileTemp, false ); + } +} + +bool CATProject::SetArguments( ARGUMENTS& arguments ) +{ + LOG_FUNC_ENTRY("CATProject::SetArguments"); + bool bRet = true; + + //Project mode. + if( arguments.eHookSwitch == HOOK_INTERNAL ) + { + SetMode( CATProject::COMPILE ); + SetLoggingMode( CATProject::FILE ); + } + else if ( arguments.eHookSwitch == HOOK_EXTERNAL ) + { + SetMode( CATProject::COMPILE ); + SetLoggingMode( CATProject::TRACE ); + } + else if ( arguments.eHookSwitch == HOOK_EXTERNAL_FAST ) + { + SetMode( CATProject::COMPILE ); + SetLoggingMode( CATProject::TRACE_FAST ); + } + /* Extension*/ + else if ( arguments.eHookSwitch == HOOK_EXTENSION_INTERNAL ) + { + SetMode( CATProject::INSTRUMENT ); + SetLoggingMode( CATProject::FILE ); + } + else if ( arguments.eHookSwitch == HOOK_EXTENSION_EXTERNAL ) + { + SetMode( CATProject::INSTRUMENT ); + SetLoggingMode( CATProject::TRACE ); + } + else if ( arguments.eHookSwitch == HOOK_EXTENSION_EXTERNAL_FAST ) + { + SetMode( CATProject::INSTRUMENT ); + SetLoggingMode( CATProject::TRACE_FAST ); + } + else if ( arguments.eHookSwitch == HOOK_EXTENSION_UNINSTRUMENT ) + { + SetMode( CATProject::UNINSTRUMENT ); + } + else if ( arguments.eHookSwitch == HOOK_EXTENSION_FAILED ) + { + SetMode( CATProject::UNINSTRUMENT_FAILED ); + } + //Return if uninstrumenting because no other arguments are set. + if ( GetMode() == CATProject::UNINSTRUMENT + || GetMode() == CATProject::UNINSTRUMENT_FAILED ) + { + return bRet; + } + + // No build / instrument. + if ( arguments.HOOK.bNoBuild ) + SetMode( CATProject::INSTRUMENT_CONSOLE ); + + // Call stack sizes + SetAllocCallStackSize( arguments.HOOK.iAllocCallStackSize ); + SetFreeCallStackSize( arguments.HOOK.iFreeCallStackSize ); + + //Build system. + if ( arguments.HOOK.iBuildSystem == 1 ) + SetBuildSystem( CATProject::SBS_V1 ); + else if ( arguments.HOOK.iBuildSystem == 2 ) + SetBuildSystem( CATProject::SBS_V2 ); + + //Test module build only + if ( arguments.HOOK.bAbldTest == true ) + m_bAbldTest = true; + + //Platform. + if ( !_stricmp( arguments.HOOK.sPlatform.c_str(), "armv5" ) ) + SetPlatform( arguments.HOOK.sPlatform ); + else if ( !_stricmp( arguments.HOOK.sPlatform.c_str(), "gcce" ) ) + SetPlatform( arguments.HOOK.sPlatform ); + else if ( !_stricmp( arguments.HOOK.sPlatform.c_str(), "winscw" ) ) + SetPlatform( arguments.HOOK.sPlatform ); + else + { + LOG_STRING( "Error, no supported platform specified (armv5/gcce/winscw)."); + bRet = false; + } + + //BuildType. + if ( !_stricmp( arguments.HOOK.sBuildType.c_str(), "urel" ) ) + SetBuildType( CATProject::UREL ); + else if ( !_stricmp( arguments.HOOK.sBuildType.c_str(), "udeb" ) ) + SetBuildType( CATProject::UDEB ); + else + { + LOG_STRING( "Error, no build type specified."); + bRet = false; + } + + //Internal data file. + if ( arguments.HOOK.bDataFileName ) + SetS60FileName( arguments.HOOK.sDataFileName ); + + //Build command. + if ( arguments.HOOK.sBuildCmd.empty() && ( + GetMode() == CATProject::COMPILE || + GetMode() == CATProject::INSTRUMENT || + GetMode() == CATProject::INSTRUMENT_CONSOLE + )) + { + cout << AT_MSG << "Error, no build command specified." << endl; + bRet = false; + } + + SetBuildCommand( arguments.HOOK.sBuildCmd ); + + //Variant. + SetVariant( arguments.HOOK.sFeatureVariant ); + + //Target programs. + SetTargetModules( arguments.HOOK.vTargetPrograms ); + + return bRet; +} + +void CATProject::CleanModuleVectors() +{ + LOG_FUNC_ENTRY("CATProject::CleanModuleVectors"); + // delete modules from vector. + for( size_t i = 0; i < m_vModules.size() ; i++ ) + delete m_vModules[i]; + m_vModules.clear(); + + // Delete modules from vector (unsupported). + for( size_t i = 0; i < m_vUnsupportedModules.size() ; i++ ) + delete m_vUnsupportedModules[i]; + m_vUnsupportedModules.clear(); + + // Delete modules from static library vector. + for( size_t i = 0; i < m_vStaticLibraries.size() ; i++ ) + delete m_vStaticLibraries[i]; + m_vStaticLibraries.clear(); +} +// ---------------------------------------------------------------------------- +// CATProject::Run +// ---------------------------------------------------------------------------- +int CATProject::Run() +{ + LOG_FUNC_ENTRY("CATProject::Run"); + int iReturnCode = 0; + switch( m_eMode ) + { + case COMPILE: + // Run compile + iReturnCode = RunCompile(); + if ( iReturnCode == AT_RETURN_CODE::READ_MAKEFILE_ERROR + || iReturnCode == AT_RETURN_CODE::KERNEL_SIDE_MODULE_ERROR + || iReturnCode == AT_RETURN_CODE::INVALID_MMP_DEFINED ) + { + DeleteTemporaryDirs(); + DirDelete( AT_TEMP_DIR, true ); + } + else + { + DisplayCompileSummary(); + DisplayBuildSummary(); + } + break; + case CLEAN: + iReturnCode = RunClean(); + break; + case ANALYZE: + iReturnCode = RunAnalyze(); + break; + case INSTRUMENT: + iReturnCode = RunInstrument(); + break; + case INSTRUMENT_CONSOLE: + iReturnCode = RunInstrumentConsole(); + if ( iReturnCode == AT_RETURN_CODE::READ_MAKEFILE_ERROR + || iReturnCode == AT_RETURN_CODE::KERNEL_SIDE_MODULE_ERROR ) + { + DeleteTemporaryDirs(); + DirDelete( AT_TEMP_DIR, true ); + } + else + { + DisplayBuildSummary(); + } + break; + case UNINSTRUMENT: + iReturnCode = RunUninstrument(); + // Show summary + DisplayCompileSummary(); + DisplayBuildSummary(); + break; + case UNINSTRUMENT_CONSOLE: + iReturnCode = RunUninstrumentConsole(); + // Show summary + DisplayCompileSummary(); + DisplayBuildSummary(); + break; + case UNINSTRUMENT_FAILED: + iReturnCode = RunUninstrumentFailed(); + // Display message + cout << AT_MSG << "Build aborted, because project contains compile error(s)." + << endl; + break; + default: + cout << AT_MSG << "Error, mode not supported / implemented." << endl; + break; + } + // Error messages + switch( iReturnCode ) + { + case AT_RETURN_CODE::MAKEFILE_ERROR: + cout << AT_MSG << "Error, creating/reading makefiles." << endl; + break; + case AT_RETURN_CODE::COMPILE_ERROR: + cout << AT_MSG << "Error, compiling project." << endl; + break; + case AT_RETURN_CODE::UNKNOWN: + cout << AT_MSG << "Error, unknown." << endl; + break; + case AT_RETURN_CODE::WRONG_DATA_FILE_VERSION: + cout << AT_MSG << "unable to analyze the data file.\n"; + cout << AT_MSG << "wrong data file version.\n"; + break; + case AT_RETURN_CODE::INVALID_DATA_FILE: + cout << AT_MSG << "Error, invalid datafile." << endl; + break; + case AT_RETURN_CODE::RELEASABLES_ERROR: + cout << AT_MSG << "Error, copying releasable(s)." << endl; + break; + case AT_RETURN_CODE::RESTORE_MODULES_ERROR: + cout << AT_MSG << "Error, restoring mmp file(s)." << endl; + break; + case AT_RETURN_CODE::CREATING_TEMP_CPP_ERROR: + cout << AT_MSG << "Error, creating temporary cpp file(s)." << endl; + break; + case AT_RETURN_CODE::CLEANING_TEMP_ERROR: + cout << AT_MSG << "Error, cleaning temporary dir(s)." << endl; + break; + case AT_RETURN_CODE::READ_MAKEFILE_ERROR: + cout << AT_MSG << "Error, reading makefile." << endl; + break; + case AT_RETURN_CODE::MODIFY_MODULES_ERROR: + cout << AT_MSG << "Error, modifying mmp file(s)." << endl; + break; + case AT_RETURN_CODE::INVALID_MMP_DEFINED: + break; + case AT_RETURN_CODE::WRITE_ATTRIBUTES_ERROR: + cout << AT_MSG << "Error, writing attributes." << endl; + break; + case AT_RETURN_CODE::READ_ATTRIBUTES_ERROR: + cout << AT_MSG << "Error, reading project configuration. Instrument project again." << endl; + break; + case AT_RETURN_CODE::EMPTY_DATA_FILE: + cout << AT_MSG << "Error, no data to be analyzed." << endl; + break; + case AT_RETURN_CODE::NO_SUPPORTED_MODULES_ERROR: + cout << AT_MSG << "Error, no modules found with supported target type." << endl; + break; + case AT_RETURN_CODE::KERNEL_SIDE_MODULE_ERROR: + cout << AT_MSG << "Error, kernel side component found component. Build/instrument aborted." << endl; + break; + } + return iReturnCode; +} +// ---------------------------------------------------------------------------- +// CATProject::RunRecoveryAndExit() +// Restore modules quick and exit. Used when user wants to kill/end process. +// ---------------------------------------------------------------------------- +int CATProject::RunRecoveryAndExit() +{ + LOG_FUNC_ENTRY("CATProject::RunRecoveryAndExit"); + cout << AT_MSG << "Error, user requested exit." << endl; + VerifyAndRecoverModules(); + DeleteTemporaryDirs(); + DirDelete( AT_TEMP_DIR, true ); + cout << AT_MSG << "Exit." << endl; + return AT_RETURN_CODE::USER_ISSUED_EXIT; +} + +// ---------------------------------------------------------------------------- +// CATProject::IsUninstrumented() +// Reads projects configuration file if it exists. +// Return false in case the data contains information that project is +// uninstrumented. Otherwise returns always true. +// ---------------------------------------------------------------------------- +bool CATProject::IsUninstrumented() +{ + LOG_FUNC_ENTRY("CATProject::IsUninstrumented"); + string sCfgFile( AT_TEMP_DIR ); + sCfgFile.append( "\\" ); + sCfgFile.append( AT_PROJECT_ATTRIBUTES_FILE_NAME ); + if ( ! FileExists( sCfgFile.c_str() ) ) + return true; + if( !ReadAttributes() ) + { + LOG_STRING( "Error, reading project.cfg file." ); + return false; + } + return m_bUninstrumented; +} + +// ---------------------------------------------------------------------------- +// CATProject::RunCompile() +// Helper functions to run different modes. +// ---------------------------------------------------------------------------- +int CATProject::RunCompile() +{ + LOG_FUNC_ENTRY("CATProject::RunCompile"); + // Store attributes + if( ! MakeTempDirIfNotExist() ) + return AT_RETURN_CODE::WRITE_ATTRIBUTES_ERROR; + if ( ! WriteAttributes() ) + return AT_RETURN_CODE::WRITE_ATTRIBUTES_ERROR; + // Create makefile + if ( ! CreateMakeFile() ) + return AT_RETURN_CODE::MAKEFILE_ERROR; + // Read makefile to get project attributes + if ( ! ReadMakeFile() ) + return AT_RETURN_CODE::READ_MAKEFILE_ERROR; + // Filter unsupported + FilterModules(); + // Check that we have some "valid" modules to hook + if ( m_vModules.size() == 0 &&( m_vUnsupportedModules.size() > 0 || m_vStaticLibraries.size() > 0 ) ) + return AT_RETURN_CODE::NO_SUPPORTED_MODULES_ERROR; + // Check is possible target module defined in project + if ( ! IsTargetModuleInProject() ) + return AT_RETURN_CODE::INVALID_MMP_DEFINED; + // Clean temporary dirs of modules + if ( ! CleanTemporaryDirs() ) + return AT_RETURN_CODE::CLEANING_TEMP_ERROR; + // Create temporary cpps for modulse + if (! CreateTemporaryCpps() ) + return AT_RETURN_CODE::CREATING_TEMP_CPP_ERROR; + // Hook modules + if (! ModifyModules() ) + return AT_RETURN_CODE::MODIFY_MODULES_ERROR; + // Compile all + // Return code + int iRetCode = AT_RETURN_CODE::OK; + // Compile + if ( ! Compile() ) + iRetCode = AT_RETURN_CODE::COMPILE_ERROR; + // Listings + if (! CreateListings() ) + iRetCode = AT_RETURN_CODE::COMPILE_ERROR; + // Releasables + if (! CopyReleasables() ) + iRetCode = AT_RETURN_CODE::RELEASABLES_ERROR; + // Restore "unhook" modules + if (! RestoreModules() ) + iRetCode = AT_RETURN_CODE::RESTORE_MODULES_ERROR; + // Return error code OK + return iRetCode; +} + +int CATProject::RunClean() +{ + LOG_FUNC_ENTRY("CATProject::RunClean"); + int iRetCode = AT_RETURN_CODE::OK; + bool bNothingFound = true; + // Read attributes. + if ( ReadAttributes() ) + { + bNothingFound = false; + if ( m_eBuildSystem == SBS_V1 ) + InitSbs1MakeFileWithPathToTemp(); + // Read makefile to get project attributes + if( ReadMakeFile() ) + { + // Filter unsupported + FilterModules(); + // Restore modules to make sure no changes left + if( VerifyAndRecoverModules() ) + { + // Run reallyclean + switch ( m_eBuildSystem ) + { + case SBS_V1: + RunReallyCleanSbs1(); + break; + case SBS_V2: + RunReallyCleanSbs2(); + break; + default: + break; + } + // Delete temporary dirs of modules + if(! DeleteTemporaryDirs() ) + { + + } + } + else + { + + } + } + } + // Projects + if ( ! DirDelete( AT_TEMP_DIR, true ) ) + { + + } + else + bNothingFound = false; + + if ( bNothingFound ) + cout << AT_MSG << "Nothing found to clean." << endl; + else + cout << AT_MSG << "Cleaning done." << endl; + return iRetCode; +} + +int CATProject::RunAnalyze() +{ + LOG_FUNC_ENTRY("CATProject::RunAnalyze"); + + // Parse data file if it is trace. + if ( !IsDataFile( m_sDataFile ) ) + { + m_sDataFileTemp.clear(); + m_sDataFileTemp.append( m_sDataFile ); + m_sDataFileTemp.append( ".atool" ); + cout << AT_MSG << "Parsing trace file..." << endl; + CATParseTraceFile Parser; + if ( ! Parser.StartParse( m_sDataFile.c_str(), m_sDataFileTemp.c_str() ) ) + { + return AT_RETURN_CODE::EMPTY_DATA_FILE; + } + m_sDataFile = m_sDataFileTemp; + } + + // Init makefile member for this run mode. + if ( m_eBuildSystem == SBS_V1 ) + InitSbs1MakeFileWithPathToTemp(); + // Read makefile to get project attributes + if( ! ReadMakeFile() ) + { + cout << AT_MSG << "Error, cannot find project build with AnalyzeTool." << endl; + } + else + FilterModules(); + + #ifndef ADDR2LINE + // Initialize modules locating code lines. + for( size_t i = 0 ; i < m_vModules.size() ; i++ ) + { + m_vModules.at(i)->InitializeAddressToLine(); + } + #endif + + // Create analyzer + m_pAnalyzer = new CATDatParser( &m_vModules ); + + // Pass some info from project if it "exists" to analyzer. + if ( m_vModules.size() > 0 ) + { + // Pass platform. + m_pAnalyzer->SetProjectPlatform( m_sPlatform ); + // Pass build type. + m_pAnalyzer->SetProjectBuildType( m_eBuildType ); + } + + // Set file. + m_pAnalyzer->SetInputFile( m_sDataFile ); + + // Set rom symbol file. + m_pAnalyzer->SetRomSymbolFiles( m_vRomSymbolFiles ); + + // Set output file if specified + if ( ! m_sDataFileOutput.empty() ) + { + m_pAnalyzer->SetOutputFile( m_sDataFileOutput ); + } + // Set log level + m_pAnalyzer->SetLogLevel( m_iLoggingLevel ); + + // Analyze + return m_pAnalyzer->Analyze(); +} + +int CATProject::RunInstrument() +{ + LOG_FUNC_ENTRY("CATProject::RunInstrument"); + // Store attributes + if( ! MakeTempDirIfNotExist() ) + return AT_RETURN_CODE::WRITE_ATTRIBUTES_ERROR; + if ( ! WriteAttributes() ) + return AT_RETURN_CODE::WRITE_ATTRIBUTES_ERROR; + if ( m_eBuildSystem == SBS_V1 ) + { + // Initialize level 1 make file member. + if ( ! InitSbs1MakeFileWithPath() ) + return AT_RETURN_CODE::MAKEFILE_ERROR; + // Copy it to temporary folder. + CopyMakeFileSbs1ToTemporaryFolder(); + // Run export. + if( ! RunExportSbs1() ) + return AT_RETURN_CODE::MAKEFILE_ERROR; + // Create level 2 makefiles. + if ( ! CreateMakeFileSbs1Level2() ) + return AT_RETURN_CODE::MAKEFILE_ERROR; + } + else if ( m_eBuildSystem == SBS_V2 ) + { + // Create makefile only when using SBS v.2 + if ( ! CreateMakeFile() ) + return AT_RETURN_CODE::MAKEFILE_ERROR; + } + else + { + return AT_RETURN_CODE::UNKNOWN; + } + // Read makefile to get project attributes + if ( ! ReadMakeFile() ) + return AT_RETURN_CODE::READ_MAKEFILE_ERROR; + // Filter unsupported + FilterModules(); + // Check that we have some "valid" modules to hook + if ( m_vModules.size() == 0 &&( m_vUnsupportedModules.size() > 0 || m_vStaticLibraries.size() > 0 ) ) + return AT_RETURN_CODE::NO_SUPPORTED_MODULES_ERROR; + + // Clean temporary dirs of modules + if ( ! CleanTemporaryDirs() ) + return AT_RETURN_CODE::CLEANING_TEMP_ERROR; + // Create temporary cpps for modulse + if (! CreateTemporaryCpps() ) + return AT_RETURN_CODE::CREATING_TEMP_CPP_ERROR; + // Hook modules + if (! ModifyModules() ) + return AT_RETURN_CODE::MODIFY_MODULES_ERROR; + return AT_RETURN_CODE::OK; +} + +int CATProject::RunInstrumentConsole() +{ + LOG_FUNC_ENTRY("CATProject::RunInstrumentConsole"); + if( ! MakeTempDirIfNotExist() ) + return AT_RETURN_CODE::UNKNOWN; + // Store attributes + m_bUninstrumented = false; + if ( ! WriteAttributes() ) + return AT_RETURN_CODE::WRITE_ATTRIBUTES_ERROR; + // Create makefile + if ( ! CreateMakeFile() ) + return AT_RETURN_CODE::MAKEFILE_ERROR; + // Read makefile to get project attributes + if ( ! ReadMakeFile() ) + return AT_RETURN_CODE::READ_MAKEFILE_ERROR; + // Filter unsupported + FilterModules(); + // Check that we have some "valid" modules to hook + if ( m_vModules.size() == 0 &&( m_vUnsupportedModules.size() > 0 || m_vStaticLibraries.size() > 0 ) ) + return AT_RETURN_CODE::NO_SUPPORTED_MODULES_ERROR; + + // Clean temporary dirs of modules + if ( ! CleanTemporaryDirs() ) + return AT_RETURN_CODE::CLEANING_TEMP_ERROR; + // Create temporary cpps for modulse + if (! CreateTemporaryCpps() ) + return AT_RETURN_CODE::CREATING_TEMP_CPP_ERROR; + // Hook modules + if (! ModifyModules() ) + return AT_RETURN_CODE::MODIFY_MODULES_ERROR; + // Run Reallyclean when using abld. + if ( m_eBuildSystem == SBS_V1 ) + RunReallyCleanSbs1(); + return AT_RETURN_CODE::OK; +} + +int CATProject::RunUninstrument() +{ + LOG_FUNC_ENTRY("CATProject::RunUninstrument"); + // Read attributes. + if ( ! ReadAttributes() ) + return AT_RETURN_CODE::READ_ATTRIBUTES_ERROR; + // Init makefile member for this run mode. + if ( m_eBuildSystem == SBS_V1 ) + InitSbs1MakeFileWithPathToTemp(); + // Read makefile to get project attributes + if ( ! ReadMakeFile() ) + return AT_RETURN_CODE::READ_MAKEFILE_ERROR; + // Filter unsupported + FilterModules(); + // Check that we have some "valid" modules to hook + if ( m_vModules.size() == 0 &&( m_vUnsupportedModules.size() > 0 || m_vStaticLibraries.size() > 0 ) ) + return AT_RETURN_CODE::NO_SUPPORTED_MODULES_ERROR; + // Create lst files + if (! CreateListings() ) + return AT_RETURN_CODE::COMPILE_ERROR; + // Copy releasables of modules + if (! CopyReleasables() ) + return AT_RETURN_CODE::RELEASABLES_ERROR; + // Restore "unhook" modules + if (! RestoreModules() ) + return AT_RETURN_CODE::RESTORE_MODULES_ERROR; + // Return error code OK + return AT_RETURN_CODE::OK; +} + +int CATProject::RunUninstrumentConsole() +{ + LOG_FUNC_ENTRY("CATProject::RunUninstrumentConsole"); + int iErrorCode = AT_RETURN_CODE::OK; + // Read attributes + if ( ReadAttributes() ) + { + // Init makefile member for this run mode. + if ( m_eBuildSystem == SBS_V1 ) + InitSbs1MakeFileWithPathToTemp(); + // Read makefile to get project attributes + if( ReadMakeFile() ) + { + // Filter unsupported + FilterModules(); + // Create lst files + CreateListings(); + if (! CopyReleasables() ) + iErrorCode = AT_RETURN_CODE::RELEASABLES_ERROR; + } + else + iErrorCode = AT_RETURN_CODE::READ_MAKEFILE_ERROR; + // Change state to uninstrumented and write status + m_bUninstrumented = true; + if ( ! WriteAttributes() ) + iErrorCode = AT_RETURN_CODE::WRITE_ATTRIBUTES_ERROR; + } + else + { + iErrorCode = AT_RETURN_CODE::READ_ATTRIBUTES_ERROR; + } + return iErrorCode; +} + +int CATProject::RunUninstrumentFailed() +{ + LOG_FUNC_ENTRY("CATProject::RunUninstrumentFailed"); + // Read attributes. + if ( ! ReadAttributes() ) + return AT_RETURN_CODE::READ_ATTRIBUTES_ERROR; + // Init makefile member for this run mode. + if ( m_eBuildSystem == SBS_V1 ) + InitSbs1MakeFileWithPathToTemp(); + // Read makefile to get project attributes + if( ReadMakeFile() ) + { + // Filter modules + FilterModules(); + // Restore modules to make sure no changes left + if( RestoreModules() ) + { + // Delete temporary dirs of modules + if(! DeleteTemporaryDirs() ) + { + + } + + } + else + { + + } + } + else + { + + } + // Projects + if ( ! DirDelete( AT_TEMP_DIR, true ) ) + { + + } + return AT_RETURN_CODE::OK; +} + +// ---------------------------------------------------------------------------- +// Main Functions +// ---------------------------------------------------------------------------- +void CATProject::DisplayCompileSummary() +{ + LOG_FUNC_ENTRY("CATProject::DisplayCompileSummary"); + cout << AT_BUILD_SUMMARY_HEADER; + // Supported modules + for( size_t i = 0; i < m_vModules.size(); i++ ) + { + // Successful + if ( m_vModules.at(i)->GetErrors().empty() ) + { + // Create build complete file for Carbide xtension + m_vModules.at(i)->CreateBuildCompleteFile(); + cout << AT_BUILD_SUMMARY_INSTRUMENTED_BUILD_COMPLETE + << GetPathOrFileName( true, m_vModules.at(i)->GetMmpFile() ) + << endl + << AT_BUILD_SUMMARY_TARGET + << m_vModules.at(i)->GetBinaryName() + << endl; + // Datafiles + // Use module data file name if project's data file not defined. + if ( m_eLoggingMode == CATProject::FILE + && m_vModules.at(i)->GetTargetType().compare("exe") == 0 ) + { + if ( m_sS60FileName.empty() ) + cout << AT_BUILD_SUMMARY_DATA_FILE_NAME + << m_vModules.at(i)->GetS60FileName() + << endl; + else + cout << AT_BUILD_SUMMARY_DATA_FILE_NAME + << m_sS60FileName + << endl; + } + } + else + { + // Failed + cout << AT_BUILD_SUMMARY_FAILED + << GetPathOrFileName( true, m_vModules.at(i)->GetMmpFile() ) + << endl + << AT_BUILD_SUMMARY_TARGET + << m_vModules.at(i)->GetBinaryName() + << endl; + // Print errors. + cout << AT_BUILD_SUMMARY_ERRORS + << m_vModules.at(i)->GetErrors() + << endl; + } + } + + // Static libraries + for( size_t i = 0; i < m_vStaticLibraries.size(); i++ ) + { + if ( m_vStaticLibraries.at(i)->GetErrors().empty() ) + { + cout << AT_BUILD_SUMMARY_NORMAL_BUILD_COMPLETE + << GetPathOrFileName( true, m_vStaticLibraries.at(i)->GetMmpFile()) + << endl + << AT_BUILD_SUMMARY_TARGET + << m_vStaticLibraries.at(i)->GetBinaryName() + << endl + << AT_BUILD_SUMMARY_STATIC_LIBRARY + << endl; + + } + else + { + // Failed + cout << AT_BUILD_SUMMARY_FAILED + << GetPathOrFileName( true, m_vStaticLibraries.at(i)->GetMmpFile() ) + << endl + << AT_BUILD_SUMMARY_TARGET + << m_vStaticLibraries.at(i)->GetBinaryName() + << endl; + // Print errors. + cout << AT_BUILD_SUMMARY_ERRORS + << m_vStaticLibraries.at(i)->GetErrors() + << endl; + } + } + + // Unsupported modules + for( size_t i = 0; i < m_vUnsupportedModules.size(); i++ ) + { + cout << AT_BUILD_SUMMARY_NORMAL_BUILD_COMPLETE + << GetPathOrFileName( true, m_vUnsupportedModules.at(i)->GetMmpFile() ) + << endl + << AT_BUILD_SUMMARY_TARGET + << m_vUnsupportedModules.at(i)->GetBinaryName() + << endl; + cout << m_vUnsupportedModules.at(i)->GetCompileInfoText() << endl; + } +} + +void CATProject::DisplayBuildSummary( void ) +{ + LOG_FUNC_ENTRY("CATProject::DisplayBuildSummary"); + cout << endl; + // Build information + cout << AT_BUILD_SUMMARY_BUILD_TYPE << GetBuildTypeString() << endl; + // Platform + cout << AT_BUILD_SUMMARY_BUILD_PLATFORM << m_sPlatform << endl; + // Possible variant + if ( ! m_sVariant.empty() ) + cout << AT_BUILD_SUMMARY_BUILD_VARIANT << m_sVariant << endl; + // Logging mode + cout << AT_BUILD_SUMMARY_LOGGING_MODE; + if ( m_eLoggingMode == FILE ) + cout << AT_BUILD_SUMMARY_FILE; + else if ( m_eLoggingMode == TRACE ) + cout << AT_BUILD_SUMMARY_TRACE; + else if ( m_eLoggingMode == TRACE_FAST ) + cout << AT_BUILD_SUMMARY_TRACE_FAST; + cout << endl; + // Call stack sizes + cout << AT_BUILD_SUMMARY_ALLOC_CALL_STACK_SIZE + << m_iAllocCallStackSize + << endl; + cout << AT_BUILD_SUMMARY_FREE_CALL_STACK_SIZE + << m_iFreeCallStackSize + << endl; + + if(!_stricmp(m_sPlatform.c_str(), ("winscw"))) + { + //print version info only when version is not up-to-date + cout << endl; + showDbgHelpVersionInfo( false ); + } +} + +bool CATProject::CreateMakeFile() +{ + switch ( m_eBuildSystem ) + { + case SBS_V1: + if( ! CreateMakeFileSbs1() ) + return false; + // Copy main make file. + if( ! CopyMakeFileSbs1ToTemporaryFolder() ) + return false; + // Run export. + if( ! RunExportSbs1() ) + return false; + // Create level 2 makefiles. + if( ! CreateMakeFileSbs1Level2() ) + return false; + return true; + case SBS_V2: + return CreateMakeFileSbs2(); + default: + return false; + } +} + +bool CATProject::CreateMakeFileSbs1() +{ + LOG_FUNC_ENTRY("CATProject::CreateMakeFileSbs1"); + + // If variant defined check does it exist. + if( ! m_sVariant.empty() ) + { + if ( ! CheckVariant( m_sEpocRoot, m_sVariant ) ) + { + cout << INVALID_VARIANT_ERROR; + if ( IsDefaultVariant( m_sEpocRoot ) ) + { + m_sVariant = "default"; + cout << USING_DEFAULT_VARIANT_MESSAGE; + if ( ! WriteAttributes() ) + return false; + } + else + { + cout << NO_DEFAULT_VARIANT_ERROR; + return false; + } + } + } + + // Create level 1 make file. + string sCmd( "bldmake bldfiles " ); + sCmd.append( m_sPlatform ); + cout << AT_MSG_SYSTEM_CALL << sCmd << endl; + (void)system( sCmd.c_str() ); + return InitSbs1MakeFileWithPath(); +} + +bool CATProject::CopyMakeFileSbs1ToTemporaryFolder() +{ + LOG_FUNC_ENTRY("CATProject::CopyMakeFileSbs1ToTemporaryFolder"); + // Check that temporary dir exists if not create it. + if ( ! MakeTempDirIfNotExist() ) + return false; + // Copy makefile to temporary directory + string sMakeFileInTemp( AT_TEMP_DIR ); + sMakeFileInTemp.append( "\\" ); + sMakeFileInTemp.append( AT_LEVEL_1_MAKEFILE_NAME ); + if ( ! FileCopyToPath( m_sMakeFile, sMakeFileInTemp ) ) + return false; + return true; + +} + +bool CATProject::RunReallyCleanSbs1() +{ + LOG_FUNC_ENTRY("CATProject::RunReallyCleanSbs1"); + // Check that abld.bat has been made. + if ( ! FileExists( "abld.bat" ) ) + return false; + // Run reallyclean. + string sCmd; + if ( m_bAbldTest ) + sCmd = "abld test reallyclean "; + else + sCmd = "abld reallyclean "; + sCmd.append( m_sPlatform ); + if ( ! m_sVariant.empty() ) + { + sCmd.append( "." ); + sCmd.append( m_sVariant ); + } + sCmd.append( " " ); + sCmd.append( GetBuildTypeString() ); + if ( m_vTargetModules.size() > 1 ) + { + RunAbldCommandToAllTargets( sCmd ); + } + else + { + AddTargetModuleIfDefined( sCmd ); + cout << AT_MSG_SYSTEM_CALL << sCmd << endl; + (void) system( sCmd.c_str() ); + } + return true; +} + +bool CATProject::RunReallyCleanSbs2() +{ + LOG_FUNC_ENTRY("CATProject::RunReallyCleanSbs2"); + string sCmd(""); + if ( m_sBuildCommand.empty() ) + { + // If no build command defined (not found in project.cfg). + sCmd.append( RAPTOR_CMD_BASE );; + sCmd.append( m_sPlatform ); + sCmd.append( "_" ); + sCmd.append( GetBuildTypeString() ); + if ( ! m_sVariant.empty() ) + { + sCmd.append( "." ); + sCmd.append( m_sVariant ); + } + sCmd.append( RAPTOR_REALLYCLEAN_LOG ); + AddTargetModuleIfDefined( sCmd ); + sCmd.append( " REALLYCLEAN" ); + } + else + { + // When build command set use it. + sCmd.append( m_sBuildCommand ); + sCmd.append( RAPTOR_REALLYCLEAN_LOG ); + sCmd.append( " REALLYCLEAN" ); + } + cout << AT_MSG_SYSTEM_CALL << sCmd << endl; + int iRet = (int)system( sCmd.c_str() ); + if ( iRet == 0 ) + return true; + return false; +} + +bool CATProject::RunExportSbs1() +{ + LOG_FUNC_ENTRY("CATProject::RunExportSbs1"); + // Run export. + string sCmd; + if ( m_bAbldTest ) + sCmd = "abld test export"; + else + sCmd = "abld export"; + cout << AT_MSG_SYSTEM_CALL << sCmd << endl; + (void) system( sCmd.c_str() ); + return true; +} + +bool CATProject::CreateMakeFileSbs1Level2() +{ + LOG_FUNC_ENTRY("CATProject::CreateMakeFileSbs1Level2"); + // Create level 2 makefiles. + + string sCmd; + + if ( m_bAbldTest ) + sCmd ="abld test makefile "; + else + sCmd ="abld makefile "; + + sCmd.append( m_sPlatform ); + if ( ! m_sVariant.empty() ) + { + sCmd.append( "." ); + sCmd.append( m_sVariant ); + } + + // Check if multiple targets defined and sbs 1. + if ( m_vTargetModules.size() > 1 ) + { + RunAbldCommandToAllTargets( sCmd ); + } + else + { + AddTargetModuleIfDefined( sCmd ); + cout << AT_MSG_SYSTEM_CALL << sCmd << endl; + (void) system( sCmd.c_str() ); + } + return true; +} + +bool CATProject::CreateMakeFileSbs2() +{ + LOG_FUNC_ENTRY("CATProject::CreateMakeFileSbs2"); + // Delete build directory if it exists before creating new makefiles. + if ( DirectoryExists( "atool_temp\\build" ) ) + DirDelete( "atool_temp\\build", true ); + // Create command to create makefiles. + string sCmd( m_sBuildCommand ); + sCmd.append( " " ); + sCmd.append( RAPTOR_MAKEFILE_SWITCH ); + sCmd.append( " " ); + sCmd.append( RAPTOR_NOBUILD_SWITCH ); + cout << AT_MSG_SYSTEM_CALL << sCmd << endl; + int iRet = (int)system( sCmd.c_str() ); + if ( iRet == 0 ) + return true; + return false; +} + +bool CATProject::ReadMakeFile() +{ + // Clean modules before reading. + CleanModuleVectors(); + if ( m_eBuildSystem == SBS_V1 ) + { + // Read level 1 makefile which contains module name and makefiles. + if( ! ReadMakeFileSbs1Level1() ) + return false; + // Read level 2 makefiles. + vector<CATModule2*>::iterator it; + // If we are compiling or etc... we need to create temporary directories. + if ( m_eMode == COMPILE || m_eMode == INSTRUMENT || m_eMode == INSTRUMENT_CONSOLE ) + { + // Read make makefiles from /epoc32/build... and create temporary directory. + bool bLevel2 = true; + for( it = m_vModules.begin(); it != m_vModules.end() ; it ++ ) + { + if( ! (*it)->CreateTemporaryDirectory() ) + return false; + if( ! (*it)->ReadMakeFile() ) + { + bLevel2 = false; + break; + } + } + // If failed reading modules from level 2 makefiles. + if ( ! bLevel2 ) + { + // Clean modules. + CleanModuleVectors(); + // Try use default variant if it exists. + if ( CheckVariant( m_sEpocRoot, "default" ) ) + { + m_sVariant = "default"; + cout << USING_DEFAULT_VARIANT_MESSAGE; + if ( ! WriteAttributes() ) + return false; + if ( ! InitSbs1MakeFileWithPath() ) + return false; + if ( ! ReadMakeFileSbs1Level1() ) + return false; + for( it = m_vModules.begin(); it != m_vModules.end() ; it ++ ) + { + if( ! (*it)->CreateTemporaryDirectory() ) + return false; + if( ! (*it)->ReadMakeFile() ) + return false; + } + + } + } + } + else + { + // Read make files from temporary directories. + for( it = m_vModules.begin(); it != m_vModules.end() ; it ++ ) + { + if ( ! (*it)->ReadMakeFileFromTemp() ) + return false; + } + } + return true; + } + else if ( m_eBuildSystem == SBS_V2 ) + { + // Read make file. + if( ! ReadMakeFileSbs2() ) + return false; + // Create module temporary directories if we are compiling or etc... + if ( m_eMode == COMPILE || m_eMode == INSTRUMENT || m_eMode == INSTRUMENT_CONSOLE ) + { + for( vector<CATModule2*>::iterator it = m_vModules.begin(); it < m_vModules.end(); it++ ) + (*it)->CreateTemporaryDirectory(); + for( vector<CATModule2*>::iterator it = m_vStaticLibraries.begin(); it < m_vStaticLibraries.end(); it++ ) + (*it)->CreateTemporaryDirectory(); + } + } + return true; +} + +bool CATProject::ReadMakeFileSbs1Level1() +{ + LOG_FUNC_ENTRY("CATProject::ReadMakeFileSbs1Level1"); + + bool bRet = false; + + //Try to open makefile + ifstream in; + in.open( m_sMakeFile.c_str() ); + + //File open ok? + if( !in.good() ) + { + printf( "Can not open file: %s\n", m_sMakeFile.c_str() ); + in.close(); + return bRet; + } + + // Add also these so "compatible with sbs2". + // Releasables path (binaries). + string sReleasePath( m_sEpocRoot ); + // add trailing '\' if root path is missing it + if ( sReleasePath.size() < 1 ) + sReleasePath.append( "\\" ); + else if ( sReleasePath.at( sReleasePath.length() -1 ) != '\\' ) + sReleasePath.append( "\\" ); + sReleasePath.append( "epoc32\\release" ); + string sFullVariantPath( m_sPlatform ); + sFullVariantPath.append( "\\" ); + sFullVariantPath.append( GetBuildTypeString() ); + + char cTemp[MAX_LINE_LENGTH]; + bool bContinueSearch = true; + bool bMmpInfoFound = false; + CATModule2* pModule = 0; + string sTempLineFromFile; + string sMmpFileSearchString; + if ( m_bAbldTest ) + sMmpFileSearchString = MMPTESTFILE_SEARCH_STRING; + else + sMmpFileSearchString = MMPFILE_SEARCH_STRING; + do + { + // get line from file + in.getline( cTemp, MAX_LINE_LENGTH ); + sTempLineFromFile.clear(); + sTempLineFromFile.append( cTemp ); + + //Search makefile string + if( sTempLineFromFile.find( MAKEFILE_SEARCH_STRING ) != string::npos ) + { + bMmpInfoFound = true; + if( sTempLineFromFile.find( sMmpFileSearchString ) != string::npos ) + { + bRet = true; + //Parse mmp path + mmp filename + sTempLineFromFile.erase( 0, sTempLineFromFile.find_first_of("\"") ); + sTempLineFromFile.erase( 0, 1 ); + + string sPath = sTempLineFromFile.substr(0, sTempLineFromFile.find_first_of("\"") ); + + sPath = ChangeSlashToBackSlash( sPath ); + //Remove text "bld.inf" + sPath.erase( (sPath.find_last_of( "\\" ) + 1) , string::npos ); + + string sFileName = sTempLineFromFile.substr( (sTempLineFromFile.find( sMmpFileSearchString ) + sMmpFileSearchString.length() + 3), string::npos ); + sFileName = ChangeSlashToBackSlash( sFileName ); + sFileName = sFileName.substr( 0, sFileName.find_first_of("\"") ); + + // Append .mmp to filename if it does not exist + if ( sFileName.find(".mmp") == string::npos ) + sFileName.append(".mmp"); + + //Insert drive letter + sPath.insert(0, string( m_cCurrentDir).substr(0,2) ); + + //Insert mmp file to the end + sPath.append( sFileName ); + + ChangeToLower( sPath ); + + // If target programs defined find from those or do not + // add module to vector. + bool bAddToVector = true; + if ( m_vTargetModules.size() > 0 ) + { + bAddToVector = false; + vector<string>::iterator it; + for( it = m_vTargetModules.begin() ; it != m_vTargetModules.end() ; it++ ) + { + string sFind( *it ); + sFind.insert( 0, "\\" ); + if ( sPath.find( sFind ) != string::npos ) + { + bAddToVector = true; + break; + } + } + } + + if ( bAddToVector ) + { + pModule = new CATModule2(); + pModule->SetMmpFile( sPath ); + pModule->SetVariantType( GetBuildTypeString() ); + pModule->SetVariantPlatform( m_sPlatform ); + pModule->SetReleasePath( sReleasePath ); + pModule->SetFullVariantPath( sFullVariantPath ); + pModule->SetBuildSystem( SBS_V1 ); + m_vModules.push_back( pModule ); + } + } + } + else if( bMmpInfoFound ) + //Do not continue search if mmp info lines are all handled + bContinueSearch = false; + if( !in.good() ) + bContinueSearch = false; + } + while( bContinueSearch ); + + bContinueSearch = true; + + //Search MAKEFILES for invidual modules + do + { + in.getline( cTemp, MAX_LINE_LENGTH ); + sTempLineFromFile.clear(); + sTempLineFromFile.append( cTemp ); + // find the lines 'MAKEFILE[modulename]_FILES' + if( (sTempLineFromFile.find( "MAKEFILE" ) == 0) && (sTempLineFromFile.find( "_FILES" ) != string::npos) ) + { + //Math the makefile line with one of our modules + for( size_t i = 0 ; i < m_vModules.size() ; i++ ) + { + //Create name + string sMakeFile( "MAKEFILE" ); + string sTempMmpFile( RemovePathAndExt( m_vModules.at(i)->GetMmpFile(), true ) ); + ChangeToUpper( sTempMmpFile ); + sMakeFile.append( sTempMmpFile ); + sMakeFile.append( "_FILES" ); + // matched + if( sTempLineFromFile.find( sMakeFile ) != string::npos ) + { + //parse the makefile name from line + in.getline( cTemp, MAX_LINE_LENGTH ); + sTempLineFromFile.clear(); + sTempLineFromFile.append( cTemp ); + //Remove character "\"" + sTempLineFromFile.erase( 0, ( sTempLineFromFile.find_first_of("\"") + 1 ) ); + // in winscw last part is '" \' and on armd '"' so remove all after last '"' + sTempLineFromFile.erase( sTempLineFromFile.find_last_of("\""), sTempLineFromFile.size() ); + // Set correct makefile for module + m_vModules.at( i )->SetMakeFile( sTempLineFromFile ); + // break + break; + } // If mathed to mmp + } // End of mmp file loop + } // found lines 'MAKEFILE[modulename]_FILES' + if( !in.good() ) + bContinueSearch = false; + } + while( bContinueSearch ); + in.close(); + return bRet; +} + +bool CATProject::ReadMakeFileSbs2( void ) +{ + LOG_FUNC_ENTRY("CATProject::ReadMakeFileSbs2(void)"); + // File is by default named make_build.default but when building specific layer + // make_build_LAYERNAME.default is produced by Raptor. + // So find makefile(s) and read them. + vector<string> vMakeFiles = DirList( "atool_temp\\build\\", false, true ); + bool bRet = true; + for( vector<string>::iterator it = vMakeFiles.begin(); it != vMakeFiles.end() ; it++ ) + { + // Recognize multiple makefiles. + if ( it->find("make_build_") != string::npos && it->find(".default") != string::npos ) + { + if ( ! ReadMakeFileSbs2( *it ) ) + bRet = false; + } + // Single makefile. + else if ( it->find( "make_build.default" ) != string::npos ) + { + if ( ! ReadMakeFileSbs2( *it ) ) + bRet = false; + } + } + // We got some modules? + if ( m_vModules.size() == 0 ) + bRet = false; + return bRet; +} + +bool CATProject::ReadMakeFileSbs2( string& sMakeFile ) +{ + LOG_FUNC_ENTRY("CATProject::ReadMakeFileSbs2(string)"); + try { + // Open file + ifstream in; + in.open( sMakeFile.c_str() , ios_base::in ); + // Check that open ok + if ( ! in.good() ) + { + cout << AT_MSG << "Error, opening file " + << RAPTOR_MAKEFILE << endl; + in.close(); + return false; + } + // Source line from file + string sSourceLine; + // Module pointer + CATModule2* pModule = 0; + // Are we looking for module attributes + bool bFindAttributes = false; + // Until end of file + while( in.good() ) + { + // Get new line from file + string sLine; + getline(in, sLine); + // New module + if ( sLine.find( RAPTOR_PROJECT_META ) == 0 ) + { + // Remove project_meta from line + sLine.erase(0, strlen( RAPTOR_PROJECT_META ) ); + LOG_STRING("Found module: " << sLine ); + // Check is name empty + // This seems to happen when sbs2 "wraps" i.e. mifconv to a module type item + if ( sLine.empty() ) + { + LOG_STRING("skipping empty module"); + // Skip it + continue; + } + // If module add it to vector + if ( pModule ) + { + // Add sources, + pModule->AddSources( sSourceLine ); + // Build system. + pModule->SetBuildSystem( SBS_V1 ); + // Push to vector. + m_vModules.push_back( pModule ); + } + // New module + pModule = new CATModule2(); + // Clear sourceline + sSourceLine.clear(); + // Set modules mmp with path + + if ( ! pModule->SetMmpFile( sLine ) ) + { + // Fatal error setting mmp file + in.close(); + return false; + } + // Find attributes on + bFindAttributes = true; + // Get new line from file + getline(in, sLine); + } + // If attribute finding on + if ( bFindAttributes ) + { + // Pickup modules attributes + if ( sLine.find ( RAPTOR_SOURCE ) == 0 ) + { + sLine.erase(0, strlen( RAPTOR_SOURCE ) ); + sSourceLine = sLine; + } + else if ( sLine.find ( RAPTOR_TARGET ) == 0 ) + { + sLine.erase(0, strlen( RAPTOR_TARGET ) ); + pModule->SetTarget( sLine ); + } + else if ( sLine.find ( RAPTOR_TARGETYPE ) == 0 ) + { + sLine.erase(0, strlen( RAPTOR_TARGETYPE )); + pModule->SetTargetType( sLine ); + } + else if ( sLine.find( RAPTOR_REQUESTEDTARGETEXT ) == 0 ) + { + sLine.erase(0, strlen( RAPTOR_REQUESTEDTARGETEXT ) ); + pModule->SetRequestedTargetExt( sLine ); + } + else if ( sLine.find ( RAPTOR_VARIANTPLATFORM ) == 0 ) + { + sLine.erase(0, strlen( RAPTOR_VARIANTPLATFORM )); + pModule->SetVariantPlatform( sLine ); + } + else if ( sLine.find ( RAPTOR_VARIANTTYPE ) == 0 ) + { + sLine.erase(0, strlen( RAPTOR_VARIANTTYPE )); + pModule->SetVariantType( sLine ); + } + else if ( sLine.find ( RAPTOR_FEATUREVARIANT ) == 0 ) + { + sLine.erase(0, strlen( RAPTOR_FEATUREVARIANT )); + pModule->SetFeatureVariant( sLine ); + } + else if ( sLine.find ( RAPTOR_FEATUREVARIANTNAME ) == 0 ) + { + sLine.erase(0, strlen( RAPTOR_FEATUREVARIANTNAME )); + pModule->SetFeatureVariantName( sLine ); + } + else if ( sLine.find ( RAPTOR_RELEASEPATH ) == 0 ) + { + sLine.erase(0, strlen( RAPTOR_RELEASEPATH )); + pModule->SetReleasePath( sLine ); + } + else if ( sLine.find ( RAPTOR_FULLVARIANTPATH ) == 0 ) + { + sLine.erase(0, strlen( RAPTOR_FULLVARIANTPATH )); + pModule->SetFullVariantPath( sLine ); + } + else if ( sLine.find ( RAPTOR_COMPILE_DEFINITIONS ) == 0 ) + { + sLine.erase(0, strlen( RAPTOR_COMPILE_DEFINITIONS ) ); + pModule->SetCompileDefinitions( sLine ); + } + } + } // while in.good() + // Add last module if n number of modules found + if ( pModule ) + { + if ( ! pModule->GetTarget().empty() ) + { + // Add sources + pModule->AddSources( sSourceLine ); + // Build system. + pModule->SetBuildSystem( SBS_V1 ); + // Push back to vector + m_vModules.push_back( pModule ); + } + } + // Close file + in.close(); + return true; + } // try. + catch(...) + { + LOG_STRING("Unexpected exception reading sbs 2 makefile"); + return false; + } +} +bool CATProject::CreateTemporaryDirectories() +{ + LOG_FUNC_ENTRY("CATProject::CreateTemporaryDirectories"); + bool bRet = true; + for( size_t i = 0 ; i < m_vModules.size(); i++) + { + if( ! m_vModules.at(i)->CreateTemporaryDirectory() ) + bRet = false; + } + for( size_t i = 0 ; i < m_vStaticLibraries.size(); i++) + { + if( ! m_vStaticLibraries.at(i)->CreateTemporaryDirectory() ) + bRet = false; + } + return bRet; + +} + +bool CATProject::CreateTemporaryCpps() +{ + LOG_FUNC_ENTRY("CATProject::CreateTemporaryCpps"); + bool bRet = true; + for( size_t i = 0 ; i < m_vModules.size(); i++) + { + if( ! m_vModules.at(i)->CreateTempCpp( + m_sS60FileName, m_eLoggingMode, m_eBuildType, m_iAllocCallStackSize, m_iFreeCallStackSize ) ) + bRet = false; + } + return bRet; +} + +bool CATProject::FilterModules() +{ + LOG_FUNC_ENTRY("CATProject::FilterModules"); + vector<CATModule2*>::iterator it; + // Loop thru modules. + it = m_vModules.begin(); + while( it != m_vModules.end() ) + { + // Get target type of module to separate string (will be modified). + string sTargetType = (*it)->GetTargetType(); + // Modules compile definitions. + string sCompileDefinition = (*it)->GetCompileDefinitions(); + // Check is it supported. + if ( !IsTargetTypeSupported( sTargetType) ) + { + (*it)->SetCompileInfoText( AT_UNSUPPORTED_TARGET_TYPE ); + // Not supported add to not supported vector. + m_vUnsupportedModules.push_back( *it ); + // Erase cell. + it = m_vModules.erase( it ); + } + // Check if its static library + else if ( _stricmp( sTargetType.c_str(), "lib" ) == 0 ) + { + // Static librarie move to their vector. + m_vStaticLibraries.push_back( *it ); + // Erase cell. + it = m_vModules.erase( it ); + + } + else if ( sCompileDefinition.find( KERNEL_MODE_COMPILE_DEFINITION ) != string::npos ) + { + (*it)->SetCompileInfoText( AT_UNSUPPORTED_COMPILE_DEFINITION ); + // Not supported add to not supported vector. + m_vUnsupportedModules.push_back( *it ); + // Erase cell. + it = m_vModules.erase( it ); + } + else + it++; + } + return true; +} + +bool CATProject::ModifyModules() +{ + LOG_FUNC_ENTRY("CATProject::ModifyModules"); + bool bRet = true; + for( size_t i = 0; i < m_vModules.size(); i++ ) + { + if (! m_vModules.at(i)->ModifyMmp() ) + bRet = false; + } + for( size_t i = 0; i < m_vStaticLibraries.size(); i++ ) + { + if (! m_vStaticLibraries.at(i)->ModifyMmp() ) + bRet = false; + } + return bRet; +} + +bool CATProject::RestoreModules() +{ + LOG_FUNC_ENTRY("CATProject::RestoreModules"); + bool bRet = true; + for( size_t i = 0; i < m_vModules.size(); i++ ) + { + if (! m_vModules.at(i)->RestoreMmp() ) + bRet = false; + } + for( size_t i = 0; i < m_vStaticLibraries.size(); i++ ) + { + if (! m_vStaticLibraries.at(i)->RestoreMmp() ) + bRet = false; + } + return bRet; +} + +bool CATProject::VerifyAndRecoverModules() +{ + LOG_FUNC_ENTRY("CATProject::VerifyAndRecoverModules"); + bool bRet = true; + for( size_t i = 0; i < m_vModules.size(); i++ ) + { + if (! m_vModules.at(i)->VerifyAndRecoverMmp() ) + bRet = false; + } + for( size_t i = 0; i < m_vStaticLibraries.size(); i++ ) + { + if (! m_vStaticLibraries.at(i)->VerifyAndRecoverMmp() ) + bRet = false; + } + return bRet; +} +bool CATProject::Compile() +{ + switch ( m_eBuildSystem ) + { + case SBS_V1: + // Run Reallyclean. + if( ! RunReallyCleanSbs1() ) + return false; + return CompileSbs1(); + case SBS_V2: + return CompileSbs2(); + default: + return false; + } +} + +bool CATProject::CompileSbs1() +{ + LOG_FUNC_ENTRY("CATProject::CompileSbs1"); + string sCommand(""); + if ( m_sBuildCommand.empty() ) + { + sCommand = "abld build"; + // -debug if urel + if ( m_eBuildType == UREL ) + sCommand.append( " -debug" ); + + // No variant + if ( m_sVariant.empty() ) + { + sCommand.append( " " ); + sCommand.append( m_sPlatform ); + } + else + { + // Add variant + sCommand.append( " " ); + sCommand.append( m_sPlatform ); + sCommand.append( "." ); + sCommand.append( m_sVariant ); + } + + // urel vs udeb + sCommand.append( " " ); + sCommand.append( GetBuildTypeString() ); + + // Possible target module + AddTargetModuleIfDefined( sCommand ); + } + // Check that build command contains -debug switch if sbs v.1 used + else if ( ! m_sBuildCommand.empty() + && m_eBuildType == UREL + && m_eBuildSystem == SBS_V1 + && m_sBuildCommand.find( "-debug" ) == string::npos ) + { + // Find correct index to insert -debug switch + size_t iPos = m_sBuildCommand.find( "build" ); + if ( iPos != string::npos ) + { + sCommand = m_sBuildCommand; + sCommand.insert( iPos+5, " -debug" ); + } + else + { + LOG_STRING("Overwriting given build command to add -debug switch. Original command is: " << m_sBuildCommand ); + if ( m_bAbldTest ) + sCommand = "abld test build -debug "; + else + sCommand = "abld build -debug "; + // No variant + if ( m_sVariant.empty() ) + { + sCommand.append( m_sPlatform ); + } + else + { + // Add variant + sCommand.append( m_sPlatform ); + sCommand.append( "." ); + sCommand.append( m_sVariant ); + } + + // urel vs udeb + sCommand.append( " " ); + sCommand.append( GetBuildTypeString() ); + // Possible target module + AddTargetModuleIfDefined( sCommand ); + } + } + else + sCommand = m_sBuildCommand; + // Run command + cout << AT_MSG_SYSTEM_CALL << sCommand << endl; + (void)system( sCommand.c_str() ); + return true; +} + +bool CATProject::CompileSbs2() +{ + LOG_FUNC_ENTRY("CATProject::CompileSbs2"); + // Create command to compile with raptor + string sCmd( m_sBuildCommand ); + sCmd.append( RAPTOR_BUILD_LOG ); + cout << AT_MSG_SYSTEM_CALL << sCmd << endl; + int iRet = (int)system( sCmd.c_str() ); + if ( iRet == 0 ) + return true; + return false; +} + +bool CATProject::CreateListings() +{ + // Create listings if no addr2line defined + #ifndef ADDR2LINE + if ( _stricmp( m_sPlatform.c_str(), "armv5" ) == 0 ) + { + switch ( m_eBuildSystem ) + { + case SBS_V1: + return CreateListingsSbs1(); + case SBS_V2: + return CreateListingsSbs2(); + default: + return false; + } + } + #endif + return true; +} + +bool CATProject::CreateListingsSbs1() +{ + LOG_FUNC_ENTRY("CATProject::CreateListingsSbs1"); + string sCommand; + if ( m_bAbldTest ) + sCommand = "abld test listing "; + else + sCommand = "abld listing "; + + // Listing + if ( m_sVariant.empty() ) + { + // No variant + sCommand.append( m_sPlatform ); + } + else + { + // Use specified variant + sCommand.append( m_sPlatform ); + sCommand.append( "." ); + sCommand.append( m_sVariant ); + } + // udeb vs urel + sCommand.append( " " ); + sCommand.append( GetBuildTypeString() ); + + if ( m_vTargetModules.size() > 1 ) + { + RunAbldCommandToAllTargets( sCommand ); + } + else + { + AddTargetModuleIfDefined( sCommand ); + cout << AT_MSG_SYSTEM_CALL << sCommand << endl; + (void)system( sCommand.c_str() ); + } + return true; +} + +bool CATProject::CreateListingsSbs2() +{ + LOG_FUNC_ENTRY("CATProject::CreateListingsSbs2"); + string sCmd( m_sBuildCommand ); + sCmd.append( RAPTOR_LISTING_LOG ); + sCmd.append( " LISTING"); + cout << AT_MSG_SYSTEM_CALL << sCmd << endl; + int iRet = (int)system( sCmd.c_str() ); + if ( iRet == 0 ) + return true; + return false; +} + +bool CATProject::CopyReleasables() +{ + bool bRet = true; + LOG_FUNC_ENTRY("CATProject::CopyReleasables"); + // Only copy releasables on armv5 platform and no addr2line defined. + #ifndef ADDR2LINE + if ( _stricmp( m_sPlatform.c_str(), "armv5" ) == 0 ) + { + for( size_t i = 0; i < m_vModules.size(); i++ ) + { + if ( ! m_vModules.at(i)->CopyReleasables() ) + bRet = false; + } + // Static libraries lst files. + // First create directory for them (delete old one if exists). + if ( ! DirectoryExists( AT_TEMP_LST_DIR ) ) + { + DirCreate( AT_TEMP_LST_DIR, true ); + } + else + { + DirDelete( AT_TEMP_LST_DIR, true ); + DirCreate( AT_TEMP_LST_DIR, true ); + } + for ( size_t i = 0 ; i < m_vStaticLibraries.size(); i ++ ) + { + if( ! m_vStaticLibraries.at(i)->CopyLstFilesToDir( AT_TEMP_LST_DIR ) ) + bRet = false; + } + + // Delete lst files from all type of modules in project. + // Ignoring errors because different modules might use same source/lst files. + for( size_t i = 0; i < m_vModules.size(); i++ ) + m_vModules.at(i)->DeleteLstFilesFromSrc(); + for ( size_t i = 0 ; i < m_vUnsupportedModules.size(); i ++ ) + m_vUnsupportedModules.at(i)->DeleteLstFilesFromSrc(); + for ( size_t i = 0 ; i < m_vStaticLibraries.size(); i ++ ) + m_vStaticLibraries.at(i)->DeleteLstFilesFromSrc(); + + return bRet; + } + #endif + // When addr2line defined and used we use symbol and map file(s). + #ifdef ADDR2LINE + if ( _stricmp( m_sPlatform.c_str(), "armv5" ) == 0 ) + { + // Verify that module(s) symbol file(s) exist + for( size_t i = 0; i < m_vModules.size(); i++ ) + { + // Check symbol file. + if ( ! m_vModules.at(i)->SymbolFileExist() ) + bRet = false; + // Check map file. + if ( ! m_vModules.at(i)->MapFileExist() ) + bRet = false; + } + } + #endif + // Platform winscw. + else if ( _stricmp( m_sPlatform.c_str(), "winscw" ) == 0 ) + { + // Verify that module(s) binaries exist + for( size_t i = 0; i < m_vModules.size(); i++ ) + { + if ( ! m_vModules.at(i)->BinaryFileExist() ) + bRet = false; + } + // For static libraries binary/target is same as their library. + for ( size_t i = 0 ; i < m_vStaticLibraries.size(); i ++ ) + if ( ! m_vStaticLibraries.at(i)->BinaryFileExist() ) + bRet = false; + } + // Platform gcce. + else if ( _stricmp( m_sPlatform.c_str(), "gcce" ) == 0 ) + { + // Verify that module(s) symbol file(s) exist + for( size_t i = 0; i < m_vModules.size(); i++ ) + { + // Check symbol file. + if ( ! m_vModules.at(i)->SymbolFileExist() ) + bRet = false; + } + } + return bRet; +} + +// ---------------------------------------------------------------------------- +// Write project's (user) attributes to a file under temp folder +// ---------------------------------------------------------------------------- +bool CATProject::WriteAttributes() const +{ + LOG_FUNC_ENTRY("CATProject::WriteAttributes"); + // File to write to + string sOutFile( AT_TEMP_DIR ); + sOutFile.append( "\\" ); + sOutFile.append( AT_PROJECT_ATTRIBUTES_FILE_NAME ); + // Open file truncate if exists + ofstream out( sOutFile.c_str(), ios_base::trunc ); + // Check file opened successfully + if ( ! out.good() ) + return false; + // Write attributes line by line + out << m_bUninstrumented << endl; // Is project instrumented + // Sbs version + if ( m_eBuildSystem == CATProject::SBS_V2 ) + out << "SBS_2" << endl; + else + out << "SBS_1" << endl; + out << endl; // Reserved for possible binary data + out << m_sPlatform << endl; + out << m_sVariant << endl; + out << m_eLoggingMode << endl; + out << m_eBuildType << endl; + out << m_sS60FileName << endl; + out << m_iAllocCallStackSize << endl; + out << m_iFreeCallStackSize << endl; + for ( size_t i = 0 ; i < m_vTargetModules.size() ; i++ ) + out << m_vTargetModules.at(i) << AT_PROJECT_ATTRIBUTES_SEPARATOR; + out << endl; + out << m_sBuildCommand << endl; + out.close(); + return true; +} +// ---------------------------------------------------------------------------- +// Reads project's (user) attributes to a file under temp folder +// ---------------------------------------------------------------------------- +bool CATProject::ReadAttributes() +{ + LOG_FUNC_ENTRY("CATProject::ReadAttributes"); + // File to read on + string sInFile( AT_TEMP_DIR ); + sInFile.append( "\\" ); + sInFile.append( AT_PROJECT_ATTRIBUTES_FILE_NAME ); + // Open file + ifstream in( sInFile.c_str() ); + // Check file opened successfully + if ( ! in.good() ) + return false; + // Read attributes + char cLine[ MAX_LINE_LENGTH ]; + string sLine; + in.getline( cLine, MAX_LINE_LENGTH ); + int iValue = atoi( cLine ); + if ( iValue == 1 ) + m_bUninstrumented = true; + else + m_bUninstrumented = false; + // Sbs version + in.getline( cLine, MAX_LINE_LENGTH ); string sBuildSystem = string( cLine ); + if ( sBuildSystem.compare( "SBS_1" ) == 0 ) + m_eBuildSystem = CATProject::SBS_V1; + else if ( sBuildSystem.compare( "SBS_2" ) == 0 ) + m_eBuildSystem = CATProject::SBS_V2; + else { + LOG_STRING("Error invalid build system defined in project.cfg"); + m_eBuildSystem = CATProject::SBS_V1; + } + in.getline( cLine, MAX_LINE_LENGTH ); // reserverd for possible binary timestamp or similar + in.getline( cLine, MAX_LINE_LENGTH ); m_sPlatform = string( cLine ); + in.getline( cLine, MAX_LINE_LENGTH ); m_sVariant = string( cLine ); + in.getline( cLine, MAX_LINE_LENGTH ); m_eLoggingMode = atoi( cLine ); + in.getline( cLine, MAX_LINE_LENGTH ); m_eBuildType = atoi( cLine ); + in.getline( cLine, MAX_LINE_LENGTH ); m_sS60FileName = string( cLine ); + in.getline( cLine, MAX_LINE_LENGTH ); m_iAllocCallStackSize = atoi( cLine ); + in.getline( cLine, MAX_LINE_LENGTH ); m_iFreeCallStackSize = atoi( cLine ); + in.getline( cLine, MAX_LINE_LENGTH ); sLine = cLine; + size_t iSpot = sLine.find( AT_PROJECT_ATTRIBUTES_SEPARATOR ); + while ( iSpot != string::npos ) + { + string sTarget = sLine.substr(0, iSpot ); + m_vTargetModules.push_back( sTarget ); + sLine.erase(0, iSpot + AT_PROJECT_ATTRIBUTES_SEPARATOR.size() ); + iSpot = sLine.find( AT_PROJECT_ATTRIBUTES_SEPARATOR ); + } + in.getline( cLine, MAX_LINE_LENGTH ); m_sBuildCommand = cLine; + in.close(); + return true; +} + +// ---------------------------------------------------------------------------- +// Creates atool_temp directory to current folder if does not exist +// ---------------------------------------------------------------------------- +bool CATProject::MakeTempDirIfNotExist() +{ + LOG_FUNC_ENTRY("CATProject::MakeTempDirIfNotExist"); + if ( ! DirectoryExists( AT_TEMP_DIR ) ) + { + if( !CreateDirectory( AT_TEMP_DIR , NULL ) ) + { + return false; + } + } + return true; +} +// ---------------------------------------------------------------------------- +// Utilities +// ---------------------------------------------------------------------------- + +bool CATProject::RunAbldCommandToAllTargets( const string& sCommand ) +{ + LOG_FUNC_ENTRY("CATProject::RunAbldCommandToAllTargets"); + + // Check for space at the commands end. + string sSystemCall( sCommand ); + if ( *(sSystemCall.rbegin()) != ' ' ) + sSystemCall.append( " " ); + + // Loop calls. + bool bRet = true; + for ( vector<string>::iterator it = m_vTargetModules.begin(); it < m_vTargetModules.end(); it++ ) + { + string sCall( sSystemCall ); + sCall.append( RemovePathAndExt( *it, true ) ); + cout << AT_MSG_SYSTEM_CALL << sCall << endl; + if ( (int) system( sCall.c_str() ) != 0 ) + bRet = false; + } + return bRet; +} + +void CATProject::AddTargetModuleIfDefined( string& sCmd ) +{ + LOG_FUNC_ENTRY("CATProject::AddTargetModuleIfDefined"); + // Do we have target modules defined + if ( m_vTargetModules.size() > 0 ) + { + switch( m_eBuildSystem ) + { + case SBS_V1: + // Add first target modules name without extension to build cmd. + sCmd.append( " " ); + sCmd.append( RemovePathAndExt( m_vTargetModules.at( 0 ), true ) ); + break; + case SBS_V2: + // Add all target modules to build command using raptor switch '-p'. + for( size_t i = 0 ; i < m_vTargetModules.size() ; i++ ) + { + LOG_STRING("Adding :" << m_vTargetModules.at( i ) ); + sCmd.append( " -p " ); + sCmd.append( m_vTargetModules.at( i ) ); + } + break; + } + } +} + +bool CATProject::IsTargetModuleInProject() const +{ + LOG_FUNC_ENTRY("CATProject::IsTargetModuleInProject"); + vector<CATModule2*>::const_iterator modules; + vector<CATModule2*>::const_iterator staticModules; + vector<string>::const_iterator targets; + bool bRet = true; + // Do we have target modules defined + if ( m_vTargetModules.size() > 0 ) + { + // Sbs version 1 support only single target module. + if ( m_eBuildSystem == SBS_V1 ) + { + // Try to find module from project. + bRet = false; + string sTarget = m_vTargetModules.at(0); + for( modules = m_vModules.begin() ; modules != m_vModules.end() ; modules++ ) + { + if( (*modules)->GetMmpFile().find( sTarget ) != string::npos ) + { + // Found it return true. + bRet = true; + break; + } + } + for( staticModules = m_vStaticLibraries.begin(); staticModules != m_vStaticLibraries.end(); staticModules++ ) + { + if( (*staticModules)->GetMmpFile().find( sTarget ) != string::npos ) + { + bRet = true; + break; + } + } + if ( ! bRet ) + { + // Not found display error message. + cout << AT_MSG << "Error, " << sTarget << " not defined in project." << endl; + } + } + // Sbs version 2 supports multiple target modules. + else if ( m_eBuildSystem == SBS_V2 ) + { + // Check that all targets are defined in project. + for( targets = m_vTargetModules.begin(); targets != m_vTargetModules.end() ; targets++ ) + { + // Found iterated target? + bool bFound = false; + for ( modules = m_vModules.begin() ; modules != m_vModules.end() ; modules++ ) + { + if( (*modules)->GetMmpFile().find( *targets ) != string::npos ) + { + // yes. + bFound = true; + break; + } + } + for( staticModules = m_vStaticLibraries.begin(); staticModules != m_vStaticLibraries.end(); staticModules++ ) + { + if( (*staticModules)->GetMmpFile().find( *targets ) != string::npos ) + { + bFound = true; + break; + } + } + if ( ! bFound ) + { + // Display error when not found and set return value false. + bRet = false; + cout << AT_MSG << "Error, " << targets->c_str() << " not defined in project." << endl; + } + } + } + } + return bRet; +} + +string CATProject::GetBuildTypeString() +{ + LOG_LOW_FUNC_ENTRY("CATProject::GetBuildTypeString"); + // Return build type as lowercase string + switch( m_eBuildType ) + { + case UDEB: + return string("udeb"); + case UREL: + return string("urel"); + default: + return ""; + } +} + +string CATProject::GetBuildTypeString( int eType ) +{ + LOG_LOW_FUNC_ENTRY("CATProject::GetBuildTypeString( int eType )"); + // Return build type as lowercase string + switch( eType ) + { + case UDEB: + return string("udeb"); + case UREL: + return string("urel"); + default: + return string("unknown"); + } +} + +bool CATProject::CleanTemporaryDirs() +{ + LOG_FUNC_ENTRY("CATProject::CleanTemporaryDirs"); + bool bRet = true; + // Modules + for( size_t i = 0; i < m_vModules.size(); i++ ) + { + if ( ! m_vModules.at(i)->CleanTemporaryDir() ) + bRet = false; + } + for( size_t i = 0; i < m_vStaticLibraries.size(); i++ ) + { + if ( ! m_vStaticLibraries.at(i)->CleanTemporaryDir() ) + bRet = false; + } + // Projects + vector<string> vFileList = DirList( AT_TEMP_DIR, false , true ); + vector<string>::iterator it2 = vFileList.begin(); + // Size of constant table + int iCount = sizeof( TEMP_EXTENSION_NO_DELETE ) / sizeof( string ); + while ( it2 != vFileList.end() ) + { + // Get extension and compare it to list + bool bDelete = true; + string sExtension = GetExtension( *it2 ); + ChangeToLower( sExtension ); + for ( int i = 0 ; i < iCount ; i++ ) + { + if( sExtension.compare( TEMP_EXTENSION_NO_DELETE[i] ) == 0 ) + { + bDelete = false; + break; + } + } + if ( bDelete ) + { + // Delete file + if ( ! FileDelete( *it2, true ) ) + bRet = false; + } + // Increment + it2++; + } + return bRet; +} + +bool CATProject::DeleteTemporaryDirs() +{ + LOG_FUNC_ENTRY("CATProject::DeleteTemporaryDirs"); + bool bRet = true; + // Modules + for( size_t i = 0; i < m_vModules.size(); i++ ) + { + if (! m_vModules.at(i)->DeleteTemporaryDir() ) + bRet = false; + } + for( size_t i = 0; i < m_vStaticLibraries.size(); i++ ) + { + if (! m_vStaticLibraries.at(i)->DeleteTemporaryDir() ) + bRet = false; + } + return bRet; +} + +bool CATProject::InitSbs1MakeFileWithPathToTemp() +{ + LOG_FUNC_ENTRY("CATProject::InitSbs1MakeFileWithPathToTemp"); + // Use temporary folder + m_sMakeFile.clear(); + m_sMakeFile.append( AT_TEMP_DIR ); + m_sMakeFile.append( "\\" ); + m_sMakeFile.append( AT_LEVEL_1_MAKEFILE_NAME ); + // At end check does it exist, return the result. + return FileExists( m_sMakeFile.c_str() ); +} + +bool CATProject::InitSbs1MakeFileWithPath() +{ + LOG_FUNC_ENTRY("CATProject::InitMakeFileWithPath"); + if ( m_sEpocRoot.empty() ) + { + LOG_STRING("Error, epocroot is not set."); + return false; + } + m_sMakeFile.clear(); + m_sMakeFile.append( m_sEpocRoot ); + if( *m_sMakeFile.rbegin() != '\\' ) + m_sMakeFile.append( "\\" ); + m_sMakeFile.append( "epoc32\\build\\" ); + // Add current directory to path (first remove driveletter). + string sCurrentDir( m_cCurrentDir ); + if ( sCurrentDir.length() < 3 ) + { + LOG_STRING("Error, current dir invalid."); + return false; + } + sCurrentDir.erase(0,3); + m_sMakeFile.append( sCurrentDir ); + m_sMakeFile.append( "\\" ); + // Platform + string sPlatInUpper( m_sPlatform); + ChangeToUpper( sPlatInUpper ); + m_sMakeFile.append( sPlatInUpper ); + // Possible variant + if ( m_sVariant.empty() ) + { + // Test modules only? + if ( m_bAbldTest ) + m_sMakeFile.append( "TEST" ); + m_sMakeFile.append( "." ); + m_sMakeFile.append( "MAKE" ); + } + else + { + m_sMakeFile.append( "." ); + m_sMakeFile.append( m_sVariant ); + // Test modules only? + if ( m_bAbldTest ) + m_sMakeFile.append( "TEST" ); + m_sMakeFile.append( ".MAKE" ); + } + // At end check does it exist, return the result. + return FileExists( m_sMakeFile.c_str() ); +} + +// ---------------------------------------------------------------------------- +// Get & Sets +// ---------------------------------------------------------------------------- +void CATProject::SetBuildSystem( BUILD_SYSTEM eSystem ) +{ + LOG_FUNC_ENTRY("CATProject::SetBuildSystem"); + m_eBuildSystem = eSystem; +} +void CATProject::SetMode( PROJECT_MODE eMode ) +{ + LOG_FUNC_ENTRY("CATProject::SetMode"); + m_eMode = eMode; +} +int CATProject::GetMode() const +{ + LOG_LOW_FUNC_ENTRY("CATProject::GetMode"); + return m_eMode; +} +void CATProject::SetEpocRoot( const string& sEpocRoot ) +{ + LOG_FUNC_ENTRY("CATProject::SetEpocRoot"); + m_sEpocRoot = sEpocRoot; +} +void CATProject::SetPlatform( const string& sPlatform ) +{ + LOG_FUNC_ENTRY("CATProject::SetPlatform"); + m_sPlatform = sPlatform; +} +void CATProject::SetVariant( const string& sVariant ) +{ + LOG_FUNC_ENTRY("CATProject::SetVariant"); + m_sVariant = sVariant; +} +void CATProject::SetLoggingMode( LOGGING_MODE eLoggingMode) +{ + LOG_FUNC_ENTRY("CATProject::SetLoggingMode"); + m_eLoggingMode = eLoggingMode; +} +void CATProject::SetAllocCallStackSize( int iAllocCallStackSize ) +{ + m_iAllocCallStackSize = iAllocCallStackSize; +} +void CATProject::SetFreeCallStackSize( int iFreeCallStackSize ) +{ + m_iFreeCallStackSize = iFreeCallStackSize; +} +void CATProject::SetBuildType( BUILD_TYPE eType ) +{ + LOG_FUNC_ENTRY("CATProject::SetBuildType"); + m_eBuildType = eType; +} +void CATProject::SetS60FileName( const string& sFileName) +{ + LOG_FUNC_ENTRY("CATProject::SetS60FileName"); + m_sS60FileName = sFileName; +} +void CATProject::SetRomSymbolFiles(const vector<string>& vRomSymbolFiles) +{ + LOG_FUNC_ENTRY("CATProject::SetRomSymbolFiles"); + m_vRomSymbolFiles = vRomSymbolFiles; +} +void CATProject::SetTargetModule(const string& sTargetModule) +{ + LOG_FUNC_ENTRY("CATProject::SetTargetModule"); + m_sTargetModule = sTargetModule; + ChangeToLower( m_sTargetModule); +} +void CATProject::SetBinaryTarget(const string& sBinaryTarget) +{ + LOG_FUNC_ENTRY("CATProject::SetBinaryTarget"); + m_sBinaryTarget = sBinaryTarget; + ChangeToLower( m_sBinaryTarget ); +} +void CATProject::SetDataFile( const string& sDataFile ) +{ + LOG_FUNC_ENTRY("CATProject::SetDataFile"); + m_sDataFile = sDataFile; +} +void CATProject::SetLogLevel( int iLogLevel ) +{ + LOG_FUNC_ENTRY("CATProject::SetLogLevel"); + m_iLoggingLevel = iLogLevel; +} +void CATProject::SetDataFileOutput( const string& sDataFileOutput ) +{ + LOG_FUNC_ENTRY("CATProject::SetDataFileOutput"); + m_sDataFileOutput = sDataFileOutput; +} +void CATProject::SetTargetModules( const vector<string>& vTargetModules ) +{ + LOG_FUNC_ENTRY("CATProject::SetTargetModules"); + m_vTargetModules = vTargetModules; +} +void CATProject::SetBuildCommand( const string& sBuildCommand ) +{ + LOG_FUNC_ENTRY("CATProject::SetBuildCommand"); + m_sBuildCommand = sBuildCommand; +} +// End of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/arguments.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/arguments.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,798 @@ +/* +* 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: Argument parsing functions. +*/ +#include "../inc/ATCommonDefines.h" +#include "../inc/CATBase.h" + +//Forward declarations. +bool parseBaseArguments( vector<string>& vArgs, ARGUMENTS& args ); +bool parseHookArguments( vector<string>& vArgs, ARGUMENTS& args ); +bool parseAnalyzeArguments( vector<string>& vArgs, ARGUMENTS& args ); +bool parseParseArguments( vector<string>& vArgs, ARGUMENTS& args ); +bool checkDataFileName( string& sFileName ); +bool parseSbsConfiguration( string& sConfiguration, ARGUMENTS& args ); + +// Constants for old "hooking" parameter parsing. +#define INVALID_PARAMETER "AnalyzeTool : Error, invalid parameter: " +const char DATAFILENAME_INVALID_CHARS[] = " &^+-@$%*()|\\/[]{}<>?;:,\"'"; + +/** +* Check datafile name for invalid characters. +* @return true if file name ok. +*/ +bool checkDataFileName( string& sFileName ) +{ + for ( size_t i = 0; i < sFileName.length(); i++ ) + { + const char c = sFileName.at( i ); + if( strchr( DATAFILENAME_INVALID_CHARS, c ) != 0 ) + return false; + } + return true; +} + +/** +* Parse base arguments from given vector of strings. +* Removes debug / help arguments from vector. +*/ +bool parseBaseArguments( vector<string>& vArgs, ARGUMENTS& args ) +{ + // Iterator used in this function. + vector<string>::iterator it; + // If no arguments set show help true. + if ( vArgs.size() == 0 ) + { + args.eMainSwitch = SWITCH_UNKNOWN; + args.bHelp = true; + } + //Try find help and debug switches. + //Note: -help is main switch what shows syntax examples. + for(it = vArgs.begin(); it != vArgs.end(); it++ ) + { + //Help switches. + if ( ! _stricmp( (*it).c_str(), "-?" ) ) + { + args.bHelp = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "--?" ) ) + { + args.bHelp = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "--help" ) ) + { + args.bHelp = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "/?" ) ) + { + args.bHelp = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + //Debug switches. + else if ( ! _stricmp( (*it).c_str(), "-show_debug" ) ) + { + args.bDebugConsole = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "--show_debug" ) ) + { + args.bDebugConsole = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "-show_debug_all" ) ) + { + args.bDebugConsole = true; + args.bDebugLowLevel = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "--show_debug_all" ) ) + { + args.bDebugConsole = true; + args.bDebugLowLevel = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "-show_dbgview" ) ) + { + args.bDebugDbgView = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "--show_dbgview" ) ) + { + args.bDebugDbgView = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "-show_dbgview_all" ) ) + { + args.bDebugDbgView = true; + args.bDebugLowLevel = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "--show_dbgview_all" ) ) + { + args.bDebugDbgView = true; + args.bDebugLowLevel = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + //Raptor switch. + else if ( ! _stricmp( (*it).c_str(), "-sbs2" ) ) + { + args.bEnableSbs2 = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + } + if ( vArgs.size() > 0 ) + { + //Pick up main switch. + it = vArgs.begin(); + if ( ! _stricmp( (*it).c_str(), "-a" ) ) + args.eMainSwitch = SWITCH_ANALYZE; + else if ( ! _stricmp( (*it).c_str(), "-p" ) ) + args.eMainSwitch = SWITCH_PARSE_TRACE; + else if ( ! _stricmp( (*it).c_str(), "-c" ) ) + args.eMainSwitch = SWITCH_CLEAN; + else if ( ! _stricmp( (*it).c_str(), "-v" ) ) + args.eMainSwitch = SWITCH_VERSION; + else if ( ! _stricmp( (*it).c_str(), "-vdbghelp" ) ) + args.eMainSwitch = SWITCH_DBGHELP_VERSION; + else if ( ! _stricmp( (*it).c_str(), "-help" ) ) + args.eMainSwitch = SWITCH_HELP; + else if ( ! _stricmp( (*it).c_str(), "-me" ) ) + { + args.eMainSwitch = SWITCH_HOOK; + args.eHookSwitch = HOOK_EXTERNAL; + } + else if ( ! _stricmp( (*it).c_str(), "-e" ) ) + { + args.eMainSwitch = SWITCH_HOOK; + args.eHookSwitch = HOOK_EXTERNAL_FAST; + } + else if ( ! _stricmp( (*it).c_str(), "-mi" ) ) + { + args.eMainSwitch = SWITCH_HOOK; + args.eHookSwitch = HOOK_INTERNAL; + } + else if ( ! _stricmp( (*it).c_str(), "-instrument_i" ) ) + { + args.eMainSwitch = SWITCH_HOOK; + args.eHookSwitch = HOOK_EXTENSION_INTERNAL; + } + else if ( ! _stricmp( (*it).c_str(), "-instrument_e" ) ) + { + args.eMainSwitch = SWITCH_HOOK; + args.eHookSwitch = HOOK_EXTENSION_EXTERNAL; + } + else if ( ! _stricmp( (*it).c_str(), "-instrument_ef" ) ) + { + args.eMainSwitch = SWITCH_HOOK; + args.eHookSwitch = HOOK_EXTENSION_EXTERNAL_FAST; + } + else if ( ! _stricmp( (*it).c_str(), "-uninstrument" ) ) + { + args.eMainSwitch = SWITCH_UNHOOK; + args.eHookSwitch = HOOK_EXTENSION_UNINSTRUMENT; + } + else if ( ! _stricmp( (*it).c_str(), "-uninstrument_failed" ) ) + { + args.eMainSwitch = SWITCH_UNHOOK; + args.eHookSwitch = HOOK_EXTENSION_FAILED; + } + } + return true; +} + +/** +* Parse analyze related arguments from given vector of strings. +*/ +bool parseAnalyzeArguments( vector<string>& vArgs, ARGUMENTS& args ) +{ + bool bRet = true; + if ( vArgs.size() < 2 ) + { + cout << AT_MSG << "Error, missing datafile." << endl; + return false; + } + // Iterator used in this function. + vector<string>::const_iterator it; + for(it = vArgs.begin()+1; it != vArgs.end(); it++ ) + { + if ( it->find("-l") != string::npos ) + { + if ( it->length() == 3 ) + { + // Create char array for atoi function + char level[2]; + level[0] = it->at(2); + level[1] = 0; // null terminate + // check that its digit first + if ( isdigit(level[0]) ) + { + // pass array to atoi + int iLoggingLevel = atoi( level ); + if ( iLoggingLevel >= 0 && iLoggingLevel <= 3 ) + { + // log level ok + args.ANALYZE.iLoggingLevel = iLoggingLevel; + continue; + } + } + bRet = false; + cout << AT_MSG << "Invalid logging level specified (0-3)." << endl; + args.ANALYZE.iLoggingLevel = -1; + } + } + // No else here because logging level check is done to all args in list. + // Rom symbol file + if( _stricmp( it->c_str(), "-s" ) == 0 ) + { + it++; + if ( it == vArgs.end() ) + { + bRet = false; + cout << AT_MSG << "Missing symbol file." << endl; + break; // Leave for loop. + } + else + { + args.ANALYZE.bSymbolFile = true; + args.ANALYZE.vSymbolFiles.push_back( *it ); + continue; + } + } + else + { + // If we got datafile we must assume this is output + if( ! args.ANALYZE.sDataFile.empty() ) + { + if ( args.ANALYZE.sOutputFile.empty() ) + args.ANALYZE.sOutputFile = *it; + else + { + bRet = false; + cout << AT_MSG << "Invalid parameter: " << *it << endl; + } + } + // If this is file we assume datafile + else if( CATBase::FileExists( it->c_str() ) ) + { + args.ANALYZE.sDataFile = *it; + } + else + { + bRet = false; + cout << AT_MSG << "Specified datafile does not exist." << endl; + } + } + } + if ( args.ANALYZE.sDataFile.empty() ) + bRet = false; + return bRet; +} + + +/** +* Parse hooking related arguments from given vector of strings. +*/ +bool parseHookArguments( vector<string>& vArgs, ARGUMENTS& args ) +{ + bool bRet = true; + try { + // Iterator used in this function. + vector<string>::const_iterator it; + + // Check that we have some arguments except main switch. + if ( vArgs.size() < 2 ) + { + if ( args.eHookSwitch == HOOK_EXTENSION_UNINSTRUMENT + || args.eHookSwitch == HOOK_EXTENSION_FAILED + ) + return bRet; + cout << AT_MSG << "Error, Missing build command." << endl; + bRet = false; + } + bool bBuildFound = false; + for(it = vArgs.begin()+1; it != vArgs.end(); it++ ) + { + // If's to pickup atool options + // no build switch + if ( _stricmp( it->c_str(), "-nobuild" ) == 0 ) + { + args.HOOK.bNoBuild = true; + } + // call stack size(s) + else if ( _stricmp( it->c_str(), "-acs" ) == 0 || _stricmp( it->c_str(), "-fcs" ) == 0 ) + { + // Free vs Alloc + bool bAlloc = true; + if ( _stricmp( it->c_str(), "-fcs" ) == 0 ) + bAlloc = false; + // Value + it++; + if ( it== vArgs.end() ) + { + bRet = false; + cout << AT_MSG << "Error, missing call stack size parameter." << endl; + break; + } + else if ( ! _stricmp( it->c_str(), "sbs" ) + || ! _stricmp( it->c_str(), "abld" ) + || ! _stricmp( it->c_str(), "-f" ) ) + { + bRet = false; + cout << AT_MSG << "Error, missing call stack size parameter." << endl; + break; + } + else + { + int i; + // Try to parse integer value using stream. + istringstream ss( *it ); + if ( ss>>i ) + { + // Value parsed ok now check bounds. + if ( i < AT_CALL_STACK_SIZE_MIN ) + { + bRet = false; + cout << AT_MSG << "Error, specified call stack size value too small." << endl; + break; + } + else if ( i > AT_CALL_STACK_SIZE_MAX ) + { + bRet = false; + cout << AT_MSG << "Error, specified call stack size value too big." << endl; + break; + } + else + { + // Value valid. + if ( bAlloc ) + args.HOOK.iAllocCallStackSize = i; + else + args.HOOK.iFreeCallStackSize = i; + } + } + else + { + // Error parsing value using stream. + bRet = false; + cout << AT_MSG << "Error, specified call stack size value invalid." << endl; + break; + } + + } + } + // Data file name. + else if ( _stricmp( it->c_str(), "-f" ) == 0 ) + { + it++; + if ( it == vArgs.end() ) + { + bRet = false; + cout << AT_MSG << "Error, missing internal data gathering file name." << endl; + break; + } + else if ( ! _stricmp( it->c_str(), "sbs" ) || ! _stricmp( it->c_str(), "abld" ) ) + { + bRet = false; + cout << AT_MSG << "Error, missing internal data gathering file name." << endl; + break; + } + else + { + if ( checkDataFileName( string( *it ) ) ) + { + // Pickup filename. + args.HOOK.bDataFileName = true; + args.HOOK.sDataFileName = *it; + } + else + { + bRet = false; + cout << AT_MSG << "Error, specified internal data gathering file name contains invalid character(s)." << endl; + break; + } + } + } + // Build command parsing. + else if ( _stricmp( it->c_str(), "sbs" ) == 0 ) + { + // By default sbs command is not valid. + bRet = false; + // By default build found + bBuildFound = true; + // Use raptor build system, pickup all rest arguments to sbs commmand. + bool bFoundConfig = false; // Is configuration defined. + args.HOOK.iBuildSystem = 2; + vector<string>::const_iterator itC = it; + args.HOOK.sBuildCmd.clear(); + for ( ; itC != vArgs.end() ; itC++ ) + { + args.HOOK.sBuildCmd.append( *itC ); + args.HOOK.sBuildCmd.append( " " ); + args.HOOK.vBuildCmd.push_back( *itC ); + } + // Remove last space + if ( args.HOOK.vBuildCmd.size() > 1 ) + args.HOOK.sBuildCmd.erase( args.HOOK.sBuildCmd.size()-1 ); + + // Parse needed variables from sbs command. + vector<string>::iterator itSbs; + for( itSbs = args.HOOK.vBuildCmd.begin(); itSbs != args.HOOK.vBuildCmd.end() ; itSbs++ ) + { + // Program(s). + if ( _stricmp( itSbs->c_str(), "-p" ) == 0 ) + { + // Next is program. + itSbs++; + args.HOOK.vTargetPrograms.push_back( *itSbs ); + } + else if ( itSbs->find( "--project=" ) != string::npos ) + { + itSbs->erase(0, 10 ); + args.HOOK.vTargetPrograms.push_back( *itSbs ); + } + // platform & build type ( configuration ) + else if ( _stricmp( itSbs->c_str(), "-c" ) == 0 || itSbs->find( "--config=" ) != string::npos ) + { + // Error message if config found more than once. + if ( bFoundConfig ) + { + cout << AT_MSG << "Error, no support defining more than one configuration." << endl; + bRet = false; + continue; + } + + if (_stricmp( itSbs->c_str(), "-c" ) == 0 ) + { + // Next is the configuration + itSbs++; + // Check that iterator is valid. + if ( itSbs == args.HOOK.vBuildCmd.end() ) + break; + } + else + { + // Remove the "--config=". + itSbs->erase( 0, 9 ); + // Check its not empty. + if ( itSbs->size() == 0 ) + break; + } + + // Identify configuration, if successful set sbs command as valid. + if ( parseSbsConfiguration( *itSbs, args ) ) + bRet = true; + // Set we encountered one configuration. + bFoundConfig = true; + } + } + // Error message if command is missing configuration. + if ( !bFoundConfig ) + cout << AT_MSG << "Error, missing configuration definition from sbs cmd." << endl; + } + else if ( _stricmp( it->c_str(), "abld" ) == 0 ) + { + bBuildFound = true; + // Use abld build system, pickup all rest argumenst as abld options. + args.HOOK.iBuildSystem = 1; + + vector<string>::const_iterator itC = it; + args.HOOK.sBuildCmd.clear(); + for ( ; itC != vArgs.end() ; itC++ ) + { + args.HOOK.sBuildCmd.append( *itC ); + args.HOOK.sBuildCmd.append( " " ); + args.HOOK.vBuildCmd.push_back( *itC ); + } + + string sCmd( args.HOOK.sBuildCmd ); // build command to lower case here. + for( size_t i = 0 ; i < sCmd.size(); i++ ) + sCmd.at(i) = tolower( sCmd.at(i) ); + + // Remove all until platform + if ( sCmd.find("build ") != string::npos ) + { + // Check is test defined + if ( sCmd.substr(0, sCmd.find("build ")).find("test") != string::npos ) + args.HOOK.bAbldTest = true; + sCmd.erase( 0, sCmd.find("build")+6 ); + } + else + return false; + + //Is -debug switch in command? + if( sCmd.find( "-debug " ) != string::npos ) + { + sCmd.erase( sCmd.find( "-debug " ), 7 ); + } + + // Parse needed "variables" from command. + bool bOk = false; + + // Find platform + if ( sCmd.find( "armv5" ) != string::npos ) + { + bOk = true; + args.HOOK.sPlatform = "armv5"; + sCmd.erase( sCmd.find( "armv5" ), 5 ); + } + else if ( sCmd.find( "winscw" ) != string::npos ) + { + bOk = true; + args.HOOK.sPlatform = "winscw"; + sCmd.erase( sCmd.find( "winscw" ), 6 ); + } + else if ( sCmd.find( "gcce" ) != string::npos ) + { + bOk = true; + args.HOOK.sPlatform = "gcce"; + sCmd.erase( sCmd.find( "gcce" ), 4 ); + } + if ( bOk ) + { + // Feature variant. + if ( sCmd.at(0 ) == '.' ) + { + sCmd.erase(0,1); + args.HOOK.sFeatureVariant = sCmd.substr( 0, sCmd.find_first_of(' ') ); + sCmd.erase(0, sCmd.find_first_of(' ')+1 ); + } + } + else + { + // not platform specified. + cout << AT_MSG << "Error, no supported platform found in abld parameters (armv5/winscw/gcce)." << endl; + bRet = false; + } + + // find build type + bOk = false; + if ( sCmd.find( "urel" ) != string::npos ) + { + bOk = true; + args.HOOK.sBuildType = "urel"; + sCmd.erase( sCmd.find( "urel" ), 4 ); + } + + else if ( sCmd.find( "udeb" ) != string::npos ) + { + bOk = true; + args.HOOK.sBuildType = "udeb"; + sCmd.erase( sCmd.find( "udeb" ), 4 ); + } + if( !bOk ) + { + // no build type specified. + cout << AT_MSG << "Error, no build type specified in abld parameters (udeb/urel)." << endl; + bRet = false; + } + + // Is there multiple programs (only should be used from extension). + if ( sCmd.find(" -p") != string::npos ) + { + sCmd.erase( sCmd.find(" -p" ), sCmd.size() - sCmd.find(" -p" ) ); + // Loop thru all parameters and pick up programs. + vector<string>::iterator it; + for( it = args.HOOK.vBuildCmd.begin(); it != args.HOOK.vBuildCmd.end(); it++ ) + { + if ( _stricmp( it->c_str(), "-p" ) == 0 ) + { + // Next is program. + it++; + string sProgram = *it; + // Make sure program name ends with ".mmp". + CATBase::ChangeToLower( sProgram ); + if ( sProgram.length() >= 4 ) + { + string sEnd = sProgram.substr( sProgram.length()-4, 4 ); + if ( sEnd.compare( ".mmp" ) != 0 ) + sProgram.append( ".mmp" ); + } + else + sProgram.append( ".mmp" ); + args.HOOK.vTargetPrograms.push_back( sProgram ); + } + } + } + else { + // find single defined program. + if ( sCmd.find_first_not_of(' ') != string::npos ) + { + size_t iS = sCmd.find_first_not_of(' '); + size_t iE = sCmd.find_first_of(' ', iS ); + string sProgram; + if ( iE == string::npos ) + sProgram = sCmd.substr( iS, sCmd.size()-iS ); + else + sProgram = sCmd.substr( iS, iE-iS); + // Make sure program name ends with ".mmp". + CATBase::ChangeToLower( sProgram ); + if ( sProgram.length() >= 4 ) + { + string sEnd = sProgram.substr( sProgram.length()-4, 4 ); + if ( sEnd.compare( ".mmp" ) != 0 ) + sProgram.append( ".mmp" ); + } + else + sProgram.append( ".mmp" ); + args.HOOK.vTargetPrograms.push_back( sProgram ); + } + } + } + else + { + if ( ! bBuildFound ) + { + bRet = false; + cout << AT_MSG << "Error, invalid parameter :" << *it << endl; + break; + } + } + } + } + catch(...) + { + bRet = false; + cout << AT_MSG << "Error parsing arguments." << endl; + } + return bRet; +} + + +/** +* Parse trace parsing related arguments from given vector of strings. +*/ +bool parseParseArguments( vector<string>& vArgs, ARGUMENTS& args ) +{ + // Iterator used in this function. + vector<string>::const_iterator it = vArgs.begin(); + + if ( it == vArgs.end() ) + return false; + + it++; + + if ( it == vArgs.end() ) + { + cout << AT_MSG << "Error, input file not defined (raw data file)." << endl; + return false; + } + + //Input. + args.PARSE.bDataFile = true; + args.PARSE.sDataFile = *it; + + it++; + if ( it == vArgs.end() ) + { + + cout << AT_MSG << "Error, output file not defined (device data file)." << endl; + return false; + } + + //Output. + args.PARSE.bOutputFile = true; + args.PARSE.sOutputFile = *it; + return true; +} + +/** +* Identifies/parses the configuration string when raptor used (-c / --config= ). +*/ +bool parseSbsConfiguration( string& sConfiguration, ARGUMENTS& args ) +{ + CATBase::ChangeToLower( sConfiguration ); + vector<string> tokens = CATBase::ParseStringToVector( sConfiguration, '.' ); + + //we check if winscw/armv5 and udeb/urel is used + //rest of the "." are variants which we all support by default. + + //first we check if some of aliases is used + if ( tokens.at(0).compare("armv5_urel") == 0 ) + { + args.HOOK.sPlatform = "armv5"; + args.HOOK.sBuildType = "urel"; + return true; + } + else if ( tokens.at(0).compare("armv5_udeb") == 0 ) + { + args.HOOK.sPlatform = "armv5"; + args.HOOK.sBuildType = "udeb"; + return true; + } + else if ( tokens.at(0).compare("winscw_udeb") == 0) + { + args.HOOK.sPlatform = "winscw"; + args.HOOK.sBuildType = "udeb"; + return true; + } + else if ( tokens.at(0).compare("winscw_urel") == 0 ) + { + args.HOOK.sPlatform = "winscw"; + args.HOOK.sBuildType = "urel"; + return true; + } + //if 1st token is not an alias, lets try dot configurations + else if ( tokens.at(0).compare("arm") == 0 ) + { + // check we have atleast 3 tokens. i.e arm v5 debug x ... + if ( tokens.size() >= 3 ) + { + // Next configuration is arm version, we only support v5. + if ( tokens.at(1).compare( "v5" ) == 0) + { + args.HOOK.sPlatform = "armv5"; + + // Check next configuration part is debug or release + if ( tokens.at(2).compare( "udeb" ) == 0) + { + args.HOOK.sBuildType = "udeb"; + return true; + } + else if ( tokens.at(2).compare( "urel" ) == 0 ) + { + args.HOOK.sBuildType = "urel"; + return true; + } + else + { + cout << AT_MSG << "Error in sbs configuration part: " << tokens.at(2) << endl; + cout << AT_MSG << "Supported are: udeb,urel." << endl; + return false; + } + } + else + { + cout << AT_MSG << "Error in sbs configuration part: " << tokens.at(1) << endl; + cout << AT_MSG << "Supported are: v5." << endl; + return false; + } + } + } + + cout << AT_MSG << "Error in sbs configuration part: " << tokens.at(0) << endl; + cout << AT_MSG << "Supported are: arm, armv5_urel, armv5_udeb, winscw_udeb, winscw_urel." << endl; + return false; + +} + +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/atool.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/atool.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,236 @@ +/* +* 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: Defines the entry point for the console application. +* +*/ + +// Includes. +#include "../inc/ATCommonDefines.h" +#include "../inc/CATDatParser.h" +#include "../inc/CATParseTraceFile.h" +#include "../inc/CATProject.h" + +//Debug logging parameters +//To enable debugging as argument to atool.exe use: +//--show_debug / -show_debug : Normal logging in console. +//--show_debug_all / -show_debug_all : Log all (low level functions also) to console. +//--show_dbgview / -show_dbgview : Normal logging to windows debug messages. +//--show_dbgview_all / -show_dbgview_all : Log all (low level functions also) to windows debug messages. + +//Return codes (errorlevel) defined in AT_RETURN_CODE structure see ATCommonDefines.h. + +extern bool g_bDebugConsole = false; +extern bool g_bDebugDbgView = false; +extern bool g_bDebugLowLevel = false; + +//Argument parsing. +extern bool parseBaseArguments( vector<string>& vArgs, ARGUMENTS& args ); +extern bool parseHookArguments( vector<string>& vArgs, ARGUMENTS& args ); +extern bool parseAnalyzeArguments( vector<string>& vArgs, ARGUMENTS& args ); +extern bool parseParseArguments( vector<string>& vArgs, ARGUMENTS& args ); + +//Helps. +extern void print_help( void ); +extern void print_syntax_examples( void ); + +//AT Library check functions +extern bool CheckATLibrariesArmv5( string sEpocRoot ); +extern bool CheckATLibrariesArmv5Abiv2( string sEpocRoot ); +extern bool CheckATLibrariesWinscw( string sEpocRoot ); + +//CLE version functions. +extern int showVersionInfo( void ); + +//dbghelp.dll version function. +extern int showDbgHelpVersionInfo( bool showVersion ); + +//Miscelllanaeous functions. +extern bool CheckSBS2Folder( void ); + +const char DEBUG_PARAMETER_CONSOLE[] = "-debug"; +const char DEBUG_PARAMETER_DBGVIEW[] = "-dbgview"; +const char SBS2_PARAMETER[] = "-sbs2"; +char g_cCurrentDir[MAX_LINE_LENGTH]; + +//Global compile class objects are neededif ctrl+c is pressed mmp file must be restored. +CATProject project_module; + +//Parse object. +CATParseTraceFile Parser; + +/** +* Handle process control signals. +*/ +BOOL WINAPI HandlerRoutine( DWORD dwCtrlType ) +{ + //Run recovery and exit for project if user presses ctrl+c + //or close signal is received. + if( dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_CLOSE_EVENT ) + { + int iMode = project_module.GetMode(); + if ( iMode == CATProject::COMPILE + || iMode == CATProject::INSTRUMENT + || iMode == CATProject::INSTRUMENT_CONSOLE ) + project_module.RunRecoveryAndExit(); + } + //Return false so program execution is stopped. + return false; +} +// TESTING +int _tmain( int argc, _TCHAR* argv[] ) +{ + #ifdef MEM_LEAK_CHECK + _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); + #endif + try { + //Set function to handle process control signals. + SetConsoleCtrlHandler( HandlerRoutine, true ); + vector<string> vArguments; + for( int i = 1 ; i < argc ; i++ ) + { + vArguments.push_back( argv[i] ); + } + //Help variables. + string sEpocRoot(""); + //Parse base arguments. + ARGUMENTS args; + parseBaseArguments( vArguments, args ); + + // Debugging messages. + if ( args.bDebugConsole == true ) + g_bDebugConsole = true; + if ( args.bDebugDbgView == true ) + g_bDebugDbgView = true; + if ( args.bDebugLowLevel == true ) + g_bDebugLowLevel = true; + + //According to main switch parse rest arguments. + switch( args.eMainSwitch ) + { + case SWITCH_UNKNOWN: + print_help(); + return AT_RETURN_CODE::INVALID_ARGUMENT_ERROR; + case SWITCH_ANALYZE: + if ( ! parseAnalyzeArguments( vArguments, args ) ) + return AT_RETURN_CODE::INVALID_ARGUMENT_ERROR; + // Get epocroot + if( ! CATBase::GetEpocRoot( sEpocRoot ) ) + return AT_RETURN_CODE::CANNOT_FIND_EPOCROOT; + project_module.SetEpocRoot( sEpocRoot ); + // project not uninstrumented run it first. + if ( ! project_module.IsUninstrumented() ) + { + project_module.SetMode( CATProject::UNINSTRUMENT_CONSOLE ); + project_module.Run(); + } + // Set mode. + project_module.SetMode( CATProject::ANALYZE ); + project_module.SetLogLevel( args.ANALYZE.iLoggingLevel ); + project_module.SetDataFile( args.ANALYZE.sDataFile ); + if ( args.ANALYZE.bSymbolFile ) + project_module.SetRomSymbolFiles( args.ANALYZE.vSymbolFiles ); + project_module.SetDataFileOutput( args.ANALYZE.sOutputFile); + return project_module.Run(); + case SWITCH_HOOK: + // Parse arguments related to hooking. + if ( ! parseHookArguments( vArguments, args ) ) + return AT_RETURN_CODE::INVALID_ARGUMENT_ERROR; + // Set variables for project. + if ( ! project_module.SetArguments( args ) ) + return AT_RETURN_CODE::INVALID_ARGUMENT_ERROR; + // Get epocroot + if( ! CATBase::GetEpocRoot( sEpocRoot ) ) + return AT_RETURN_CODE::CANNOT_FIND_EPOCROOT; + project_module.SetEpocRoot( sEpocRoot ); + // Check AnalyzeTool libraries + if ( _stricmp( args.HOOK.sPlatform.c_str(), "winscw") == 0 ) + { + // Emulator winscw platform + if ( ! CheckATLibrariesWinscw(sEpocRoot) ) + return AT_RETURN_CODE::AT_LIBS_MISSING; + } + else + { + // Armv5 + if ( args.HOOK.iBuildSystem == 2 ) + { + // Abiv2 + if ( ! CheckATLibrariesArmv5Abiv2(sEpocRoot) ) + return AT_RETURN_CODE::AT_LIBS_MISSING; + } + else + { + // Abiv1 + if( ! CheckATLibrariesArmv5(sEpocRoot) ) + return AT_RETURN_CODE::AT_LIBS_MISSING; + } + } + // Run hooking. + return project_module.Run(); + //Uninstrument + case SWITCH_UNHOOK: + // Set variables for project. + if ( ! project_module.SetArguments( args ) ) + return AT_RETURN_CODE::INVALID_ARGUMENT_ERROR; + // Get epocroot + if( ! CATBase::GetEpocRoot( sEpocRoot ) ) + return AT_RETURN_CODE::CANNOT_FIND_EPOCROOT; + project_module.SetEpocRoot( sEpocRoot ); + return project_module.Run(); + case SWITCH_VERSION: + return showVersionInfo(); + case SWITCH_DBGHELP_VERSION: + return showDbgHelpVersionInfo( true ); + case SWITCH_CLEAN: + project_module.SetMode( CATProject::CLEAN ); + if ( CheckSBS2Folder() ) + project_module.SetBuildSystem( CATProject::SBS_V2 ); + else + project_module.SetBuildSystem( CATProject::SBS_V1 ); + return project_module.Run(); + case SWITCH_PARSE_TRACE: + if ( ! parseParseArguments( vArguments, args ) ) + return AT_RETURN_CODE::INVALID_ARGUMENT_ERROR; + if ( CATBase::IsDataFile( args.PARSE.sDataFile ) ) + { + cout << AT_MSG << "Error, " << args.PARSE.sDataFile << " is already parsed." << endl; + return AT_RETURN_CODE::INVALID_ARGUMENT_ERROR; + } + if ( args.PARSE.bOutputFile ) + { + //Save data with name in arguments[3] + Parser.StartParse( args.PARSE.sDataFile.c_str(), args.PARSE.sOutputFile.c_str() ); + } + else + { + Parser.StartParse( args.PARSE.sDataFile.c_str(), NULL ); + } + return AT_RETURN_CODE::OK; + case SWITCH_HELP: + print_help(); + print_syntax_examples(); + return AT_RETURN_CODE::OK; + default: + cout << AT_MSG << "Invalid parameters." << endl; + return AT_RETURN_CODE::INVALID_ARGUMENT_ERROR; + } + + } catch(...) + { + cout << AT_MSG << "Error, unhandled exception." << endl; + return AT_RETURN_CODE::UNHANDLED_EXCEPTION; + } +} + +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/cataddr2line.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/cataddr2line.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,388 @@ +/* +* 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: Main module for addr2line pinpointing. +* +*/ + +#include "../inc/cataddr2line.h" +#include "../inc/CATMemoryAddress.h" +#include "../inc/CATBase.h" +#include "../inc/CATDatParser.h" + +#define ASCII_CHAR_CARRIAGE_RETURN 0x0D + +CATAddr2line::CATAddr2line() +{ + LOG_FUNC_ENTRY("CATAddr2line::CATAddr2line"); +} + +bool CATAddr2line::Open( const string& sParameter, const unsigned long /* iLong */ ) +{ + LOG_FUNC_ENTRY("CATAddr2line::Open"); + //Debugging for addr2line task. + //debug.open( "addr2line-lines.txt", ios_base::trunc ); + + m_sMapFileName.clear(); + // Add .map extendsion + m_sMapFileName.append( sParameter ); + m_sMapFileName.append( ".map" ); + + ReadMapFileArmv5(); + + //Make symfile path+name + string sFullPathToSymFile(sParameter); + sFullPathToSymFile.erase( sFullPathToSymFile.find_last_of( "." ), string::npos ); + sFullPathToSymFile.append( ".sym" ); + + // Check with extension + .sym also. + if ( ! CATBase::FileExists( sFullPathToSymFile.c_str() ) ) + { + sFullPathToSymFile.clear(); + sFullPathToSymFile.append( sParameter ); + sFullPathToSymFile.append( ".sym" ); + } + + return server.Initialize( sFullPathToSymFile ); +} + +string CATAddr2line::GetError( void ) +{ + LOG_FUNC_ENTRY("CATAddr2line::GetError"); + string s; + return s; +} + +bool CATAddr2line::Close( void ) +{ + LOG_FUNC_ENTRY("CATAddr2line::Close"); + //Debugging for addr2line task. + //debug.close(); + return true; +} + +bool CATAddr2line::AddressToLine( CATMemoryAddress* result ) +{ + LOG_FUNC_ENTRY("CATAddr2line::AddressToLine"); + + result->SetAddressToLineState( CATMemoryAddress::OUT_OF_RANGE); + + if( !server.GetProcessCreatedState() ) + return false; + //Count address + ULONG uStartA = result->GetModuleStartAddress(); + ULONG uMemoryA = result->GetAddress(); + ULONG uCountedA = uMemoryA - uStartA; + uCountedA += FUNCTIONS_OFFSET_IN_GCCE; + + string sTemp = CATBase::NumberToHexString( uCountedA ); + //Remove "0x" + size_t iCounter = sTemp.find_first_of('x'); + if( iCounter != string::npos ) + { + sTemp.erase( 0, (int)iCounter+1 ); + } + // Write to pipe that is the standard input for a child process. + server.WriteToPipe( sTemp ); + + // Read from pipe that is the standard output for child process. + string s = server.ReadFromPipe(); + + //If output not empty, parse output + if( !s.empty() ) + { + //Debugging code for addr2line task. + //debug.write( "##########\n", 12 ); + //debug.write( s.c_str(), s.size() ); + result->SetAddressToLineState( CATMemoryAddress::EXACT ); + + string s2; + size_t iLocation = s.find_first_of( ASCII_CHAR_CARRIAGE_RETURN ); + + bool bFunctionNameFoundUsingAddr2line = false; + + //Function name + + if(iLocation != string::npos ) + { + s2 = s.substr( 0, iLocation ); + //All characters ascii? + if( CATBase::IsAscii( s2.c_str(), (int)s2.length() ) ) + { + //addr2line returns $x if function name not found + //length must over 2 to be real function name + if( s2.length() > 2 ) + { + bFunctionNameFoundUsingAddr2line = true; + result->SetFunctionName( s2 ); + s.erase( 0, iLocation+2 ); + } + } + } + //If function name not found using addr2line find it from map file + if( !bFunctionNameFoundUsingAddr2line ) + { + string sFuncName( GetFunctionNameUsingAddress( uCountedA ) ); + //If function name empty, print "???" + if( sFuncName.empty() ) + { + s2 = "???"; + result->SetFunctionName( s2 ); + if(iLocation != string::npos ) + { + s.erase( 0, iLocation+2 ); + } + } + else + result->SetFunctionName( sFuncName ); + } + iLocation = s.find_first_of( ':' ); + + //Filename and location + + if(iLocation != string::npos ) + { + s2 = s.substr( 0, iLocation ); + result->SetFileName( s2 ); + s.erase( 0, iLocation+1 ); + } + + //Exact line number + + s2 = s.substr( 0, s.find_first_of( ASCII_CHAR_CARRIAGE_RETURN ) ); + result->SetExactLineNumber( atoi( s2.c_str() ) ); + } + return true; +} + +bool CATAddr2line::ReadMapFileArmv5() +{ + LOG_FUNC_ENTRY("CATModule2::ReadMapFileArmv5"); + // Open .map file + ifstream in( m_sMapFileName.c_str() ); + // File open ok? + if( ! in.good() ) + { + in.close(); + return false; + } + char cTemp[MAX_LINE_LENGTH]; + bool bFirstFuncFound = false; + bool bFirstLine = true; + // Get all lines where is "Thumb" + do + { + // Load one line from .map file + in.getline( cTemp, MAX_LINE_LENGTH ); + if( bFirstLine ) + { + bFirstLine = false; + if( strstr( cTemp, "ARM Linker" ) == NULL ) + return false; + } + // Find _E32Startup + if( !bFirstFuncFound && ( strstr( cTemp, "_E32Startup" ) != NULL) ) + { + bFirstFuncFound = true; + } + else if( !bFirstFuncFound && ( strstr( cTemp, "_E32Dll" ) != NULL) ) + { + bFirstFuncFound = true; + } + else if( !bFirstFuncFound ) + // Skip if _E32Startup not found + continue; + + if( strstr( cTemp, "Thumb Code" ) != NULL || strstr( cTemp, "ARM Code" ) != NULL) + { + MAP_FUNC_INFO structMapFileLineInfo; + structMapFileLineInfo.sWholeLine.append( cTemp ); + + // Get memory string address from line + char* pStart = strstr( cTemp, "0x" ); + // Check did strstr return null. + if ( pStart == NULL ) + continue; + char* pTemp = pStart; + char TempString[MAX_LINE_LENGTH]; + TempString[0] = 0; + size_t iLength = 0; + while( *pTemp != ' ' ) + { + TempString[iLength] = *pTemp; + pTemp++; + iLength++; + } + TempString[iLength] = 0; + + structMapFileLineInfo.iAddress = CATDatParser::_httoi( TempString ); + + pTemp = cTemp; + TempString[0] = 0; + + // Get function name + + // Skip spaces + while( *pTemp == ' ' ) + { + pTemp++; + } + iLength = 0; + // Find end of function name + string sTemp( pTemp ); + + // Location of character ')' + iLength = sTemp.find_first_of(')'); + + // Location of character ' ' + size_t iLength2 = sTemp.find_first_of(' '); + + // If ')' character is the last char and + // character ' ' is closer than ')' use location of ' ' + if( ( iLength + 1 ) == sTemp.length() && iLength2 < iLength ) + iLength = iLength2 - 1; + + if( iLength != string::npos ) + sTemp.resize( (iLength + 1) ); + + structMapFileLineInfo.sFunctionName.append( sTemp.c_str() ); + + bool bARM = false; + // Find function length + pStart = strstr( cTemp, "Thumb Code" ); + if( pStart == NULL ) + { + pStart = strstr( cTemp, "ARM Code" ); + bARM = true; + } + if( pStart != NULL ) + { + if( bARM ) + pStart += 8; + else + pStart += 10; + while(*pStart == ' ') + { + pStart++; + } + sTemp.clear(); + sTemp.append( pStart ); + size_t iSize = sTemp.find_first_of(' '); + if( iSize != string::npos ) + sTemp.resize( iSize ); + } + + structMapFileLineInfo.iFuncLength = atoi( sTemp.c_str() ); + if( bFirstFuncFound && structMapFileLineInfo.iFuncLength > 0 ) + // Save to list + m_vMapFileFuncList.push_back( structMapFileLineInfo ); + } + } + while( in.good() ); + in.close(); + return true; +} + +// Find function name of given address +string CATAddr2line::GetFunctionNameUsingAddress( unsigned long iAddress ) +{ + LOG_LOW_FUNC_ENTRY("CATAddr2line::GetSymbolIndexUsingAddress"); + string sRet; + for( size_t i = 0; i < m_vMapFileFuncList.size(); i++ ) + { + unsigned long iStart = m_vMapFileFuncList.at( i ).iAddress; + unsigned long iEnd = ( m_vMapFileFuncList.at( i ).iAddress + + m_vMapFileFuncList.at( i ).iFuncLength ); + + if ( iAddress >= iStart && iAddress < iEnd ) + return m_vMapFileFuncList.at( i ).sFunctionName; + } + return sRet; +} + +//Note: New filtering functions commented out until they are taken into use. +/** +* Filter string out of unwanted characters. +*/ +/* +void CATAddr2line::FilterString( string &sString ) +{ + LOG_LOW_FUNC_ENTRY("CATAddr2line::FilterString"); + string sFiltered(""); + for( size_t i = 0 ; i < sString.length() ; i++ ) + { + const char p = sString.at( i ); + if ( p != 0 && strchr( ADDR2LINEALLOWEDCHARS, p ) != 0 ) + sFiltered.push_back( p ); + } + sString = sFiltered; +} +*/ +/** +* Find line feed position from string. +*/ +/* +size_t CATAddr2line::FindLineFeed( const string& sString ) +{ + LOG_LOW_FUNC_ENTRY("CATAddr2line::FindLineFeed"); + size_t iLineFeed1 = sString.find( 12 ); + size_t iLineFeed2 = sString.find( 15 ); + if ( iLineFeed1 < iLineFeed2 && iLineFeed1 != string::npos ) + return iLineFeed1; + else if ( iLineFeed2 != string::npos ) + return iLineFeed2; + else + return string::npos; +} +*/ +/** +* Erase characters from start of the string until other char than linefeed found. +*/ +/* +void CATAddr2line::EraseUntilNoLineFeed( string& sString ) +{ + LOG_LOW_FUNC_ENTRY("CATAddr2line::EraseUntilNoLineFeed"); + for ( size_t i = 0 ; i < sString.length() ; i++ ) + { + if ( sString.at( i ) != 15 && sString.at( i ) != 12 ) + break; + } + sString.erase( 0, i ); +} +*/ +/** +* Split multiple line string with unexpected line feeds to vector of strings. +*/ +/* +vector<string> CATAddr2line::SplitToStrings( string& sMultiLineString ) +{ + LOG_LOW_FUNC_ENTRY("CATAddr2line::SplitToStrings"); + vector<string> vLines; + while ( 1 ) + { + size_t iLineFeed = FindLineFeed( sMultiLineString ); + if ( iLineFeed == string::npos ) + break; + string sCell = sMultiLineString.substr(0, iLineFeed ); + sMultiLineString.erase(0, iLineFeed ); + EraseUntilNoLineFeed( sMultiLineString ); + FilterString( sCell ); + vLines.push_back( sCell ); + } + // If no lines were found set single one. + if ( vLines.size() == 0 ) + vLines.push_back( sMultiLineString ); + return vLines; +} +*/ +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/cataddr2lineserver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/cataddr2lineserver.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,286 @@ +/* +* 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: Class representing a server that uses addr2line.exe. +* +*/ + +#include "../inc/cataddr2lineserver.h" +#include "../inc/CATBase.h" + +// ---------------------------------------------------------------------------- +// Constructor +// ---------------------------------------------------------------------------- +CATAddr2lineServer::CATAddr2lineServer() +{ + LOG_FUNC_ENTRY("CATAddr2lineServer::CATAddr2lineServer"); + m_bProcessCreated = false; + + // Pipe handles. + m_hChildErroutRd = 0; + m_hChildErroutRdDup = 0; + m_hChildErroutWr = 0; + m_hChildStdinRd = 0; + m_hChildStdinWr = 0; + m_hChildStdinWrDup = 0; + m_hChildStdoutRd = 0; + m_hChildStdoutWr = 0; + m_hChildStdoutRdDup = 0; + + m_hSaveErrout = 0; + m_hSaveStdin = 0; + m_hSaveStdout = 0; + + // Set the bInheritHandle flag so pipe handles are inherited. + m_saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + m_saAttr.bInheritHandle = TRUE; + m_saAttr.lpSecurityDescriptor = NULL; + + // Symbol file. + m_sFullPathAndBinaryName = ""; +} +// ---------------------------------------------------------------------------- +// Destructor +// ---------------------------------------------------------------------------- +CATAddr2lineServer::~CATAddr2lineServer() +{ + LOG_FUNC_ENTRY("CATAddr2lineServer::~CATAddr2lineServer"); + // Close the pipe handle so the child process stops reading. + CloseHandle(m_hChildStdinWrDup); + // Close the write end of the pipe + CloseHandle(m_hChildStdoutWr); + // Close the write end of the error pipe + CloseHandle(m_hChildErroutWr); +} +bool CATAddr2lineServer::Initialize( const string& sFullPathAndBinaryName ) +{ + LOG_FUNC_ENTRY("CATAddr2lineServer::Initialize"); + BOOL fSuccess; + m_sFullPathAndBinaryName = sFullPathAndBinaryName; + + // The steps for redirecting child process's STDOUT: + // 1. Save current STDOUT, to be restored later. + // 2. Create anonymous pipe to be STDOUT for child process. + // 3. Set STDOUT of the parent process to be write handle to + // the pipe, so it is inherited by the child process. + // 4. Create a noninheritable duplicate of the read handle and + // close the inheritable read handle. + + // Save the handle to the current STDOUT. + m_hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); + + // Create a pipe for the child process's STDOUT. + if (! CreatePipe(&m_hChildStdoutRd, &m_hChildStdoutWr, &m_saAttr, 0)) + return PrintErrorAndExit( "Stdout pipe creation failed\n" ); + + // Set a write handle to the pipe to be STDOUT. + if (! SetStdHandle(STD_OUTPUT_HANDLE, m_hChildStdoutWr)) + return PrintErrorAndExit( "Redirecting STDOUT failed\n" ); + + // Create noninheritable read handle and close the inheritable read + // handle. + fSuccess = DuplicateHandle(GetCurrentProcess(), m_hChildStdoutRd, + GetCurrentProcess(), &m_hChildStdoutRdDup , 0, + FALSE, + DUPLICATE_SAME_ACCESS); + if( !fSuccess ) + return PrintErrorAndExit( "DuplicateHandle failed" ); + CloseHandle(m_hChildStdoutRd); + + // The steps for redirecting child process's STDIN: + // 1. Save current STDIN, to be restored later. + // 2. Create anonymous pipe to be STDIN for child process. + // 3. Set STDIN of the parent to be the read handle to the + // pipe, so it is inherited by the child process. + // 4. Create a noninheritable duplicate of the write handle, + // and close the inheritable write handle. + + // Save the handle to the current STDIN. + m_hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); + + // Create a pipe for the child process's STDIN. + if (! CreatePipe(&m_hChildStdinRd, &m_hChildStdinWr, &m_saAttr, 0)) + return PrintErrorAndExit( "Stdin pipe creation failed\n" ); + + // Set a read handle to the pipe to be STDIN. + if (! SetStdHandle(STD_INPUT_HANDLE, m_hChildStdinRd)) + return PrintErrorAndExit( "Redirecting Stdin failed\n" ); + + // Duplicate the write handle to the pipe so it is not inherited. + + fSuccess = DuplicateHandle(GetCurrentProcess(), m_hChildStdinWr, + GetCurrentProcess(), &m_hChildStdinWrDup, 0, + FALSE, // not inherited + DUPLICATE_SAME_ACCESS); + if (! fSuccess) + return PrintErrorAndExit( "DuplicateHandle failed\n" ); + + CloseHandle(m_hChildStdinWr); + + // The steps for redirecting child process's ERROUT: + // 1. Save current STDOUT, to be restored later. + // 2. Create anonymous pipe to be STDOUT for child process. + // 3. Set STDOUT of the parent process to be write handle to + // the pipe, so it is inherited by the child process. + // 4. Create a noninheritable duplicate of the read handle and + // close the inheritable read handle. + + // Save the handle to the current STDOUT. + m_hSaveErrout = GetStdHandle( STD_ERROR_HANDLE ); + + // Create a pipe for the child process's ERROUT. + if (! CreatePipe(&m_hChildErroutRd, &m_hChildErroutWr, &m_saAttr, 0)) + return PrintErrorAndExit( "Errout pipe creation failed\n" ); + + // Set a write handle to the pipe to be ERROUT. + if (! SetStdHandle(STD_ERROR_HANDLE, m_hChildErroutWr)) + return PrintErrorAndExit( "Redirecting ERROUT failed\n" ); + + // Create noninheritable read handle and close the inheritable read + // handle. + + fSuccess = DuplicateHandle(GetCurrentProcess(), m_hChildErroutRd, + GetCurrentProcess(), &m_hChildErroutRdDup , 0, + FALSE, + DUPLICATE_SAME_ACCESS); + if( !fSuccess ) + return PrintErrorAndExit( "DuplicateHandle failed" ); + + CloseHandle(m_hChildErroutRd); + CloseHandle(m_hChildErroutRdDup); + + // Now create the child process. + fSuccess = CreateChildProcess(); + if (!fSuccess ) + return PrintErrorAndExit( "Create process failed\n" ); + + // After process creation, restore the saved STDIN and STDOUT. + if (! SetStdHandle(STD_INPUT_HANDLE, m_hSaveStdin)) + return PrintErrorAndExit( "Re-redirecting Stdin failed\n" ); + + if (! SetStdHandle(STD_OUTPUT_HANDLE, m_hSaveStdout)) + return PrintErrorAndExit( "Re-redirecting Stdout failed\n" ); + + if (! SetStdHandle(STD_ERROR_HANDLE, m_hSaveErrout)) + return PrintErrorAndExit( "Re-redirecting Stderrout failed\n" ); + + m_bProcessCreated = true; + return true; +} +BOOL CATAddr2lineServer::CreateChildProcess() +{ + LOG_FUNC_ENTRY("CATAddr2lineServer::CreateChildProcess"); + PROCESS_INFORMATION piProcInfo; + STARTUPINFO siStartInfo; + BOOL bFuncRetn = FALSE; + + // Set up members of the PROCESS_INFORMATION structure. + ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); + + // Set up members of the STARTUPINFO structure. + ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); + siStartInfo.cb = sizeof(STARTUPINFO); + + //atool.exe:s path + filename + char buffer[MAX_PATH]; + + GetModuleFileName( NULL, buffer, MAX_PATH ); + + string sCommand( buffer ); + + //Remove 'atool.exe' + size_t tPos = sCommand.rfind( "\\" ); + if ( tPos != string::npos ) + sCommand.resize( sCommand.rfind( "\\" )+1 ); + else + sCommand.clear(); + + sCommand.append( "addr2line.exe" ); + + //addr2line file exists + if( !CATBase::FileExists( sCommand.c_str() ) ) + return PrintErrorAndExit( "File not found addr2line.exe\n" ); + + //Sym file exists + if( !CATBase::FileExists( m_sFullPathAndBinaryName.c_str() ) ) + { + string sTemp( "File not found " ); + sTemp.append( m_sFullPathAndBinaryName ); + sTemp.append( "\n" ); + return PrintErrorAndExit( sTemp ); + } + + sCommand.append(" -f -C -e "); + sCommand.append( m_sFullPathAndBinaryName ); + + // Create the child process. + bFuncRetn = CreateProcess(NULL, + (LPSTR)sCommand.c_str(), // command line + NULL, // process security attributes + NULL, // primary thread security attributes + TRUE, // handles are inherited + 0, // creation flags + NULL, // use parent's environment + NULL, // use parent's current directory + &siStartInfo, // STARTUPINFO pointer + &piProcInfo); // receives PROCESS_INFORMATION + + if (bFuncRetn == 0) + { + //CreateProcess failed + return false; + } + else + { + CloseHandle(piProcInfo.hProcess); + CloseHandle(piProcInfo.hThread); + return bFuncRetn; + } +} +VOID CATAddr2lineServer::WriteToPipe( const string& sAddress ) +{ + LOG_LOW_FUNC_ENTRY("CATAddr2lineServer::WriteToPipe"); + DWORD dwRead, dwWritten; + CHAR chBuf[2]; //This is for enter key + + //Write data to a pipe. + dwRead = (DWORD)sAddress.length(); + WriteFile(m_hChildStdinWrDup, sAddress.c_str(), dwRead, &dwWritten, NULL); + + chBuf[0] = 0x0A; //Enter + chBuf[1] = 0; //NULL + //Write enter key to a pipe + WriteFile(m_hChildStdinWrDup, chBuf, 1, &dwWritten, NULL); +} +string CATAddr2lineServer::ReadFromPipe(VOID) +{ + LOG_LOW_FUNC_ENTRY("CATAddr2lineServer::ReadFromPipe"); + string s; + DWORD dwRead; + CHAR chBuf[BUFSIZE]; + // Read output from the child process, and save data to string. + ReadFile( m_hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead, NULL); + s.append( chBuf ); + return s; +} +bool CATAddr2lineServer::GetProcessCreatedState( void ) +{ + LOG_LOW_FUNC_ENTRY("CATAddr2lineServer::GetProcessCreatedState"); + return m_bProcessCreated; +} +bool CATAddr2lineServer::PrintErrorAndExit( const string sInput ) +{ + LOG_FUNC_ENTRY("CATAddr2lineServer::PrintErrorAndExit"); + cout << AT_MSG << sInput; + return false; +} diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/catalloc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/catalloc.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,64 @@ +/* +* 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: +* +*/ +#include "../inc/ATCommonDefines.h" +#include "../inc/catalloc.h" + +string CATAlloc::GetAllocString( void ) +{ + LOG_LOW_FUNC_ENTRY("CATAlloc::GetAllocString"); + // Create alloc string + string sLine(""); + sLine.append( m_sTime ); sLine.append(" " ); + sLine.append( m_sSize ); + + // Add all call stack fragments to line. + string sCallStack; + map<unsigned long, string>::iterator it; + for( it = m_vCallStack.begin() ; it != m_vCallStack.end() ; it++ ) + { + sCallStack.append( (*it).second ); + sCallStack.append( " " ); + } + // Remove the last space + if ( sCallStack.size() > 0 ) + sCallStack.erase( sCallStack.size()-1, 1 ); + + if ( m_iCSCount != 0 ) + { + // Check integrity (calculate number of spaces in call stack) + unsigned long iCount = 0; + size_t pos = 0; + while ( pos != string::npos ) + { + iCount++; + pos = sCallStack.find_first_of( ' ', pos+1 ); + } + if ( iCount != m_iCSCount ) + cout << AT_MSG << "Error, integrity check failed in alloc." << endl; + } + + // Add call stack to line. + if ( sCallStack.size() > 0 ) + { + sLine.append(" " ); + sLine.append( sCallStack ); + } + + // return alloc line. + return sLine; +} + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/catallocs.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/catallocs.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,176 @@ +/* +* 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: +* +*/ +#include "../inc/ATCommonDefines.h" +#include "../inc/catallocs.h" + +void CATAllocs::Alloc( const string& sAllocString ) +{ + LOG_LOW_FUNC_ENTRY("CATAllocs::Alloc"); + string sAlloc( sAllocString ); + CATAlloc alloc; + string sAddress = GetStringUntilNextSpace( sAlloc, true ); + alloc.m_sTime = GetStringUntilNextSpace( sAlloc, true ); + alloc.m_sSize = GetStringUntilNextSpace( sAlloc, true ); + alloc.m_vCallStack.insert( pair<unsigned long,string>(1, sAlloc) ); + // Add allocation + pair< map<string,CATAlloc>::iterator, bool> ret; + ret = m_vAllocs.insert( pair<string, CATAlloc>( sAddress, alloc ) ); + if( ret.second == false ) + { + // Allocation to this memory address was already added. + LOG_STRING( "CATAllocs: Allocating same address again, address: " << sAddress ); + } +} + +void CATAllocs::AllocH( const string& sAllocHString ) +{ + LOG_LOW_FUNC_ENTRY("CATAllocs::AllocH"); + string sAllocH( sAllocHString ); + // Parse alloc & create new allocation. + CATAlloc alloc; + string sAddress = GetStringUntilNextSpace( sAllocH, true ); + alloc.m_sTime = GetStringUntilNextSpace( sAllocH, true ); + alloc.m_sSize = GetStringUntilNextSpace( sAllocH, true ); + alloc.m_iCSCount = _httoi( string( GetStringUntilNextSpace( sAllocH, true ) ).c_str() ); + // Insert call stack fragment as "first" 1 because we are header. + if ( alloc.m_iCSCount > 0 ) + alloc.m_vCallStack.insert( pair<unsigned long,string>( 0, sAllocH ) ); + // Add allocation + pair< map<string,CATAlloc>::iterator, bool> ret; + ret = m_vAllocs.insert( pair<string, CATAlloc>( sAddress, alloc ) ); + if( ret.second == false ) + { + // Allocation to this memory address was already added. + LOG_STRING( "CATAllocs: Allocating same address again, address: " << sAddress ); + } +} + +void CATAllocs::AllocF( const string& sAllocFString ) +{ + LOG_LOW_FUNC_ENTRY("CATAllocs::AllocF"); + string sAllocF( sAllocFString ); + string sAddress = GetStringUntilNextSpace( sAllocF, true ); + string sTime = GetStringUntilNextSpace( sAllocF, true ); + unsigned long iNumber = _httoi( string( GetStringUntilNextSpace( sAllocF, true ) ).c_str() ); + string sCallSstack = sAllocF; + // Find correct allocation into which add call stack fragment. + map<string, CATAlloc>::iterator it; + it = m_vAllocs.find( sAddress ); + // TODO: If cannot find, create new in cache. + if ( it == m_vAllocs.end() ) + { + LOG_STRING( "CATAllocs: Allocate fragment without header: " << sAddress ); + return; + } + pair< map<unsigned long,string>::iterator, bool> ret; + // Add call stack to it. + ret = it->second.m_vCallStack.insert( pair<unsigned long,string>( iNumber, sCallSstack ) ); + if( ret.second == false ) + { + LOG_STRING( "CATAllocs: Same allocation fragment again: " << sAddress ); + } +} + +// Free message. +void CATAllocs::Free( const string& sFreeString ) +{ + LOG_LOW_FUNC_ENTRY("CATAllocs::Free"); + string sFree( sFreeString ); + string sKey = GetStringUntilNextSpace( sFree ); + // Find related allocation. + map<string, CATAlloc>::iterator it; + it = m_vAllocs.find( sKey ); + if ( it == m_vAllocs.end() ) + { + LOG_STRING( "CATAllocs: Free message which has no alloc pair: " << sKey ); + return; + } + // Delete it. + m_vAllocs.erase( it ); +} + +// FreeH. +void CATAllocs::FreeH( const string& sFreeH ) +{ + LOG_LOW_FUNC_ENTRY("CATAllocs::FreeH"); + // Current implementation does not use call stack of + // free message to anything. + string sFree( sFreeH ); + string sKey = GetStringUntilNextSpace( sFree ); + // Time stamp. (not used currently) + // Call stack count. (not used currently) + // Call stack data. (not used currently) + + // Find related allocation. + map<string, CATAlloc>::iterator it; + it = m_vAllocs.find( sKey ); + if ( it == m_vAllocs.end() ) + { + LOG_STRING( "CATAllocs: FreeH message which has no alloc pair: " << sKey ); + return; + } + // Delete it. + m_vAllocs.erase( it ); +} + +// FreeF. +void CATAllocs::FreeF( const string& /* sFreeF */ ) +{ + LOG_LOW_FUNC_ENTRY("CATAllocs::FreeF"); + // Fragments are currently ignored. + // Memory address. (not used currently) + // Time stamp. (not used currently) + // Packet number. (not used currently) + // Call stack data. (not used currently) +} + +// Get "leak" list ordered by allocation time. +void CATAllocs::GetLeakList( vector<string>& vLeakList ) +{ + LOG_LOW_FUNC_ENTRY("CATAllocs::GetLeakList"); + + // Create multimap where key is timestamp. + // Add allocations there so they will go ascending order. + multimap<string,string> mmap; + multimap<string,string>::iterator itMmap; + + map<string, CATAlloc>::iterator it; + for( it = m_vAllocs.begin(); it != m_vAllocs.end() ; it++ ) + { + string sTime = it->second.m_sTime; + + string sLine = it->first; + sLine.append(" "); + sLine.append( it->second.GetAllocString() ); + + mmap.insert( pair<string,string>( sTime, sLine ) ); + } + + // Iterate list to parameter vector. + vLeakList.clear(); + for ( itMmap = mmap.begin(); itMmap != mmap.end(); itMmap++ ) + vLeakList.push_back( itMmap->second ); +} + +// Clear alloc data. +void CATAllocs::ClearAllocs( void ) +{ + LOG_LOW_FUNC_ENTRY("CATAllocs::ClearAllocs"); + m_vAllocs.clear(); +} + +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/catdbghelper.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/catdbghelper.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,314 @@ +/* +* 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: Windows debug api implementation for IAddressToLine interface. +* +*/ + +#include "../inc/catdbghelper.h" +#include "../inc/CATBase.h" +#include "../inc/CATMemoryAddress.h" +#include <dbghelp.h> + +/** +* Notes on version number of api functions. +* 5.1 Windows XP +* 5.2 Windows Server 2003 +* 6.8 Debugging Tools for Windows 6.8 +* SymSetOptions DbgHelp.dll 5.1 or later +* SymSetSearchPath DbgHelp.dll 5.1 or later +* SymLoadModuleEx Versions 5.2 and 6.0 +* SymLoadModule64 DbgHelp.dll 5.1 or later +* SymFromAddr Versions 4.0 and 5.1 +* SymGetLineFromAddr64 DbgHelp.dll 5.1 or later +*/ + +// Wrapper class for symbol information package. +struct CSymbolInfo : public SYMBOL_INFO_PACKAGE +{ + CSymbolInfo() + { + si.SizeOfStruct = sizeof( SYMBOL_INFO ); + si.MaxNameLen = sizeof( name ); + } +}; + +// Wrapper class for line information container. +struct CLineInfo : public IMAGEHLP_LINE64 +{ + CLineInfo() + { + SizeOfStruct = sizeof( IMAGEHLP_LINE64 ); + } +}; + +CATDbgHelper::CATDbgHelper() +{ + LOG_FUNC_ENTRY("CATDbgHelper::CDbgHelper"); + // Set the some "default" base address. + m_BaseAddress = 0x2; + m_bMap = false; + m_pBinaryFile = NULL; +} + +CATDbgHelper::~CATDbgHelper() +{ + LOG_FUNC_ENTRY("CATDbgHelper::~CDbgHelper"); + // Close dbghelper only once. + if ( CDBGHELPER_OPEN ) + { + Close(); + } + if ( m_pBinaryFile ) + { + delete[] m_pBinaryFile; + m_pBinaryFile = NULL; + } +} + +bool CATDbgHelper::Open( const string& sParameter, const unsigned long iLong ) +{ + LOG_FUNC_ENTRY("CATDbgHelper::Open"); + // Verify that file exits. Version 5.1.2600.5512 of dbghelp.dll does not correctly + // return error code if missing image file. This can lead upto applicaton crash. + if ( ! CATBase::FileExists( sParameter.c_str() ) ) + { + LOG_STRING( "Missing image file: " << sParameter ); + return false; + } + + // Is it urel try read map? + if ( sParameter.find( "\\urel\\" ) != string::npos ) + { + string sMapFile = sParameter; + sMapFile.append( ".map" ); + ReadMapFile( sMapFile ); + } + + // Set base address used + m_BaseAddress = iLong + AT_VIRTUAL_OFFSET_DBGHELPER; + // Binary file (also referred as symbol). + size_t length = sParameter.length(); + if ( length == 0 ) + { + LOG_STRING("DbgHelp:Invalid binary parameter."); + return false; + } + + char* pChar = new char[ sParameter.length()+1 ]; + strcpy( pChar, sParameter.c_str() ); + // Have to be casted to PSTR before using dbg api. Even tho its typedef same. + // This will avoid access violations bug. + // Note pChar is not deleted because its the member pointer just casted its + // memory allocation freed in destructor. + if ( m_pBinaryFile ) + delete[] m_pBinaryFile; + + m_pBinaryFile = (PSTR) pChar; + + // Initialize dbghelper if not done only once. + if ( ! CDBGHELPER_OPEN ) + { + // Set symbol options + SymSetOptions( SYMOPT_LOAD_LINES | SYMOPT_DEBUG | SYMOPT_UNDNAME | SYMOPT_LOAD_ANYTHING ); + if ( !SymInitialize( GetCurrentProcess(), NULL, TRUE ) ) + { + LOG_STRING("DbgHelp:Error initializing dbghelper " << (int) GetLastError()); + return false; + } + LOG_STRING("DbgHelp:dbghelper opened."); + CDBGHELPER_OPEN = true; + } + + // Set symbol search path. + if ( !SymSetSearchPath( GetCurrentProcess(), NULL ) ) + { + LOG_STRING("DbgHelp:Error setting symbol search path " << (int) GetLastError()); + return false; + } + + // Load module. + DWORD64 ret; + ret = SymLoadModule64( GetCurrentProcess(), NULL, m_pBinaryFile, NULL, m_BaseAddress, NULL ); // 5.1 api version. + if ( ret != m_BaseAddress && ret != 0) + { + LOG_STRING("Dbghelp:Module load failed " << (int) GetLastError()); + return false; + } + CDBGHELPER_CLIENTS++; + return true; +} + +string CATDbgHelper::GetError( void ) +{ + LOG_FUNC_ENTRY("CATDbgHelper::GetError"); + return string("not implemented."); +} + +bool CATDbgHelper::Close( void ) +{ + LOG_FUNC_ENTRY("CATDbgHelper::Close"); + if ( ! SymUnloadModule64( GetCurrentProcess(), m_BaseAddress ) ) + { + LOG_STRING("Dbghelp:Module unload failed."); + } + CDBGHELPER_CLIENTS--; + if ( CDBGHELPER_OPEN && CDBGHELPER_CLIENTS == 0) + { + // Cleanup dbghelper. + if ( ! SymCleanup( GetCurrentProcess() ) ) + { + LOG_STRING("dbghelper cleanup failed."); + return false; + } + LOG_STRING("dbghelper closed."); + // Set state not opened. + CDBGHELPER_OPEN = false; + } + return true; +} + +bool CATDbgHelper::AddressToLine( CATMemoryAddress* result ) +{ + LOG_FUNC_ENTRY("CATDbgHelper::AddressToLine"); + + // Set state out of range + result->SetAddressToLineState( CATMemoryAddress::OUT_OF_RANGE ); + + // check that dbghelper has been initialized successfully. + if ( ! CDBGHELPER_OPEN ) + return false; + + // Check has binary been moved, if so unload and load to new base address. + if ( result->GetModuleStartAddress() + AT_VIRTUAL_OFFSET_DBGHELPER != m_BaseAddress ) + { + // Unload. + if ( SymUnloadModule64( GetCurrentProcess(), m_BaseAddress ) ) + { + // Set new base address. + m_BaseAddress = result->GetModuleStartAddress() + AT_VIRTUAL_OFFSET_DBGHELPER; + // (Re)load. + DWORD64 loading = SymLoadModule64( GetCurrentProcess(), NULL, m_pBinaryFile, NULL, m_BaseAddress, NULL ); + if ( loading != m_BaseAddress && loading != 0) + { + LOG_STRING("Dbghelp:Module load failed " << (int) GetLastError()); + return false; + } + } + else + LOG_STRING("Dbghelp:Module unload failed " << (int) GetLastError() ); + } + // Address to find (offset+given address). + unsigned long iAddressToFind = result->GetAddress() + AT_VIRTUAL_OFFSET_DBGHELPER; + // Displacements of line/symbol information. + DWORD64 displacementSymbol; + DWORD displacementLine; + // Structure to get symbol information. + CSymbolInfo symbol; + // Structure to get line information. + CLineInfo line; + // Find Symbol for given address + if( ! SymFromAddr( GetCurrentProcess(), iAddressToFind , &displacementSymbol, &symbol.si ) ) + { + LOG_STRING("Failed to find symbol information for given line."); + return AddressToFunction( result ); + } + // Find line information + if( ! SymGetLineFromAddr64( GetCurrentProcess(), iAddressToFind, &displacementLine, &line ) ) + { + // If it fails get symbol line information + LOG_STRING("Dbghelp:Failed to find line information for address, trying for symbol of address."); + if( ! SymGetLineFromAddr64( GetCurrentProcess(), symbol.si.Address, &displacementLine, &line ) ) + { + LOG_STRING("Dbghelp:Failed to find line information for symbol address."); + return AddressToFunction( result ); + } + } + // Set the results. + result->SetFileName( string( line.FileName ) ); + result->SetFunctionName( string( symbol.si.Name ) ); + result->SetExactLineNumber( (int) line.LineNumber ); + result->SetAddressToLineState( CATMemoryAddress::EXACT ); + // Return. + return true; +} + +bool CATDbgHelper::AddressToFunction( CATMemoryAddress* result ) +{ + LOG_FUNC_ENTRY("CATDbgHelper::AddressToFunction"); + bool bFound = false; + // If map file read use it and return. + if ( m_bMap ) + { + ULONG uCountedA = result->GetOffSetFromModuleStart(); + for ( vector<MAP_FUNC_INFO>::iterator it = m_vMapFileFuncList.begin() ; it != m_vMapFileFuncList.end() ; it++ ) + { + // Check is this the symbol where address is. + unsigned long iStart = it->iAddress; + unsigned long iEnd = it->iAddress + it->iFuncLength; + if ( uCountedA >= iStart + && uCountedA < iEnd ) + { + result->SetAddressToLineState( CATMemoryAddress::SYMBOL ); + result->SetFunctionName( it->sMangledName ); + bFound = true; + break; + } + } + } + return bFound; +} + +void CATDbgHelper::ReadMapFile( const string sMapFileName ) +{ + LOG_FUNC_ENTRY("CATDbgHelper::ReadMapFile"); + try { + ifstream in( sMapFileName.c_str() ); + if ( ! in.good() ) + { + in.close(); + return; + } + char cLine[MAX_LINE_LENGTH]; + do { + in.getline( cLine, MAX_LINE_LENGTH ); + // Search pattern for 'image ro' symbols is ".text" + string sLine( cLine ); + if ( sLine.find( ".text" ) != string::npos ) + { + MAP_FUNC_INFO symbol; + // Pickup symbol attributes + // Address + string sAddress = CATBase::GetStringUntilNextSpace( sLine, true ); + symbol.iAddress = CATBase::_httoi( sAddress.c_str() ); + // Lenght + string sLength = CATBase::GetStringUntilNextSpace( sLine, true ); + symbol.iFuncLength = CATBase::_httoi( sLength.c_str() ); + // Name + size_t iStart = sLine.find_first_of( '(' ); + size_t iEnd = sLine.find_last_of( ')' ); + if ( iStart != string::npos && iEnd != string::npos ) + { + symbol.sMangledName = sLine.substr( iStart+1, iEnd-iStart-1 ); + // Add symbol to vector + m_vMapFileFuncList.push_back( symbol ); + } + } + } while ( in.good() ); + in.close(); + m_bMap = true; + } catch (...) { + m_bMap = false; + LOG_STRING("DbgHelp: Error reading map file."); + } +} \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/catfilereader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/catfilereader.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,111 @@ +/* +* 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: Class for reading ascii files in AnalyzeTool. +* +*/ + +#include "../inc/ATCommonDefines.h" +#include "../inc/catfilereader.h" + +// ----------------------------------------------------------------------------- +// CATFileReader::CATFileReader +// Constructor. +// ----------------------------------------------------------------------------- +CATFileReader::CATFileReader() +{ + LOG_FUNC_ENTRY("CATFileReader::CATFileReader"); + m_cDelimiter = '\r'; // default line delimeter +} + +// ----------------------------------------------------------------------------- +// CATFileReader::~CATFileReader +// Destructor. +// ----------------------------------------------------------------------------- +CATFileReader::~CATFileReader() +{ + LOG_FUNC_ENTRY("CATFileReader::~CATFileReader"); +} + +// ----------------------------------------------------------------------------- +// CATFileReader::Open +// Open / Read file. +// ----------------------------------------------------------------------------- +bool CATFileReader::Open( const char* cFile ) +{ + LOG_FUNC_ENTRY("CATFileReader::Open"); + if ( strlen( cFile ) < 1 ) + { + LOG_STRING("CATFileReader::Open empty file argument."); + return false; + } + try { + ifstream in; + in.open( cFile, ios::binary ); + if ( ! in.good() ) + return false; + m_stream << in.rdbuf(); + in.close(); + } + catch(...) + { + LOG_STRING("CATFileReader::Open unhandled exception."); + return false; + } + return true; +} + +// ----------------------------------------------------------------------------- +// CATFileReader::Close +// Close file. +// ----------------------------------------------------------------------------- +bool CATFileReader::Close( void ) +{ + LOG_FUNC_ENTRY("CATFileReader::Close"); + return true; +} + +// ----------------------------------------------------------------------------- +// CATFileReader::GetLine +// Get line from file. +// ----------------------------------------------------------------------------- +bool CATFileReader::GetLine( string& sLine ) +{ + //LOG_FUNC_ENTRY("CATFileReader::GetLine"); + char cLine[MAX_LINE_LENGTH]; + if ( !m_stream.good() ) + return false; + m_stream.getline( cLine, MAX_LINE_LENGTH, m_cDelimiter ); m_stream.get(); + sLine = cLine; + return true; +} + +// ----------------------------------------------------------------------------- +// CATFileReader::SetDelimiter +// Set line delimiting character. +// ----------------------------------------------------------------------------- +void CATFileReader::SetDelimiter( char cDelimiter ) +{ + LOG_FUNC_ENTRY("CATFileReader::SetDelimiter"); + m_cDelimiter = cDelimiter; +} + +// ----------------------------------------------------------------------------- +// CATFileReader::GetDelimiter +// Get current line delimiting character. +// ----------------------------------------------------------------------------- +char CATFileReader::GetDelimiter() const +{ + LOG_FUNC_ENTRY("CATFileReader::GetDelimiter()"); + return m_cDelimiter; +} \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/catromsymbol.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/catromsymbol.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,656 @@ +/* +* 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: Reads rom symbol file and provides interface to acquire +* binary and function information using memory addresss. +* +*/ + +#include "../inc/ATCommonDefines.h" +#include "../inc/catromsymbol.h" +#include "../inc/catfilereader.h" +#include "../inc/CATBase.h" +#include "../inc/CATMemoryAddress.h" + +// ----------------------------------------------------------------------------- +// RofsBinary::RofsBinary +// Default construcor +// ----------------------------------------------------------------------------- +RofsBinary::RofsBinary() +{ + LOG_LOW_FUNC_ENTRY("RofsBinary::RofsBinary"); + m_sBinary = ""; + vSymbols.clear(); +} + +// ----------------------------------------------------------------------------- +// RofsBinary::RofsBinary +// Construcor +// ----------------------------------------------------------------------------- +RofsBinary::RofsBinary( const string& sBinary ) +{ + LOG_LOW_FUNC_ENTRY("RofsBinary::RofsBinary"); + m_sBinary = sBinary; + vSymbols.clear(); +} + +// ----------------------------------------------------------------------------- +// RofsBinary::~RofsBinary +// Destructor +// ----------------------------------------------------------------------------- +RofsBinary::~RofsBinary() +{ + LOG_LOW_FUNC_ENTRY("RofsBinary::~RofsBinary"); + for ( vector<Symbol*>::iterator it = vSymbols.begin() ; it != vSymbols.end() ; it++ ) + delete *it; + vSymbols.clear(); +} + +// ----------------------------------------------------------------------------- +// CATRomSymbol::CATRomSymbol +// Constructor. +// ----------------------------------------------------------------------------- +CATRomSymbol::CATRomSymbol() +{ + LOG_FUNC_ENTRY("CATRomSymbol::CATRomSymbol"); + m_bSymbolsRead = false; + m_iRomEndAddress = 0; + m_iRomStartAddress = 0; + m_vRomFiles.clear(); + m_sErrorMessage = ""; + m_vRomCache.clear(); + m_vRomSymbols.clear(); + m_bShowProgressMessages = false; +} + +// ----------------------------------------------------------------------------- +// CATRomSymbol::~CATRomSymbol +// Destructor. +// ----------------------------------------------------------------------------- +CATRomSymbol::~CATRomSymbol() +{ + LOG_FUNC_ENTRY("CATRomSymbol::~CATRomSymbol"); + // Rom + for ( vector<Symbol*>::iterator it = m_vRomSymbols.begin() ; it != m_vRomSymbols.end() ; it++ ) + { + delete *it; + } + m_vRomSymbols.clear(); + // Rofs + for ( vector<RofsBinary*>::iterator it = m_vRofsBinaries.begin() ; it != m_vRofsBinaries.end() ; it++ ) + { + delete *it; + } + m_vRofsBinaries.clear(); +} + +// ----------------------------------------------------------------------------- +// CATRomSymbol::Open +// This funtion should not be used anymore since +// we support multiple rom/rofs files. +// ----------------------------------------------------------------------------- +bool CATRomSymbol::Open( const string& /*sString*/, const unsigned long /*iLong*/) +{ + LOG_FUNC_ENTRY("CATRomSymbol::Open"); + return false; +} + +// ----------------------------------------------------------------------------- +// CATRomSymbol::SetSymbols +// Set symbol file(s) to be used. +// This also checks that files exists and identifies them as rom/rofs. +// ----------------------------------------------------------------------------- +bool CATRomSymbol::SetSymbols( const vector<string>& vSymbols ) +{ + LOG_FUNC_ENTRY("CATRomSymbol::SetSymbols"); + bool ok = true; + // Check no same symbol defined twice. + for( vector<string>::const_iterator it = vSymbols.begin() ; + it != vSymbols.end(); it++ ) + { + for( vector<string>::const_iterator it2 = vSymbols.begin() ; + it2 != vSymbols.end(); it2++ ) + { + if ( it == it2 ) + continue; + if ( _stricmp( (*it).c_str(), (*it2).c_str() ) == 0 ) + { + m_sErrorMessage.append( "Same symbol file defined twice (" ); + m_sErrorMessage.append( (*it) ); + m_sErrorMessage.append( ")\n" ); + return false; + } + } + } + // Loop given symbol files. + for( vector<string>::const_iterator it = vSymbols.begin() ; + it != vSymbols.end(); it++ ) + { + // Symbol file exists? + if ( ! CATBase::FileExists( (*it).c_str() ) ) + { + ok = false; + m_sErrorMessage.append( "Symbol file does not exists (" ); + m_sErrorMessage.append( *it ); + m_sErrorMessage.append( ").\n"); + continue; + } + // Identify symbol file. + int type = IdentifySymbolFile( *it ); + // Depending on type move it correct vector. + switch( type ) + { + case SYMBOL_FILE_INVALID: + ok = false; + m_sErrorMessage.append( "Symbol file with invalid content (" ); + m_sErrorMessage.append( *it ); + m_sErrorMessage.append( ").\n"); + break; + case SYMBOL_FILE_ROM: + m_vRomFiles.push_back( *it ); + break; + case SYMBOL_FILE_ROFS: + m_vRofsFiles.push_back( *it ); + break; + default: + ok = false; + LOG_STRING("IdentifySymbolFile returned unknown type."); + break; + } + } + if ( ok ) + { + // Read symbols. + if ( m_vRomFiles.size() > 0 ) + { + if ( ! ReadRomFiles() ) + ok = false; + else + m_bSymbolsRead = true; + } + if ( m_vRofsFiles.size() > 0 ) + { + if ( ! ReadRofsFiles() ) + ok = false; + else + m_bSymbolsRead = true; + } + } + return ok; +} + +// ----------------------------------------------------------------------------- +// CATRomSymbol::IdentifySymbolFile +// Identify given file is it rom / rofs. +// ----------------------------------------------------------------------------- +int CATRomSymbol::IdentifySymbolFile( const string& sFile ) +{ + LOG_FUNC_ENTRY("CATRomSymbol::IdentifySymbolFile"); + // Set type as invalid. + int iType = SYMBOL_FILE_INVALID; + // Line counter. + int iLineCount = 0; + // Minimun line length to identify it. + size_t iLineMinLength = MAX_LINE_LENGTH; + if ( ROFS_SYMBOL_IDENTIFY_STRING.length() > ROM_SYMBOL_IDENTIFY_STRING.length() ) + iLineMinLength = ROFS_SYMBOL_IDENTIFY_STRING.length(); + else + iLineMinLength = ROM_SYMBOL_IDENTIFY_STRING.length(); + try { + ifstream in; + in.open( sFile.c_str(), ios::in ); + if ( ! in.good() ) + return SYMBOL_FILE_INVALID; + char cLine[MAX_LINE_LENGTH]; + do { + // Dont read too many lines. (File might be contain invalid data). + iLineCount++; + if ( iLineCount > IDENTIFY_MAX_LINES_READ ) + break; + + // Get line -> string. + in.getline( cLine, MAX_LINE_LENGTH ); + string sLine(cLine); + + // Check its not too short. + if( sLine.length() < iLineMinLength ) + continue; + + // Take substring from start of line to identify it to rofs/rom. + if ( ! sLine.substr( 0, ROFS_SYMBOL_IDENTIFY_STRING.length() ).compare( ROFS_SYMBOL_IDENTIFY_STRING ) ) + { + iType = SYMBOL_FILE_ROFS; + break; + } + else if ( ! sLine.substr( 0, ROM_SYMBOL_IDENTIFY_STRING.length() ).compare( ROM_SYMBOL_IDENTIFY_STRING ) ) + { + iType = SYMBOL_FILE_ROM; + break; + } + } while ( in.good() ); + in.close(); + } + catch(...) + { + LOG_STRING("CATRomSymbol::IdentifySymbolFile unhandled exception."); + } + return iType; +} + +// ----------------------------------------------------------------------------- +// CATRomSymbol::ReadRomFiles +// Reads rom file(s) and creates symbols to vector. +// ----------------------------------------------------------------------------- +bool CATRomSymbol::ReadRomFiles() +{ + LOG_FUNC_ENTRY("CATRomSymbol::ReadRomFile"); + + // Clear symbols. + for ( vector<Symbol*>::iterator it = m_vRomSymbols.begin() ; it != m_vRomSymbols.end() ; it++ ) + { + delete *it; + } + m_vRomSymbols.clear(); + + // Clear cache. note cache is just pointers dont delete them. + m_vRomCache.clear(); + + // Any errors? + bool ok = true; + + for( vector<string>::iterator it = m_vRomFiles.begin(); + it != m_vRomFiles.end() ; it++ ) + ok = ReadRomFile( *it ); + + // If size smaller than 1 it is not good rom file(s). + if ( m_vRomSymbols.size() < 1 || ok != true) + return false; + + // Rom start and end addresses. + m_iRomStartAddress = (*m_vRomSymbols.begin())->iStartAddress; + m_iRomEndAddress = (*m_vRomSymbols.rbegin())->iEndAddress; + return true; +} + +// ----------------------------------------------------------------------------- +// CATRomSymbol::ReadRofsFiles +// Read rofs files. +// ----------------------------------------------------------------------------- +bool CATRomSymbol::ReadRofsFiles() +{ + LOG_FUNC_ENTRY("CATRomSymbol::ReadRofsFiles"); + // Clear. + for ( vector<RofsBinary*>::iterator it = m_vRofsBinaries.begin() ; it != m_vRofsBinaries.end() ; it++ ) + { + delete *it; + } + m_vRofsBinaries.clear(); + + // Any errors? + bool ok = true; + + for( vector<string>::iterator it = m_vRofsFiles.begin(); + it != m_vRofsFiles.end() ; it++ ) + ok = ReadRofsFile( *it ); + + // If size smaller than 1 it is not good rofs file(s). + if ( m_vRofsBinaries.size() < 1 || ok != true) + return false; + return true; +} + +// ----------------------------------------------------------------------------- +// CATRomSymbol::ReadRomFile +// Read given rom file +// ----------------------------------------------------------------------------- +bool CATRomSymbol::ReadRomFile( const string& sFile ) +{ + LOG_FUNC_ENTRY("CATRomSymbol::ReadRomfile"); + // Open rom file. + CATFileReader* reader = new CATFileReader(); + // Show progress message if flag set. + if ( m_bShowProgressMessages ) + cout << AT_MSG << "Reading rom symbol file: " << sFile << "..." << endl; + if ( ! reader->Open( sFile.c_str() ) ) + { + reader->Close(); + delete reader; + return false; + } + + // Show progress message if flag set. + if ( m_bShowProgressMessages ) + cout << AT_MSG << "Parsing rom symbol file: " << sFile << "..." << endl; + + // Loop thrue lines. + string sLine(""); + string sBinary(""); + while( reader->GetLine( sLine ) ) + { + // From rom we just read symbols that have lenght, no need to separate them into diff binaries. + try { + if ( sLine.size() < 2 ) + { + continue; + } + else if ( sLine.at(0) == '8' ) + { + // Create new item. + Symbol* symbol = new Symbol(); + ParseSymbolFromLine( sLine, symbol); + // Ignore symbols which have same start & end address (zero length). + if ( symbol->iStartAddress != symbol->iEndAddress ) + m_vRomSymbols.push_back( symbol ); + else + delete symbol; + } + } catch(...) + { + // Catch all possible exception here so analyze will succeed even rom file invalid. + m_sErrorMessage.append( "Unhandled exception parsing rom symbol file.\n" ); + // Close and delete reader. + reader->Close(); + delete reader; + return false; + } + } + // Close and delete reader. + reader->Close(); + delete reader; + return true; +} + +// ----------------------------------------------------------------------------- +// CATRomSymbol::ReadRofsFile +// Read given rofs file +// ----------------------------------------------------------------------------- +bool CATRomSymbol::ReadRofsFile( const string& sFile ) +{ + LOG_FUNC_ENTRY("CATRomSymbol::ReadRofsFile"); + // open/read rofs file. + CATFileReader* reader = new CATFileReader(); + // Show progress message if flag set. + if ( m_bShowProgressMessages ) + cout << AT_MSG << "Reading rofs symbol file: " << sFile << "..." << endl; + if ( ! reader->Open( sFile.c_str() ) ) + { + reader->Close(); + delete reader; + return false; + } + + // Show progress message if flag set. + if ( m_bShowProgressMessages ) + cout << AT_MSG << "Parsing rofs symbol file: " << sFile << "..." << endl; + + // Loop thrue lines. + string sLine(""); + string sBinary(""); + RofsBinary* rb = NULL; + while( reader->GetLine( sLine ) ) + { + try { + if ( sLine.size() < 2 ) + { + continue; + } + else if ( sLine.at(0) == 'F' ) + { + if ( rb != NULL ) + { + // Check last binary if no symbols in it dont add it. + if ( rb->vSymbols.size() == 0 ) + { + delete rb; + rb = NULL; + } + else + m_vRofsBinaries.push_back( rb ); + } + // new binary name. + size_t i = sLine.rfind("\\"); + sLine.erase(0, i+1); + rb = new RofsBinary( sLine ); + + } + else if ( sLine.at(0) == '0' ) + { + // Cannot pickup symbols if no binary defined. + if ( rb == NULL ) + continue; + // Create new item. + Symbol* symbol = new Symbol(); + ParseSymbolFromLine( sLine, symbol); + // Ignore symbols which have same start & end address (zero length). + if ( symbol->iStartAddress != symbol->iEndAddress ) + rb->vSymbols.push_back( symbol ); + else + delete symbol; + } + } catch(...) + { + // Catch all possible exception here so analyze will succeed even rofs file invalid. + m_sErrorMessage.append( "Unhandled exception parsing rofs symbol file.\n" ); + // Close and delete reader. + reader->Close(); + delete reader; + return false; + } + } + // Last added binary. + if ( rb != NULL ) + { + if ( rb->vSymbols.size() == 0 ) + { + delete rb; + rb = NULL; + } + else + m_vRofsBinaries.push_back( rb ); + } + // Close and delete reader. + reader->Close(); + delete reader; + return true; +} + +// ----------------------------------------------------------------------------- +// CATRomSymbol::ParseSymbolFromLine +// Parses given line into given symbol. +// ----------------------------------------------------------------------------- +void CATRomSymbol::ParseSymbolFromLine( const string& sLine, Symbol* pSymbol ) +{ + LOG_LOW_FUNC_ENTRY("CATRomSymbol::ParseSymbolFromLine"); + if ( pSymbol == NULL ) + return; + size_t s,x; + string temp; + // address. + x = sLine.find( ' ' ); + temp = sLine.substr( 0, x ); + pSymbol->iStartAddress = CATBase::_httoi( temp.c_str() ); + // "Erase spaces" move starting point. + s = x; + s = sLine.find_first_not_of( ' ', s ); + // length. + x = sLine.find( ' ', s ); + temp = sLine.substr(s,x-s); + unsigned long length = CATBase::_httoi( temp.c_str() ); + pSymbol->iEndAddress = pSymbol->iStartAddress + length; + // "Erase spaces" move starting point. + s = x; + s = sLine.find_first_not_of( ' ', s); + // function. Function might have spaces so we find 2 spaces which indicates end of it. + x = sLine.find( " ", s ); + temp = sLine.substr( s, x-s ); + pSymbol->sFunction = temp; +} + +// ----------------------------------------------------------------------------- +// CATRomSymbol::GetError +// Get error string if error occured in other methods. +// ----------------------------------------------------------------------------- +string CATRomSymbol::GetError( void ) +{ + LOG_FUNC_ENTRY("CATRomSymbol::GetError"); + return m_sErrorMessage; +} + +// ----------------------------------------------------------------------------- +// CATRomSymbol::Close +// Close (stop using). +// ----------------------------------------------------------------------------- +bool CATRomSymbol::Close( void ) +{ + LOG_FUNC_ENTRY("CATRomSymbol::Close"); + return true; +} + +// ----------------------------------------------------------------------------- +// CATRomSymbol::AddressToLine +// Try locate binary and function name for given memory address. +// ----------------------------------------------------------------------------- +bool CATRomSymbol::AddressToLine( CATMemoryAddress* result ) +{ + LOG_LOW_FUNC_ENTRY("CATRomSymbol::AddressToLine"); + // Have symbols been read. + if ( ! m_bSymbolsRead ) + return false; + // check that its lenght > 2 + if ( result->GetAddressString().size() < 2 ) + return false; + /* Check first is address in range of rom */ + if ( result->GetAddress() < m_iRomStartAddress + || result->GetAddress() > m_iRomEndAddress ) + { + return AddressToLineRofs( result ); + } + return AddressToLineRom( result ); +} + +// ----------------------------------------------------------------------------- +// CATRomSymbol::AddressToLineRom +// Locate function from rom address range. +// ----------------------------------------------------------------------------- +bool CATRomSymbol::AddressToLineRom( CATMemoryAddress* result ) +{ + LOG_LOW_FUNC_ENTRY( "CATRomSymbol::AddressToLineRom" ); + // Address to find in integer & string. + unsigned long iAddressToFind = result->GetAddress(); + string sAddressToFind = result->GetAddressString(); + + // Find symbol. + Symbol* pFound = NULL; + + // Check from cache first. + vector<Symbol*>::iterator it; + for ( it = m_vRomCache.begin(); it != m_vRomCache.end(); it++ ) + { + if ( iAddressToFind >= (*it)->iStartAddress + && (*it)->iEndAddress > iAddressToFind ) + { + pFound = *it; + break; + } + } + + if ( pFound == NULL ) + { + // From all symbols. + bool reverse = false; + int offSetFromStart = iAddressToFind - m_iRomStartAddress; + int offSetFromEnd = m_iRomEndAddress - iAddressToFind; + if ( offSetFromEnd < offSetFromStart ) + reverse = true; + + if ( reverse ) + { + // Iterate vector in reverse. + vector<Symbol*>::reverse_iterator it; + for ( it = m_vRomSymbols.rbegin(); it != m_vRomSymbols.rend(); ++it ) + { + if ( iAddressToFind >= (*it)->iStartAddress + && (*it)->iEndAddress > iAddressToFind ) + { + pFound = *it; + break; + } + } + } + else + { + // Iterate vector normal direction. + vector<Symbol*>::iterator it; + for ( it = m_vRomSymbols.begin(); it != m_vRomSymbols.end(); it++ ) + { + if ( iAddressToFind >= (*it)->iStartAddress + && (*it)->iEndAddress > iAddressToFind ) + { + pFound = *it; + break; + } + } + } + } + + // Set result if found. + if ( pFound != NULL ) + { + result->SetFunctionName( pFound->sFunction ); + result->SetAddressToLineState( CATMemoryAddress::SYMBOL ); + // Add found symbols pointer to cache. + m_vRomCache.push_back( pFound ); + return true; + } + return false; +} + +// ----------------------------------------------------------------------------- +// CATRomSymbol::AddressToLineRofs +// Locate function from rofs address range. +// ----------------------------------------------------------------------------- +bool CATRomSymbol::AddressToLineRofs( CATMemoryAddress* result) +{ + LOG_LOW_FUNC_ENTRY("CATRomSymbol::AddressToLineRofs"); + // Check that binary name is defined in memory address. + string sBinary = result->GetModuleName(); + if ( sBinary.empty() ) + return false; + // Try find that named module. + vector<RofsBinary*>::iterator rofs = m_vRofsBinaries.begin(); + while( rofs != m_vRofsBinaries.end() ) + { + if ( (*rofs)->m_sBinary.compare( sBinary ) == 0 ) + break; + rofs++; + } + if ( rofs == m_vRofsBinaries.end() ) + return false; + + // Offset what we are looking from binary + unsigned long offSet = result->GetAddress(); + offSet -= result->GetModuleStartAddress(); + for( vector<Symbol*>::iterator it = (*rofs)->vSymbols.begin() ; + it != (*rofs)->vSymbols.end(); it++ ) + { + if ( (*it)->iStartAddress <= offSet && offSet < (*it)->iEndAddress ) + { + result->SetFunctionName( (*it)->sFunction ); + result->SetAddressToLineState( CATMemoryAddress::SYMBOL ); + return true; + } + } + return false; +} + +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/helps.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/helps.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,180 @@ +/* +* 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: Contains help texts for CLE. +* +*/ +#include "../inc/ATCommonDefines.h" + +//Function declarations +void print_help( void ); +void print_syntax_examples( void ); + +/** +* Print help info. +*/ +void print_help( void ) +{ + cout<< "AnalyzeTool v"; + cout<< ATOOL_VERSION; + cout<< " - "; + cout<< ATOOL_DATE; + cout<< "\n"; + cout<< "Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).\nAll rights reserved.\n\n"; + cout<< "Usage:\n"; + cout<< "atool -e [optional parameters] abld [abld parameters]\n"; + cout<< " -me [optional parameters] abld [abld parameters]\n"; + cout<< " -mi [optional parameters] [-f data-file] sbs [sbs parameters]\n"; + cout<< " -a data-file [output-file] [-s symbol-file] [-l#]\n"; + cout<< " -p data-file output-file\n"; + cout<< " -c\n"; + cout<< " -v\n"; + cout<< " -help\n"; + cout<< "\n"; + cout<< "Mandatory parameter to choose:\n"; + cout<< " -e Build project for analysis using external data gathering.\n"; + cout<< " -me Build project for analysis using monitored external\n"; + cout<< " data gathering.\n"; + cout<< " -mi Build project for analysis using monitored internal\n"; + cout<< " data gathering.\n"; + cout<< " abld... Use SBS v.1 build system with defined build command,\n"; + cout<< " which includes supported platform and build type.\n"; + cout<< " sbs... Use SBS v.2 (Raptor) build system with defined sbs build\n"; + cout<< " command, which includes supported platform and build type.\n"; + cout<< " -a Analyze report file.\n"; + cout<< " -c Clear AnalyzeTool changes, temporary files and releasable(s).\n"; + cout<< " -p Parse trace file to data file.\n"; + cout<< " -help Show full help including syntax examples.\n"; + cout<< " -v Print version info.\n"; + cout<< "\n"; + + cout<< "Optional parameters:\n"; + cout<< " -acs size Specifies the call stack size gathered when memory\n"; + cout<< " is allocated. Size can be between 0-256.\n"; + cout<< " -fcs size Specifies the call stack size gathered when memory is freed.\n"; + cout<< " Size can be between 0-256.\n"; + cout<< " -f data file Specifies the filename for monitored internal data gathering\n"; + cout<< " (50 chars max). Cannot contain path.\n"; + cout<< " output-file Specifies the results data file name.\n"; + cout<< " -l Logging level of analyze report(0,1,2,3), default 3.\n"; + cout<< " -s symbol-file Specifies rom/rofs symbol file(s) to be used in analyze.\n"; + cout<< " Multiple -s options can be given.\n"; + cout<< " -nobuild Instruments the project.\n"; + //cout<< " -show_debug Print debug messages to console.\n"; + //cout<< " -show_debug_all Print debug messages to console (all).\n"; + //cout<< " -show_dbgview Print debug messages to windows debug api.\n"; + //cout<< " -show_dbgview_all Print debug messages to windows debug api (all).\n"; + + /* + * Old style parameters, just for notes. + printf("Usage:\n"); + printf("atool -m [mmp-file] [mode] [data-file] [-variant variant-name] [build] [-sbs2] [-e]\n"); + printf(" -i [mmp-file] [mode] [data-file] [-variant variant-name] [build] [-sbs2] [-e]\n"); + printf(" -a [mmp-file | target-name] data-file [-s symbol-file]\n"); + printf(" [output-file] [-l#]\n"); + printf(" -p data-file [output-file]\n"); + printf(" -c\n"); + //printf(" -u\n"); + printf(" -v\n"); + printf(" -help\n"); + printf("\n"); + printf("Mandatory option to choose:\n"); + printf(" -m Build project for analysis.\n"); + printf(" -i Instrument project.\n"); + printf(" -a Analyze report file.\n"); + //printf(" -u Create listing & map files.\n"); + printf(" -c Clear AnalyzeTool changes and temporary files.\n"); + printf(" -p Parse trace file.\n"); + printf(" -help Show full help including syntax examples.\n"); + printf("\n"); + + printf("Optional options:\n"); + printf(" mmp-file Specifies one of the component from bld.inf which is used.\n"); + printf(" target-name Specifies the target name of binary to which create\n"); + printf(" analyze report.\n"); + printf(" mode Logging mode (trace or S60), default trace.\n"); + printf(" data-file Specifies the user defined data file name (50 chars max).\n"); + printf(" build Build target (udeb or urel), default udeb.\n"); + printf(" output-file Specifies the results data file name.\n"); + printf(" -l Logging level of analyze report(0,1,2,3), default 3.\n"); + printf(" -variant Specifies Symbian binary variant to be used.\n"); + printf(" variant-name Specifies the variant name to be used.\n"); + printf(" -s Specifies rom symbol file be used in analyze.\n"); + printf(" symbol-file Full path to rom symbol file used in analyze.\n"); + printf(" -sbs2 Use Symbian Build System v.2.\n"); + printf(" -winscw Build project for emulator (winscw platform).\n"); + printf(" -v Print version info.\n"); + */ +} + +void print_syntax_examples( void ) +{ +//Helper line showing width of 80 chars. +//80cout<< "12345678901234567890123456789012345678901234567890123456789012345678901234567890"; + cout<< endl; + cout<< "Building syntax examples:" << endl; + cout<< "Cmd Description" << endl; + + cout<< "atool -e abld build armv5 udeb" << endl; + cout<< " Hooks every component from bld.inf. Using external data gathering," << endl; + cout<< " udeb build type and armv5 platform." << endl; + + cout<< "atool -mi -acs 5 sbs -c winscw_udeb" << endl; + cout<< " Hooks every component from bld.inf. Using Symbian Build System v.2" << endl; + cout<< " Using monitored internal data gathering, call stack size of 5" << endl; + cout<< " in allocations, udeb build type and winscw platform." << endl; + + cout<< "atool -me abld build armv5 udeb foobar" << endl; + cout<< " Hooks only foobar.mmp component from bld.inf. Using monitored" << endl; + cout<< " external data gathering, udeb build type and armv5 platform." << endl; + + cout<< "atool -e -acs 0 -fcs 0 abld build armv5.default udeb" << endl; + cout<< " Hooks every component from bld.inf. Using default binary variant," << endl; + cout<< " external data gathering, 0 sized callstacks in allocation(s)/free(s)," << endl; + cout<< " udeb build type and armv5 platform." << endl; + + cout<< "atool -e sbs -b bld.inf -c armv5_udeb" << endl; + cout<< " Hooks every component from bld.inf. Using Symbian Build System v.2" << endl; + cout<< " , external data gathering, udeb build type and armv5 platform." << endl; + + cout<< "atool -me sbs -s system.xml --config=winscw_udeb" << endl; + cout<< " Hooks every layer defined in system.xml system model. Using Symbian Build" << endl; + cout<< " System v.2, external data gathering, udeb build type and winscw platform." << endl; + + cout<< endl; + cout<< "Instrumenting syntax examples:" << endl; + cout<< "Cmd Description" << endl; + cout<< "atool -e -nobuild abld build winscw udeb" << endl; + cout<< " Instruments every component from bld.inf. Using external data gathering,"<<endl; + cout<< " udeb build target and winscw platform." << endl; + cout<< " After project is instrumented, it needs to compiled using same platform and" << endl; + cout<< " build type as given to instrumenting. Use -c parameter to remove changes." << endl; + + cout<< endl; + cout<< "Analyzing syntax examples:" << endl; + cout<< "Cmd Description" << endl; + cout<< "atool -a foo.dat" << endl; + cout<< " Create analyze report from foo.dat device data file." << endl; + cout<< "atool -a foo.trace" << endl; + cout<< " Create analyze report from foo.trace raw data file." << endl; + cout<< "atool -a foo.dat -s my_rom.symbol -s my_rofs1.symbol" << endl; + cout<< " Create analyze report from foo.dat using also rom and rofs symbol files." << endl; + + cout<< endl; + cout<< "Parsing syntax examples:" << endl; + cout<< "Cmd Description" << endl; + cout<< "atool -p foo.trace foo.dat" << endl; + cout<< " Parse foo.trace raw data file to foo.dat device data file." << endl; + } + +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/librarychecks.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/librarychecks.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,193 @@ +/* +* 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: Contains functions to check AT libraries. +* +*/ +#include "../inc/ATCommonDefines.h" +#include "../inc/CATBase.h" + +// Function declarations +bool CheckATLibrariesArmv5( string sEpocRoot ); +bool CheckATLibrariesArmv5Abiv2( string sEpocRoot ); +bool CheckATLibrariesWinscw( string sEpocRoot ); + +// Error msg to user if missing lib +const char cMissingAToolLibs[] = "\nCan not find AnalyzeTool libraries from current SDK\n\nInstall libraries first\n"; + +// List of libraries what AnalyzeTool needs when compiled applications on armv5 platform +const string cAToolLibsArmv5[] = { + "epoc32\\RELEASE\\armv5\\LIB\\AToolMemoryHook.lib", + "epoc32\\RELEASE\\armv5\\udeb\\AtoolStaticLib.lib", + "epoc32\\RELEASE\\armv5\\urel\\AtoolStaticLib.lib" +}; + +// List of libraries what AnalyzeTool needs when compiled applications on armv5 platform (using sbs2 / ABIV2 binaries) +const string cAToolLibsArmv5Abiv2[] = { + "epoc32\\RELEASE\\armv5\\LIB\\AToolMemoryHook.dso", + "epoc32\\RELEASE\\armv5\\udeb\\AtoolStaticLib.lib", + "epoc32\\RELEASE\\armv5\\urel\\AtoolStaticLib.lib" +}; + +// List of libraries what AnalyzeTool needs when compiled applications on winscw platform +const string cAToolLibsWinscw[] = { + "epoc32\\RELEASE\\winscw\\udeb\\AToolMemoryHook.lib", + "epoc32\\RELEASE\\winscw\\udeb\\AtoolStaticLib.lib", + "epoc32\\RELEASE\\winscw\\urel\\AtoolStaticLib.lib" +}; + +/** +* CheckATLibrariesArmv5 +* Checks that armv5 libraries are in sEpocRoot +* @param sEpocRoot, epoc root where to search libs +* @return bool true if they are found otherwise false +*/ +bool CheckATLibrariesArmv5(string sEpocRoot ) +{ + LOG_FUNC_ENTRY("CheckATLibrariesArmv5"); + + // check that epocroot is set + if ( sEpocRoot.length() <= 0 ) + { + LOG_FUNC_EXIT("CheckATLibrariesArmv5 Error, EpocRoot not set"); + return false; + } + + // add trailing '\' if root path is missing it + if ( sEpocRoot.at( sEpocRoot.length() -1 ) != '\\' ) + sEpocRoot.append( "\\" ); + + // return boolean value + bool bReturn = true; + + int arraySize = sizeof( cAToolLibsArmv5 ) / sizeof( string ); + for ( int i=0 ; i < arraySize ; i++ ) + { + // append epocroot to file + string sFileToCheck = sEpocRoot; + sFileToCheck.append( cAToolLibsArmv5[i] ); + // check does it exists + if ( ! CATBase::FileExists( sFileToCheck.c_str() ) ) + { + bReturn = false; + cout << AT_MSG << "Missing library file: " << sFileToCheck << endl; + LOG_STRING("Missing library file: " << sFileToCheck); + } + } + + if ( ! bReturn ) + { + // print error msg to user + cout << cMissingAToolLibs; + + } + return bReturn; +} + +/** +* CheckATLibrariesArmv5Abiv2 +* Checks that armv5 abiv2 libraries are in sEpocRoot +* @param sEpocRoot, epoc root where to search libs +* @return bool true if they are found otherwise false +*/ +bool CheckATLibrariesArmv5Abiv2(string sEpocRoot ) +{ + LOG_FUNC_ENTRY("CheckATLibrariesArmv5Abiv2"); + + // check that epocroot is set + if ( sEpocRoot.length() <= 0 ) + { + LOG_FUNC_EXIT("CheckATLibrariesArmv5Abiv2 Error, EpocRoot not set"); + return false; + } + + // add trailing '\' if root path is missing it + if ( sEpocRoot.at( sEpocRoot.length() -1 ) != '\\' ) + sEpocRoot.append( "\\" ); + + // return boolean value + bool bReturn = true; + + int arraySize = sizeof( cAToolLibsArmv5Abiv2 ) / sizeof( string ); + for ( int i=0 ; i < arraySize ; i++ ) + { + // append epocroot to file + string sFileToCheck = sEpocRoot; + sFileToCheck.append( cAToolLibsArmv5Abiv2[i] ); + // check does it exists + if ( ! CATBase::FileExists( sFileToCheck.c_str() ) ) + { + bReturn = false; + cout << AT_MSG << "Missing library file: " << sFileToCheck << endl; + LOG_STRING("Missing library file: " << sFileToCheck); + } + } + + if ( ! bReturn ) + { + // print error msg to user + cout << cMissingAToolLibs; + + } + return bReturn; +} + +/** +* CheckATLibrariesWinscw +* Checks that winscw libraries are in sEpocRoot +* @param sEpocRoot, epoc root where to search libs +* @return bool true if they are found otherwise false +*/ +bool CheckATLibrariesWinscw(string sEpocRoot ) +{ + LOG_FUNC_ENTRY("CheckATLibrariesWinscw"); + + // check that epocroot is set + if ( sEpocRoot.length() <= 0 ) + { + LOG_FUNC_EXIT("CheckATLibrariesArmv5Abiv2 Error, EpocRoot not set"); + return false; + } + + // add trailing '\' if root path is missing it + if ( sEpocRoot.at( sEpocRoot.length() -1 ) != '\\' ) + sEpocRoot.append( "\\" ); + + // return boolean value + bool bReturn = true; + + int arraySize = sizeof( cAToolLibsWinscw ) / sizeof( string ); + for ( int i=0 ; i < arraySize ; i++ ) + { + // append epocroot to file + string sFileToCheck = sEpocRoot; + sFileToCheck.append( cAToolLibsWinscw[i] ); + // check does it exists + if ( ! CATBase::FileExists( sFileToCheck.c_str() ) ) + { + bReturn = false; + cout << AT_MSG << "Missing library file: " << sFileToCheck << endl; + LOG_STRING("Missing library file: " << sFileToCheck); + } + } + + if ( ! bReturn ) + { + // print error msg to user + cout << cMissingAToolLibs; + + } + return bReturn; +} + +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/stdafx.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/stdafx.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,20 @@ +/* +* 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: +* +*/ + + +#include "../inc/stdafx.h" + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/utility.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/utility.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,38 @@ +/* +* 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: Miscellaneous utility functions. +* +*/ +#include "../inc/ATCommonDefines.h" +#include "../inc/CATBase.h" +#include "../inc/CATProject.h" + +//Analyze report logging level. +#define MAX_LOG_LEVEL 3 + +//Function declarations. +bool CheckSBS2Folder( void ); + +/** +* Helper function which checks does current dir contain atool_temp\build folder which +* is used in sbs2 support +*/ +bool CheckSBS2Folder( void ) +{ + LOG_FUNC_ENTRY("CheckSBS2Folder"); + if ( CATBase::DirectoryExists( RAPTOR_MAKEFILE_DIR ) ) + return true; + return false; +} +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/commandlineengine/src/version.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/version.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,258 @@ +/* +* 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: Show / Check atool version. +* +*/ +#include "../inc/ATCommonDefines.h" +#include "../inc/CATBase.h" + +//Function declarations. +int showVersionInfo( void ); +int showCoreVersionInfo( void ); +bool readCoreVersionInfo( const string& sFile, string& sVersion ); +string findAnalyzeToolHeader( void ); +int showDbgHelpVersionInfo( bool showVersion ); +int getDllVersion( LPCTSTR libName, WORD *majorVersion, WORD *minorVersion, WORD *buildNumber, WORD *revisionNumber ); + +//External GetEpocRoot function +extern bool GetEpocRoot( string &sEpocRoot ); + +void convertWriteTimeToLocalTime( FILETIME ftWrite, LPSTR lpszString ); + +int showCoreVersionInfo( void ) +{ + LOG_FUNC_ENTRY( "version.cpp::showCoreVersionInfo" ); + // Try find header from environment where to locate version info. + string sHeaderFile = findAnalyzeToolHeader(); + if ( sHeaderFile.empty() ) + return 0; + string sVersion(""); + if ( readCoreVersionInfo( sHeaderFile, sVersion ) ) + { + cout << "AnalyzeTool SDK binaries version: " + << sVersion + << endl; + } + return 0; +} + + +/** +* Find analyzetool.h header file +* @return string containing full path to file or empty string if not found. +*/ +string findAnalyzeToolHeader( void ) +{ + LOG_FUNC_ENTRY( "version.cpp::findAnalyzeToolHeader" ); + string sEpocRoot; + if ( ! CATBase::GetEpocRoot( sEpocRoot ) ) + return string(""); + int iC = sizeof( AT_CORE_INCLUDE_FILE_WITH_VERSION_NUMBER ) / sizeof ( string ); + for( int i = 0 ; i < iC ; i++ ) + { + string sCheck( sEpocRoot ); + sCheck.append( AT_CORE_INCLUDE_FILE_WITH_VERSION_NUMBER[i] ); + if ( CATBase::FileExists( sCheck.c_str() ) ) + return sCheck; + } + return string(""); +} +/** +* Read core version string. +* @param sVersion string will contain version info if funtion returns true. +* @return true if successful. +*/ +bool readCoreVersionInfo( const string& sFile, string& sVersion ) +{ + LOG_FUNC_ENTRY( "version.cpp::readCoreVersionInfo" ); + try { + ifstream in; + in.open( sFile.c_str() ); + if ( ! in.good() ) + return false; + char cBuff[MAX_LINE_LENGTH]; + while ( in.good() ) + { + in.getline( cBuff, MAX_LINE_LENGTH ); + string s( cBuff ); + if ( s.find( AT_CORE_VERSION_NUMBER_TAG ) != string::npos ) + { + // Find spot after first space (ignore first 3 chars). + size_t t = s.find_first_of( ' ', 3 )+1; + sVersion = s.substr( t, s.size()-t ); + return true; + } + } + } + catch(...) + { + LOG_STRING(AT_MSG << "Exception reading core version info."); + } + return false; +} + +/** +* Print version information of atool.exe binary. +*/ +int showVersionInfo( void ) +{ + LOG_FUNC_ENTRY( "version.cpp::showVersionInfo" ); + string sTemp( "Version: " ); + sTemp.append( ATOOL_VERSION ); + sTemp.append( "\n" ); + //Print atool version + printf( sTemp.c_str() ); + + //atool.exe:s path + filename + char buffer[MAX_PATH]; + + GetModuleFileName( NULL, buffer, MAX_PATH ); + + printf( "Path: %s\n", buffer ); + + WIN32_FIND_DATA FindFileData; + HANDLE hFind; + //Get file handle + hFind = FindFirstFile( buffer, &FindFileData ); + + if( hFind == INVALID_HANDLE_VALUE ) + { + printf( "Can not find file:%s", buffer ); + return 0; + } + + convertWriteTimeToLocalTime( FindFileData.ftLastWriteTime , buffer ); + printf( "Modified: %s\n", buffer ); + + // Show core version information. + showCoreVersionInfo(); + return 0; +} + +// Convert the last-write time to local time. +void convertWriteTimeToLocalTime( FILETIME ftWrite, LPSTR lpszString ) +{ + LOG_FUNC_ENTRY( "version.cpp::convertWriteTimeToLocalTime" ); + SYSTEMTIME stUTC, stLocal; + // Convert the last-write time to local time. + FileTimeToSystemTime(&ftWrite, &stUTC); + SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal); + + // Build a string showing the date and time. + wsprintf(lpszString, "%02d/%02d/%d %02d:%02d:%02d", + stLocal.wDay, stLocal.wMonth, stLocal.wYear, + stLocal.wHour, stLocal.wMinute, stLocal.wSecond); +} + +/** +* Print version information of dbghelp.dll. +*/ +int showDbgHelpVersionInfo( bool showVersion ) +{ + LOG_FUNC_ENTRY( "version.cpp::showDbgHelpVersionInfo" ); + + WORD majorVersion; + WORD minorVersion; + WORD buildNumber; + WORD revisionNumber; + + if(getDllVersion( _T(DBGHELP_DLL_NAME), &majorVersion, &minorVersion, &buildNumber, &revisionNumber)) + { + //Check if current dll version is lower than latest version + if((majorVersion < DBGHELP_VERSION_MAJ) || + (majorVersion == DBGHELP_VERSION_MAJ && minorVersion < DBGHELP_VERSION_MIN) || + (majorVersion == DBGHELP_VERSION_MAJ && minorVersion == DBGHELP_VERSION_MIN && buildNumber < DBGHELP_VERSION_BUILD) || + (majorVersion == DBGHELP_VERSION_MAJ && minorVersion == DBGHELP_VERSION_MIN && buildNumber == DBGHELP_VERSION_BUILD && revisionNumber < DBGHELP_VERSION_REVIS)) + { + cout << "WARNING: Version of your dbghelp.dll is " + << majorVersion << "." + << minorVersion << "." + << buildNumber << "." + << revisionNumber << ".\n"; + + cout << "Source code pinpointing for winscw may not work properly with this version." + << endl + << "Please, update it to at least version " + << DBGHELP_VERSION_MAJ << "." + << DBGHELP_VERSION_MIN << "." + << DBGHELP_VERSION_BUILD << "." + << DBGHELP_VERSION_REVIS << ".\n" + << "dbghelp.dll file is included in Debugging Tools from Microsoft. " + << "You can download and install it from\n" + << "http://www.microsoft.com/whdc/devtools/debugging/\n"; + + return 1; + } + else + { + if( showVersion ) + { + cout << "Version of your dbghelp.dll is " + << majorVersion << "." + << minorVersion << "." + << buildNumber << "." + << revisionNumber << "." + << endl; + cout << "No need for update.\n"; + } + } + } + + return 0; +} + +/** +* Get dll version. +* @param libName library name. +* @param majorVersion will contain major version if funtion returns true. +* @param minorVersion will contain minor version if funtion returns true. +* @param buildNumber will contain build number if funtion returns true. +* @param revisionNumber will contain revision number if funtion returns true. +* @return true if successful. +*/ +int getDllVersion( LPCTSTR libName, WORD *majorVersion, WORD *minorVersion, WORD *buildNumber, WORD *revisionNumber ) +{ + LOG_FUNC_ENTRY( "version.cpp::getDllVersion" ); + + DWORD dwHandle, dwLen; + UINT BufLen; + LPTSTR lpData; + VS_FIXEDFILEINFO *pFileInfo; + dwLen = GetFileVersionInfoSize( libName, &dwHandle ); + if (!dwLen) + return 0; + + lpData = (LPTSTR) malloc (dwLen); + if (!lpData) + return 0; + + if( !GetFileVersionInfo( libName, dwHandle, dwLen, lpData ) ) + { + free (lpData); + return 0; + } + + if( VerQueryValue( lpData, _T("\\"), (LPVOID *) &pFileInfo, (PUINT)&BufLen ) ) + { + *majorVersion = HIWORD(pFileInfo->dwFileVersionMS); + *minorVersion = LOWORD(pFileInfo->dwFileVersionMS); + *buildNumber = HIWORD(pFileInfo->dwFileVersionLS); + *revisionNumber = LOWORD(pFileInfo->dwFileVersionLS); + return 1; + } + free (lpData); + return 0; +} + +//EOF diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/bwins/atoolmemoryhooku.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/bwins/atoolmemoryhooku.def Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,10 @@ +EXPORTS + ?Alloc@RAnalyzeToolAllocator@@UAEPAXH@Z @ 1 NONAME ; void * RAnalyzeToolAllocator::Alloc(int) + ?Alloc@RAnalyzeToolMainAllocator@@UAEPAXH@Z @ 2 NONAME ; void * RAnalyzeToolMainAllocator::Alloc(int) + ?Exit@CustomUser@@SAXH@Z @ 3 NONAME ; void CustomUser::Exit(int) + ?InstallAllocator@CustomUser@@CAAAVRAllocator@@HABV?$TBuf@$0BAA@@@KKKK@Z @ 4 NONAME ; class RAllocator & CustomUser::InstallAllocator(int, class TBuf<256> const &, unsigned long, unsigned long, unsigned long, unsigned long) + ?Panic@CustomUser@@SAXABVTDesC16@@H@Z @ 5 NONAME ; void CustomUser::Panic(class TDesC16 const &, int) + ?SetCritical@CustomUser@@SAHW4TCritical@User@@@Z @ 6 NONAME ; int CustomUser::SetCritical(enum User::TCritical) + ?SetProcessCritical@CustomUser@@SAHW4TCritical@User@@@Z @ 7 NONAME ; int CustomUser::SetProcessCritical(enum User::TCritical) + ?SetupThreadHeap@CustomUser@@SAHHAAUSStdEpocThreadCreateInfo@@ABV?$TBuf@$0BAA@@@KKABV?$TBuf@$0BE@@@KKV?$TRefByValue@$$CBVTDesC16@@@@ZZ @ 8 NONAME ; int CustomUser::SetupThreadHeap(int, struct SStdEpocThreadCreateInfo &, class TBuf<256> const &, unsigned long, unsigned long, class TBuf<20> const &, unsigned long, unsigned long, class TRefByValue<class TDesC16 const >, ...) + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/eabi/atoolmemoryhooku.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/eabi/atoolmemoryhooku.def Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,16 @@ +EXPORTS + _ZN10CustomUser11SetCriticalEN4User9TCriticalE @ 1 NONAME + _ZN10CustomUser15SetupThreadHeapEiR24SStdEpocThreadCreateInfoRK4TBufILi256EEmmRKS2_ILi20EEmm11TRefByValueIK7TDesC16Ez @ 2 NONAME + _ZN10CustomUser16InstallAllocatorEiRK4TBufILi256EEmmmm @ 3 NONAME + _ZN10CustomUser18SetProcessCriticalEN4User9TCriticalE @ 4 NONAME + _ZN10CustomUser4ExitEi @ 5 NONAME + _ZN10CustomUser5PanicERK7TDesC16i @ 6 NONAME + _ZTI20CLibraryEventHandler @ 7 NONAME ; #<TI># + _ZTI21RAnalyzeToolAllocator @ 8 NONAME ; #<TI># + _ZTI25RAnalyzeToolMainAllocator @ 9 NONAME ; #<TI># + _ZTI27RAnalyzeToolMemoryAllocator @ 10 NONAME ; #<TI># + _ZTV20CLibraryEventHandler @ 11 NONAME ; #<VT># + _ZTV21RAnalyzeToolAllocator @ 12 NONAME ; #<VT># + _ZTV25RAnalyzeToolMainAllocator @ 13 NONAME ; #<VT># + _ZTV27RAnalyzeToolMemoryAllocator @ 14 NONAME ; #<VT># + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/group/atoolmemoryhook.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/group/atoolmemoryhook.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,68 @@ +/* +* 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: The .mmp file for AToolMemoryHook. +* +*/ + +#include <platform_paths.hrh> +#include "../../symbian_version.hrh" + +TARGET atoolmemoryhook.dll +TARGETTYPE dll +UID 0x1000008d 0x2001242F +CAPABILITY ALL -TCB + +#if ( SYMBIAN_VERSION_SUPPORT >= SYMBIAN_3 ) +EPOCALLOWDLLDATA +#endif + +SMPSAFE + +SOURCEPATH ../src + +SOURCE analyzetooleventhandler.cpp +SOURCE codeblock.cpp +SOURCE threadstack.cpp +SOURCE customuser.cpp +SOURCE analyzetoolmemoryallocator.cpp +SOURCE analyzetoolmainallocator.cpp +SOURCE analyzetoolallocator.cpp +SOURCE analyzetoolfastlog.cpp + +SOURCEPATH ../../storageserver/server/src +SOURCE atdriveinfo.cpp + +USERINCLUDE ../inc +USERINCLUDE ../../inc +USERINCLUDE ../../storageserver/inc +USERINCLUDE ../../storageserver/server/inc + +#ifdef WINSCW +APP_LAYER_SYSTEMINCLUDE +#endif + +OS_LAYER_SYSTEMINCLUDE + +LIBRARY efsrv.lib +LIBRARY euser.lib +LIBRARY atoolstorageserverclnt.lib +LIBRARY flogger.lib +LIBRARY charconv.lib +LIBRARY platformenv.lib + +#if ( SYMBIAN_VERSION_SUPPORT >= SYMBIAN_3 ) +MACRO USE_CLEANER_DLL +#endif + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,26 @@ +/* +* 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: +* +*/ + +PRJ_PLATFORMS +ARMV5 WINSCW + +PRJ_MMPFILES +atoolmemoryhook.mmp + +PRJ_TESTMMPFILES +../internal/tsrc/group/analyzetoolmemoryhooktest.mmp + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/inc/analyzetoolallocator.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/inc/analyzetoolallocator.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,247 @@ +/* +* 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: Declaration of the class RAnalyzeToolAllocator. +* +*/ + + +#ifndef ANALYZETOOLALLOCATOR_H +#define ANALYZETOOLALLOCATOR_H + +// INCLUDES +#include <u32std.h> +#include "codeblock.h" +#include "threadstack.h" +#include "analyzetoolmemoryallocator.h" +#include <analyzetool/atstorageserverclnt.h> +#include <analyzetool/analyzetool.h> +#include <analyzetool/atcommon.h> + +// CLASS DECLARATION + +/** +* Class which overloads the RAlloctor functions and provides access to +* the overloaded functions +*/ +class RAnalyzeToolAllocator : public RAnalyzeToolMemoryAllocator + { + + public: + + /** + * C++ default constructor. + * @param aNotFirst Is this first thread using this heap + * @param aStorageServer A reference to the + * <code>RATStorageServer</code> which is + * used to store kernel events + * @param aCodeblocks A reference to array of code segments + * @param aMutex A reference to mutex for schedule access to the + * shared resources + * @param aProcessId A reference to the observed process id + * @param aAnalyzeTool Reference to device driver + * @param aStorageServerOpen Variable to check if Storage server is connected + * @param aLogOption The logging option for storage server + * @param aAllocCallStackSize Max number of stored callstack items when memory allocated + * @param aFreeCallStackSize Max number of stored callstack items when memory freed + */ + RAnalyzeToolAllocator( TBool aNotFirst, + RATStorageServer& aStorageServer, + RArray<TCodeblock>& aCodeblocks, + RMutex& aMutex, + TUint aProcessId, + RAnalyzeTool& aAnalyzeTool, + TBool aStorageServerOpen, + TUint32 aLogOption, + TUint32 aAllocCallStackSize, + TUint32 aFreeCallStackSize ); + /** + * Destructor. + */ + ~RAnalyzeToolAllocator(); + + /** + * Allocates a cell of specified size from the heap. + * @param aSize The size of the cell to be allocated from the heap. + * @return TAny* A pointer to the allocated cell. + */ + TAny* Alloc( TInt aSize ); + + /** + * Frees the specified cell and returns it to the heap. + * @param aPtr A pointer to a cell to be freed. + */ + void Free( TAny* aPtr ); + + /** + * Increases or decreases the size of an existing cell. + * @param aPtr A pointer to the cell to be reallocated. + * @param aSize The new size of the cell. This may be bigger + * or smaller than the size of the original cell. + * @param aMode Flags controlling the reallocation. + * @return TAny* A pointer to the reallocated cell. This may be the + * same as the original pointer supplied through aCell. + */ + //lint --e{1735} suppress "Virtual function has default parameter" + TAny* ReAlloc( TAny* aPtr, TInt aSize, TInt aMode = 0 ); + + /** + * Gets the length of the available space in the specified + * allocated cell. + * @param aCell A pointer to the allocated cell. + * @return TInt The length of the available space in the allocated cell. + */ + TInt AllocLen( const TAny* aCell ) const; + + #ifndef __KERNEL_MODE__ + + /** + * Opens this heap for shared access. Opening the heap increases + * the heap's access count by one. + */ + TInt Open(); + + /** + * Closes this shared heap. Closing the heap decreases the heap's + * access count by one. + */ + void Close(); + + /** + * The function frees excess committed space from the top of the heap. + * The size of the heap is never reduced below the minimum size + * specified during creation of the heap. + * @return TInt The space reclaimed. If no space can be reclaimed, + then this value is zero. + */ + TInt Compress(); + + /** + * Frees all allocated cells on this heap. + */ + void Reset(); + + /** + * Gets the number of cells allocated on this heap, and + * the total space allocated to them. + * @param aTotalAllocSize On return, contains the total + * space allocated to the cells. + * @return TInt The number of cells allocated on this heap. + */ + TInt AllocSize( TInt& aTotalAllocSize ) const; + + /** + * Gets the total free space currently available on the heap and the + * space available in the largest free block. The space available + * represents the total space which can be allocated. Note that + * compressing the heap may reduce the total free space available + * and the space available in the largest free block. + * @param aBiggestBlock On return, contains the space available + * in the largest free block on the heap. + + * @return TInt The total free space currently available on the heap. + + */ + TInt Available( TInt& aBiggestBlock ) const; + + #endif + + /** + * Invocates specified debug funtionality. + * @param aFunc The debug function + * @param a1 Debug function specific paramenter. + * @param a2 Debug function specific paramenter. + * @return TInt Returns KErrNone, if successful otherwise one + * of the other system-wide error codes. + */ + //lint --e{1735} suppress "Virtual function has default parameter" + TInt DebugFunction( TInt aFunc, TAny* a1 = NULL, TAny* a2 = NULL ); + + protected: + + /** + * Extension function + * @param aExtensionId The extension id + * @param a0 Extension specific paramenter. + * @param a1 Extension specific paramenter. + * @return TInt Returns KErrNone, if successful otherwise one + * of the other system-wide error codes. + */ + TInt Extension_( TUint aExtensionId, TAny*& a0, TAny* a1 ); + + public: // from RAnalyzeToolMemoryAllocator + + /** + * Installs the RTraceAllocator allocator + */ + void Uninstall(); + + /** + * Shares the heap + */ + void ShareHeap(); + + private: + + /** + * Find the current thread which is using the heap + * @param aStackStart A reference where the stack start is stored + * @return TBool ETrue if a thread can be found, EFalse otherwise + */ + TBool FindCurrentThreadStack( TUint32& aStackStart ); + + private: + + /* Handle to the storage server*/ + RATStorageServer& iStorageServer; + + /* A reference to codeblocks of the observed process */ + RArray<TCodeblock>& iCodeblocks; + + /* The mutex for serializing access to the shared resources */ + RMutex& iMutex; + + /* The process id */ + TUint iProcessId; + + /* Array for storing the callstack */ + TFixedArray<TUint32, KATMaxCallstackLength> iCallStack; + + /* Array for storing the reallocation callstack */ + TFixedArray <TUint32, KATMaxCallstackLength> iReCallStack; + + /* Array for storing the reallocation callstack */ + TFixedArray<TUint32, KATMaxFreeCallstackLength> iFreeCallStack; + + /* Array of threads using this heap */ + RArray<TThreadStack> iThreadArray; + + RAnalyzeTool& iAnalyzeTool; + + /* A flag for indicating that the RATStorageServer is open */ + TBool iStorageServerOpen; + + /* Log option */ + TUint32 iLogOption; + + /* Max items on stored call stack when memory allocated */ + TUint32 iAllocMaxCallStack; + + /* Max items on stored call stack when memory freed */ + TUint32 iFreeMaxCallStack; + + }; + +#endif // ANALYZETOOLALLOCATOR_H + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/inc/analyzetooleventhandler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/inc/analyzetooleventhandler.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,122 @@ +/* +* 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: Declaration of the class CLibraryEventHandler. +* +*/ + + +#ifndef ANALYZETOOLEVENTHANDLER_H +#define ANALYZETOOLEVENTHANDLER_H + +// INCLUDES +#include <e32cmn.h> +#include "codeblock.h" +#include <analyzetool/atstorageserverclnt.h> +#include <analyzetool/analyzetool.h> + +// FORWARD DECLARATIONS +class MAnalyzeToolEventhandlerNotifier; + +// CLASS DECLARATION + +/** +* Class for receiving library load/unlaod events from the kernel +*/ +class CLibraryEventHandler : public CActive + { + + public: + + /** + * C++ default constructor. + * @param aAnalyzeTool A reference to the <code>RAnalyzeTool</code> + which is used to observe kernel events + * @param aCodeblocks A reference to array of code segments + * @param aStorageServer A reference to the + * <code>RATStorageServer</code> which is + * used to store kernel events + * @param aProcessId A reference to the observed process id + * @param aMutex A reference to mutex to schedule access to the + * shared resources + * @param aNotifier A reference to notifier object which is used to + * inform killed threads + * @param aLogOption Current used log option on allocator. + */ + CLibraryEventHandler( RAnalyzeTool& aAnalyzeTool, + RArray<TCodeblock>& aCodeblocks, + RATStorageServer& aStorageServer, + TUint aProcessId, + RMutex& aMutex, + MAnalyzeToolEventhandlerNotifier& aNotifier, + TUint32 aLogOption ); + + /** + * Destructor. + */ + ~CLibraryEventHandler(); + + /* Start receiving events from the kernel */ + void Start(); + + /** + * Returns eventhandler's state. + * @return TBool ETrue if eventhandler is started, EFalse otherwise + */ + TBool IsStarted(); + + protected: // Functions from base classes + + /** + * Process active object's task + */ + void RunL(); + + /** + * Cancels active object's task + */ + void DoCancel(); + + private: // Member variables + + /* Handle to the analyze tool device driver*/ + RAnalyzeTool& iAnalyzeTool; + + /* A reference to codeblocks of the observed process */ + RArray<TCodeblock>& iCodeblocks; + + /* Handle to the storage server*/ + RATStorageServer& iStorageServer; + + /* The observered process id */ + TUint iProcessId; + + /* The library info */ + TLibraryEventInfo iLibraryInfo; + + /* The mutex for serializing access to the shared resources */ + RMutex& iMutex; + + /* Inform if handler is started */ + TBool iStarted; + + /* A reference to event handler notifier */ + MAnalyzeToolEventhandlerNotifier& iNotifier; + + /* Current used log option */ + TUint32 iLogOption; + }; + +#endif // ANALYZETOOLEVENTHANDLER_H + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/inc/analyzetooleventhandlernotifier.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/inc/analyzetooleventhandlernotifier.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,45 @@ +/* +* 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: Declaration of the class MAnalyzeToolEventhandlerNotifier +* +*/ + + +#ifndef ANALYZETOOLEVENTHANDLERNOTIFIER_H +#define ANALYZETOOLEVENTHANDLERNOTIFIER_H + +// INCLUDES +#include <e32base.h> + +// CLASS DECLARATION + +/** +* MAnalyzeToolEventhandlerNotifier class +* An interface class for informing killed thread. +*/ +class MAnalyzeToolEventhandlerNotifier + { + public: // New functions + + /** + * Inform when thread killed. + * @param aThreadId - Killed thread Id. + */ + virtual void RemoveKilledThread( const TUint aThreadId ) = 0; + + }; + +#endif // ANALYZETOOLEVENTHANDLERNOTIFIER_H + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/inc/analyzetoolfastlog.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/inc/analyzetoolfastlog.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,96 @@ +/* +* 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: +* +*/ + + +#ifndef __ANALYZETOOLFASTLOG_H__ +#define __ANALYZETOOLFASTLOG_H__ + +// INCLUDES +#include <e32base.h> +#include <analyzetool/atcommon.h> +#include <analyzetool/analyzetooltraceconstants.h> + +// Function prototypes. + +/** + * TBD + * @param aProcessName The name of the new process started. The length of this + * descriptor must not be greater than KMaxProcessName. + * @param aProcessId The ID of the process started. + * @param aIsDebug Determines whether a binary is UDEB or UREL + * @return KErrNone. +*/ +GLREF_C TInt ATFastLogProcessStarted( const TDesC8& aProcessName, + TUint aProcessId, + TUint32 aIsDebug ); + +/** + * TBD + * @param aProcessId The ID number of the process ended. + * @param aHandleLeakCount Number of handles open. + * @return KErrNone, if successful; otherwise one of the other + * system-wide error codes. + */ +GLREF_C TInt ATFastLogProcessEnded( TUint aProcessId, + TUint aHandleLeakCount ); + +/** + * TBD + * @param aProcessId The ID number of the process ended. + * @param aDllName The name of the new DLL loaded. The length of this descriptor + * must not be greater than KMaxLibraryName. + * @param aStartAddress The start address of the DLL loaded. + * @param aEndAddress The end address of the DLL loaded. + * @return KErrNone. +*/ +GLREF_C TInt ATFastLogDllLoaded( TUint aProcessId, const TDesC8& aDllName, TUint32 aStartAddress, + TUint32 aEndAddress ); + +/** + * TBD + * @param aProcessId The ID number of the process ended. + * @param aDllName The name of the DLL to be unloaded. The length of this + * descriptor must not be greater than KMaxLibraryName. + * @param aStartAddress The start address of the DLL to be unloaded. + * @param aEndAddress The end address of the DLL to be unloaded. + * @return KErrNone. +*/ +GLREF_C TInt ATFastLogDllUnloaded( TUint aProcessId, const TDesC8& aDllName, TUint32 aStartAddress, + TUint32 aEndAddress ); + +/** + * TBD + * @param aProcessId The ID number of the process ended. + * @param aMemAddress The memory location where memory has been allocated. + * @param aCallstack An array including the current call stack. + * @param aSize The size of the newly allocated memory chunk. + * @return KErrNone. +*/ +GLREF_C TInt ATFastLogMemoryAllocated( TUint aProcessId, TUint32 aMemAddress, + TFixedArray<TUint32, KATMaxCallstackLength>& aCallstack, + TInt aSize ); + +/** + * TBD + * @param aProcessId The ID number of the process ended. + * @param aMemAddress The memory location where memory has been deallocated. + * @param aFreeCallstack An array including the current call stack. + * @return KErrNone. +*/ +GLREF_C TInt ATFastLogMemoryFreed( TUint aProcessId, TUint32 aMemAddress, + TFixedArray<TUint32, KATMaxFreeCallstackLength>& aFreeCallstack ); +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/inc/analyzetoolmainallocator.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/inc/analyzetoolmainallocator.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,329 @@ +/* +* 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: Declaration of the class RAnalyzeToolMainAllocator. +* +*/ + + +#ifndef ANALYZETOOLMAINALLOCATOR_H +#define ANALYZETOOLMAINALLOCATOR_H + +// INCLUDES +#include <u32std.h> +#include "codeblock.h" +#include <analyzetool/atstorageserverclnt.h> +#include <analyzetool/analyzetool.h> +#include <analyzetool/atcommon.h> +#include "analyzetoolmemoryallocator.h" +#include "analyzetooleventhandlernotifier.h" + +// FORWARD DECLARATIONS +class CLibraryEventHandler; + +// CLASS DECLARATION + +/** +* Class which overloads the RAlloctor functions and provides access to +* the overloaded functions +*/ +class RAnalyzeToolMainAllocator : public RAnalyzeToolMemoryAllocator, + public MAnalyzeToolEventhandlerNotifier + { + + public: + + /** + * C++ default constructor. + * @param aNotFirst Is this first thread using this heap + * @param aFileName The name of the log file + * @param aLogOption The logging option for storage server + * @param aIsDebug Determines whether a binary is UDEB or UREL + * @param aAllocCallStackSize Max number of stored callstack items when memory allocated + * @param aFreeCallStackSize Max number of stored callstack items when memory freed + */ + RAnalyzeToolMainAllocator( TBool aNotFirst, + const TFileName aFileName, + TUint32 aLogOption, TUint32 aIsDebug, + TUint32 aAllocCallStackSize, + TUint32 aFreeCallStackSize ); + + /** + * Destructor. + */ + ~RAnalyzeToolMainAllocator(); + + /** + * Allocates a cell of specified size from the heap. + * @param aSize The size of the cell to be allocated from the heap. + * @return TAny* A pointer to the allocated cell. + */ + TAny* Alloc( TInt aSize ); + + /** + * Frees the specified cell and returns it to the heap. + * @param aPtr A pointer to a cell to be freed. + */ + void Free( TAny* aPtr ); + + /** + * Increases or decreases the size of an existing cell. + * @param aPtr A pointer to the cell to be reallocated. + * @param aSize The new size of the cell. This may be bigger + * or smaller than the size of the original cell. + * @param aMode Flags controlling the reallocation. + * @return TAny* A pointer to the reallocated cell. This may be the + * same as the original pointer supplied through aCell. + */ + TAny* ReAlloc( TAny* aPtr, TInt aSize, TInt aMode = 0 ); + + /** + * Gets the length of the available space in the specified + * allocated cell. + * @param aCell A pointer to the allocated cell. + * @return TInt The length of the available space in the allocated cell. + */ + TInt AllocLen(const TAny* aCell) const; + + #ifndef __KERNEL_MODE__ + + /** + * Opens this heap for shared access. Opening the heap increases + * the heap's access count by one. + */ + TInt Open(); + + /** + * Closes this shared heap. Closing the heap decreases the heap's + * access count by one. + */ + void Close(); + + /** + * The function frees excess committed space from the top of the heap. + * The size of the heap is never reduced below the minimum size + * specified during creation of the heap. + * @return TInt The space reclaimed. If no space can be reclaimed, + then this value is zero. + */ + TInt Compress(); + + /** + * Frees all allocated cells on this heap. + */ + void Reset(); + + /** + * Gets the number of cells allocated on this heap, and + * the total space allocated to them. + * @param aTotalAllocSize On return, contains the total + * space allocated to the cells. + * @return TInt The number of cells allocated on this heap. + */ + TInt AllocSize( TInt& aTotalAllocSize ) const; + + /** + * Gets the total free space currently available on the heap and the + * space available in the largest free block. The space available + * represents the total space which can be allocated. Note that + * compressing the heap may reduce the total free space available + * and the space available in the largest free block. + * @param aBiggestBlock On return, contains the space available + * in the largest free block on the heap. + + * @return TInt The total free space currently available on the heap. + + */ + TInt Available( TInt& aBiggestBlock ) const; + + #endif + + /** + * Invocates specified debug funtionality. + * @param aFunc The debug function + * @param a1 Debug function specific paramenter. + * @param a2 Debug function specific paramenter. + * @return TInt Returns KErrNone, if successful otherwise one + * of the other system-wide error codes. + */ + TInt DebugFunction( TInt aFunc, TAny* a1 = NULL, TAny* a2 = NULL ); + + // From MAnalyzeToolEventhandlerNotifier + + /** + * Remove killed thread from threads array. + * @param aThreadId - Thread Id + */ + void RemoveKilledThread( const TUint aThreadId ); + + protected: + + /** + * Extension function + * @param aExtensionId The extension id + * @param a0 Extension specific paramenter. + * @param a1 Extension specific paramenter. + * @return TInt Returns KErrNone, if successful otherwise one + * of the other system-wide error codes. + */ + TInt Extension_( TUint aExtensionId, TAny*& a0, TAny* a1 ); + + public: // from RAnalyzeToolMemoryAllocator + + /** + * Installs the RTraceAllocator allocator + */ + void Uninstall(); + + /** + * Shares the heap + */ + void ShareHeap(); + + public: // inlines + + /** + * Acquires the open RATStorageServer handle + * @return RATStorageServer& The open RATStorageServer handle + */ + inline RATStorageServer& StorageServer(); + + /** + * Acquires the codeblocks of the process + * @return RArray<TCodeblock>& The process codeblocks + */ + inline RArray<TCodeblock>& Codeblocks(); + + /** + * Acquires the mutex used to access shared objects + * @return RMutex& A reference to open mutex + */ + inline RMutex& Mutex(); + + /** + * Acquires the current process id + * @return TInt The process id + */ + inline TInt ProcessId(); + + /** + * Acquires the logical channel handle + * @return RAnalyzeTool A reference to logical channel + */ + inline RAnalyzeTool& AnalyzeTool(); + + /** + * Acquires information if storage server is open + * @return TBool iStorageServerOpen + */ + inline TBool StorageServerOpen(); + + /** + * Acquires the log option type + * @return TUint32 iLogOption + */ + inline TUint32 LogOption(); + + /** + * Acquires the max size of call stack when memory allocated + * @return TUint32 iAllocMaxCallStack + */ + inline TUint32 AllocMaxCallStack(); + + /** + * Acquires the max size of call stack when memory freed + * @return TUint32 iFreeMaxCallStack + */ + inline TUint32 FreeMaxCallStack(); + + private: // private functions + + /** + * Log the process initial information + * @param aFileName The name of the log file + * @param aLogOption The logging option for storage serve + * @param aIsDebug Determines whether a binary is UDEB or UREL + */ + void LogProcessInformation( const TFileName aFileName, TUint32 aLogOption, + TUint32 aIsDebug ); + + /** + * Find the current thread which is using the heap + * @param aStackStart A reference where the stack start is stored + * @return TBool ETrue if a thread can be found, EFalse otherwise + */ + TBool FindCurrentThreadStack( TUint32& aStackStart ); + + /** + * Installs the eventhandler, if possible + */ + void InstallEventHandler(); + + private: // member variables + + /* Handle to the RATStorageServer */ + RATStorageServer iStorageServer; + + /* Handle to the RAnalyzeTool */ + RAnalyzeTool iAnalyzeTool; + + /* A flag for indicating that the RAnalyzeTool is open */ + TBool iAnalyzeToolOpen; + + /* A flag for indicating that the device driver is loaded */ + TBool iDeviceDriverLoaded; + + /* The codeblocks of the process */ + RArray<TCodeblock> iCodeblocks; + + /* The handler for kerner events */ + CLibraryEventHandler* iEventHandler; + + /* The mutex for serializing access to the shared resources */ + mutable RMutex iMutex; + + /* Array for storing the callstack */ + TFixedArray <TUint32, KATMaxCallstackLength> iCallStack; + + /* Array for storing the reallocation callstack */ + TFixedArray <TUint32, KATMaxCallstackLength> iReCallStack; + + /* Array for storing the reallocation callstack */ + TFixedArray<TUint32, KATMaxFreeCallstackLength> iFreeCallStack; + + /* Array of threads using this heap */ + RArray<TThreadStack> iThreadArray; + + /* A flag for indicating that the RATStorageServer is open */ + TBool iStorageServerOpen; + + /* Log option */ + TUint32 iLogOption; + + /* The process id */ + TUint iProcessId; + + /* Max items on stored call stack when memory allocated */ + TUint32 iAllocMaxCallStack; + + /* Max items on stored call stack when memory freed */ + TUint32 iFreeMaxCallStack; + + }; + +// INLINES +#include "analyzetoolmainallocator.inl" + +#endif // ANALYZETOOLMAINALLOCATOR_H + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/inc/analyzetoolmainallocator.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/inc/analyzetoolmainallocator.inl Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,109 @@ +/* +* 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: Definition for the inline functions of RAnalyzeToolMainAllocator. +* +*/ + + +#include "analyzetoolmemoryallocator.h" + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::StorageServer() +// Acquires reference to open RATStorageServer +// ----------------------------------------------------------------------------- +// +inline RATStorageServer& RAnalyzeToolMainAllocator::StorageServer() + { + return iStorageServer; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::Codeblocks() +// Acquires reference to process used codeblocks +// ----------------------------------------------------------------------------- +// +inline RArray<TCodeblock>& RAnalyzeToolMainAllocator::Codeblocks() + { + return iCodeblocks; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::Mutex() +// Acquires reference to mutex which is used to share resources +// ----------------------------------------------------------------------------- +// +inline RMutex& RAnalyzeToolMainAllocator::Mutex() + { + return iMutex; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::ProcessId() +// Acquires the process id +// ----------------------------------------------------------------------------- +// +inline TInt RAnalyzeToolMainAllocator::ProcessId() + { + return iProcessId; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::AnalyzeTool() +// Acquires the logical channel handle +// ----------------------------------------------------------------------------- +// +inline RAnalyzeTool& RAnalyzeToolMainAllocator::AnalyzeTool() + { + return iAnalyzeTool; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::StorageServerOpen() +// Acquires the iStorageServerOpen variable +// ----------------------------------------------------------------------------- +// +inline TBool RAnalyzeToolMainAllocator::StorageServerOpen() + { + return iStorageServerOpen; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::LogOption() +// Acquires the iLogOption variable +// ----------------------------------------------------------------------------- +// +inline TUint32 RAnalyzeToolMainAllocator::LogOption() + { + return iLogOption; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::AllocMaxCallStack() +// Acquires the iAllocMaxCallStack variable +// ----------------------------------------------------------------------------- +// +inline TUint32 RAnalyzeToolMainAllocator::AllocMaxCallStack() + { + return iAllocMaxCallStack; + } +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::FreeMaxCallStack() +// Acquires the iFreeMaxCallStack variable +// ----------------------------------------------------------------------------- +// +inline TUint32 RAnalyzeToolMainAllocator::FreeMaxCallStack() + { + return iFreeMaxCallStack; + } +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/inc/analyzetoolmemoryallocator.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/inc/analyzetoolmemoryallocator.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,94 @@ +/* +* 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: Declaration of the class RAnalyzeToolMemoryAllocator. +* +*/ + + +#ifndef ANALYZETOOLMEMORYALLOCATOR_H +#define ANALYZETOOLMEMORYALLOCATOR_H + +// INCLUDES +#include <u32std.h> +#include "threadstack.h" +#include "../../symbian_version.hrh" + +// CONSTANTS +#if ( SYMBIAN_VERSION_SUPPORT >= SYMBIAN_3 ) + #ifndef __WINS__ + const TInt KDummyHandle = -1000; + #endif +#endif + +// CLASS DECLARATION + +/** +* Abstract class for basic RAnalyzeToolMemoryAllocator funtions +*/ +class RAnalyzeToolMemoryAllocator : public RAllocator + { + public: + + /** + * C++ default constructor. + * @param aNotFirst Is this first thread using this heap + */ + RAnalyzeToolMemoryAllocator( TBool aNotFirst ); + + /** + * Destructor. + */ + //lint -e{1510} suppress "base class 'RAllocator' has no destructor" + virtual ~RAnalyzeToolMemoryAllocator(); + + /** + * Uninstall the RAnalyzeToolMemoryAllocator + */ + virtual void Uninstall() = 0; + + /** + * Shares the heap for another thread + */ + virtual void ShareHeap() = 0; + + protected: + + /** + * Switch original allocator in use. + * Switches original allocator in use if not already. + */ + void SwitchOriginalAllocator(); + + /** + * Checks is the given address in loaded code memory area. + */ + inline bool IsAddressLoadedCode( TUint32& aAddress ); + + /* The original thread RAllocator */ + RAllocator* iAllocator; + + /* Is this the first thread using this heap */ + TBool iNotFirst; + + /* Memorymodel */ + TUint32 iMemoryModel; + + }; + +// INLINES +#include "analyzetoolmemoryallocator.inl" + +#endif // ANALYZETOOLMEMORYALLOCATOR_H + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/inc/analyzetoolmemoryallocator.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/inc/analyzetoolmemoryallocator.inl Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,54 @@ +/* +* 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: Definition for the inline functions of RAnalyzeToolMemoryAllocator. +* +*/ + + + +#include <analyzetool/atcommon.h> + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMemoryAllocator::IsAddressLoadedCode() +// Checks is the given address in loaded code memory area. +// ----------------------------------------------------------------------------- +// +inline bool RAnalyzeToolMemoryAllocator::IsAddressLoadedCode( TUint32& aAddress ) + { + // Debug log strings in this function are not used because + // this is called so many times. + /* + * TMemModelAttributes models. + * EMemModelTypeDirect // direct memory model on hardware + * EMemModelTypeMoving=1 // moving memory model on hardware + * EMemModelTypeMultiple=2 // multiple memory model on hardware + * EMemModelTypeEmul=3 // emulation using single host process + * Flexible ? + */ + switch( iMemoryModel ) + { + case EMemModelTypeMultiple: + // Use low & high limits which define rofs loading->rom area + // in multiple memory model. + if ( aAddress < KATMultipleMemoryModelLowLimit + || aAddress > KATMultipleMemoryModelHighLimit ) + return false; + return true; + default: + return true; + } + } + +// End of File + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/inc/analyzetoolpanics.pan --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/inc/analyzetoolpanics.pan Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,46 @@ +/* +* 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: Panic codes and definition of a panic function for the Memory Hook +* +*/ + + +#ifndef ANALYZETOOLPANICS_PAN_H +#define ANALYZETOOLPANICS_PAN_H + +_LIT( KAnalyzeToolName, "AnalyzeTool" ); + +/** AnalyzeTool application panic codes */ +enum TAnalyzeToolPanics + { + ENoMemory = 1, + EFailedToCreateHeap, + ECantOpenHandle, + ECantLoadDevice, + ECantAppendToTheArray, + ECantFindRightThread, + ECantConnectStorageServer, + ECantShareStorageServer, + ECantCreateMutex, + ECantLoadDeviceDriver, + ECantConnectDeviceDriver + // add further panics here + }; + +inline void AssertPanic(TAnalyzeToolPanics aReason) + { + User::Panic( KAnalyzeToolName, aReason ); + } + +#endif // ANALYZETOOLPANICS_PAN_H diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/inc/codeblock.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/inc/codeblock.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,74 @@ +/* +* 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: Declaration of the class TCodeblock. +* +*/ + + +#ifndef CODEBLOCK_H +#define CODEBLOCK_H + +// INCLUDES +#include <u32std.h> + +/** +* Stores information of process loaded code segments +*/ +class TCodeblock + { + + public: // Constructors + + /** + * C++ default constructor. + * @param aRunAddress Start address of the memory block. + * @param aSize The size of the memory block. + * @param aName The name of the library + */ + TCodeblock( TLinAddr aRunAddress, TUint32 aSize, TBuf8<KMaxLibraryName>& aName ); + + public: // New functions + + /** + * Checks if the given address is in this memory block area + * @param aAddress A address to be checked. + * @return TBool Returns ETrue if the given address is in this + * memory block area, EFalse otherwise + */ + TBool CheckAddress( TUint32 aAddress ); + + /** + * Matches if the given parameters represents this memory block + * @param aName The name of the library + * @return TBool Returns ETrue if the given parameters represents + * this memory block, EFalse otherwise + */ + TBool Match( TBuf8<KMaxLibraryName>& aName ); + + private: // Member variables + + /* Start address of the memory block */ + TLinAddr iStartAddress; + + /* End address of the memory block */ + TLinAddr iEndAddress; + + /* End address of the memory block */ + TBuf8<KMaxLibraryName> iName; + }; + +#endif // CODEBLOCK_H + +// End of File + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/inc/customuser.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/inc/customuser.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,207 @@ +/* +* 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: Declaration of the class CustomUser containing overloaded User static functions. +* +*/ + + +#ifndef CUSTOMUSER_H +#define CUSTOMUSER_H + +// INCLUDES +#include <u32std.h> + +// CONSTANTS +const TInt KATVersionLength = 20; +const TInt KATDefaultLogOption = 0; +const TInt KATDefaultDebug = 1; +const TInt KATDefaultAllocCallStackSize = 40; +const TInt KATDefaultFreeCallStackSize = 0; + +// TYPEDEFS +typedef TBuf<KATVersionLength> TATVersion; + +// Argument list for SetupThreadHeap function parameters. (currently not used) +// When needed, update the argument type directly inside _LIT macro. +_LIT( KATArgumentList, "%i%i" ); //etc. + +// CLASS DECLARATION + +/** +* Class which overloads the User functions and provides access to +* the overloaded functions +*/ +class CustomUser + { + public: // Enumerations + enum TATOptions + { + /** Acquiring the log filename */ + ELogFileName = 1, + /** Acquiring the version number */ + EVersion, + /** Acquiring logging option */ + ELogOption, + /** Acquiring UDEB/UREL information */ + EDebug, + /** Acquiring max allocation call stack size */ + EAllocCallStackSize, + /** Acquiring max free call stack size */ + EFreeCallStackSize + }; + + public: + + /** + * Overloaded version of User::Exit() + * Terminates the current thread, specifying a reason. All child + * threads are terminated and all resources are cleaned up.If the + * current thread is the main thread in a process, the process is + * also terminated. + * @param aReason The reason code. + */ + IMPORT_C static void Exit( TInt aReason ); + + /** + * Overloaded version of User::Panic() + * Panics the current thread, specifying a category name and panic + * number. Keep the length of the category name small; + * a length of 16 is ideal. + * @param aCategory A reference to the descriptor containing the text + * that defines the category for this panic. + * @param aReason The panic number. + */ + IMPORT_C static void Panic( const TDesC& aCategory, TInt aReason ); + + /** + * Overloaded version of UserHeap::SetupThreadHeap() + * Setups the threads heap. + * @param aNotFirst Is this first thread using specified heap + * @param aInfo Specifies the thread heap properties + * @param aFileName The name of the log file + * @param aLogOption The logging option for storage server + * @param aIsDebug Determines whether a binary is UDEB or UREL + * @param aVersion Atool version number + * @param aAllocCallStackSize Max number of stored callstack items when memory allocated + * @param aFreeCallStackSize Max number of stored callstack items when memory freed + * @param aFmt A descriptor containing the format string + * @return TInt KErrNone, if the insertion is successful, otherwise + * one of the system wide error codes. + */ + IMPORT_C static TInt SetupThreadHeap( + TBool aNotFirst, + SStdEpocThreadCreateInfo& aInfo, + const TFileName& aFileName, + TUint32 aLogOption, TUint32 aIsDebug, + const TATVersion& aVersion, + TUint32 aAllocCallStackSize, + TUint32 aFreeCallStackSize, + TRefByValue<const TDesC> aFmt, ... ); + + /** + * Overloaded version of UserHeap::SetCritical() + * Sets up or changes the effect that termination of the current + * thread has, either on its owning process, or on the whole system. + * The precise effect of thread termination is defined by the following + * specific values of the TCritical enum: + * ENotCritical + * EProcessCritical + * EProcessPermanent + * ESystemCritical + * ESystemPermanent + * Notes: The enum value EAllThreadsCritical cannot be set using this + * function. It is associated with a process, not a thread, and, if + * appropriate, should be set using User::SetProcessCritical(). + * The states associated with ENotCritical, EProcessCritical, + * EProcessPermanent, ESystemCritical and ESystemPermanent are all + * mutually exclusive, i.e. the thread can only be in one of these + * states at any one time. + * @param aCritical The state to be set. + * @return TInt KErrNone, if successful; KErrArgument, if + * EAllThreadsCritical is passed - this is a state associated with a + * process, and you use User::SetProcessCritical() to set it. + */ + IMPORT_C static TInt SetCritical( User::TCritical aCritical ); + + /** + * Overloaded version of UserHeap::SetCritical() + * Sets up or changes the effect that termination of subsequently + * created threads will have, either on the owning process, + * or on the whole system. It is important to note that we are not + * referring to threads that have already been created, but threads + * that will be created subsequent to a call to this function. + * The precise effect of thread termination is defined by the following + * specific values of the TCritical enum: + * ENotCritical + * EAllThreadsCritical + * ESystemCritical + * ESystemPermanent + * Notes: + * The enum values EProcessCritical and EProcessPermanent cannot be set + * using this function. They are states associated with a thread, not a + * process, and, if appropriate, should be set using + * User::SetCritical(). The states associated with ENotCritical, + * EAllThreadsCritical, ESystemCritical and ESystemPermanent are all + * mutually exclusive, i.e. the process can only be in one of these + * states at any one time. + * @param aCritical The state to be set. + * @return TInt 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. + */ + IMPORT_C static TInt SetProcessCritical( User::TCritical aCritical ); + + private: // Private functions + + /** + * Factory function for creating RAllocator instances. + * @param aNotFirst Is this first thread using specified heap + * @param aLogOption The logging option for storage server + * @param aFileName The name of the logging file + * @param aIsDebug Determines whether a binary is UDEB or UREL + * @param aAllocCallStackSize Max number of stored callstack items when memory allocated + * @param aFreecallStackSize Max number of stored callstack items when memory freed + * @return RAllocator& A reference to created allocator + */ + static RAllocator& InstallAllocator( TBool aNotFirst, + const TFileName& aFileName, + TUint32 aLogOption, TUint32 aIsDebug, + TUint32 aAllocCallStackSize, + TUint32 aFreeCallStackSize ); + + /** + * Check atool version + * @param aVersion - Atool version number. + * @param aToolVersion The atool version number + * @return KErrNone if correct version found, otherwise one of the system wide + * error codes. + */ + static TInt CheckVersion( const TATVersion& aVersion, TDes& aToolVersion ); + + /** + * Function for showing incorrect version information (file or debug channel). + * @param aLogOption The logging option + * @param aFileName The name of the log file + * @param aToolVersion The atool version number + */ + static void ReportIncorrectVersion( const TUint32 aLogOption, + const TFileName& aFileName, + const TDes& aToolVersion ); + + }; + +#endif // CUSTOMUSER_H + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/inc/threadstack.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/inc/threadstack.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,70 @@ +/* +* 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: Declaration of the class TThreadStack. +* +*/ + + +#ifndef THREADSTACK_H +#define THREADSTACK_H + +// INCLUDES +#include <u32std.h> + +// CLASS DECLARATION + +/** +* Stores thread id and the start of the thread's callstack +*/ +class TThreadStack + { + public: + + /** + * C++ default constructor. + * @param aId The thread id + * @param aStackStart The start of thread's stack + */ + TThreadStack( TThreadId aId, TUint32 aStackStart ); + + /** + * Checks if this is the current thread and if this is the current + * thread assings value to the given parameter + * @param aStackStart& A reference to stack start + * @return TBool The start of thread's stack + */ + TBool ThreadStackStart( TUint32& aStackStart ); + + /** + * Checks if this the the current thread + * @param aThreadId A thread id + * @return TBool ETrue it this is the current thread, EFalse otherwise + */ + TBool Match( const TUint aThreadId = 0 ); + + private: // Member variables + + /* The id of the thread */ + TThreadId iId; + + /* The start addess of this thread */ + TUint32 iStackStart; + }; + + +#endif // THREADSTACK_H + +// End of File + + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/sis/analyzetoolmemoryhook.pkg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/sis/analyzetoolmemoryhook.pkg Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,34 @@ +; +; 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: +; + +;Language - standard language definitions +&EN + +; standard SIS file header +#{"AnalyzeToolMemoryHook"},(0xEDF5A8B1),1,8,1 + +;Localised Vendor name +%{"Vendor-EN"} + +;Unique Vendor name +:"Vendor" + +;Supports Series 60 v 3.0 +[0x101F7961], 0, 0, 0, {"Series60ProductID"} + +; 1 File to install +"\epoc32\release\armv5\urel\atoolmemoryhook.dll"-"!:\sys\bin\atoolmemoryhook.dll" +"\epoc32\release\armv5\urel\atoolcleaner.dll" -"!:\sys\bin\atoolcleaner.dll" \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/src/analyzetoolallocator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/src/analyzetoolallocator.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,1014 @@ +/* +* 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 RAnalyzeToolAllocator. +* +*/ + + +#include "analyzetoolallocator.h" +#include "analyzetoolmemoryallocator.h" +#include "atlog.h" +#include "analyzetoolpanics.pan" +#include "analyzetoolfastlog.h" +#include <e32svr.h> + +// CONSTANTS + +// Length of the callstack address +const TUint32 KAddressLength = 4; + +// Thread count +const TInt KThreadCount = 1; + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::RAnalyzeToolAllocator() +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +RAnalyzeToolAllocator::RAnalyzeToolAllocator( TBool aNotFirst, + RATStorageServer& aStorageServer, + RArray<TCodeblock>& aCodeblocks, + RMutex& aMutex, + TUint aProcessId, + RAnalyzeTool& aAnalyzeTool, + TBool aStorageServerOpen, + TUint32 aLogOption, + TUint32 aAllocCallStackSize, + TUint32 aFreeCallStackSize ) : + RAnalyzeToolMemoryAllocator( aNotFirst ), + iStorageServer( aStorageServer ), + iCodeblocks( aCodeblocks ), + iMutex( aMutex ), + iProcessId( aProcessId ), + iThreadArray( KATMaxCallstackLength ), + iAnalyzeTool( aAnalyzeTool ), + iStorageServerOpen( aStorageServerOpen ), + iLogOption( aLogOption ), + iAllocMaxCallStack( aAllocCallStackSize ), + iFreeMaxCallStack( aFreeCallStackSize ) + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::RAnalyzeToolAllocator()" ); + + // Append thread to array of the users of this allocator + TThreadParamsBuf params; + params().iThreadId = RThread().Id().operator TUint(); + TInt error = iAnalyzeTool.ThreadStack( params ); + if ( KErrNone == error ) + { + LOGSTR2( "ATMH Thread stack address: %x", params().iStackAddress ); + LOGSTR2( "ATMH Thread stack size: %x", params().iStackSize ); + error = iThreadArray.Append( TThreadStack( RThread().Id(), + params().iStackAddress + params().iStackSize ) ); + } + + __ASSERT_ALWAYS( KErrNone == error, AssertPanic( ECantAppendToTheArray ) ); + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::~RAnalyzeToolAllocator() +// Destructor. +// ----------------------------------------------------------------------------- +// +RAnalyzeToolAllocator::~RAnalyzeToolAllocator() + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::~RAnalyzeToolAllocator()" ); + + // Close the thread array + iThreadArray.Close(); + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::Uninstall() +// Uninstalls the current allocator +// ----------------------------------------------------------------------------- +// +void RAnalyzeToolAllocator::Uninstall() + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::Uninstall()" ); + + // Switch back to the original allocator + SwitchOriginalAllocator(); + + // Check if this is shared allocator between threads + if ( iThreadArray.Count() > KThreadCount ) + { + // Close the shared allocator + Close(); + return; + } + +#if ( SYMBIAN_VERSION_SUPPORT >= SYMBIAN_3 ) + #ifndef __WINS__ + // Remove dummy Tls handle + UserSvr::DllFreeTls( KDummyHandle ); + #endif +#endif + + // Since this is the last thread using this allocator it can be deleted + delete this; + } + +#ifdef __WINS__ + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::Alloc() WINS version +// Allocates a cell of specified size from the heap. +// ----------------------------------------------------------------------------- +// +UEXPORT_C TAny* RAnalyzeToolAllocator::Alloc( TInt aSize ) + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::Alloc()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Alloc memory from the original allocator + TAny* p = iAllocator->Alloc( aSize ); + + LOGSTR3( "ATMH RAnalyzeToolAllocator::Alloc() - aSize: %i, address: %x", + aSize, (TUint32) p ); + + // Don't collect call stack and log data + // if storage server not open or logging mode not fast. + if ( iStorageServerOpen || iLogOption == EATLogToTraceFast ) + { + // Reset the callstack + iCallStack.Reset(); + + // Find the current thread callstack start address + TUint32 stackstart( 0 ); + TBool found( FindCurrentThreadStack( stackstart ) ); + LOGSTR3( "ATMH > stackstart: %x , found = %i", stackstart, found ); + + TUint32 _sp; + __asm + { + mov [_sp], esp + } + + // Get codeblocks count + TInt blocksCount( iCodeblocks.Count() ); + TInt error( KErrNone ); + TUint arrayCounter = 0; + + for ( TUint32 i = _sp; i < stackstart; i = i + KAddressLength )//lint !e1055 !e526 !e628 !e348 + { + TUint32 addr = (TUint32) *( (TUint32*) i ); + if ( ! IsAddressLoadedCode( addr ) ) + continue; + for ( TInt j = 0; j < blocksCount; j++ ) + { + if ( iCodeblocks[j].CheckAddress( addr ) ) + { + // To avoid recursive call to ReAlloc specifying granularity + // Add address to the callstack + iCallStack[arrayCounter] = ( addr ); + arrayCounter++; + break; + } + } + if ( arrayCounter == KATMaxCallstackLength || + arrayCounter == iAllocMaxCallStack ) + { + LOGSTR2( "ATMH > Wanted CallStack items ready( %i )", arrayCounter ); + break; + } + } + // Log the memory allocation information + if ( iLogOption == EATLogToTraceFast ) + { + // Using fast mode. + ATFastLogMemoryAllocated( iProcessId, (TUint32) p, iCallStack, aSize ); + } + else + { + // Using storage server. + error = iStorageServer.LogMemoryAllocated( (TUint32) p, + iCallStack, + aSize ); + if ( KErrNone != error ) + { + LOGSTR2( "ATMH LogMemoryAllocated error %i", error ); + switch ( error ) + { + case KErrNoMemory: + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Alloc() - KErrNoMemory case" ); + if ( iStorageServerOpen ) + { + iStorageServerOpen = EFalse; + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Alloc() - close iStorageServer" ); + iStorageServer.Close(); + } + break; + } + } + } + } + // Release the mutex + iMutex.Signal(); + + return p; + } +#else + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::Alloc() ARMV5 version +// Allocates a cell of specified size from the heap. +// ----------------------------------------------------------------------------- +// +TAny* RAnalyzeToolAllocator::Alloc( TInt aSize ) + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::Alloc()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Alloc memory from the original allocator + TAny* p = iAllocator->Alloc( aSize ); + + // Don't collect call stack and log data + // if storage server not open or logging mode not fast. + if ( iStorageServerOpen || iLogOption == EATLogToTraceFast ) + { + // Reset the callstack + iCallStack.Reset(); + + // Find the current thread callstack start address + TUint32 stackstart( 0 ); + TBool found( FindCurrentThreadStack( stackstart ) ); + LOGSTR3( "ATMH > stackstart: %x , found = %i", stackstart, found ); + + // Get codeblocks count + TInt blocksCount( iCodeblocks.Count() ); + TInt error( KErrNone ); + TUint arrayCounter = 0; + + for ( TUint32 i = __current_sp(); i < stackstart; i = i + KAddressLength )//lint !e1055 !e526 !e628 !e348 + { + TUint32 addr = (TUint32) *( (TUint32*) i ); + if ( ! IsAddressLoadedCode( addr ) ) + continue; + for ( TInt j = 0; j < blocksCount; j++ ) + { + if ( iCodeblocks[j].CheckAddress( addr ) ) + { + // To avoid recursive call to ReAlloc specifying granularity + // Add address to the callstack + iCallStack[arrayCounter] = ( addr ); + arrayCounter++; + break; + } + } + if ( arrayCounter == KATMaxCallstackLength || + arrayCounter == iAllocMaxCallStack ) + { + LOGSTR2( "ATMH > Wanted CallStack items ready( %i )", arrayCounter ); + break; + } + } + // Log the memory allocation information + if ( iLogOption == EATLogToTraceFast ) + { + // Fast mode. + ATFastLogMemoryAllocated( iProcessId, (TUint32) p, iCallStack, aSize ); + } + else + { + // Using storage server. + error = iStorageServer.LogMemoryAllocated( (TUint32) p, + iCallStack, + aSize ); + if ( KErrNone != error ) + { + LOGSTR2( "ATMH LogMemoryAllocated error %i", error ); + switch ( error ) + { + case KErrNoMemory: + LOGSTR1( "ATMH RAnalyzeToolAllocator::Alloc() - KErrNoMemory case" ); + if ( iStorageServerOpen ) + { + iStorageServerOpen = EFalse; + LOGSTR1( "ATMH RAnalyzeToolAllocator::Alloc() - close iStorageServer" ); + iStorageServer.Close(); + } + break; + } + } + } + } + + // Release the mutex + iMutex.Signal(); + + // Return the allocatated memory + return p; + } +#endif // __WINS__ + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::Free() +// Frees the allocated memory +// ----------------------------------------------------------------------------- +// +TAny RAnalyzeToolAllocator::Free( TAny* aPtr ) + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::Free()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Don't collect or log data if storage server not open or logging mode not fast. + if ( iStorageServerOpen || iLogOption == EATLogToTraceFast ) + { + // Reset the callstack + iFreeCallStack.Reset(); + + // Check if trace logging mode because free call stack is not used in other log options. + if ( (iLogOption == EATUseDefault || iLogOption == EATLogToTrace || iLogOption == EATLogToTraceFast ) + && iFreeMaxCallStack > 0 ) + { + // Find the current thread callstack start address + TUint32 stackstart( 0 ); + TBool found( FindCurrentThreadStack( stackstart ) ); + LOGSTR3( "ATMH > stackstart: %x , found = %i", stackstart, found ); + TUint32 _sp; + + #ifdef __WINS__ + __asm + { + mov [_sp], esp + } + #else + _sp = __current_sp(); + #endif + + // Get codeblocks count + TInt blocksCount( iCodeblocks.Count() ); + TUint arrayCounter = 0; + + for ( TUint32 i = _sp; i < stackstart; i = i + KAddressLength )//lint !e1055 !e526 !e628 !e348 + { + TUint32 addr = (TUint32) *( (TUint32*) i ); + if ( ! IsAddressLoadedCode( addr ) ) + continue; + for ( TInt j = 0; j < blocksCount; j++ ) + { + if ( iCodeblocks[j].CheckAddress( addr ) ) + { + // To avoid recursive call to ReAlloc specifying granularity + // Add address to the callstack + iFreeCallStack[arrayCounter] = addr; + arrayCounter++; + break; + } + } + if ( arrayCounter == KATMaxFreeCallstackLength || + arrayCounter == iFreeMaxCallStack ) + { + break; + } + } + LOGSTR2( "ATMH > iFreeCallStack count ( %i )", arrayCounter ); + } + + // Log freed memory. + if ( iLogOption == EATLogToTraceFast ) + { + // Using fast mode. + ATFastLogMemoryFreed( iProcessId, (TUint32) aPtr, iFreeCallStack ); + } + else + { + // Using storage server. + TInt err( iStorageServer.LogMemoryFreed( (TUint32) aPtr, iFreeCallStack ) ); + if ( err != KErrNone ) + { + LOGSTR2( "ATMH > LogMemoryFreed err( %i )", err ); + } + } + } + + // Free the memory using original allocator + iAllocator->Free( aPtr ); + + LOGSTR2( "ATMH RAnalyzeToolAllocator::Free() - aPtr: %x", (TUint32)aPtr ); + + // Release the mutex + iMutex.Signal(); + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::Open() +// Opens this heap for shared access. Opening the heap increases +// the heap's access count by one. +// ----------------------------------------------------------------------------- +// +TInt RAnalyzeToolAllocator::Open() + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::Open()"); + + // Acquire the mutex + iMutex.Wait(); + + // Share the memory using original allocator + TInt error = iAllocator->Open(); + + // If everything is OK add thread to the array which use this allocator + if ( KErrNone == error ) + { + TThreadParamsBuf params; + params().iThreadId = RThread().Id().operator TUint(); + error = iAnalyzeTool.ThreadStack( params ); + + __ASSERT_ALWAYS( KErrNone == error, AssertPanic( ECantAppendToTheArray ) ); + + if ( KErrNone == error ) + { + LOGSTR2( "ATMH Thread stack address: %x", params().iStackAddress ); + LOGSTR2( "ATMH Thread stack size: %x", params().iStackSize ); + iThreadArray.Append( TThreadStack( RThread().Id(), + params().iStackAddress + params().iStackSize ) ); + } + } + + // Release the mutex + iMutex.Signal(); + + // Return the error code + return error; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::Close() +// Closes this shared heap. Closing the heap decreases the heap's +// access count by one. +// ----------------------------------------------------------------------------- +// +void RAnalyzeToolAllocator::Close() + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::Close()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Close the memory using original allocator + iAllocator->Close(); + + TInt count = iThreadArray.Count(); + + // Iterate through array of threads to remove current thread + for ( TInt i = 0; i < count; i++ ) + { + // Check if this is current thread + if ( iThreadArray[ i ].Match() ) + { + // Remove the thread + iThreadArray.Remove( i ); + break; + } + } + + // Release the mutex + iMutex.Signal(); + } + +#ifdef __WINS__ + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::ReAlloc() +// Increases or decreases the size of an existing cell. +// ----------------------------------------------------------------------------- +// +TAny* RAnalyzeToolAllocator::ReAlloc( TAny* aPtr, TInt aSize, TInt aMode ) + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::ReAlloc()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Realloc the memory using original allocator + TAny* ptr = iAllocator->ReAlloc( aPtr, aSize, aMode ); + + // NULL addresses are not in a process under test + if ( ptr && !( aMode & ENeverMove ) ) + { + LOGSTR3( "ATMH RAnalyzeToolAllocator::ReAlloc() - aPtr: %x, ptr: %x", + (TUint32)aPtr, (TUint32)ptr ); + LOGSTR3( "ATMH RAnalyzeToolAllocator::ReAlloc() - aSize: %i, aMode: %i", + aSize, aMode ); + + // Don't collect or log data if storage server not open or logging mode fast. + if ( iStorageServerOpen || iLogOption == EATLogToTraceFast ) + { + // Reset the callstack + iReCallStack.Reset(); + + // Find the current thread callstack start address + TUint32 stackstart( 0 ); + TBool found( FindCurrentThreadStack( stackstart ) ); + LOGSTR3( "ATMH > stackstart: %x , found = %i", stackstart, found ); + + // Get current sp + TUint32 _sp( 0 ); + __asm + { + mov [_sp], esp + } + + // Get codeblocks count + TInt blocksCount( iCodeblocks.Count() ); + TInt error( KErrNone ); + TUint arrayCounter = 0; + + for ( TUint32 i = _sp; i < stackstart; i = i + KAddressLength )//lint !e1055 !e526 !e628 !e348 + { + TUint32 addr = (TUint32) *( (TUint32*) i ); + if ( ! IsAddressLoadedCode( addr ) ) + continue; + for ( TInt j = 0; j < blocksCount; j++ ) + { + if ( iCodeblocks[j].CheckAddress( addr ) ) + { + // To avoid recursive call to ReAlloc specifying granularity + // Add address to the callstack + iReCallStack[arrayCounter] = addr; + arrayCounter++; + break; + } + } + if ( arrayCounter == KATMaxCallstackLength || + arrayCounter == iAllocMaxCallStack ) + { + LOGSTR2( "ATMH > Wanted CallStack items ready( %i )", arrayCounter ); + break; + } + } + + // No need to report free if the aPtr was NULL + if ( aPtr != NULL ) + { + // Reset the free callstack + iFreeCallStack.Reset(); + + // if trace logging mode(s) we also log call stack in free. + if ( ( iLogOption == EATUseDefault || iLogOption == EATLogToTrace || iLogOption == EATLogToTraceFast ) + && iFreeMaxCallStack > 0 ) + { + for ( TInt i = 0; i < arrayCounter; i++ ) + { + if ( i == KATMaxFreeCallstackLength || i == iFreeMaxCallStack ) + { + break; + } + iFreeCallStack[i] = iReCallStack[i]; + } + } + + // Try to remove old address from the storage server's + // leak array. If found it's removed from the array because system frees + // old address directly in the RHeap in ReAlloc case. + if ( iLogOption == EATLogToTraceFast ) + { + ATFastLogMemoryFreed( iProcessId, (TUint32) aPtr, iFreeCallStack ); + } + else + { + iStorageServer.LogMemoryFreed( (TUint32) aPtr, iFreeCallStack ); + } + } + + // Log the memory allocation information + if ( iLogOption == EATLogToTraceFast ) + { + // Using fast mode. + ATFastLogMemoryAllocated( iProcessId, (TUint32) ptr, iFreeCallStack, aSize); + } + else + { + // Using storage server. + error = iStorageServer.LogMemoryAllocated( (TUint32) ptr, + iReCallStack, + aSize ); + if ( KErrNone != error ) + { + LOGSTR2( "ATMH LogMemoryAllocated ReAlloc error %i", error ); + switch ( error ) + { + case KErrNoMemory: + LOGSTR1( "ATMH RAnalyzeToolAllocator::ReAlloc() - KErrNoMemory case" ); + if ( iStorageServerOpen ) + { + iStorageServerOpen = EFalse; + LOGSTR1( "ATMH RAnalyzeToolAllocator::ReAlloc() - close iStorageServer" ); + iStorageServer.Close(); + } + break; + } + } + } + } + } + + // Release the mutex + iMutex.Signal(); + + // Return pointer to the reallocated cell + return ptr; + } + +#else + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::ReAlloc() +// Increases or decreases the size of an existing cell. +// ----------------------------------------------------------------------------- +// +TAny* RAnalyzeToolAllocator::ReAlloc( TAny* aPtr, TInt aSize, TInt aMode ) + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::ReAlloc()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Realloc the memory using original allocator + TAny* ptr = iAllocator->ReAlloc( aPtr, aSize, aMode ); + + // NULL addresses are not in a process under test + if ( ptr && !( aMode & ENeverMove ) ) + { + LOGSTR3( "ATMH RAnalyzeToolAllocator::ReAlloc() - aPtr: %x, ptr: %x", + (TUint32)aPtr, (TUint32)ptr ); + LOGSTR3( "ATMH RAnalyzeToolAllocator::ReAlloc() - aSize: %i, aMode: %i", + aSize, aMode ); + + // Don't collect or log data if storage server not open or logging mode fast. + if ( iStorageServerOpen || iLogOption == EATLogToTraceFast ) + { + // Reset the callstack + iReCallStack.Reset(); + + // Find the current thread callstack start address + TUint32 stackstart( 0 ); + TBool found( FindCurrentThreadStack( stackstart ) ); + LOGSTR3( "ATMH > stackstart: %x , found = %i", stackstart, found ); + + // Get codeblocks count + TInt blocksCount( iCodeblocks.Count() ); + TInt error( KErrNone ); + TUint arrayCounter = 0; + + for ( TUint32 i = __current_sp(); i < stackstart; i = i + KAddressLength )//lint !e1055 !e526 !e628 !e348 + { + TUint32 addr = (TUint32) *( (TUint32*) i ); + if ( ! IsAddressLoadedCode( addr ) ) + continue; + for ( TInt j = 0; j < blocksCount; j++ ) + { + if ( iCodeblocks[j].CheckAddress( addr ) ) + { + // To avoid recursive call to ReAlloc specifying granularity + // Add address to the callstack + iReCallStack[arrayCounter] = ( addr ); + arrayCounter++; + break; + } + } + if ( arrayCounter == KATMaxCallstackLength || + arrayCounter == iAllocMaxCallStack ) + { + LOGSTR2( "ATMH > Wanted CallStack items ready( %i )", arrayCounter ); + break; + } + } + + // No need to report free if the aPtr was NULL + if ( aPtr != NULL ) + { + // Reset the free callstack + iFreeCallStack.Reset(); + + // if trace logging mode(s) we also log call stack with free. + if ( ( iLogOption == EATUseDefault || iLogOption == EATLogToTrace || iLogOption == EATLogToTraceFast ) + && iFreeMaxCallStack > 0 ) + { + for ( TInt i = 0; i < arrayCounter; i++ ) + { + if ( i == iFreeCallStack.Count() ) + { + break; + } + iFreeCallStack[i] = iReCallStack[i]; + } + } + + // Try to remove old address from the storage server's + // leak array. If found it's removed from the array because system frees + // old address directly in the RHeap in ReAlloc case. + if ( iLogOption == EATLogToTraceFast ) + { + ATFastLogMemoryFreed( iProcessId, (TUint32) aPtr, iFreeCallStack ); + } + else + { + iStorageServer.LogMemoryFreed( (TUint32) aPtr, iFreeCallStack ); + } + } + + // Log the memory allocation information + if ( iLogOption == EATLogToTraceFast ) + { + // Using fast mode. + ATFastLogMemoryAllocated( iProcessId, (TUint32) ptr, iReCallStack, aSize ); + } + else + { + // Using storage server. + error = iStorageServer.LogMemoryAllocated( (TUint32) ptr, + iReCallStack, + aSize ); + if ( KErrNone != error ) + { + LOGSTR2( "ATMH LogMemoryAllocated ReAlloc error %i", error ); + switch ( error ) + { + case KErrNoMemory: + LOGSTR1( "ATMH RAnalyzeToolAllocator::ReAlloc() - KErrNoMemory case" ); + if ( iStorageServerOpen ) + { + iStorageServerOpen = EFalse; + LOGSTR1( "ATMH RAnalyzeToolAllocator::ReAlloc() - close iStorageServer" ); + iStorageServer.Close(); + } + break; + } + } + } + } + } + + // Release the mutex + iMutex.Signal(); + + // Return pointer to the reallocated cell + return ptr; + } + +#endif // __WINS__ + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::Compress() +// The function frees excess committed space from the top of the heap. +// The size of the heap is never reduced below the minimum size +// specified during creation of the heap. +// ----------------------------------------------------------------------------- +// +TInt RAnalyzeToolAllocator::Compress() + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::Compress()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Compress the memory using original allocator + TInt compress = iAllocator->Compress(); + + // Release the mutex + iMutex.Signal(); + + // Return the space reclaimed + return compress; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::Reset() +// Frees all allocated cells on this heap. +// ----------------------------------------------------------------------------- +// +void RAnalyzeToolAllocator::Reset() + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::Reset()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Reset the memory using original allocator + iAllocator->Reset(); + + // Release the mutex + iMutex.Signal(); + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::AllocSize() +// Gets the number of cells allocated on this heap, and +// the total space allocated to them. +// ----------------------------------------------------------------------------- +// +TInt RAnalyzeToolAllocator::AllocSize( TInt& aTotalAllocSize ) const + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::AllocSize()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Acquire the memory information using original allocator + TInt size = iAllocator->AllocSize( aTotalAllocSize ); + + // Release the mutex + iMutex.Signal(); + + // Return the number of cells allocated on this heap. + return size; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::Available() +// Gets the total free space currently available on the heap and the +// space available in the largest free block. The space available +// represents the total space which can be allocated. Note that +// compressing the heap may reduce the total free space available +// and the space available in the largest free block. +// ----------------------------------------------------------------------------- +// +TInt RAnalyzeToolAllocator::Available( TInt& aBiggestBlock ) const + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::Available()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Acquire the memory information using original allocator + TInt available = iAllocator->Available( aBiggestBlock ); + + // Release the mutex + iMutex.Signal(); + + // Return the total free space currently available on the heap + return available; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::AllocLen() +// Gets the length of the available space in the specified +// allocated cell. +// ----------------------------------------------------------------------------- +// +TInt RAnalyzeToolAllocator::AllocLen( const TAny* aCell ) const + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::AllocLen()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Acquire the memory information using original allocator + TInt len = iAllocator->AllocLen( aCell ); + + // Release the mutex + iMutex.Signal(); + + // Return the length of the available space in the allocated cell. + return len; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::DebugFunction() +// Invocates specified debug funtionality. +// ----------------------------------------------------------------------------- +// +TInt RAnalyzeToolAllocator::DebugFunction( TInt aFunc, TAny* a1, TAny* a2 ) + { + LOGSTR2( "ATMH RAnalyzeToolAllocator::DebugFunction() %i", aFunc ); + + // Acquire the mutex + iMutex.Wait(); + + // Invocate debug funtion using original allocator + TInt debug = iAllocator->DebugFunction( aFunc, a1, a2 ); + + switch( aFunc ) + { + case EMarkEnd: + { + // Disables the __UHEAP_MARKEND macro + LOGSTR1( "ATMH __UHEAP_MARKEND macro called" ); + if ( debug > 0 ) + { + LOGSTR2( "ATMH __UHEAP_MARKEND detects leaks: %d", debug ); + // Because there is leaks the alloc panic will occur but + // lets return a zero to pretend that everything is OK + debug = 0; + } + } + break; + + default: + { + } + break; + } + + // Release the mutex + iMutex.Signal(); + + // Return information of the debug function success + return debug; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::Extension_() +// Extension function +// ----------------------------------------------------------------------------- +// +TInt RAnalyzeToolAllocator::Extension_( TUint aExtensionId, TAny*& a0, + TAny* a1 ) + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::Extension_()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Invocate extension funtion using original allocator + TInt ext = RAllocator::Extension_( aExtensionId, a0, a1 ); + + // Release the mutex + iMutex.Signal(); + + // Return information of the extension function success + return ext; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::ShareHeap() +// Share heap with other thread +// ----------------------------------------------------------------------------- +// +void RAnalyzeToolAllocator::ShareHeap() + { + LOGSTR1( "ATMH RAnalyzeToolAllocator::ShareHeap()" ); + + // Call the overwrited Open function + Open(); + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolAllocator::FindCurrentThreadStack() +// Find the current thread which is using the heap +// ----------------------------------------------------------------------------- +// +TBool RAnalyzeToolAllocator::FindCurrentThreadStack( TUint32& aStackStart ) + { + LOGSTR2( "ATMH RAnalyzeToolAllocator::FindCurrentThreadStack(), count( %i )", + iThreadArray.Count() ); + + // Flag for indicating that right thread has been found + TBool found( EFalse ); + // If threre is only one thread it must be the right thread + if ( iThreadArray.Count() == KThreadCount ) + { + if ( !iThreadArray[ 0 ].ThreadStackStart( aStackStart ) ) + { + // This MUST BE the right thread + //__ASSERT_ALWAYS( EFalse, AssertPanic( ECantFindRightThread ) ); + } + else if ( iThreadArray[ 0 ].ThreadStackStart( aStackStart ) ) + { + found = ETrue; + } + } + else + { + // Iterate through array to find right thread + TInt count( iThreadArray.Count() ); + + for ( TInt i = 0; i < count; i++ ) + { + // Check if this is the right thread + if ( iThreadArray[ i ].ThreadStackStart( aStackStart ) ) + { + // Right thread found. Mark the flag + found = ETrue; + break; + } + } + // If right thread was not found the panic must be raised + if ( !found ) + { + //__ASSERT_ALWAYS( EFalse, AssertPanic( ECantFindRightThread ) ); + } + } + return found; + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/src/analyzetooleventhandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/src/analyzetooleventhandler.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,230 @@ +/* +* 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 CLibraryEventHandler. +* +*/ + + +// INCLUDE FILES +#include "atlog.h" +#include "analyzetooleventhandler.h" +#include "analyzetooleventhandlernotifier.h" +#include "analyzetoolmemoryallocator.h" +#include "analyzetoolfastlog.h" + +// ----------------------------------------------------------------------------- +// CLibraryEventHandler::~CLibraryEventHandler() +// Destructor. +// ----------------------------------------------------------------------------- +// +CLibraryEventHandler::~CLibraryEventHandler() + { + LOGSTR1( "ATMH CLibraryEventHandler::~CLibraryEventHandler()" ); + Cancel(); + } + +// ----------------------------------------------------------------------------- +// CLibraryEventHandler::RunL() +// Process active object's task +// ----------------------------------------------------------------------------- +// +void CLibraryEventHandler::RunL() + { + LOGSTR1( "ATMH CLibraryEventHandler::RunL()" ); + + if ( KErrNone != iStatus.Int() ) + { + LOGSTR2( "ATMH RunL error: %i", iStatus.Int() ); + return; + } + // Acquire the mutex + iMutex.Wait(); + + // Check that this is observed process + if ( iLibraryInfo.iEventType == TLibraryEventInfo::ELibraryAdded ) + { + LOGSTR1( "ATMH CLibraryEventHandler::RunL() - TLibraryEventInfo::ELibraryAdded" ); + if ( iLibraryInfo.iProcessId == iProcessId ) + { + TInt error( KErrNone ); + + // Log library load event. + if ( iLogOption == EATLogToTraceFast ) + { + LOGSTR1( "ATMH CLibraryEventHandler::RunL() - ATFastLog.LogDllLoaded() " ); + ATFastLogDllLoaded( iProcessId, + iLibraryInfo.iLibraryName, + iLibraryInfo.iRunAddress, + iLibraryInfo.iRunAddress + iLibraryInfo.iSize ); + } + else + { + LOGSTR1( "ATMH CLibraryEventHandler::RunL() - iStorageServer.LogDllLoaded() " ); + error = iStorageServer.LogDllLoaded( + iLibraryInfo.iLibraryName, + iLibraryInfo.iRunAddress, + iLibraryInfo.iRunAddress + iLibraryInfo.iSize ); + LOGSTR2( "ATMH StorageServer error: %i", error ); + } + if ( KErrNone == error ) + { + iCodeblocks.Append( TCodeblock( iLibraryInfo.iRunAddress, + iLibraryInfo.iSize, + iLibraryInfo.iLibraryName ) ); + } + } + } + else if ( iLibraryInfo.iEventType == TLibraryEventInfo::ELibraryRemoved ) + { + LOGSTR1( "ATMH CLibraryEventHandler::RunL() - TLibraryEventInfo::ELibraryRemoved " ); + TInt count = iCodeblocks.Count(); + LOGSTR2( "ATMH count of code blocks: %i", count ); + for ( TInt i = 0; i < count; i++ ) + { + if ( iCodeblocks[ i ].Match( iLibraryInfo.iLibraryName ) ) + { + TBuf8<KMaxLibraryName> libraryName; + libraryName.Copy( iLibraryInfo.iLibraryName ); + + // Log library unloaded event + if ( iLogOption == EATLogToTraceFast ) + { + LOGSTR1( "ATMH CLibraryEventHandler::RunL() - ATFastLogDllUnloaded() " ); + ATFastLogDllUnloaded( iProcessId, + libraryName, + iLibraryInfo.iRunAddress, + iLibraryInfo.iRunAddress + iLibraryInfo.iSize ); + } + else + { + LOGSTR1( "ATMH CLibraryEventHandler::RunL() - iStorageServer.LogDllUnloaded() " ); + #ifdef LOGGING_ENABLED + TInt error = iStorageServer.LogDllUnloaded( + libraryName/*iLibraryInfo.iLibraryName*/, + iLibraryInfo.iRunAddress, + iLibraryInfo.iRunAddress + iLibraryInfo.iSize ); + + LOGSTR2( "ATMH StorageServer error: %i", error ); + #else + iStorageServer.LogDllUnloaded( + libraryName/*iLibraryInfo.iLibraryName*/, + iLibraryInfo.iRunAddress, + iLibraryInfo.iRunAddress + iLibraryInfo.iSize ); + #endif + } + iCodeblocks.Remove( i ); + break; + } + } + } + else if ( iLibraryInfo.iEventType == TLibraryEventInfo::EKillThread ) + { + LOGSTR1( "ATMH CLibraryEventHandler::RunL() - TLibraryEventInfo::EKillThread" ); + + iNotifier.RemoveKilledThread( iLibraryInfo.iThreadId ); + } + + Start(); + + // Release the mutex + iMutex.Signal(); + } + +// ----------------------------------------------------------------------------- +// CLibraryEventHandler::DoCancel() +// Cancels active object's task +// ----------------------------------------------------------------------------- +// +void CLibraryEventHandler::DoCancel() + { + LOGSTR1( "ATMH CLibraryEventHandler::DoCancel()" ); + // Cancel the subscription of the library events + if ( IsActive() ) + { + iStarted = EFalse; + + iAnalyzeTool.CancelLibraryEvent(); + } + } + +// ----------------------------------------------------------------------------- +// CLibraryEventHandler::Start() +// Creates CActiveScheduler and variables for the child thread +// ----------------------------------------------------------------------------- +// +void CLibraryEventHandler::Start() + { + LOGSTR1( "ATMH CLibraryEventHandler::Start()" ); + + // Acquire the mutex + iMutex.Wait(); + + if ( !IsAdded() ) + { + CActiveScheduler::Add( this ); + } + + // Cancel current subscribetion + if ( IsActive() ) + { + iStarted = EFalse; + Cancel(); + } + + iStatus = KErrNone; + iAnalyzeTool.LibraryEvent( iStatus, iLibraryInfo ); + SetActive(); + + iStarted = ETrue; + // Release the mutex + iMutex.Signal(); + } + +// ----------------------------------------------------------------------------- +// CLibraryEventHandler::CLibraryEventHandler() +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CLibraryEventHandler::CLibraryEventHandler( RAnalyzeTool& aAnalyzeTool, + RArray<TCodeblock>& aCodeblocks, RATStorageServer& aStorageServer, + TUint aProcessId, RMutex& aMutex, + MAnalyzeToolEventhandlerNotifier& aNotifier, + TUint32 aLogOption ) + : CActive( EPriorityNormal ), + iAnalyzeTool( aAnalyzeTool ), + iCodeblocks( aCodeblocks ), + iStorageServer( aStorageServer ), + iProcessId( aProcessId ), + iMutex( aMutex ), + iStarted( EFalse ), + iNotifier( aNotifier ), + iLogOption( aLogOption ) + { + LOGSTR1( "ATMH CLibraryEventHandler::CLibraryEventHandler()" ); + } + +// ----------------------------------------------------------------------------- +// CLibraryEventHandler::IsStarted() +// Returns eventhandler's state. +// ----------------------------------------------------------------------------- +// +TBool CLibraryEventHandler::IsStarted() + { + LOGSTR2( "ATMH CLibraryEventHandler::IsStarted(%i)", iStarted ); + + return iStarted; + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/src/analyzetoolfastlog.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/src/analyzetoolfastlog.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,298 @@ +/* +* 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: +* +*/ + + +#include <e32debug.h> // RDebug +#include <analyzetool/analyzetooltraceconstants.h> +#include "analyzetoolfastlog.h" +#include "atlog.h" + +// Local time function. +TInt64 CurrentTime() + { + LOGSTR1( "ATFL CurrentTime()" ); + TTime time; + time.UniversalTime(); + return time.Int64() - KMicroSecondsAt1970; + } + +TInt ATFastLogProcessStarted( const TDesC8& aProcessName, + TUint aProcessId, + TUint32 aIsDebug ) + { + LOGSTR1( "ATFL ATFastLogProcessStarted()" ); + // Convert process name to 16-bit descriptor. + TBuf<KMaxProcessName> processName; + processName.Copy( aProcessName ); + // Buffer to trace. + TBuf<KProcessStartBufLength> buffer; + // Format process name and id. + buffer.Format( KProcessStart16, &processName, aProcessId ); + // Timestamp. + buffer.AppendNum( CurrentTime(), EHex ) ; + // Append udeb/urel information to the process start. + buffer.Append( KSpaceTrace ); + buffer.AppendNum( aIsDebug, EHex ); + // Append version number. + buffer.Append( KSpaceTrace ); + buffer.AppendNum( KATTraceVersion, EHex ); + // Log to trace. + RDebug::Print( KTraceMessage, aProcessId ,&buffer ); + return KErrNone; + } + +TInt ATFastLogProcessEnded( TUint aProcessId, + TUint aHandleLeakCount ) + { + LOGSTR1( "ATFL ATFastLogProcessEnded()" ); + // Handle leaks. + if ( aHandleLeakCount > 0 ) + { + // Buffer to trace. + TBuf<KHandleLeakBufLength> buffer2; + buffer2.Format( KHandleLeak16, &KUnknownModule16, aHandleLeakCount ); + // Trace it. + RDebug::Print( KTraceMessage, aProcessId, &buffer2 ); + } + // Process end trace. + TBuf<KProcessEndBufLength> buffer; + buffer.Format( KProcessEnd16, aProcessId ); + buffer.AppendNum( CurrentTime(), EHex); + buffer.Append( KNewLineTrace ); + RDebug::Print( KTraceMessage, aProcessId, &buffer ); + return KErrNone; + } + +TInt ATFastLogDllLoaded( TUint aProcessId, + const TDesC8& aDllName, + TUint32 aStartAddress, + TUint32 aEndAddress ) + { + LOGSTR1( "ATFL ATFastLogDllLoaded()" ); + // Timestamp. + TInt64 time = CurrentTime(); + // Convert dll name to 16-bit descriptor. + TBuf<KMaxLibraryName> dll; + dll.Copy( aDllName ); + // Buffer to trace. + TBuf<KDllLoadBufLength> buffer; + buffer.Format( KDllLoad16, &dll, time, aStartAddress, aEndAddress ); + RDebug::Print( KTraceMessage, aProcessId, &buffer ); + return KErrNone; + } + +TInt ATFastLogDllUnloaded( TUint aProcessId, const TDesC8& aDllName, TUint32 aStartAddress, + TUint32 aEndAddress ) + { + LOGSTR1( "ATFL ATFastLogDllUnloaded()" ); + // Timestamp. + TInt64 time = CurrentTime(); + // Convert dll name to 16-bit descriptor. + TBuf<KMaxLibraryName> dll; + dll.Copy( aDllName ); + // Buffer to trace. + TBuf<KDllLoadBufLength> buffer; + buffer.Format( KDllUnload16, &dll, time, aStartAddress, aEndAddress ); + RDebug::Print( KTraceMessage, aProcessId, &buffer ); + return KErrNone; + } + +TInt ATFastLogMemoryAllocated( TUint aProcessId, TUint32 aMemAddress, + TFixedArray<TUint32, KATMaxCallstackLength>& aCallstack, + TInt aSize ) + { + LOGSTR1( "ATFL ATFastLogMemoryAllocated()" ); + // ALLOCH <Memory address> <Time stamp> <Allocation size> <Call stack address count> + // <Call stack address> <Call stack address> ... + + // Timestamp. + TInt64 time = CurrentTime(); + + // Trace buffer and pointer to it. + TBufC<KMemAllocBufLength> buffer; + TPtr ptr( buffer.Des() ); + // Append the tag implying a memory allocation line in the data file + ptr.Append( KMemoryAllocHeader ); + + // Append the start address of this allocation in the 32-bit (max 8 characters) + // hexadecimal text format. + ptr.AppendNum( aMemAddress, EHex ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + ptr.Append( KSpaceTrace ); + ptr.AppendNum( time, EHex ); + + // Append the size of the allocation in the 32-bit (max 8 characters) hexadecimal + // text format. + ptr.Append( KSpaceTrace ); + ptr.AppendNum( aSize, EHex ); + + // Search call stack for address count. + TInt addrCount(0); + for ( TInt j = 0; j < aCallstack.Count() ; j++ ) + { + if ( aCallstack.At(j) == 0 ) + break; + addrCount++; + } + // Current position in call stack. + TInt addrPos( 0 ); + + // Append address count. + ptr.Append( KSpaceTrace ); + ptr.AppendNum( addrCount, EHex ); + + // Calculate last item length + TInt lastItemLength( KTraceMessage().Length() + KHexa32Length + + KSpaceLength + KNewlineLength ); + + TUint packetNumber( 1 ); + + // Go through all call stack's memory addresses associated with + // this memory allocation + for ( TInt j = 0; j < addrCount; j++ ) + { + // ALLOCF <Memory address> <Time stamp> <Packet number> + // <Call stack address> <Call stack address> ... + if ( ptr.Length() <= 0 ) + { + // Create alloc fragment message header + ptr.Append( KMemoryAllocFragment ); + ptr.AppendNum( aMemAddress, EHex ); + ptr.Append( KSpaceTrace ); + ptr.AppendNum( time, EHex ); + ptr.Append( KSpaceTrace ); + ptr.AppendNum( packetNumber, EHex ); + // Increase packet number + packetNumber++; + } + + // Append call stack address. + ptr.AppendFormat( KHexaNumberTrace, aCallstack.At( addrPos ) ); + + // Move the call stack position. + addrPos++; + + // Check if buffer max length exceed + if ( lastItemLength + ptr.Length() >= KMemAllocBufLength ) + { + ptr.Append( KNewLineTrace ); + // Log through debug channel + RDebug::Print( KTraceMessage, aProcessId, &buffer ); + // Empty trace buffer + ptr.Delete( 0, ptr.MaxLength() ); + } + } + // Send last message if exists. + if ( ptr.Length() > 0 ) + { + ptr.Append( KNewLineTrace ); + RDebug::Print( KTraceMessage, aProcessId, &buffer); + } + return KErrNone; + } + + +TInt ATFastLogMemoryFreed( TUint aProcessId, TUint32 aMemAddress, + TFixedArray<TUint32, KATMaxFreeCallstackLength>& aFreeCallstack ) + { + LOGSTR1( "ATFL ATFastLogMemoryFreed()" ); + // FREEH <Memory address> <Time tamp> <Call stack address count> <Call stack address> + // <Call stack address> ... + + // Timestamp. + TInt64 time = CurrentTime(); + + // Trace buffer and pointer to it. + TBufC<KMemFreedBufLength> buffer; + TPtr ptr( buffer.Des() ); + + // Append the tag implying a memory allocation line in the data file + ptr.Append( KMemoryFreedHeader ); + + // Append the start address of this allocation in the 32-bit (max 8 characters) + // hexadecimal text format. + ptr.AppendNum( aMemAddress, EHex ); + + // Append timestamp; + ptr.Append( KSpaceTrace ); + ptr.AppendNum( time, EHex); + + // Search call stack for address count. + TInt addrCount(0); + for ( TInt j = 0; j < aFreeCallstack.Count() ; j++ ) + { + if ( aFreeCallstack.At(j) == 0 ) + break; + addrCount++; + } + // Current position in call stack. + TInt addrPos( 0 ); + + // Append address count. + ptr.Append( KSpaceTrace ); + ptr.AppendNum( addrCount, EHex ); + + // Calculate last item length + TInt lastItemLength( KTraceMessage().Length() + KHexa32Length + + KSpaceLength + KNewlineLength ); + + TUint packetNumber( 1 ); + + // Go through all call stack's memory addresses associated with + // this memory allocation + for ( TInt j = 0; j < addrCount; j++ ) + { + // ALLOCF <Memory address> <Time stamp> <Packet number> + // <Call stack address> <Call stack address> ... + if ( ptr.Length() <= 0 ) + { + // Create alloc fragment message header + ptr.Append( KMemoryFreedFragment ); + ptr.AppendNum( aMemAddress, EHex ); + ptr.Append( KSpaceTrace ); + ptr.AppendNum( packetNumber, EHex ); + // Increase packet number + packetNumber++; + } + + // Append call stack address. + ptr.AppendFormat( KHexaNumberTrace, aFreeCallstack.At( addrPos ) ); + + // Move the call stack position. + addrPos++; + + // Check if buffer max length exceed + if ( lastItemLength + ptr.Length() >= KMemFreedBufLength ) + { + ptr.Append( KNewLineTrace ); + // Log through debug channel + RDebug::Print( KTraceMessage, aProcessId, &buffer ); + // Empty trace buffer + ptr.Delete( 0, ptr.MaxLength() ); + } + } + // Send last message if exists. + if ( ptr.Length() > 0 ) + { + ptr.Append( KNewLineTrace ); + RDebug::Print( KTraceMessage, aProcessId, &buffer); + } + return KErrNone; + } + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/src/analyzetoolmainallocator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/src/analyzetoolmainallocator.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,1509 @@ +/* +* 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 RAnalyzeToolMainAllocator. +* +*/ + + +#include "analyzetoolmainallocator.h" +#include "atlog.h" +#include "analyzetooleventhandler.h" +#include "analyzetoolmemoryallocator.h" +#include "analyzetoolpanics.pan" +#include "analyzetoolfastlog.h" +#include <e32svr.h> + + +// CONSTANTS + +// The name of the memoryhook dll +_LIT8( KMemoryHook, "AToolMemoryHook.dll" ); + +// The name of the storage server dll +_LIT8( KStorageServer, "AToolStorageServerClnt.dll" ); + +// Length of the callstack address +const TUint32 KAddressLength = 4; + +// Thread count +const TInt KThreadCount = 1; + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::RAnalyzeToolMainAllocator() +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +RAnalyzeToolMainAllocator::RAnalyzeToolMainAllocator( TBool aNotFirst, + const TFileName aFileName, TUint32 aLogOption, TUint32 aIsDebug, + TUint32 aAllocCallStackSize, TUint32 aFreeCallStackSize ) : + RAnalyzeToolMemoryAllocator( aNotFirst ), + iAnalyzeToolOpen( EFalse ), + iDeviceDriverLoaded( EFalse ), + iCodeblocks( KATMaxCallstackLength ), + iThreadArray( KATMaxCallstackLength ), + iLogOption( aLogOption ), + iProcessId( RProcess().Id().operator TUint() ), + iAllocMaxCallStack( aAllocCallStackSize ), + iFreeMaxCallStack( aFreeCallStackSize ) + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::RAnalyzeToolMainAllocator()" ); + + // Basic error variable used in method. + TInt error( KErrNone ); + + // Connect to the storage server if logging mode not fast trace. + if ( iLogOption != EATLogToTraceFast ) + { + error = iStorageServer.Connect(); + + LOGSTR2( "ATMH Opening RATStorageServer error %i", error ); + + if ( KErrNone == error ) + { + iStorageServerOpen = ETrue; + } + else + { + iStorageServerOpen = EFalse; + } + + if ( KErrNone == error ) + { + // Make the storage server handle shared between threads + error = iStorageServer.ShareAuto(); + } + + LOGSTR2( "ATMH Sharing RATStorageServer error %i", error ); + } + + // Create mutex for schedule access to shared resources + error = iMutex.CreateLocal(); + + __ASSERT_ALWAYS( KErrNone == error, AssertPanic( ECantCreateMutex ) ); + + LOGSTR2( "ATMH Creating mutex error %i", error ); + + // Load the kernel side device driver + error = User::LoadLogicalDevice( KAnalyzeToolLddName ); + + if ( error != KErrNone && error != KErrAlreadyExists ) + { + __ASSERT_ALWAYS( EFalse, AssertPanic( ECantLoadDeviceDriver ) ); + } + else + { + iDeviceDriverLoaded = ETrue; + } + + LOGSTR2( "ATMH Loading device driver error %i", error ); + + // Open handle to the kernel sidedevice driver + error = iAnalyzeTool.Open(); + + __ASSERT_ALWAYS( KErrNone == error, AssertPanic( ECantConnectDeviceDriver ) ); + + if ( KErrNone == error ) + { + iAnalyzeToolOpen = ETrue; + } + + LOGSTR2( "ATMH Opening RAnalyzeTool handle %i error", error ); + + // Set memory model by asking kernel side device driver + if ( iAnalyzeToolOpen ) + { + TATMemoryModelBuf model; + if ( KErrNone == iAnalyzeTool.GetMemoryModel( model ) ) + { + iMemoryModel = model().iMemoryModel; + LOGSTR2( "ATMH AnalyzeTool MemoryModel: %i", iMemoryModel ); + } + else + LOGSTR2( "ATMH AnalyzeTool GetMemoryModel error: %i", error ); + } + + // Retrieve the initial process information + LogProcessInformation( aFileName, aLogOption, aIsDebug ); + + // Create handler for receiving kernel events + iEventHandler = new CLibraryEventHandler( iAnalyzeTool, + iCodeblocks, + iStorageServer, + iProcessId, + iMutex, + *this, + aLogOption); + + __ASSERT_ALWAYS( iEventHandler != NULL, AssertPanic( ENoMemory ) ); + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::~RAnalyzeToolMainAllocator() +// Destructor. +// ----------------------------------------------------------------------------- +// +RAnalyzeToolMainAllocator::~RAnalyzeToolMainAllocator() + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::~RAnalyzeToolMainAllocator()" ); + + TUint handleLeakCount( 0 ); + if ( iAnalyzeToolOpen && iThreadArray.Count() > 0 ) + { + TProcessHandleInfoBuf params; + params().iProcessId = iProcessId; + TInt error( iAnalyzeTool.GetProcessHandleInfo( params ) ); + handleLeakCount = params().iThreadHandleCount; + } + + // Close handle for process memory blocks + iCodeblocks.Close(); + + // Delete the eventhandler + delete iEventHandler; + + // The count of device driver users + TClientCountBuf count; + + // Check the flag + if ( iAnalyzeToolOpen ) + { + TInt error = iAnalyzeTool.ClientCount( count ); + LOGSTR2( "ATMH closing analyze tool handle error: %i", error ); + iAnalyzeTool.Close(); + } + + // Check the flag + if ( iDeviceDriverLoaded ) + { + LOGSTR2( "ATMH device driver client count: %i", count().iClientCount ); + + // Check if there is another user for device driver + if ( count().iClientCount <= 1 ) + { + // There was no other users -> unload the device driver + TInt error = User::FreeLogicalDevice( KAnalyzeToolLddName ); + LOGSTR2( "ATMH Unloading ldd error: %i", error ); + } + } + + // Close the thread array + iThreadArray.Close(); + + if ( iStorageServerOpen || iLogOption == EATLogToTraceFast ) + { + if ( iLogOption == EATLogToTraceFast ) + { + LOGSTR1( "ATMH ATFastLogProcessEnded()" ); + ATFastLogProcessEnded( iProcessId, handleLeakCount ); + } + else + { + iStorageServerOpen = EFalse; + // Inform that process has ended and close the handle + LOGSTR1( "ATMH iStorageServer.LogProcessEnded()" ); + iStorageServer.LogProcessEnded( iProcessId, handleLeakCount ); + // Close the handle + iStorageServer.Close(); + } + } + + // Close the mutex + iMutex.Close(); + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::ShareHeap() +// Share heap with other thread +// ----------------------------------------------------------------------------- +// +void RAnalyzeToolMainAllocator::ShareHeap() + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::ShareHeap()" ); + + // Call the overwrited Open function + Open(); + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::Uninstall() +// Uninstalls the current allocator +// ----------------------------------------------------------------------------- +// +void RAnalyzeToolMainAllocator::Uninstall() + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Uninstall()" ); + + // Acquire the mutex + iMutex.Wait(); + + TMainThreadParamsBuf params; + params().iProcessId = iProcessId; + iAnalyzeTool.MainThreadAlloctor( params ); + + // Release the mutex + iMutex.Signal(); + + // Check if this is shared allocator between threads + if ( iThreadArray.Count() > KThreadCount && !params().iAlone ) + { + // Close the shared allocator + Close(); + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Uninstall() - Close called" ); + return; + } + +#if ( SYMBIAN_VERSION_SUPPORT >= SYMBIAN_3 ) + #ifndef __WINS__ + // Remove dummy Tls handle + UserSvr::DllFreeTls( KDummyHandle ); + #endif +#endif + + // Since this is the last thread using this allocator it can be deleted + delete this; + } + +#ifdef __WINS__ +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::Alloc() WINS version +// Allocates a cell of specified size from the heap. +// ----------------------------------------------------------------------------- +// +UEXPORT_C TAny* RAnalyzeToolMainAllocator::Alloc( TInt aSize ) + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Alloc()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Alloc memory from the original allocator + TAny* p = iAllocator->Alloc( aSize ); + + LOGSTR3( "ATMH RAnalyzeToolMainAllocator::Alloc() - aSize: %i, address: %x", + aSize, (TUint32) p ); + + // Don't collect or log data if storage server not open or logging mode fast. + if ( iStorageServerOpen || iLogOption == EATLogToTraceFast ) + { + TInt error( KErrNone ); + + // Check if eventhandler is started already + if ( !iEventHandler->IsStarted() ) + { + // Install the eventhandler if needed + InstallEventHandler(); + } + + // Reset the callstack + iCallStack.Reset(); + + // If we don't want any call stack to be saved skip the next part + if( iAllocMaxCallStack > 0 ) + { + // Find the current thread callstack start address + TUint32 stackstart( 0 ); + TBool found( FindCurrentThreadStack( stackstart ) ); + LOGSTR3( "ATMH > stackstart: %x , found = %i", stackstart, found ); + + // Returns the value of the stack pointer at the + // current point in your program. + TUint32 _sp; + __asm + { + mov [_sp], esp + } + + // Get process loaded code segments count + TInt blocksCount( iCodeblocks.Count() ); + TUint arrayCounter = 0; + + // Iterate through callstack to find wanted callstack addresses + // - Start: current stack address + // - Stop: stack start address(Run-address of user stack) + // - Add: address length(The word size in the current system is 32 bits, which is 4 bytes) + for ( TUint32 i = _sp; i < stackstart; i = i + KAddressLength )//lint !e1055 !e526 !e628 !e348 + { + TUint32 addr = (TUint32) *( (TUint32*) i ); + + // Checks is the given address in loaded code memory area. + if ( !IsAddressLoadedCode( addr ) ) + continue; + + // Iterate through array of code blocks to check if address is in code segment area + for ( TInt j = 0; j < blocksCount; j++ ) + { + // Checks if the given address is in this memory block area + if ( iCodeblocks[j].CheckAddress( addr ) ) + { + // To avoid recursive call to ReAlloc specifying granularity + // Add address to the callstack + iCallStack[arrayCounter] = ( addr ); + arrayCounter++; + break; + } + } + + // Checks if the wanted callstack items are gathered + if ( arrayCounter == KATMaxCallstackLength || + arrayCounter == iAllocMaxCallStack ) + { + LOGSTR2( "ATMH > Wanted CallStack items ready( %i )", arrayCounter ); + break; + } + } + } + + // Log the memory allocation information + if ( iLogOption == EATLogToTraceFast ) + { + // Using fast mode. + ATFastLogMemoryAllocated( iProcessId, (TUint32) p , iCallStack, aSize ); + } + else + { + // Using storage server. + error = iStorageServer.LogMemoryAllocated( (TUint32) p, + iCallStack, + aSize ); + if ( KErrNone != error ) + { + switch ( error ) + { + case KErrNoMemory: + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Alloc() - KErrNoMemory case" ); + // Check if eventhandler is active + if ( iEventHandler->IsActive() ) + { + // Cancel iEventHandler because not needed anymore + iEventHandler->Cancel(); + } + if ( iStorageServerOpen ) + { + // Close storage server + iStorageServerOpen = EFalse; + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Alloc() - close iStorageServer" ); + iStorageServer.Close(); + } + break; + } + default: + { + LOGSTR2( "ATMH LogMemoryAllocated error %i", error ); + break; + } + } + } + } + } + // Release the mutex + iMutex.Signal(); + + return p; + } +#else + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::Alloc() ARMV5 version +// Allocates a cell of specified size from the heap. +// ----------------------------------------------------------------------------- +// +TAny* RAnalyzeToolMainAllocator::Alloc( TInt aSize ) + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Alloc()" ); + + // acquire the mutex + iMutex.Wait(); + + // Alloc memory from the original allocator + TAny* p = iAllocator->Alloc( aSize ); + + LOGSTR3( "ATMH RAnalyzeToolMainAllocator::Alloc() - aSize: %i, address: %x", + aSize, (TUint32) p ); + + TInt error( KErrNone ); + + if ( iStorageServerOpen || iLogOption == EATLogToTraceFast ) + { + // Check if eventhandler is active already + // IsActive might return false value if a tested software has created many + // threads which install own CActiveScheduler. + if ( !iEventHandler->IsStarted() ) + { + // Install the eventhandler if needed + InstallEventHandler(); + } + + // Reset the callstack + iCallStack.Reset(); + + // If we don't want any call stack to be saved skip the next part + if( iAllocMaxCallStack > 0 ) + { + // Find the current thread callstack start address + TUint32 stackstart( 0 ); + TBool found( FindCurrentThreadStack( stackstart ) ); + LOGSTR3( "ATMH > stackstart: %x , found = %i", stackstart, found ); + + // Get process loaded code segments count + TInt blocksCount( iCodeblocks.Count() ); + TUint arrayCounter = 0; + + // Iterate through callstack to find wanted callstack addresses + // - Start: current stack address(__current_sp(): Returns the value of the + // stack pointer at the current point in your program.) + // - Stop: stack start address(Run-address of user stack) + // - Add: address length(The word size in the current system is 32 bits, which is 4 bytes) + for ( TUint32 i = __current_sp(); i < stackstart; i = i + KAddressLength )//lint !e1055 !e526 !e628 !e348 + { + TUint32 addr = (TUint32) *( (TUint32*) i ); + + // Checks is the given address in loaded code memory area. + if ( !IsAddressLoadedCode( addr ) ) + continue; + + // Iterate through array of code blocks to check if address is in code segment area + for ( TInt j = 0; j < blocksCount; j++ ) + { + // Checks if the given address is in this memory block area + if ( iCodeblocks[j].CheckAddress( addr ) ) + { + // To avoid recursive call to ReAlloc specifying granularity + // Add address to the callstack + iCallStack[arrayCounter] = ( addr ); + arrayCounter++; + break; + } + } + + // Checks if the wanted callstack items are gathered + if ( arrayCounter == KATMaxCallstackLength || + arrayCounter == iAllocMaxCallStack ) + { + LOGSTR2( "ATMH > Wanted CallStack items ready( %i )", arrayCounter ); + break; + } + } + } + // Log the memory allocation information + if ( iLogOption == EATLogToTraceFast ) + { + // Using fast mode. + ATFastLogMemoryAllocated( iProcessId, (TUint32) p, iCallStack, aSize ); + } + else + { + // Using storage server. + error = iStorageServer.LogMemoryAllocated( (TUint32) p, + iCallStack, + aSize ); + if ( KErrNone != error ) + { + switch ( error ) + { + case KErrNoMemory: + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Alloc() - KErrNoMemory case" ); + // Check if eventhandler is active + if ( iEventHandler->IsActive() ) + { + // Cancel ieventhandler because not needed anymore + iEventHandler->Cancel(); + } + if ( iStorageServerOpen ) + { + // Close storage server + iStorageServerOpen = EFalse; + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Alloc() - close iStorageServer" ); + iStorageServer.Close(); + } + break; + } + default: + { + LOGSTR2( "ATMH LogMemoryAllocated error %i", error ); + break; + } + } + } + } + } + + // Release the mutex + iMutex.Signal(); + + // Return the allocatated memory + return p; + } +#endif // __WINS__ + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::Free() +// Frees the allocated memory +// ----------------------------------------------------------------------------- +// +void RAnalyzeToolMainAllocator::Free( TAny* aPtr ) + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Free()" ); + + // Acquire the mutex + iMutex.Wait(); + + if ( iStorageServerOpen || iLogOption == EATLogToTraceFast ) + { + // Reset the callstack + iFreeCallStack.Reset(); + + // Check if trace logging mode + // Also if we don't want any call stack to be stored skip the next part + if ( (iLogOption == EATUseDefault || iLogOption == EATLogToTrace || iLogOption == EATLogToTraceFast ) + && iFreeMaxCallStack > 0 ) + { + // Find the current thread callstack start address + TUint32 stackstart( 0 ); + TBool found( FindCurrentThreadStack( stackstart ) ); + LOGSTR3( "ATMH > stackstart: %x , found = %i", stackstart, found ); + TUint32 _sp; + + // Returns the value of the stack pointer at the + // current point in your program. + #ifdef __WINS__ + __asm + { + mov [_sp], esp + } + #else + _sp = __current_sp(); + #endif + + // Get process loaded code segments count + TInt blocksCount( iCodeblocks.Count() ); + TUint arrayCounter = 0; + + // Iterate through callstack to find wanted callstack addresses + // - Start: current stack address + // - Stop: stack start address(Run-address of user stack) + // - Add: address length(The word size in the current system is 32 bits, which is 4 bytes) + for ( TUint32 i = _sp; i < stackstart; i = i + KAddressLength )//lint !e1055 !e526 !e628 !e348 + { + TUint32 addr = (TUint32) *( (TUint32*) i ); + // Checks is the given address in loaded code memory area. + if ( ! IsAddressLoadedCode( addr ) ) + continue; + + // Iterate through array of code blocks to check if address is in code segment area + for ( TInt j = 0; j < blocksCount; j++ ) + { + // Checks if the given address is in this memory block area + if ( iCodeblocks[j].CheckAddress( addr ) ) + { + // To avoid recursive call to ReAlloc specifying granularity + // Add address to the callstack + iFreeCallStack[arrayCounter] = addr; + arrayCounter++; + break; + } + } + // Checks if the wanted callstack items are gathered + if ( arrayCounter == KATMaxFreeCallstackLength || + arrayCounter == iFreeMaxCallStack ) + { + break; + } + } + LOGSTR2( "ATMH > iFreeCallStack count ( %i )", arrayCounter ); + } + // Log the memory free information. + if ( iLogOption == EATLogToTraceFast ) + { + // Using fast mode. + ATFastLogMemoryFreed( iProcessId, (TUint32) aPtr, iFreeCallStack ); + } + else + { + // Using storage server. + TInt err( iStorageServer.LogMemoryFreed( (TUint32) aPtr, iFreeCallStack ) ); + if ( err != KErrNone ) + { + LOGSTR2( "ATMH > LogMemoryFreed err( %i )", err ); + } + } + } + + // Free the memory using original allocator + iAllocator->Free( aPtr ); + + LOGSTR2( "ATMH RAnalyzeToolMainAllocator::Free() - aPtr: %x", (TUint32)aPtr ); + + // Release the mutex + iMutex.Signal(); + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::Open() +// Opens this heap for shared access. Opening the heap increases +// the heap's access count by one. +// ----------------------------------------------------------------------------- +// +TInt RAnalyzeToolMainAllocator::Open() + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Open() " ); + + // Acquire the mutex + iMutex.Wait(); + + // Share the memory using original allocator + TInt error = iAllocator->Open(); + + // If everything is OK add thread to the array which use this allocator + if ( KErrNone == error ) + { + TThreadParamsBuf params; + params().iThreadId = RThread().Id().operator TUint(); + error = iAnalyzeTool.ThreadStack( params ); + + __ASSERT_ALWAYS( KErrNone == error, AssertPanic( ECantAppendToTheArray ) ); + + if ( KErrNone == error ) + { + LOGSTR2( "ATMH Thread stack address: %x", params().iStackAddress ); + LOGSTR2( "ATMH Thread stack size: %x", params().iStackSize ); + iThreadArray.Append( TThreadStack( RThread().Id(), + params().iStackAddress + params().iStackSize ) ); + } + } + + // Release the mutex + iMutex.Signal(); + + // Return the error code + return error; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::Close() +// Closes this shared heap. Closing the heap decreases the heap's +// access count by one. +// ----------------------------------------------------------------------------- +// +void RAnalyzeToolMainAllocator::Close() + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Close()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Close the memory using original allocator + iAllocator->Close(); + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Close() - allocator closed" ); + TInt count = iThreadArray.Count(); + + // Iterate through array of threads to remove current thread + for ( TInt i = 0; i < count; i++ ) + { + // Check if this is current thread + if ( iThreadArray[ i ].Match() ) + { + // Remove the thread + iThreadArray.Remove( i ); + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Close() - thread removed" ); + break; + } + } + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Close() - about to mutex signal" ); + // Release the mutex + iMutex.Signal(); + } + +#ifdef __WINS__ + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::ReAlloc() +// Increases or decreases the size of an existing cell. +// ----------------------------------------------------------------------------- +// +TAny* RAnalyzeToolMainAllocator::ReAlloc( TAny* aPtr, TInt aSize, TInt aMode ) + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::ReAlloc()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Realloc the memory using original allocator + TAny* ptr = iAllocator->ReAlloc( aPtr, aSize, aMode ); + + // NULL addresses are not in a process under test + if ( ptr && !( aMode & ENeverMove ) ) + { + LOGSTR3( "ATMH RAnalyzeToolMainAllocator::ReAlloc() - aPtr: %x, ptr: %x", + (TUint32)aPtr, (TUint32)ptr ); + LOGSTR3( "ATMH RAnalyzeToolMainAllocator::ReAlloc() - aSize: %i, aMode: %i", + aSize, aMode ); + + // Don't collect or log data if storage server not open or logging mode is not fast. + if ( iStorageServerOpen || iLogOption == EATLogToTraceFast ) + { + TInt error( KErrNone ); + TUint arrayCounter = 0; + + // Reset the callstack + iReCallStack.Reset(); + + // If we don't want any call stack to be saved skip the next part + if( iAllocMaxCallStack > 0 ) + { + // Find the current thread callstack start address + TUint32 stackstart( 0 ); + TBool found( FindCurrentThreadStack( stackstart ) ); + LOGSTR3( "ATMH > stackstart: %x , find = %i", stackstart, found ); + + // Returns the value of the stack pointer at the + // current point in your program. + TUint32 _sp( 0 ); + __asm + { + mov [_sp], esp + } + + // Get process loaded code segments count + TInt blocksCount( iCodeblocks.Count() ); + + // Iterate through callstack to find wanted callstack addresses + // - Start: current stack address + // - Stop: stack start address(Run-address of user stack) + // - Add: address length(The word size in the current system is 32 bits, which is 4 bytes) + for ( TUint32 i = _sp; i < stackstart; i = i + KAddressLength )//lint !e1055 !e526 !e628 !e348 + { + TUint32 addr = (TUint32) *( (TUint32*) i ); + // Checks is the given address in loaded code memory area. + if ( ! IsAddressLoadedCode( addr ) ) + continue; + + // Iterate through array of code blocks to check if address is in code segment area + for ( TInt j = 0; j < blocksCount; j++ ) + { + // Checks if the given address is in this memory block area + if ( iCodeblocks[j].CheckAddress( addr ) ) + { + // To avoid recursive call to ReAlloc specifying granularity + // Add address to the callstack + iReCallStack[arrayCounter] = addr; + arrayCounter++; + break; + } + } + // Checks if the wanted callstack items are gathered + if ( arrayCounter == KATMaxCallstackLength || + arrayCounter == iAllocMaxCallStack ) + { + LOGSTR2( "ATMH > Wanted CallStack items ready( %i )", arrayCounter ); + break; + } + } + } + + // No need to report free if the aPtr was NULL + if ( aPtr != NULL ) + { + // Reset the free callstack + iFreeCallStack.Reset(); + + // Check that logging mode is trace/trace fast so we use free call stack + // and call stack size bigger than zero + if ( ( iLogOption == EATUseDefault || iLogOption == EATLogToTrace || iLogOption == EATLogToTraceFast ) && iFreeMaxCallStack > 0 ) + { + for ( TInt i = 0; i < arrayCounter; i++ ) + { + if ( i == KATMaxFreeCallstackLength || i == iFreeMaxCallStack ) + { + break; + } + iFreeCallStack[i] = iReCallStack[i]; + } + } + // Try to remove old address from the storage server's + // leak array. If found. it's removed from the array because system frees + // old address directly in the RHeap in ReAlloc case. + if ( iLogOption == EATLogToTraceFast ) + { + ATFastLogMemoryFreed( iProcessId, (TUint32) aPtr, iFreeCallStack ); + } + else + { + iStorageServer.LogMemoryFreed( (TUint32) aPtr, iFreeCallStack ); + } + } + // Log the memory allocation information + if ( iLogOption == EATLogToTraceFast ) + { + // Using fast logging mode. + ATFastLogMemoryAllocated( iProcessId, (TUint32) ptr, iReCallStack, aSize ); + } + else + { + // Using storage server. + error = iStorageServer.LogMemoryAllocated( (TUint32) ptr, + iReCallStack, + aSize ); + if ( KErrNone != error ) + { + switch ( error ) + { + case KErrNoMemory: + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::ReAlloc() - KErrNoMemory case" ); + // Check if eventhandler is active + if ( iEventHandler->IsActive() ) + { + // Cancel iEventHandler because not needed anymore + iEventHandler->Cancel(); + } + if ( iStorageServerOpen ) + { + // Close storage server + iStorageServerOpen = EFalse; + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::ReAlloc() - close iStorageServer" ); + iStorageServer.Close(); + } + break; + } + default: + { + LOGSTR2( "ATMH LogMemoryAllocated error %i", error ); + break; + } + } + } + } + } + } + + // Release the mutex + iMutex.Signal(); + + // Return pointer to the reallocated cell + return ptr; + } + +#else + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::ReAlloc() +// Increases or decreases the size of an existing cell. +// ----------------------------------------------------------------------------- +// +TAny* RAnalyzeToolMainAllocator::ReAlloc( TAny* aPtr, TInt aSize, TInt aMode ) + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::ReAlloc()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Realloc the memory using original allocator + TAny* ptr = iAllocator->ReAlloc( aPtr, aSize, aMode ); + + TInt error( KErrNone ); + TUint arrayCounter = 0; + + // NULL addresses are not in a process under test + if ( ptr && !( aMode & ENeverMove ) ) + { + LOGSTR3( "ATMH RAnalyzeToolMainAllocator::ReAlloc() - aPtr: %x, ptr: %x", + (TUint32)aPtr, (TUint32)ptr ); + LOGSTR3( "ATMH RAnalyzeToolMainAllocator::ReAlloc() - aSize: %i, aMode: %i", + aSize, aMode ); + + // Don't collect or log data if storage server not open or logging mode is not fast. + if ( iStorageServerOpen || iLogOption == EATLogToTraceFast ) + { + // Reset the callstack + iReCallStack.Reset(); + + // If we don't want any call stack to be saved skip the next part + if( iAllocMaxCallStack > 0 ) + { + // Find the current thread callstack start address + TUint32 stackstart( 0 ); + TBool found( FindCurrentThreadStack( stackstart ) ); + LOGSTR3( "ATMH > stackstart: %x , find = %i", stackstart, found ); + + // Get process loaded code segments count + TInt blocksCount( iCodeblocks.Count() ); + + // Iterate through callstack to find wanted callstack addresses + // - Start: current stack address(__current_sp(): Returns the value of the + // stack pointer at the current point in your program.) + // - Stop: stack start address(Run-address of user stack) + // - Add: address length(The word size in the current system is 32 bits, which is 4 bytes) + for ( TUint32 i = __current_sp(); i < stackstart; i = i + KAddressLength )//lint !e1055 !e526 !e628 !e348 + { + TUint32 addr = (TUint32) *( (TUint32*) i ); + + // Checks is the given address in loaded code memory area. + if ( !IsAddressLoadedCode( addr ) ) + continue; + + // Iterate through array of code blocks to check if address is in code segment area + for ( TInt j = 0; j < blocksCount; j++ ) + { + // Checks if the given address is in this memory block area + if ( iCodeblocks[j].CheckAddress( addr ) ) + { + // To avoid recursive call to ReAlloc specifying granularity + // Add address to the callstack + iReCallStack[arrayCounter] = ( addr ); + arrayCounter++; + break; + } + } + // Checks if the wanted callstack items are gathered + if ( arrayCounter == KATMaxCallstackLength || + arrayCounter == iAllocMaxCallStack ) + { + LOGSTR2( "ATMH > Wanted CallStack items ready( %i )", arrayCounter ); + break; + } + } + } + + // No need to report free if the aPtr was NULL + if ( aPtr != NULL ) + { + // Reset the free callstack + iFreeCallStack.Reset(); + + // Check that logging mode is trace/trace fast so we use free call stack + // and call stack size bigger than zero + if ( (iLogOption == EATUseDefault || iLogOption == EATLogToTrace || iLogOption == EATLogToTraceFast ) + && iFreeMaxCallStack > 0 ) + { + for ( TInt i = 0; i < arrayCounter; i++ ) + { + if ( i == KATMaxFreeCallstackLength || i == iFreeMaxCallStack ) + { + break; + } + iFreeCallStack[i] = ( iReCallStack[i] ); + } + } + + // Try to remove old address from the storage server's + // leak array. If found. it's removed from the array because system frees + // old address directly in the RHeap in ReAlloc case. + if ( iLogOption == EATLogToTraceFast ) + { + ATFastLogMemoryFreed( iProcessId, (TUint32) aPtr, iFreeCallStack ); + } + else + { + iStorageServer.LogMemoryFreed( (TUint32) aPtr, iFreeCallStack ); + } + } + + // Log the memory allocation information + if ( iLogOption == EATLogToTraceFast ) + { + // Using fast logging mode. + ATFastLogMemoryAllocated( iProcessId, (TUint32) ptr, iReCallStack, aSize ); + } + else + { + // Using storage server. + error = iStorageServer.LogMemoryAllocated( (TUint32) ptr, + iReCallStack, + aSize ); + if ( KErrNone != error ) + { + switch ( error ) + { + case KErrNoMemory: + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::ReAlloc() - KErrNoMemory case" ); + // Check if eventhandler is active + if ( iEventHandler->IsActive() ) + { + // Cancel iEventHandler because not needed anymore + iEventHandler->Cancel(); + } + if ( iStorageServerOpen ) + { + // Close storage server + iStorageServerOpen = EFalse; + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::ReAlloc() - close iStorageServer" ); + iStorageServer.Close(); + } + break; + } + default: + { + LOGSTR2( "ATMH LogMemoryAllocated error %i", error ); + break; + } + } + } + } + } + } + + // Release the mutex + iMutex.Signal(); + + // Return pointer to the reallocated cell + return ptr; + } + +#endif // __WINS__ + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::Compress() +// The function frees excess committed space from the top of the heap. +// The size of the heap is never reduced below the minimum size +// specified during creation of the heap. +// ----------------------------------------------------------------------------- +// +TInt RAnalyzeToolMainAllocator::Compress() + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Compress()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Compress the memory using original allocator + TInt compress = iAllocator->Compress(); + + // Release the mutex + iMutex.Signal(); + + // Return the space reclaimed + return compress; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::Reset() +// Frees all allocated cells on this heap. +// ----------------------------------------------------------------------------- +// +void RAnalyzeToolMainAllocator::Reset() + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Reset()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Reset the memory using original allocator + iAllocator->Reset(); + + // Release the mutex + iMutex.Signal(); + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::AllocSize() +// Gets the number of cells allocated on this heap, and +// the total space allocated to them. +// ----------------------------------------------------------------------------- +// +TInt RAnalyzeToolMainAllocator::AllocSize( TInt& aTotalAllocSize ) const + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::AllocSize()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Acquire the memory information using original allocator + TInt size = iAllocator->AllocSize( aTotalAllocSize ); + + // Release the mutex + iMutex.Signal(); + + // Return the number of cells allocated on this heap. + return size; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::Available() +// Gets the total free space currently available on the heap and the +// space available in the largest free block. The space available +// represents the total space which can be allocated. Note that +// compressing the heap may reduce the total free space available +// and the space available in the largest free block. +// ----------------------------------------------------------------------------- +// +TInt RAnalyzeToolMainAllocator::Available( TInt& aBiggestBlock ) const + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Available()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Acquire the memory information using original allocator + TInt available = iAllocator->Available( aBiggestBlock ); + + // Release the mutex + iMutex.Signal(); + + // Return the total free space currently available on the heap + return available; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::AllocLen() +// Gets the length of the available space in the specified +// allocated cell. +// ----------------------------------------------------------------------------- +// +TInt RAnalyzeToolMainAllocator::AllocLen( const TAny* aCell ) const + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::AllocLen()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Acquire the memory information using original allocator + TInt len = iAllocator->AllocLen( aCell ); + + // Release the mutex + iMutex.Signal(); + + // Return the length of the available space in the allocated cell. + return len; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::DebugFunction() +// Invocates specified debug funtionality. +// ----------------------------------------------------------------------------- +// +TInt RAnalyzeToolMainAllocator::DebugFunction( TInt aFunc, TAny* a1, TAny* a2 ) + { + LOGSTR2( "ATMH RAnalyzeToolMainAllocator::DebugFunction() %i", aFunc ); + + // Acquire the mutex + iMutex.Wait(); + + // Invocate debug funtion using original allocator + TInt debug = iAllocator->DebugFunction( aFunc, a1, a2 ); + + switch( aFunc ) + { + case EMarkEnd: + { + // Disables the __UHEAP_MARKEND macro + LOGSTR1( "ATMH __UHEAP_MARKEND macro called" ); + if ( debug > 0 ) + { + LOGSTR2( "ATMH __UHEAP_MARKEND detects leaks: %d", debug ); + // Because there is leaks the alloc panic will occur but + // lets return a zero to pretend that everything is OK + debug = 0; + } + } + break; + + default: + { + } + break; + } + + // Release the mutex + iMutex.Signal(); + + // Return information of the debug function success + return debug; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::RemoveKilledThread() +// Remove killed thread from threads array. +// ----------------------------------------------------------------------------- +// +void RAnalyzeToolMainAllocator::RemoveKilledThread( const TUint aThreadId ) + { + LOGSTR2( "ATMH RAnalyzeToolMainAllocator::RemoveKilledThread(%i)", + aThreadId ); + + // Acquire the mutex + iMutex.Wait(); + + // Iterate through array of threads to remove current thread + TInt count( iThreadArray.Count() ); + LOGSTR2( "ATMH > iThreadArray.Count() %i", count ); + + for ( TInt i = 0; i < count; i++ ) + { + // Check if this is current thread + if ( iThreadArray[ i ].Match( aThreadId ) ) + { + // Remove the thread + iThreadArray.Remove( i ); + LOGSTR1( "ATMH > thread removed" ); + break; + } + } + + // Release the mutex + iMutex.Signal(); + } +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::Extension_() +// Extension function +// ----------------------------------------------------------------------------- +// +TInt RAnalyzeToolMainAllocator::Extension_( TUint aExtensionId, TAny*& a0, + TAny* a1) + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Extension_()" ); + + // Acquire the mutex + iMutex.Wait(); + + // Invocate extension funtion using original allocator + TInt ext = RAllocator::Extension_( aExtensionId, a0, a1 ); + + // Release the mutex + iMutex.Signal(); + + // Return information of the extension function success + return ext; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::LogProcessInformation() +// Retrieve and log the process initial information +// ----------------------------------------------------------------------------- +// +void RAnalyzeToolMainAllocator::LogProcessInformation( const TFileName aFileName, + TUint32 aLogOption, TUint32 aIsDebug ) + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::LogProcessInformation()" ); + + // Create local variable and retrieve the process information + TProcessIdentityParamsBuf params; + params().iProcessId = iProcessId; + params().iThreadId = RThread().Id().operator TUint(); + TInt error = iAnalyzeTool.GetProcessInfo( params ); + + LOGSTR2( "ATMH GetProcessInfo %i error", error ); + + if ( KErrNone == error ) + { + LOGSTR2( "ATMH Process %i", iProcessId ); + + // Store stack start address + LOGSTR2( "ATMH Thread stack address: %x", params().iStackAddress ); + LOGSTR2( "ATMH Thread stack size: %x", params().iStackSize ); + + // Append thread to array of the users of this allocator + error = iThreadArray.Append( + TThreadStack( RThread().Id(), params().iStackAddress + params().iStackSize) ); + + __ASSERT_ALWAYS( KErrNone == error, AssertPanic( ECantAppendToTheArray ) ); + + // Log process information + if ( iStorageServerOpen || iLogOption == EATLogToTraceFast ) + { + if ( iLogOption == EATLogToTraceFast ) + { + // Using fast logging mode. + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::LogProcessInformation() - ATFastLogProcessStarted() #1" ); + ATFastLogProcessStarted( params().iProcessName, iProcessId, aIsDebug ); + } + else + { + // Using storage server. + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::LogProcessInformation() - iStorageServerOpen #1" ); + error = iStorageServer.LogProcessStarted( + aFileName, + params().iProcessName, + iProcessId, + aLogOption, + aIsDebug ); + } + } + + LOGSTR2( "ATMH LogProcessStarted error %i", error ); + + // Iterate through process codesegments + for( TInt i = 0; i < params().iCodesegCount; i++ ) + { + // Create local variable and retrieve codesegment info + TCodesegInfoBuf codeinfo; + codeinfo().iProcessId = iProcessId; + codeinfo().iIndex = i; + error = iAnalyzeTool.GetCodesegInfo( codeinfo ); + + LOGSTR2( "ATMH GetCodesegInfo error %i", error ); + if ( KErrNone == error ) + { + // Don't log AnalyzeTool libraries + if ( 0 != codeinfo().iFullName.CompareC( KMemoryHook ) && + 0 != codeinfo().iFullName.CompareC( KStorageServer ) ) + { + // Log the loaded codesegment(s) + if ( iStorageServerOpen || iLogOption == EATLogToTraceFast ) + { + if ( iLogOption == EATLogToTraceFast ) + { + // Using fast logging mode. + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::LogProcessInformation() - ATFastLogDllLoaded() #2" ); + ATFastLogDllLoaded( iProcessId, + codeinfo().iFullName, + codeinfo().iRunAddress, + codeinfo().iRunAddress + codeinfo().iSize ); + } + else + { + // Using storage server. + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::LogProcessInformation() - iStorageServerOpen #2" ); + error = iStorageServer.LogDllLoaded( + codeinfo().iFullName, + codeinfo().iRunAddress, + codeinfo().iRunAddress + codeinfo().iSize ); + } + } + + LOGSTR2( "ATMH LogDllLoaded error %i", error ); + + // Check that everything is OK + if ( KErrNone == error ) + { + // Append the codesegment to the array + error = iCodeblocks.Append( + TCodeblock( codeinfo().iRunAddress, + codeinfo().iSize, + codeinfo().iFullName ) ); + LOGSTR2( "ATMH Append error %i", error ); + } + } + } + } + + // Iterate through process dynamic codesegments + for ( TInt i = 0; i < params().iDynamicCount; i++ ) + { + // Create local variable and retrieve codesegment info + TLibraryInfoBuf info; + info().iProcessId = iProcessId; + info().iIndex = i; + error = iAnalyzeTool.GetLibraryInfo( info ); + LOGSTR2( "ATMH GetLibraryInfo error %i", error ); + if ( KErrNone == error ) + { + // Log the loaded dynamic codesegment(s) + if ( iStorageServerOpen || iLogOption == EATLogToTraceFast ) + { + if ( iLogOption == EATLogToTraceFast ) + { + // Using fast logging mode. + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::LogProcessInformation() - - ATFastLogDllLoaded()#3" ); + ATFastLogDllLoaded( iProcessId, + info().iLibraryName, + info().iRunAddress, + info().iRunAddress + info().iSize ); + } + else + { + // Using storage server. + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::LogProcessInformation() - iStorageServerOpen #3" ); + error = iStorageServer.LogDllLoaded( + info().iLibraryName, + info().iRunAddress, + info().iRunAddress + info().iSize ); + } + } + + + LOGSTR2( "ATMH LogDllLoaded error %i", error ); + + if ( KErrNone == error ) + { + // Append the codesegment to the array + error = iCodeblocks.Append( + TCodeblock( info().iRunAddress, + info().iSize, info().iLibraryName ) ); + LOGSTR2( "ATMH Append error %i", error ); + } + } + } + } + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::FindCurrentThreadStack() +// Find the current thread which is using the heap +// ----------------------------------------------------------------------------- +// +TBool RAnalyzeToolMainAllocator::FindCurrentThreadStack( TUint32& aStackStart ) + { + LOGSTR2( "ATMH RAnalyzeToolMainAllocator::FindCurrentThreadStack(), count( %i )", + iThreadArray.Count() ); + + // Flag for indicating that right thread has been found + TBool found( EFalse ); + // If threre is only one thread it must be the right thread + if ( iThreadArray.Count() == KThreadCount ) + { + if ( !iThreadArray[ 0 ].ThreadStackStart( aStackStart ) ) + { + // This MUST BE the right thread + //__ASSERT_ALWAYS( EFalse, AssertPanic( ECantFindRightThread ) ); + } + else if ( iThreadArray[ 0 ].ThreadStackStart( aStackStart ) ) + { + found = ETrue; + } + } + else + { + // Iterate through array to find right thread + TInt count = iThreadArray.Count(); + + for ( TInt i = 0; i < count; i++ ) + { + // Check if this is the right thread + if ( iThreadArray[ i ].ThreadStackStart( aStackStart ) ) + { + // Right thread found. Mark the flag + found = ETrue; + break; + } + } + // If right thread was not found the panic must be raised + if ( !found ) + { + //__ASSERT_ALWAYS( EFalse, AssertPanic( ECantFindRightThread ) ); + } + } + return found; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMainAllocator::InstallEventHandler() +// Installs the eventhandler, if possible +// ----------------------------------------------------------------------------- +// +void RAnalyzeToolMainAllocator::InstallEventHandler() + { + LOGSTR1( "ATMH RAnalyzeToolMainAllocator::InstallEventHandler()" ); + + // Active eventhalder is not active, trying to start it + if ( NULL != CActiveScheduler::Current() ) + { + iEventHandler->Start(); + } + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/src/analyzetoolmemoryallocator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/src/analyzetoolmemoryallocator.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,71 @@ +/* +* 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 RAnalyzeToolMemoryAllocator. +* +*/ + + +#include "analyzetoolmemoryallocator.h" +#include "analyzetoolpanics.pan" +#include "atlog.h" + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMemoryAllocator::RAnalyzeToolMemoryAllocator() +// C++ default constructor. +// ----------------------------------------------------------------------------- +// +RAnalyzeToolMemoryAllocator::RAnalyzeToolMemoryAllocator( TBool aNotFirst ) : + RAllocator(), + iNotFirst( aNotFirst )/*, + iStorageServerOpen( EFalse )*/ + { + LOGSTR1( "ATMH RAnalyzeToolMemoryAllocator::RAnalyzeToolMemoryAllocator()" ); + + // Acquire the original allocator + iAllocator = &User::Allocator(); + + // Set memory model zero + iMemoryModel = 0; + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMemoryAllocator::~RAnalyzeToolMemoryAllocator() +// Destructor. +// ----------------------------------------------------------------------------- +// +RAnalyzeToolMemoryAllocator::~RAnalyzeToolMemoryAllocator() + { + LOGSTR1( "ATMH RAnalyzeToolMemoryAllocator::~RAnalyzeToolMemoryAllocator()" ); + + // Call switching orinigal allocator back. + // Just in case, if uninstall was not called. + SwitchOriginalAllocator(); + } + +// ----------------------------------------------------------------------------- +// RAnalyzeToolMemoryAllocator::SwitchOriginalAllocator() +// Switches original allocator in use if not already. +// ----------------------------------------------------------------------------- +// +void RAnalyzeToolMemoryAllocator::SwitchOriginalAllocator() + { + LOGSTR1( "ATMH RAnalyzeToolMemoryAllocator::SwitchOriginalAllocator()" ); + + if ( iAllocator != &User::Allocator() ) + { + User::SwitchAllocator( iAllocator ); + } + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/src/codeblock.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/src/codeblock.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,62 @@ +/* +* 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 TCodeblock. +* +*/ + + +#include "codeblock.h" +#include "atlog.h" + +// ----------------------------------------------------------------------------- +// TCodeblock::TCodeblock +// C++ default constructor. +// ----------------------------------------------------------------------------- +// +TCodeblock::TCodeblock( TLinAddr aRunAddress, + TUint32 aSize, + TBuf8<KMaxLibraryName>& aName ) : + iStartAddress( aRunAddress ), + iEndAddress( aRunAddress + aSize ) + { + LOGSTR3( "ATMH TCodeblock::TCodeblock() %x - %x", iStartAddress, iEndAddress ); + iName.Copy( aName ); + } + +// ----------------------------------------------------------------------------- +// TCodeblock::CheckAddress +// Checks if the given address is in this memory block area +// ----------------------------------------------------------------------------- +// +TBool TCodeblock::CheckAddress( TUint32 aAddress ) + { + if ( iStartAddress <= aAddress && aAddress <= iEndAddress ) + { + return ETrue; + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// TCodeblock::Match +// Matches if the given parameters represents this memory block +// ----------------------------------------------------------------------------- +// +TBool TCodeblock::Match( TBuf8<KMaxLibraryName>& aName ) + { + LOGSTR1( "ATMH TCodeblock::Match()" ); + return ( 0 == iName.CompareF( aName ) ) ? ETrue : EFalse; + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/src/customuser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/src/customuser.cpp Thu May 13 23:59:27 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 diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/dynamicmemoryhook/src/threadstack.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/dynamicmemoryhook/src/threadstack.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,76 @@ +/* +* 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 TThreadStack. +* +*/ + + +#include "threadstack.h" +#include "atlog.h" + +// ----------------------------------------------------------------------------- +// TThreadStack::TThreadStack() +// C++ default constructor. +// ----------------------------------------------------------------------------- +// +TThreadStack::TThreadStack( TThreadId aId, TUint32 aStackStart ) : + iId( aId ), + iStackStart( aStackStart ) + { + LOGSTR2( "ATMH TThreadStack::TThreadStack() aStackStart: %i", aStackStart ); + } + +// ----------------------------------------------------------------------------- +// TThreadStack::ThreadStackStart() +// Checks if this is the current thread and if this is the current +// thread assings value to the given parameter +// ----------------------------------------------------------------------------- +// +TBool TThreadStack::ThreadStackStart( TUint32& aStackStart ) + { + LOGSTR1( "ATMH TThreadStack::ThreadStackStart"); + + if ( RThread().Id() == iId ) + { + aStackStart = iStackStart; + return ETrue; + } + else + { + aStackStart = 0; + return EFalse; + } + } + +// ----------------------------------------------------------------------------- +// TThreadStack::Match() +// Checks if this is the the current thread. +// ----------------------------------------------------------------------------- +// +TBool TThreadStack::Match( const TUint aThreadId ) + { + LOGSTR2( "ATMH TThreadStack::Match( %d )", aThreadId ); + + if ( aThreadId != 0 ) + { + LOGSTR2( "ATMH > iId.operator TUint() = %d", iId.operator TUint() ); + return ( aThreadId == iId.operator TUint() ) ? ETrue : EFalse; + } + else + { + return ( RThread().Id() == iId ) ? ETrue : EFalse; + } + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/envpatcher/EnvPatcher.pl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/envpatcher/EnvPatcher.pl Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,544 @@ +# +# 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: +# Environment Patcher - Patches older S60 SDKs for supporting +# tricks in newer platforms +# + + +require v5.6.1; + +use File::Copy; +use strict; + +# check amount of commandline options is valid +if (@ARGV != 1) +{ + print "Usage: EnvPatcher <EPOCROOT>\n"; + exit 1; +} + + +# get epocroot and convert, convert \ -> / +(my $epocroot = $ARGV[0]) =~ s{\\}{/}g; + +# remove any trailing forward slashes +$epocroot =~ s/\/$//; + + +# create variables for paths +my $e32toolsdir = $epocroot."/epoc32/tools"; +my $e32includedir = $epocroot."/epoc32/include"; +my $e32includeoemdir = $e32includedir."/oem"; +my $platformpathspath = $e32includedir."/platform_paths.hrh"; +my $domainplatformpathspath = $e32includedir."/domain/osextensions/platform_paths.hrh"; +my $mmppmpath = $e32toolsdir."/mmp.pm"; +my $pathutlpmpath = $e32toolsdir."/pathutl.pm"; +my $prepfilepmpath = $e32toolsdir."/prepfile.pm"; + +# variables for hacked content +my $dependshack = "\t\t\tif (/^DEPENDS\$/o) {\r\n\t\t\t\tnext LINE; # Ignore DEPENDS keyword, not needed by ABLD\r\n\t\t\t}\r\n"; +my $smpsafehack = "\t\tif (/^SMPSAFE\$/o) {\r\n\t\t\tnext LINE; # Ignore SMPSAFE keyword, not needed by older environments\r\n\t\t}\r\n"; +my $forwardslashhack = "\t\t# EnvPatcher forwardslash hack begins\r\n\t\t\$_=~s{/}{\\\\}g; # convert all forward slashes to backslashes\r\n\t\t# EnvPatcher forwardslash hack ends\r\n\r\n"; +my $coreibyexportsupport = "\r\n// Following definition is used for exporting tools and stubs IBY files to\r\n// Core image.\r\n#define CORE_IBY_EXPORT_PATH(path,exported) /epoc32/rom/include/##exported\r\n"; + + +# check epoc32\tools exists +unless (-d $e32toolsdir) +{ + print "$e32toolsdir not found, please check valid epocroot has been given!\n"; + exit 1; +} + +# check epoc32\include exists +unless (-d $e32includedir) +{ + print "$e32includedir not found, please check valid epocroot has been given!\n"; + exit 1; +} + + +# create epoc32\include\oem if it does not exist +unless (-d $e32includeoemdir) +{ + mkdir $e32includeoemdir or die; + print "Missing directory $e32includeoemdir created succesfully.\n"; +} + + +# check if epoc32\include\domain\osextensions\platform_paths.hrh exists +if (-e $domainplatformpathspath) +{ + # show an error if the file does not have any platform macros + unless (string_exists_in_file($domainplatformpathspath, "OS_LAYER_SYSTEMINCLUDE")) + { + print "ERROR: $domainplatformpathspath does not have SF macros.\n"; + print "Please check your environment, if you have S60 3.2 OEM or newer, please get the latest version!\n"; + exit 2; + } +} + + +# check if epoc32\include\platform_paths.hrh exists +if (-e $platformpathspath) +{ + print "$platformpathspath already exists, not checking it.\n"; +} +else +{ + # create the file missing file + create_default_platform_paths_hrh(); + print "Missing file $platformpathspath created succesfully.\n"; +} + + +# check if CORE_IBY_EXPORT_PATH macro exist in the platform_paths.hrh +unless (string_exists_in_file($platformpathspath, "CORE_IBY_EXPORT_PATH")) +{ + # read content of the platform_paths.hrh + my @filecontent = read_file_to_array($platformpathspath); + + my $match_found = 0; + my $i = 0; + my $match_found_pos = 0; + + # find the position where the include guards start (this should be a safe position) + foreach (@filecontent) + { + if ($_ =~ /#define PLATFORM_PATHS_HRH/) + { + $match_found = 1; + $match_found_pos = $i; + last; + } + + $i++; + } + + if ($match_found) + { + # insert the patched content to the file + splice(@filecontent, $match_found_pos+1, 0, $coreibyexportsupport); + + # write the modified array to the file + write_file_from_array($platformpathspath, @filecontent); + + print "Platform_paths.hrh updated to support CORE_IBY_EXPORT_PATH macro.\n"; + } + else + { + print "WARNING: $platformpathspath is corrupted or not supported!\n"; + } +} + + +# check if epoc32\tools\mmp.pm exists +if (-e $mmppmpath) +{ + # check if DEPENDS keyword already exists in the file + if (string_exists_in_file($mmppmpath, "DEPENDS")) + { + print "The SDK can already handle DEPENDS keyword in a MMP file.\n"; + } + else + { + # read content of the mmp.pm file + my @filecontent = read_file_to_array($mmppmpath); + + my $match_found = 0; + my $i = 0; + my $match_found_pos = 0; + + # loop through the array to find the correct place + foreach (@filecontent) + { + if ($_ =~ /Unrecognised Resource Keyword/) + { + $match_found = 1; + $match_found_pos = $i; + last; + } + + $i++; + } + + if ($match_found) + { + # insert the patched content to the file + splice(@filecontent, $match_found_pos-1, 0, $dependshack); + + # write the modified array to the file + write_file_from_array($mmppmpath, @filecontent); + + print "Mmp.pm patched with DEPENDS keyword hack.\n"; + } + else + { + print "ERROR: Unable to find correct place from $mmppmpath for patching!\n"; + print "Your SDK environment probably is not supported by this script!\n"; + exit(2); + } + } + + # check if SMPSAFE keyword already exists in the file + if (string_exists_in_file($mmppmpath, "SMPSAFE")) + { + print "The SDK can already handle SMPSAFE keyword in a MMP file.\n"; + } + else + { + # read content of the mmp.pm file + my @filecontent = read_file_to_array($mmppmpath); + + my $match_found = 0; + my $i = 0; + my $match_found_pos = 0; + + # loop through the array to find the correct place + foreach (@filecontent) + { + if ($_ =~ /Unrecognised Keyword/) + { + $match_found = 1; + $match_found_pos = $i; + last; + } + + $i++; + } + + if ($match_found) + { + # insert the patched content to the file + splice(@filecontent, $match_found_pos, 0, $smpsafehack); + + # write the modified array to the file + write_file_from_array($mmppmpath, @filecontent); + + print "Mmp.pm patched with SMPSAFE keyword hack.\n"; + } + else + { + print "ERROR: Unable to find correct place from $mmppmpath for patching!\n"; + print "Your SDK environment probably is not supported by this script!\n"; + exit(2); + } + } +} +else +{ + print "WARNING: $mmppmpath not found, this environment is not supported!\n"; +} + + +# check if epoc32\tools\pathutl.pm exists +if (-e $pathutlpmpath) +{ + # check if "sub Path_Norm" already exists in the pathutil.pm file + # if it does not exists, then we need to patch prepfile.pm + if (string_exists_in_file($pathutlpmpath, "sub Path_Norm")) + { + print "The SDK is non Symbian OS 9.1, no need to add forward slash hack.\n"; + } + else + { + # check if prepfile.pm has already been patched + if (string_exists_in_file($prepfilepmpath, "EnvPatcher forwardslash hack")) + { + print "The SDK has already been patched with forwardslash hack.\n"; + } + else + { + # read content of the prepfile.pm file + my @filecontent = read_file_to_array($prepfilepmpath); + + my $match_found = 0; + my $i = 0; + my $match_found_pos = 0; + + # loop through the array to find the correct place + foreach (@filecontent) + { + if ($_ =~ /# skip blank lines/) + { + $match_found = 1; + $match_found_pos = $i; + last; + } + + $i++; + } + + if ($match_found) + { + # insert the patched content to the file + splice(@filecontent, $match_found_pos+6, 0, $forwardslashhack); + + # write the modified array to the file + write_file_from_array($prepfilepmpath, @filecontent); + + print "Prepfile.pm patched with forward slash hack.\n"; + } + else + { + print "ERROR: Unable to find correct place from $prepfilepmpath for patching!\n"; + print "Your SDK environment probably is not supported by this script!\n"; + exit(2); + } + } + } +} +else +{ + print "WARNING: $pathutlpmpath not found, this environment is not supported!\n"; +} + + + +# checks if string exists in the file +sub string_exists_in_file +{ + my $filepath = $_[0]; + my $findstring = $_[1]; + my $match_found = 0; + + open(FILE, "<", $filepath) or die "Failed to open $filepath for reading!"; + + # loop through the file for occurances + while (<FILE>) + { + if ($_ =~ /$findstring/) + { + $match_found = 1; + last; + } + } + + close FILE; + + return $match_found; +} + + +# reads lines from a file to an array +sub read_file_to_array +{ + my $filepath = $_[0]; + + open(FILE, "<", $filepath) or die "Failed to open $filepath for reading!"; + my @data = <FILE>; + close FILE; + + return(@data); +} + + +# writes lines from an array to a file +sub write_file_from_array +{ + my ($filepath, @data) = @_; + + # take a backup of the file + copy ($filepath, $filepath."EnvPatcher") or die "Cannot take backup of $filepath to $filepath.EnvPatcher"; + + open(FILE, ">", $filepath) or die "Failed to open $filepath for writing!"; + + # write the array to file + foreach my $line (@data) + { + print FILE "$line"; + } + + close FILE; +} + +sub create_default_platform_paths_hrh +{ + # the file does not exist, so create the missing file + open(FILE, ">", $platformpathspath) or die "Failed to open $platformpathspath for writing!\n"; + + print FILE <<ENDOFTHEFILE; +#ifndef PLATFORM_PATHS_HRH +#define PLATFORM_PATHS_HRH + +/** +* --------------------------------------- +* Location, where the applications layer specific public headers should be exported +* See usage on top of this hrh-file. +* --------------------------------------- +*/ +#define APP_LAYER_SDK_EXPORT_PATH(exported) /epoc32/include/##exported +#define APP_LAYER_PUBLIC_EXPORT_PATH(exported) /epoc32/include/##exported + +/** +* --------------------------------------- +* Location, where the applications layer specific platform headers should be exported +* See usage on top of this hrh-file. +* --------------------------------------- +*/ +#define APP_LAYER_DOMAIN_EXPORT_PATH(exported) /epoc32/include/##exported +#define APP_LAYER_PLATFORM_EXPORT_PATH(exported) /epoc32/include/##exported + +/** +* --------------------------------------- +* Location, where the middleware layer specific public headers should be exported +* See usage on top of this hrh-file. +* --------------------------------------- +*/ +#define MW_LAYER_SDK_EXPORT_PATH(exported) /epoc32/include/##exported +#define MW_LAYER_PUBLIC_EXPORT_PATH(exported) /epoc32/include/##exported + +/** +* --------------------------------------- +* Location, where the middleware layer specific platform headers should be exported +* --------------------------------------- +*/ +#define MW_LAYER_DOMAIN_EXPORT_PATH(exported) /epoc32/include/##exported +#define MW_LAYER_PLATFORM_EXPORT_PATH(exported) /epoc32/include/##exported + +/** +* --------------------------------------- +* Location, where the os layer specific public headers should be exported +* --------------------------------------- +*/ +#define OSEXT_LAYER_SDK_EXPORT_PATH(exported) /epoc32/include/##exported +#define OS_LAYER_PUBLIC_EXPORT_PATH(exported) /epoc32/include/##exported + +/** +* --------------------------------------- +* Location, where the os specific platform headers should be exported +* --------------------------------------- +*/ +#define OSEXT_LAYER_DOMAIN_EXPORT_PATH(exported) /epoc32/include/##exported +#define OS_LAYER_PLATFORM_EXPORT_PATH(exported) /epoc32/include/##exported + +/** +* --------------------------------------- +* Location, where the cenrep excel sheets should be exported +* Deprecated: should no longer be used. Kept for compability. +* --------------------------------------- +*/ +#define CENREP_XLS_EXPORT_PATH(exported) /epoc32/tools/cenrep/data/src/##exported + +/** +* This define statements defines the SYSTEMINCLUDE-line, which is intended to be +* used in the mmp-files that are part of the applications-layer. It includes all +* the needed directories from the /epoc32/include, that are valid ones for the +* application-layer components. +* +* Applications layer is the last one in the list, since most likely the most of +* the headers come from middleware or os-layer => thus they are first. +*/ +#define APP_LAYER_SYSTEMINCLUDE SYSTEMINCLUDE /epoc32/include /epoc32/include/oem + +/** +* This define statements defines the SYSTEMINCLUDE-line, which is intended to be +* used in the mmp-files that are part of the middleware-layer. It includes all +* the needed directories from the /epoc32/include, that are valid ones for the +* middleware-layer components. +*/ +#define MW_LAYER_SYSTEMINCLUDE SYSTEMINCLUDE /epoc32/include /epoc32/include/oem + +/** +* This define statements defines the SYSTEMINCLUDE-line, which is intended to be +* used in the mmp-files that are part of the osextensions-layer. It includes all +* the needed directories from the /epoc32/include, that are valid ones for the +* os-layer components. +*/ +#define OS_LAYER_SYSTEMINCLUDE SYSTEMINCLUDE /epoc32/include /epoc32/include/oem + + +// Below statement is Deprecated and the OS_LAYER_SYSTEMINCLUDE-macro has to be +// used. +#define OSEXT_LAYER_SYSTEMINCLUDE OS_LAYER_SYSTEMINCLUDE + +/** +* This define statements defines the SYSTEMINCLUDE-line, which is intended to be +* used in the mmp-files that are part of the os-layer. This is intended +* to be only used by those components which need to use in their mmp-file either +* kern_ext.mmh or nkern_ext.mmh. Reason is that those +* 2 files already contain the /epoc32/include as system include path. +* +*/ +#define OS_LAYER_KERNEL_SYSTEMINCLUDE SYSTEMINCLUDE /epoc32/include/oem + + +// Below statement is Deprecated and the OS_LAYER_KERNEL_SYSTEMINCLUDE-macro +// has to be used. +#define OSEXT_LAYER_KERNEL_SYSTEMINCLUDE OS_LAYER_KERNEL_SYSTEMINCLUDE + +/** +**************************************************************************** +* Definitions that also define the paths to the layer specific source directories. +**************************************************************************** +*/ +/** +* The below 3 macros define the paths to the layer-specific source dirs. +* See usage on top of this hrh-file, these are used the same way as +* for instance the OS_LAYER_DOMAIN_EXPORT_PATH +* Deprecated: is not allowed to be using in Symbian Foundation +*/ +#define APP_LAYER_SOURCE_PATH(rest) /s60/app/##rest +#define MW_LAYER_SOURCE_PATH(rest) /s60/mw/##rest +#define OSEXT_LAYER_SOURCE_PATH(rest) /s60/osext/##rest + +/** +**************************************************************************** +* Definitions to export IBY files to different folders where they will be taken +* to ROM image +**************************************************************************** +*/ +// Following definition is used for exporting tools and stubs IBY files to +// Core image. +#define CORE_IBY_EXPORT_PATH(path,exported) /epoc32/rom/include/##exported + +/** +* --------------------------------------- +* Macros for Configuration tool migration. +* The below macros define the location under epoc32, where the confml +* (Configuration Markup Language) and crml (Central Repository Markup Language) +* files should be exported. +* --------------------------------------- +*/ +#define CONFML_EXPORT_PATH(file,category) /epoc32/rom/config/confml_data/##category##/##file +#define CRML_EXPORT_PATH(file,category) /epoc32/rom/config/confml_data/##category##/##file +#define GCFML_EXPORT_PATH(file,category) /epoc32/rom/config/confml_data/##category##/##file +#define CONFML_CONFIG_EXPORT_PATH(file,category) /epoc32/rom/config/confml_data/##category##/config/##file + +#define APP_LAYER_CONFML(exported) CONFML_EXPORT_PATH(exported,s60) +#define APP_LAYER_CRML(exported) CRML_EXPORT_PATH(exported,s60) +#define APP_LAYER_GCFML(exported) GCFML_EXPORT_PATH(exported,s60) +#define APP_LAYER_CONFML_CONFIG(exported) CONFML_CONFIG_EXPORT_PATH(exported,s60) + +#define MW_LAYER_CONFML(exported) CONFML_EXPORT_PATH(exported,s60) +#define MW_LAYER_CRML(exported) CRML_EXPORT_PATH(exported,s60) +#define MW_LAYER_GCFML(exported) GCFML_EXPORT_PATH(exported,s60) +#define MW_LAYER_CONFML_CONFIG(exported) CONFML_CONFIG_EXPORT_PATH(exported,s60) + +// Deprecate: Use the OS_LAYER_* macros instead of OSEXT_LAYER_* +#define OSEXT_LAYER_CONFML(exported) CONFML_EXPORT_PATH(exported,s60) +#define OSEXT_LAYER_CRML(exported) CRML_EXPORT_PATH(exported,s60) +#define OSEXT_LAYER_GCFML(exported) GCFML_EXPORT_PATH(exported,s60) +#define OSEXT_LAYER_CONFML_CONFIG(exported) CONFML_CONFIG_EXPORT_PATH(exported,s60) +#define OS_LAYER_CONFML(exported) CONFML_EXPORT_PATH(exported,s60) +#define OS_LAYER_CRML(exported) CRML_EXPORT_PATH(exported,s60) +#define OS_LAYER_GCFML(exported) GCFML_EXPORT_PATH(exported,s60) +#define OS_LAYER_CONFML_CONFIG(exported) CONFML_CONFIG_EXPORT_PATH(exported,s60) + +#endif // end of PLATFORM_PATHS_HRH + +ENDOFTHEFILE + + close FILE; +} diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/envpatcher/ReadMe.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/envpatcher/ReadMe.txt Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,46 @@ +Environment Patcher v1.0.1 +========================== + +Updated: 12th November 2009 + + +Introduction: +------------- +This tool can be used to patch your S60 SDK environment so that the tricks and +macros introduced in the latest SDKs can be used in a public SDK and older +OEM releases. + +This tool can perform the following tasks: +- Adds support for forward slashes in paths in bld.inf/.mmp files in S60 3.0 +- Removes an unncessary warning about DEPENDS and SMPSAFE resource keywords in + an .mmp file +- Creates a missing epoc32\include\platform_paths.hrh file for supporting + platform macros introduced since S60 3.2 OEM and Symbian Foundation releases +- Modifies epoc32\include\platform_paths.hrh for missing macros +- Creates a missing epoc32\include\oem directory to suppress a possible warning + + +Usage: +------ +EnvPatcher.pl <EPOCROOT> + +Where EPOCROOT is the path to the root of the SDK, for example: + EnvPatcher.pl c:\Symbian\9.1\S60_3rd_MR + EnvPatcher.pl z:\ + + +Requirements: +------------- +- S60 SDK (public or OEM), version 3.0 or newer +- Perl 5.6.1 or newer + + + + +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". diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/group/ReleaseNotes_AnalyzeTool.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/group/ReleaseNotes_AnalyzeTool.txt Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,136 @@ +=============================================================================== + +RELEASE NOTES - ANALYZETOOL v1.9.1 +RELEASED 29th April 2010 + +SUPPORTS SYMBIAN^1+ + +=============================================================================== + +Product Description: +==================== +AnalyzeTool is a dynamic test tool that is used for testing Symbian software +for memory and resource leaks and pinpointing the leaks from the source code. + +Main Features: +============== +- Pinpoints memoryleaks from target hardware and emulator to source code lines +- Discovers resource leaks from processes +- Command line interface and Carbide.c++ Extension + +=============================================================================== + +What's New in v1.9.1 +==================== +- Change: Removed Avkon and Console UI's to simplify the maintenance of the + tool +- Change: Middleware layer dependencies removed so AnalyzeTool can be now used + also in OS layer builds +- Fix: Move all binaries to ROM instead of ROFS to avoid ROM build + dependencies issues in hooked components + +=============================================================================== + +Installation Notes: +=================== +AnalyzeTool is typically preinstalled on ROM. If not, it can be added to the +ROM with the .iby file. Alternatively, the .sis file can be found under the sis- +directory, but the user need to sign it with their own developer certificate. +In Nokia R&D environment, you can use directly the R&D-signed .sis file under the +internal\sis directory. + +When signing with own developer certificate, the following capabilities are +needed: + ReadDeviceData + WriteDeviceData + DiskAdmin + AllFiles + SwEvent + NetworkServices + LocalServices + ReadUserData + WriteUserData + Location + UserEnvironment + CommDD + PowerMgmt + MultimediaDD + DRM + TrustedUI + ProtServ + NetworkControl + SurroundingsDD + TCB + +When builing AnalyzeTool against S60 3.0 or 3.1, you may need to patch your SDK +environment first with some fixes. For more information, please refer to the +instructions under the "envpatcher" directory. + +=============================================================================== + +System Requirements: +==================== +Basic Requirements: +- Any S60 3.x device or emulator environment + +=============================================================================== + +Compatibility Issues: +===================== +N/A + +=============================================================================== + +Known Issues: +============= +- Kernel analysis are not supported. + +- When using monitored internal data gathering mode (-mi) and hooked + application contains huge amounts of allocations AnalyzeTool? storageserver + might run out of memory to store the data. This message "Symbian error code + -4" is seen when analyzing the data file with atool.exe. Solution is to use + external / monitored external data gathering mode. + +- Switch allocator. AnalyzeTool change the application memory allocator to + AnalyzeTool own memory allocator and using the User::SwitchAllocator function + can lead to situation where the tested application does not work properly. + +- AnalyzeTool hooked QT applications becomes too slow to run. Use small size + call stack(s) and new logging mode (external -e). + +- Stif test case with AnalyzeTool can inform wrong memory leak alert. + +- AnalyzeTool overwrites functions TInt User::ProcessCritical(TCritical + aCritical) and TInt User::SetProcessCritical(TCritical aCritical), but this + works only when the function is called from hooked exe application. So if + setting critical is done from DLL (even if it's hooked with AnalyzeTool) the + overwriting does not work and the process stays set critical during the + testing. + +- If hooked application is closed by calling User::Exit() from DLL instead of + .exe application AnalyzeTool reports "abnormal process end" and can't report + proper memory leaks. + +=============================================================================== + +Version History: +================ + +Version 1.9.0 - 8th April 2010 +============================== +- Feature: Remove false positive memory leaks with better handling of global + variables +- Feature: Automatic check of correct version of dbghelp.dll for better + emulator support +- Change: HTI support removed +- Fix: SBSVS variant compilation didn't work + +=============================================================================== + +Copyright (c) 2010 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". diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/group/atool_stub_sis.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/group/atool_stub_sis.mk Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,57 @@ +# +# 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: Stub sis makefile for Configuration UI. +# + +TARGETDIR=$(EPOCROOT)EPOC32\Data\Z\System\Install + +SISNAME=analyzeTool_stub +PKGNAME=analyzeTool_stub + +$(TARGETDIR) : + @perl -S emkdir.pl "$(TARGETDIR)" + +do_nothing : + rem do_nothing + +SISFILE=$(TARGETDIR)\$(SISNAME).sis + +$(SISFILE) : ..\sis\$(PKGNAME).pkg + makesis -s $? $@ + +# +# The targets invoked by bld... +# + +MAKMAKE : do_nothing + +RESOURCE : do_nothing + +SAVESPACE : do_nothing + +BLD : do_nothing + +FREEZE : do_nothing + +LIB : do_nothing + +CLEANLIB : do_nothing + +FINAL : $(TARGETDIR) $(SISFILE) + +CLEAN : + -erase $(SISFILE) + +RELEASABLES : + @echo $(SISFILE) \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,49 @@ +/* +* 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: +* +*/ + +#include <platform_paths.hrh> + + +#include "../commandlineengine/group/bld.inf" +#include "../staticlib/group/bld.inf" +#include "../storageserver/group/bld.inf" +#include "../kerneleventhandler/group/bld.inf" +#include "../analyzetoolcleaner/group/bld.inf" +#include "../dynamicmemoryhook/group/bld.inf" + +PRJ_EXPORTS +//../rom/analyzetool.iby CORE_IBY_EXPORT_PATH(tools,analyzetool.iby) +../rom/analyzetool_rom.iby CORE_IBY_EXPORT_PATH(tools/rom,analyzetool_rom.iby) + +/* +PRJ_MMPFILES +#ifndef SBSV2 + #ifdef MARM + gnumakefile atool_stub_sis.mk + #endif +#endif + +PRJ_EXTENSIONS +#ifdef SBSV2 + #ifdef MARM + START EXTENSION app-services/buildstubsis + OPTION SRCDIR ../sis + OPTION SISNAME analyzeTool_stub + END + #endif +#endif +*/ \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/inc/atlog.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/inc/atlog.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,128 @@ +/* +* 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 of logging macros for Analyze Tool S60 modules. +* +*/ + +#ifndef __ATLOG_H__ +#define __ATLOG_H__ + +#ifdef _DEBUG +//To enable/disable logging uncomment/comment the next line +// #define LOGGING_ENABLED //Enable logging +//Uncomment next to enable logging only LOGSTR1 lines +// #define LOGGING_ENABLED_FAST //Logging only function names + +//Disable next to use file logging + #define USE_RDEBUG +#endif + +//Do not alter the code below this + +#ifdef __KERNEL_MODE__ + + #ifdef LOGGING_ENABLED + #include <kernel.h> + #define LOGSTR1( AAA ) { Kern::Printf( AAA ); } + #define LOGSTR2( AAA, BBB ) { Kern::Printf( AAA, BBB ); } + #else + #define LOGSTR1( AAA ) + #define LOGSTR2( AAA, BBB ) + #endif + +#else // #ifdef __KERNEL_MODE__ + + #ifdef LOGGING_ENABLED + +// INCLUDES + #include <flogger.h> + #ifdef USE_RDEBUG + #include <e32svr.h> + #endif + +// CONSTANTS + _LIT( KAtLoggingFolder, "atlog" ); + _LIT( KAtLoggingFile , "LOG.TXT" ); + #define ONE_SPACE_MARGIN _S(" ") + +// --------------------------------------------------------------------------------- +// Internal MACROS. Do not call these directly, use the External MACROS instead +// --------------------------------------------------------------------------------- + + #ifdef LOGGING_ENABLED_FAST + + #ifdef USE_RDEBUG + #define INTERNAL_LOGSTR1( AAA ) { _LIT( logdes, AAA ); RDebug::Print( logdes() ); } + #else // RFileLogger is used + #define INTERNAL_LOGSTR1( AAA ) { _LIT( logdes, AAA ); RFileLogger::Write( KAtLoggingFolder(), KAtLoggingFile(), EFileLoggingModeAppend, logdes() ); } + #endif // USE_RDEBUG + #define INTERNAL_LOGSTR2( AAA, BBB ) + #define INTERNAL_LOGSTR3( AAA, BBB, CCC ) + #define INTERNAL_LOGMEM + #define INTERNAL_LOG( AAA ) + + #else + + #ifdef USE_RDEBUG + #define INTERNAL_LOGDESC8( AAA ) { TBuf<100> tmp; if( sizeof( AAA ) < 100 ) tmp.Copy( AAA ); RDebug::Print( tmp );} + #define INTERNAL_LOGSTR1( AAA ) { _LIT( logdes, AAA ); RDebug::Print( logdes() ); } + #define INTERNAL_LOGSTR2( AAA, BBB ) { _LIT( logdes, AAA ); RDebug::Print( TRefByValue<const TDesC>( logdes()), BBB ); } + #define INTERNAL_LOGSTR3( AAA, BBB, CCC ) { _LIT( logdes, AAA ); RDebug::Print( TRefByValue<const TDesC>(logdes()), BBB, CCC ); } + #define INTERNAL_LOGMEM { _LIT( logdes, "Heap size: %i" ); TBuf<50> buf; TInt a; User::AllocSize( a ); buf.Format( logdes, a ); RDebug::Print( buf ); } + #define INTERNAL_LOG( AAA ) AAA + #else // RFileLogger is used + #define INTERNAL_LOGSTR1( AAA ) { _LIT( logdes, AAA ); RFileLogger::Write( KAtLoggingFolder(), KAtLoggingFile(), EFileLoggingModeAppend, logdes() ); } + #define INTERNAL_LOGSTR2( AAA, BBB ) { _LIT( logdes, AAA ); RFileLogger::WriteFormat( KAtLoggingFolder(), KAtLoggingFile(), EFileLoggingModeAppend, TRefByValue<const TDesC>( logdes()), BBB ); } + #define INTERNAL_LOGSTR3( AAA, BBB, CCC) { _LIT( logdes, AAA ); RFileLogger::WriteFormat( KAtLoggingFolder(), KAtLoggingFile(), EFileLoggingModeAppend, TRefByValue<const TDesC>(logdes()), BBB, CCC ); } + #define INTERNAL_LOGMEM { _LIT( logdes, "Heap size: %i" ); TMemoryInfoV1Buf info; UserHal::MemoryInfo(info); TInt freeMemory = info().iFreeRamInBytes; TBuf<50> buf; buf.Format( logdes, freeMemory ); RFileLogger::WriteFormat( KAtLoggingFolder(), KAtLoggingFile(), EFileLoggingModeAppend, buf ); } + #define INTERNAL_LOG( AAA ) AAA + #endif // USE_RDEBUG + + #endif + + #else + + #define INTERNAL_LOGSTR1( AAA ) + #define INTERNAL_LOGSTR2( AAA, BBB ) + #define INTERNAL_LOGSTR3( AAA, BBB, CCC ) + #define INTERNAL_LOGMEM + #define INTERNAL_LOG( AAA ) + + #endif + +// --------------------------------------------------------------------------------- +// External MACROS. Use these in code +// --------------------------------------------------------------------------------- +// Logging of string +// i.e.: LOGSTR1( "Whoo-haa!" ); + #define LOGSTR1( AAA ) { INTERNAL_LOGSTR1( AAA ); } + +// Logging of string + integer value +// i.e.: LOGSTR2( "CHttpd status %i:", iStatus ); + #define LOGSTR2( AAA, BBB ) { INTERNAL_LOGSTR2( AAA, BBB ); } + +// Logging of descriptor + 2 integers +// i.e.: LOGSTR3( "Jippii %i %i", val1, val2 ); + #define LOGSTR3( AAA, BBB, CCC ) { INTERNAL_LOGSTR3( AAA, BBB, CCC ); } + +// Log heap size + #define LOGMEM { INTERNAL_LOGMEM } + +// Logging variable operations + #define LOG( AAA ) INTERNAL_LOG( AAA ) + +#endif // #ifdef __KERNEL_MODE__ + +#endif // __ATLOG_H__ +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/kerneleventhandler/group/atoolkerneleventhandler.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/kerneleventhandler/group/atoolkerneleventhandler.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,51 @@ +/* +* 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: The .mmp file for the AToolKernelEventHandler +* +*/ + +#include <platform_paths.hrh> +#include <kernel/kern_ext.mmh> +#include "../../symbian_version.hrh" + +TARGET atoolkerneleventhandler.ldd +TARGETTYPE ldd +CAPABILITY ALL + +SMPSAFE + +USERINCLUDE ../inc +USERINCLUDE ../../inc + +OS_LAYER_KERNEL_SYSTEMINCLUDE + +SOURCEPATH ../src + +SOURCE analyzetoolchannel.cpp +SOURCE analyzetooldevice.cpp +SOURCE analyzetooleventhandler.cpp + +LIBRARY flogger.lib +#ifdef WINSCW +LIBRARY emulator.lib + start wins + win32_headers + end +#endif // WINSCW + +#if ( SYMBIAN_VERSION_SUPPORT >= SYMBIAN_3 ) || defined(BSW_FLEXIBLE_MEMORY_MODEL) +MACRO MCL_ROBJECTIX +#endif + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/kerneleventhandler/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/kerneleventhandler/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,35 @@ +/* +* 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: +* +*/ + +#include <platform_paths.hrh> + +PRJ_PLATFORMS +ARMV5 WINSCW + +PRJ_EXPORTS +../inc/analyzetool.h OS_LAYER_PLATFORM_EXPORT_PATH(analyzetool/analyzetool.h) +../inc/atcommon.h OS_LAYER_PLATFORM_EXPORT_PATH(analyzetool/atcommon.h) +../inc/analyzetool.inl OS_LAYER_PLATFORM_EXPORT_PATH(analyzetool/analyzetool.inl) +../inc/analyzetooltraceconstants.h OS_LAYER_PLATFORM_EXPORT_PATH(analyzetool/analyzetooltraceconstants.h) + +PRJ_MMPFILES +atoolkerneleventhandler.mmp + +PRJ_TESTMMPFILES +../internal/tsrc/group/analyzetooldevicedrivertest.mmp + + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/kerneleventhandler/inc/analyzetool.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/kerneleventhandler/inc/analyzetool.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,325 @@ +/* +* 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: Declaration of the class RAnalyzeTool. +* +*/ + + +#ifndef __ANALYZETOOL_H__ +#define __ANALYZETOOL_H__ + +// INCLUDES +#include <e32cmn.h> + +//Version information for command line engine. +//Tells the version of AT core componenets. +//ANALYZETOOL_CORE_VERSION_FOR_CLE 1.9.1 + +// CONSTANTS +inline TVersion KAnalyzeToolLddVersion() { return TVersion(1, 0, 1); } + +/* The name of the analyze tool device driver*/ +_LIT( KAnalyzeToolLddName, "AToolKernelEventHandler" ); + +/* The priority of AnalyzeTool Dfc */ +const TInt KAnalyzeToolThreadPriority = 27; + +/* The name of the AnalyzeTool DFC */ +_LIT8( KAnalyzeToolThreadName, "AnalyzeToolThreadDfc" ); + +/* The panic literal */ +_LIT( KClientPanic, "AnalyzeTool" ); + +//const TInt KATMaxCallstackLength = 20; + +/* The device handler panic codes */ +enum TPanic + { + EPanicRequestPending, + EPanicNoRequestPending, + EPanicUnsupportedRequest + }; + +// Size of following must be multiple of 4 bytes. + +class TMainThreadParams + { + public: + RAllocator* iAllocator; + TBool iAlone; + TUint iProcessId; + }; +typedef TPckgBuf<TMainThreadParams> TMainThreadParamsBuf; + +class TLibraryInfo + { + public: + TBuf8<KMaxLibraryName> iLibraryName; + TLinAddr iRunAddress; + TUint32 iSize; + TInt iIndex; + TUint iProcessId; + }; + +typedef TPckgBuf<TLibraryInfo> TLibraryInfoBuf; + +class TCodesegInfo + { + public: + TBuf8<KMaxLibraryName> iFullName; + TLinAddr iRunAddress; + TUint32 iSize; + TInt iIndex; + TUint iProcessId; + TInt iCodesegIndex; + TLinAddr iFileEntryPoint; + TInt iFuntionCount; + TLibraryFunction iFirstFunction; + TModuleMemoryInfo iMemoryInfo; + }; + +typedef TPckgBuf<TCodesegInfo> TCodesegInfoBuf; + +class TThreadParams + { + public: + TLinAddr iStackAddress; + TInt iStackSize; + TUint iThreadId; + }; + +typedef TPckgBuf<TThreadParams> TThreadParamsBuf; + +class TProcessIdentityParams + { + public: + TBuf8<KMaxProcessName> iProcessName; + TInt iDynamicCount; + TInt iCodesegCount; + TUint iProcessId; + TUint iThreadId; + TLinAddr iStackAddress; + TInt iStackSize; + }; + +typedef TPckgBuf<TProcessIdentityParams> TProcessIdentityParamsBuf; + +class TLibraryEventInfo + { + public: + enum TLibraryEvent + { + ELibraryAdded = 0, + ELibraryRemoved, + EKillThread + }; + + public: + TUint iProcessId; + TBuf8<KMaxLibraryName> iLibraryName; + TLinAddr iRunAddress; + TUint32 iSize; + TLibraryEvent iEventType; + TUint iThreadId; + }; + +typedef TPckgBuf<TLibraryEventInfo> TLibraryEventInfoBuf; + +class TProcessHandleInfo + { + public: + TInt iProcessHandleCount; + TInt iThreadHandleCount; + TInt iIndex; + TInt iThreadCount; + TLinAddr iUserStackRunAddress; + TInt iUserStackSize; + TUint iProcessId; + }; + +typedef TPckgBuf<TProcessHandleInfo> TProcessHandleInfoBuf; + +/** +* A class for particular process's current handle count +*/ +class TATProcessHandles + { + public: + + /** The ID of the process. */ + TUint iProcessId; + + /** The number of current handles in the library. */ + TInt iCurrentHandleCount; + }; + +typedef TPckgBuf<TATProcessHandles> TATProcessHandlesBuf; + +class TClientCount + { + public: + + /** The count of clients */ + TInt iClientCount; + }; + +typedef TPckgBuf<TClientCount> TClientCountBuf; + +class TATMemoryModel + { + public : + /* Memory model*/ + TUint32 iMemoryModel; + }; +typedef TPckgBuf<TATMemoryModel> TATMemoryModelBuf; + +// CLASS DECLARATION + +/** +* The user-side handle to a logical channel which provides functions to +* open a channel and to make requests to a analyze tool device driver. +*/ + +class RAnalyzeTool : public RBusLogicalChannel + { + + public: + + /** Enumeration of supported functions */ + enum TBasicAnalyzerControl + { + EGetProcessInfo = 0, /* The process information */ + EGetCodesegInfo, /* The codesegment information */ + EGetLibraryInfo, /* The library information */ + EGetDynamicInfo, /* The count of dynamic code in the process */ + ELibraryEvent, /* Subscribe events from library events */ + ECancelLibraryEvent, /* Cancel subscribetion of library events */ + ECurrentClientCount, /* The count of clients in device driver */ + EMainThreadAlloctor, + EThreadStack, + EGetProcessHandle, /* Gets process global handles info*/ + EGetCurrentHandles, /* Get a process's current handle count */ + EGetMemoryModel + }; + +#ifndef __KERNEL_MODE__ + + /** + * Opens a handle to a logical channel. + * @return TInt Returns KErrNone, if successful or otherwise + one of the other system-wide error codes + */ + inline TInt Open(); + + /** + * Acquires process information. + * @param aProcessIdentityParams The process information which + is filled by the device driver + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + inline TInt GetProcessInfo( + TProcessIdentityParamsBuf& aProcessIdentityParams ); + + /** + * Acquires codeseg information. + * @param aCodesegInfo The codeseg information which + is filled by the device driver + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + inline TInt GetCodesegInfo( TCodesegInfoBuf& aCodesegInfo ); + + /** + * Acquires library information. + * @param aLibraryInfo The library information which + is filled by the device driver + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + inline TInt GetLibraryInfo( TLibraryInfoBuf& aLibraryInfo ); + + /** + * Subscribes library event. + * @param aStatus The request status object for this request. + * @param aLibraryInfo The library information which + is filled by the device driver + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + inline void LibraryEvent( TRequestStatus& aStatus, + TLibraryEventInfo& aLibraryInfo ); + + /** + * Cancels subscribetion of the library event. + */ + inline void CancelLibraryEvent(); + + /** + * Acquires device driver current client count. + * @param aClientCount A reference to TInt which is + updated by the device driver. + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + inline TInt ClientCount( TClientCountBuf& aClientCount ); + + /** + * Acquires process main thread RAllocator + * @param aMainThreadParams The main thread information which + is filled by the device driver + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + inline TInt MainThreadAlloctor( TMainThreadParamsBuf& aMainThreadParams ); + + /** + * Acquires main thread stack address. + * @param aThreadStack Pointer to the TThreadParams object. + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + inline TInt ThreadStack( TThreadParamsBuf& aThreadStack ); + + /** + * Acquires information about process global handles. + * @param aProcessHandleInfo Pointer to the TProcessHandleInfo object. + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + inline TInt GetProcessHandleInfo( TProcessHandleInfoBuf& aProcessHandleInfo ); + + /** + * Acquires a process's current handle count. + * @param aProcessHandles Pointer to the TATProcessHandles object. + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + inline TInt GetCurrentHandleCount( TATProcessHandlesBuf& aProcessHandles ); + + /** + * Acquires memory model system uses. + * @param aMemoryModel pointer to the TATMemoryModelBuf object. + */ + inline TInt GetMemoryModel( TATMemoryModelBuf& aMemoryModel ); + +#endif // #ifndef __KERNEL_MODE__ + }; + +// INLINES +#include <analyzetool/analyzetool.inl> + +#endif // #ifndef __ANALYZETOOL_H__ + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/kerneleventhandler/inc/analyzetool.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/kerneleventhandler/inc/analyzetool.inl Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,159 @@ +/* +* 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 inline methods of the class RAnalyzeTool. +* +*/ + + +#ifndef __ANALYZETOOL_INL +#define __ANALYZETOOL_INL + +#ifndef __KERNEL_MODE__ + +// ---------------------------------------------------------------------------- +// RAnalyzeTool::Open() +// Opens a handle to a analyze tool device driver +// ---------------------------------------------------------------------------- +// +inline TInt RAnalyzeTool::Open() + { + return DoCreate( KAnalyzeToolLddName, + KAnalyzeToolLddVersion(), + KNullUnit, + NULL, + NULL, + EOwnerProcess ); + } + +// ---------------------------------------------------------------------------- +// RAnalyzeTool::GetProcessInfo() +// Acquires process information. +// ---------------------------------------------------------------------------- +// +inline TInt RAnalyzeTool::GetProcessInfo( + TProcessIdentityParamsBuf& aProcessIdentityParams ) + { + return DoControl( EGetProcessInfo, &aProcessIdentityParams, NULL ); + } + +// ---------------------------------------------------------------------------- +// RAnalyzeTool::GetCodesegInfo() +// Acquires codeseg information. +// ---------------------------------------------------------------------------- +// +inline TInt RAnalyzeTool::GetCodesegInfo( TCodesegInfoBuf& aCodesegInfo ) + { + return DoControl( EGetCodesegInfo, &aCodesegInfo, NULL ); + } + +// ---------------------------------------------------------------------------- +// RAnalyzeTool::GetLibraryInfo() +// Symbian 2nd phase constructor can leave. +// ---------------------------------------------------------------------------- +// +inline TInt RAnalyzeTool::GetLibraryInfo( TLibraryInfoBuf& aLibraryinfo ) + { + return DoControl( EGetLibraryInfo, &aLibraryinfo, NULL ); + } + +// ---------------------------------------------------------------------------- +// RAnalyzeTool::LibraryEvent() +// Subscribes library event. +// ---------------------------------------------------------------------------- +// +inline void RAnalyzeTool::LibraryEvent( TRequestStatus& aStatus, + TLibraryEventInfo& aLibInfo ) + { + return DoRequest( ELibraryEvent, aStatus, (TAny*)&aLibInfo ); + } + +// ---------------------------------------------------------------------------- +// RAnalyzeTool::CancelLibraryEvent() +// Cancels subscribetion of the library event. +// ---------------------------------------------------------------------------- +// +inline void RAnalyzeTool::CancelLibraryEvent() + { + DoControl( ECancelLibraryEvent, NULL, NULL); + } + +// ---------------------------------------------------------------------------- +// RAnalyzeTool::ClientCount() +// Acquires the count of device driver current users +// ---------------------------------------------------------------------------- +// +inline TInt RAnalyzeTool::ClientCount( TClientCountBuf& aClientCount ) + { + return DoControl( ECurrentClientCount, &aClientCount, NULL ); + } + +// ---------------------------------------------------------------------------- +// RAnalyzeTool::MainThreadAlloctor() +// Acquires information about process main thread +// ---------------------------------------------------------------------------- +// +inline TInt RAnalyzeTool::MainThreadAlloctor( + TMainThreadParamsBuf& aMainThreadParams ) + { + return DoControl( EMainThreadAlloctor, &aMainThreadParams, NULL ); + } + +// ---------------------------------------------------------------------------- +// RAnalyzeTool::ThreadStack() +// Acquires main thread stack address. +// ---------------------------------------------------------------------------- +// +inline TInt RAnalyzeTool::ThreadStack( TThreadParamsBuf& aThreadStack ) + { + return DoControl( EThreadStack, &aThreadStack, NULL ); + } + +// ---------------------------------------------------------------------------- +// RAnalyzeTool::GetProcessHandleInfo() +// Acquires information about process handles +// ---------------------------------------------------------------------------- +// +inline TInt RAnalyzeTool::GetProcessHandleInfo( + TProcessHandleInfoBuf& aProcessHandleInfo ) + { + return DoControl( EGetProcessHandle, &aProcessHandleInfo, NULL ); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::GetCurrentHandleCount() +// Acquires a process's current handle count +// ----------------------------------------------------------------------------- +// +inline TInt RAnalyzeTool::GetCurrentHandleCount( + TATProcessHandlesBuf& aProcessHandles ) + { + return DoControl( EGetCurrentHandles, &aProcessHandles, NULL ); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::GetMemoryModel() +// Acquires memory model system uses. +// ----------------------------------------------------------------------------- +// +inline TInt RAnalyzeTool::GetMemoryModel( + TATMemoryModelBuf& aMemoryModel ) + { + return DoControl( EGetMemoryModel, &aMemoryModel, NULL ); + } + +#endif // #ifndef __KERNEL_MODE__ + +#endif // __ANALYZETOOL_INL + +// End of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/kerneleventhandler/inc/analyzetoolchannel.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/kerneleventhandler/inc/analyzetoolchannel.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,213 @@ +/* +* 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: Declaration of the class DAnalyzeToolChannel +* +*/ + + +#ifndef __ANALYZETOOLCHANNEL_H__ +#define __ANALYZETOOLCHANNEL_H__ + +// INCLUDES +#include <analyzetool/analyzetool.h> +#include <kernel/kernel.h> +#ifdef __WINSCW__ +#include <memmodel/emul/win32/memmodel.h> +#endif // __WINSCW__ + +// FORWARD DECLARATIONS +class DAnalyzeToolEventHandler; + +// CLASS DECLARATION + +/** +* The implementation of the abstract base class for a logical channel. +*/ +class DAnalyzeToolChannel : public DLogicalChannel + { + public: + + /** + * C++ default constructor. + */ + DAnalyzeToolChannel(); + + /** + * Destructor. + */ + ~DAnalyzeToolChannel(); + + protected: // from DLogicalChannel + + /** + * Creates the logical channel. + * @param aUnit A unit of the device. + * @param anInfo A pointer to an explicit 8-bit descriptor containing + extra information for the physical device + * @param aVer The required version of the logical device + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + virtual TInt DoCreate( TInt aUnit, + const TDesC8* anInfo, + const TVersion &aVer ); + + /** + * Handles a client request. + * @param aFunction The requested function. + * @param a1 A 32-bit value passed to the kernel-side. Its meaning + depends on the device driver requirements + * @param a2 A 32-bit value passed to the kernel-side. Its meaning + depends on the device driver requirements + * @param aMessage Reference to received thread message. + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + virtual TInt DoControl( TInt aFunction, TAny* a1, TAny* a2, TThreadMessage& aMessage ); + + /** + * Processes a message for this logical channel. + * This function is called in the context of a DFC thread. + * @param aMsg The message to process. + */ + virtual void HandleMsg( TMessageBase* aMsg ); + + /** + * Handles a client asynchronous request. + * @param aFunction The requested function. + * @param aStatus Pointer to client TRequestStatus. + * @param a1 A 32-bit value passed to the kernel-side. Its meaning + depends on the device driver requirements + * @param a2 A 32-bit value passed to the kernel-side. Its meaning + depends on the device driver requirements + * @param aMessage Reference to received thread message. + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + virtual TInt DoRequest( TInt aFunction, + TRequestStatus* aStatus, + TAny* a1, + TAny* a2, + TThreadMessage& aMessage ); + + /** + * Cancels outstanding asynchronous request. + */ + virtual void DoCancel(); + + private: + + /** + * Acquires current process information + * @param aProcessInfo Pointer to the TProcessIdentityParams object. + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + TInt GetProcessInfo( TAny* aProcessInfo, TThreadMessage& aMessage ); + + /** + * Acquires codeseg information. + * @param aCodesegInfo Pointer to the TCodesegInfo object. + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + TInt GetCodesegInfo( TAny* aCodesegInfo, TThreadMessage& aMessage ); + + /** + * Acquires library information. + * @param aLibraryInfo Pointer to the TLibraryInfo object. + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + TInt GetLibraryInfo( TAny* aLibraryInfo, TThreadMessage& aMessage ); + + /** + * Acquires information about process main thread RAllocator. + * @param aMainThreadParams Pointer to the TMainThreadParams object. + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + TInt MainThreadAllocator( TAny* aMainThreadParams, + TThreadMessage& aMessage ); + + /** + * Acquires main thread stack address. + * @param aThreadStack Pointer to the TThreadParams object. + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + TInt ThreadStack( TAny* aThreadStack, + TThreadMessage& aMessage ); + + /** + * Acquires information about process global handles. + * @param aProcessHandleInfo Pointer to the TProcessHandleInfo object. + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + TInt GetProcessHandleInfo( TAny* aProcessHandleInfo, + TThreadMessage& aMessage ); + + /** + * Acquires a process's current handle count. + * @param aProcessHandles Pointer to the TATProcessHandles object. + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + TInt GetCurrentHandleCount( TAny* aProcessHandles, + TThreadMessage& aMessage ); + + /** + * Acquires the count of current device driver users. + * @param aClientCount A reference to TInt variable + * @return TInt Returns KErrNone, if successful + * otherwise one of the other system-wide error codes + */ + TInt ClientCount( TAny* aClientCount, + TThreadMessage& aMessage ); + + /** + * Acquires memory model system uses. + * @return TInt Returns KErrNone, if successful + * otherwise one of the other system-wide error codes + */ + TInt GetMemoryModel( TAny* aMemoryModel, + TThreadMessage& aMessage ); + + #ifdef __WINSCW__ + /** + * Gets module dependencies + * @param aModule Module handle + */ + void GetModuleDependencies( HMODULE aModule ); + #endif // __WINSCW__ + + private: //Member variables + + /* Handler which receives kernel events */ + DAnalyzeToolEventHandler* iEventHandler; + + #ifdef __WINSCW__ + /* Code segment array */ + RArray<TCodesegInfo> iCodeSeg; + #endif // __WINSCW__ + + /* A DFC queue for communication */ + TDynamicDfcQue* iOwnDfcQ; + + }; + +#endif // #ifndef __ANALYZETOOLCHANNEL_H__ + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/kerneleventhandler/inc/analyzetooldevice.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/kerneleventhandler/inc/analyzetooldevice.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,68 @@ +/* +* 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: Declaration of the class DAnalyzeToolDevice. +* +*/ + + +#ifndef __ANALYZETOOLEVICE_H__ +#define __ANALYZETOOLEVICE_H__ + +// INCLUDES +#include <analyzetool/analyzetool.h> +#include <kernel/kernel.h> + +// CLASS DECLARATION + +/** +* The implementation of the abstract base class for an LDD factory object. +*/ + +class DAnalyzeToolDevice : public DLogicalDevice + { + public: + + /** + * C++ default constructor. + */ + DAnalyzeToolDevice(); + + public: // from DLogicalDevice + + /** + * Second stage constructor. + @return KErrNone or standard error code. + */ + virtual TInt Install(); + + /** + * Gets the driver's capabilities. + @param aDes A user-side descriptor into which capabilities + information is to be written. + */ + virtual void GetCaps( TDes8& aDes ) const; + + /** + * Called by the kernel's device driver framework to + * create a Logical Channel. + @param aChannel Set to point to the created Logical Channel + @return KErrNone or standard error code. + */ + virtual TInt Create( DLogicalChannelBase*& aChannel ); + }; + + +#endif // __ANALYZETOOLEVICE_H__ + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/kerneleventhandler/inc/analyzetooleventhandler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/kerneleventhandler/inc/analyzetooleventhandler.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,168 @@ +/* +* 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: Declaration of the class DAnalyzeToolEventHandler. +* +*/ + + +#ifndef __ANALYZETOOLEVENTHANDLER_H__ +#define __ANALYZETOOLEVENTHANDLER_H__ + +// INCLUDES +#include <analyzetool/analyzetool.h> +#include "atlog.h" +#include <kernel/kernel.h> + +// CLASS DECLARATION + +/** +* Callback class for kernel events +*/ + +class DAnalyzeToolEventHandler : public DKernelEventHandler + { + public: + + /** + * C++ default constructor. + */ + inline DAnalyzeToolEventHandler( TDfcQue* aDfcQ ); + + /** + * Destructor. + */ + ~DAnalyzeToolEventHandler(); + + /** + * Second stage constructor. + * @param aDevice A pointer to device where the event handler belongs. + * @param aProcessId Owner process id. + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + TInt Create( DLogicalDevice* aDevice, const TUint aProcessId ); + + /** + * Subscribes library event. + * @param aStatus The request status object for this request. + * @param aLibraryInfo The library information which + is filled by the device driver + * @param aMessage Reference to received thread message. + * @return TInt Returns KErrNone, if successful + otherwise one of the other system-wide error codes + */ + void InformLibraryEvent( TRequestStatus* aStatus, + TAny* aLibraryInfo, + TThreadMessage& aMessage ); + + /** + * Cancels subscribetion of the library event. + */ + void CancelInformLibraryEvent(); + + /** + * Static function for DFC events. + * @param aPtr Pointer to DAnalyzeToolEventHandler object. + */ + static void EventDfc( TAny* aPtr ); + + private: + + /** + * Pointer to callback function called when an event occurs. + * @param aEvent Designates what event is dispatched. + * @param a1 Event-specific paramenter. + * @param a2 Event-specific paramenter. + * @param aThis A pointer to the event handler + * @return TUint Bitmask returned by callback function. + */ + static TUint EventHandler( TKernelEvent aEvent, + TAny* a1, + TAny* a2, + TAny* aThis ); + + private: + + /** + * Handles the EEventAddLibrary and EEventRemoveLibrary events + * @param aLib* A pointer to added/removed library. + * @param aThread* A pointer to thread where the libary is. + * @param aInfo* A reference class to be written to the client + */ + void HandleLibraryEvent( DLibrary* aLib, + DThread* aThread, + TLibraryEventInfo& aInfo ); + + /** + * Handles the EEventKillThread events + * @param aThread* A pointer to the thread being terminated. + * @param aInfo* A reference class + */ + void HandleKillThreadEvent( DThread* aThread, + TLibraryEventInfo& aInfo ); + + /** + * Informs client about the occured event + */ + void DoEventComplete(); + + private: + + /* Mutex for serializing access to event handler */ + DMutex* iHandlerMutex; + + /* Mutex fof serializing access to event handler variables */ + DMutex* iDataMutex; + + /* If the client is a RAM-loaded LDD (or PDD), it is possible for the DLL to + be unloaded while the handler is still in use. This would result in an + exception. To avoid this, the handler must open a reference to the + DLogicalDevice (or DPhysicalDevice) and close it in its d'tor. */ + DLogicalDevice* iDevice; + + /* Owner process ID */ + TUint iProcessId; + + /* Event array */ + RArray<TLibraryEventInfo> iEventArray; + + /* Pointer to client's TRequestStatus */ + TRequestStatus* iClientRequestStatus; + + /* Pointer to client's thread */ + DThread* iClientThread; + + /* Pointer to client's TLibraryEventInfo */ + TAny* iClientInfo; + + /* DFC for informing events to the client */ + TDfc iEventDfc; + }; + +// ---------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::DAnalyzeToolEventHandler() +// C++ default constructor. +// ---------------------------------------------------------------------------- +// +inline DAnalyzeToolEventHandler::DAnalyzeToolEventHandler( TDfcQue* aDfcQ ) : + DKernelEventHandler( EventHandler, this ), + iEventDfc( EventDfc, this, 1 ) + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::DAnalyzeToolEventHandler()" ); + iEventDfc.SetDfcQ( aDfcQ ); + } + +#endif // __ANALYZETOOLEVENTHANDLER_H__ + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/kerneleventhandler/inc/analyzetooltraceconstants.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/kerneleventhandler/inc/analyzetooltraceconstants.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,171 @@ +/* +* 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: Common declarations/definitions for Analyze Tool. +* +*/ + + + +#ifndef __ANALYZETOOLTRACECONSTANTS_H__ +#define __ANALYZETOOLTRACECONSTANTS_H__ + +#include <analyzetool/atcommon.h> + +// Trace version information. +const TUint KATTraceVersion = 0x2; + +// The default logging mode +const TATLogOption KDefaultLoggingMode = EATLogToTrace; + +// When needed, update the storage data file's version number directly inside +// the _LIT8 macro. Note, if you change this string, also remember to update +// the constant "KVersionStringLength" below. + +_LIT8( KDataFileVersion, "DATA_FILE_VERSION 11\r\n" ); +_LIT8( KProcessStart, "PROCESS_START %S %x " ); +_LIT16( KProcessStart16, "PROCESS_START %S %x " ); +_LIT8( KDllLoad, "DLL_LOAD %S %Lx %x %x\r\n" ); +_LIT16( KDllLoad16, "DLL_LOAD %S %Lx %x %x\r\n" ); +_LIT8( KDllUnload, "DLL_UNLOAD %S %Lx %x %x\r\n" ); +_LIT16( KDllUnload16, "DLL_UNLOAD %S %Lx %x %x\r\n" ); +_LIT8( KProcessEnd, "PROCESS_END %x " ); +_LIT16( KProcessEnd16, "PROCESS_END %x " ); +_LIT8( KProcessEndAbnormal, "PROCESS_END %x ABNORMAL " ); +_LIT8( KMemoryLeak, "MEM_LEAK " ); // Remember to update value of KMemoryLeak when changing this. +_LIT8( KHandleLeak, "HANDLE_LEAK %S %x\r\n" ); +_LIT16( KHandleLeak16, "HANDLE_LEAK %S %x\r\n" ); +_LIT8( KErrorOccured, "ERROR_OCCURED %d " ); +_LIT8( KLoggingCancelled, "LOGGING_CANCELLED %x\r\n" ); +_LIT8( KNewLine, "\r\n" ); +_LIT8( KHexaNumber, " %x" ); +_LIT8( KSpace, " " ); +_LIT8( KUdeb, "UDEB" ); +_LIT8( KUrel, "UREL" ); + +// Constants for logging through debug channel +_LIT( KTraceMessage, "PCSS %x %S" ); +_LIT( KMemoryAllocHeader, "ALLOCH " ); +_LIT( KMemoryAllocFragment, "ALLOCF " ); +_LIT( KMemoryFreedHeader, "FREEH " ); +_LIT( KMemoryFreedFragment, "FREEF " ); +_LIT( KSpaceTrace, " " ); +_LIT( KNewLineTrace, "\r\n" ); +_LIT( KHexaNumberTrace, " %x" ); +_LIT( KProcessEndTrace, "PROCESS_END %x " ); +_LIT( KProcessEndAbnormalTrace, "PROCESS_END %x ABNORMAL " ); +_LIT( KErrorOccuredTrace, "ERROR_OCCURED %d " ); +_LIT( KSubtestStart, "TEST_START " ); +_LIT( KSubtestEnd, "TEST_END " ); +_LIT8( KEmpty, "" ); +_LIT( KOpenSquareBracket, "[" ); +_LIT( KCloseSquareBracket, "]" ); +_LIT( KUnderLine, "_" ); +// File name format +_LIT( KFormat, "%S%S%02d%S");// pad char="0", field width=2 + +// A string for setting time January 1st, 1970 AD nominal Gregorian +_LIT( KJanuaryFirst1970, "19700000:000000.000000" ); + +// Module name when it cannot be defined +_LIT8( KUnknownModule, "Unknown" ); +_LIT16( KUnknownModule16, "Unknown" ); + +// Constant time variable used to calculate timestamps for pc side. +const TInt64 KMicroSecondsAt1970 = 62168256000000000; + +// The length of the string KDataFileVersion +const TInt KVersionStringLength = 22; + +// The length of the string KMemoryLeak +const TInt KMemleakLength = 9; + +// The maximum length of one word (32 bits) represented in the hexadecimal text format +// without "0x" prefix +const TInt KHexa32Length = 8; + +// The maximum length of one word (32 bits) represented in the decimal text format +const TInt KDec32Length = 10; + +// The maximum length of a TInt64 represented in the hexadecimal text format without +// "0x" prefix +const TInt KHexa64Length = 16; + +// The length of one space character in text +const TInt KSpaceLength = 1; + +// The length of the combination of carriage return and new line characters. +const TInt KNewlineLength = 2; + +// The maximum length of the "PROCESS_START..." buffer. The first number is length of +// the line tag and one space character (see the descriptor constants above). +const TInt KProcessStartBufLength = 16 + KMaxProcessName + KSpaceLength + KHexa32Length + + KSpaceLength + KHexa64Length + KHexa32Length + KNewlineLength; + +// The maximum length of the "DLL_LOAD..." buffer. The first number is length of +// the line tag and one space character (see the descriptor constants above). +const TInt KDllLoadBufLength = 9 + KMaxLibraryName + KSpaceLength + KHexa64Length + KSpaceLength + + KHexa32Length + KSpaceLength + KHexa32Length + KNewlineLength; + +// The maximum length of the "DLL_UNLOAD..." buffer. The first number is length of +// the line tag and one space character (see the descriptor constants above). +const TInt KDllUnloadBufLength = 11 + KMaxLibraryName + KHexa64Length + KSpaceLength + KSpaceLength + + KHexa32Length + KSpaceLength + KHexa32Length + KNewlineLength; + +// The maximum length of the "PROCESS_END..." buffer. The first number is length of +// the line tag and one space character (see the descriptor constants above). +const TInt KProcessEndBufLength = 12 + KHexa32Length + KSpaceLength + + KHexa64Length + KNewlineLength; + +// The maximum length of the "ERROR_OCCURED..." buffer. The first number is length of +// the line tag and one space character (see the descriptor constants above). +const TInt KErrOccuredBufLength = 14 + KDec32Length + KSpaceLength + + KHexa64Length + KNewlineLength; + +// The maximum length of the "ALLOCH / ALLOCF..." buffer. +const TInt KMemAllocBufLength = 255; + +// The maximum length of the "FREE..." buffer. +const TInt KMemFreedBufLength = 255; + +// The maximum length of the "HANDLE_LEAK..." buffer. The first number is length of +// the line tag and one space character (see the descriptor constants above). +const TInt KHandleLeakBufLength = 12 + KMaxLibraryName + KSpaceLength + + KHexa32Length + KNewlineLength; + +// The maximum length of the "TEST_START..." buffer. The first number is length of +// the line tag and one space character (see the descriptor constants above). +const TInt KTestStartBufLength = 11 + KHexa64Length + KSpaceLength + + KATMaxSubtestIdLength + KSpaceLength + KHexa64Length + KNewlineLength; + +// The maximum length of the "TEST_END..." buffer. The first number is length of +// the line tag and one space character (see the descriptor constants above). +const TInt KTestEndBufLength = 9 + KHexa64Length + KSpaceLength + + KATMaxSubtestIdLength + KSpaceLength + KHexa64Length + KNewlineLength; + +// The maximun length of the "LOGGING_CANCELLED..." buffer. The first number is the +// length of the line tag and one space character (see the descriptor constants above). +const TInt KCancelBufLength = 18 + KHexa64Length + KNewlineLength; + +// The maximun length of the "PROCESS_END %x ABNORMAL..." buffer. The first number is length of +// the line tag and one space character (see the descriptor constants above). +const TInt KEndAbnormalBufLength = 22 + KHexa32Length + KHexa64Length + + KSpaceLength + KNewlineLength; + +// The maximun length of the file name extension buffer. +const TInt KExtensionLength = 50; + +// The maximun length of the process UID3 buffer. +const TInt KProcessUidLength = 20; + +#endif // __ANALYZETOOLTRACECONSTANTS_H__ diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/kerneleventhandler/inc/atcommon.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/kerneleventhandler/inc/atcommon.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,108 @@ +/* +* 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: Common declarations/definitions for Analyze Tool. +* +*/ + + +#ifndef ATCOMMON_H_ +#define ATCOMMON_H_ + +// CONSTANTS +const TInt KATMaxCallstackLength = 256; +const TInt KATMaxFreeCallstackLength = 256; +const TInt KATMaxSubtestIdLength = 256; + +// The following constants only limit the configuration UI. +// The bigger the number is, the more space will be allocated run-time +// by the client. So, change with care. +const TInt KATMaxProcesses = 20; +const TInt KATMaxDlls = 30; + +// Constants defining call stack address range in multiple memory model. +const TInt32 KATMultipleMemoryModelLowLimit = 0x70000000; +const TInt32 KATMultipleMemoryModelHighLimit = 0x90000000; + + +// CLASS DECLARATIONS + +/** +* A class for storing process information +*/ +class TATProcessInfo + { + public: + + /** The ID of the process. */ + TUint iProcessId; + + /** The name of the process. */ + TBuf8<KMaxProcessName> iProcessName; + + /** The starting time of the process. */ + TInt64 iStartTime; + }; + + +// ENUMERATIONS + +/** +* Enumeration for different logging modes of Analyze Tool +*/ +enum TATLogOption + { + /** Using the default. */ + EATUseDefault = 0, + + /** Logging to a file in S60. */ + EATLogToFile, + + /** Logging to debug channel. */ + EATLogToTrace, + + /** Logging to debug channel bypassing storage server. */ + EATLogToTraceFast, + + /** Logging switched off. */ + EATLoggingOff + }; + +/** +* Class which supports interfacing with AnalyzeTool exported +* functions. Mainly meant for STIF integration. +*/ +class AnalyzeToolInterface + { + public: + + /** + * This function starts subtest with a given name. + * @param aSubtestId The name identifying this particular sub test. The length + * of this descriptor must not be greater than KATMaxSubtestIdLength, or + * otherwise the method raises a STSEClient: 2 panic. + */ + IMPORT_C static void StartSubTest( const TDesC8& aSubtestId ); + + /** + * This function stops a subtest with a given name. + * @param aSubtestId The name identifying this particular sub test. The length + * of this descriptor must not be greater than KATMaxSubtestIdLength, or + * otherwise the method raises a STSEClient: 2 panic. + */ + IMPORT_C static void StopSubTest( const TDesC8& aSubtestId ); + + }; + + +#endif /*ATCOMMON_H_*/ diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/kerneleventhandler/sis/analyzetooldevicedriver.pkg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/kerneleventhandler/sis/analyzetooldevicedriver.pkg Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,33 @@ +; +; 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: +; + +;Language - standard language definitions +&EN + +; standard SIS file header +#{"AnalyzeToolDeviceDriver"},(0xEDF5A8A1),1,8,1 + +;Localised Vendor name +%{"Vendor-EN"} + +;Unique Vendor name +:"Vendor" + +;Supports Series 60 v 3.0 +[0x101F7961], 0, 0, 0, {"Series60ProductID"} + +; 1 File to install +"\epoc32\release\armv5\urel\atoolkerneleventhandler.ldd"-"!:\sys\bin\atoolkerneleventhandler.ldd" diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/kerneleventhandler/src/analyzetoolchannel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/kerneleventhandler/src/analyzetoolchannel.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,1019 @@ +/* +* 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 DAnalyzeToolChannel. +* +*/ + + +// INCLUDE FILES +#include "analyzetoolchannel.h" +#include "analyzetooldevice.h" +#include "analyzetooleventhandler.h" + +#include <kernel/kern_priv.h> +#ifdef __WINSCW__ +#include <emulator.h> +#endif // __WINSCW__ + +#include "atlog.h" + +// ================= MEMBER FUNCTIONS ========================================= + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::DoCreate() +// Creates the logical channel. +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolChannel::DoCreate( TInt /*aUnit*/, + const TDesC8* /*aInfo*/, const TVersion &aVer ) + { + LOGSTR1( "ATDD DAnalyzeToolChannel::DoCreate()" ); + + // Check client version. + if ( !Kern::QueryVersionSupported( KAnalyzeToolLddVersion(), aVer ) ) + { + return KErrNotSupported; + } + + TInt error = Kern::DynamicDfcQCreate( iOwnDfcQ, + KAnalyzeToolThreadPriority, + KAnalyzeToolThreadName ); + + if ( KErrNone != error ) + { + return error; + } + + SetDfcQ( iOwnDfcQ ); + + iMsgQ.Receive(); + + // Create the event handler + iEventHandler = new DAnalyzeToolEventHandler( iOwnDfcQ ); + + // Check that everything is OK + if ( !iEventHandler ) + { + return KErrNoMemory; + } + + // 2nd stage constructor for event handler + return iEventHandler->Create( iDevice, Kern::CurrentProcess().iId ); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::DAnalyzeToolChannel() +// Constructor. +// ----------------------------------------------------------------------------- +// +DAnalyzeToolChannel::DAnalyzeToolChannel() + { + LOGSTR1( "ATDD DAnalyzeToolChannel::DAnalyzeToolChannel()" ); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::~DAnalyzeToolChannel() +// Destructor. +// ----------------------------------------------------------------------------- +// +DAnalyzeToolChannel::~DAnalyzeToolChannel() + { + LOGSTR1( "ATDD DAnalyzeToolChannel::~DAnalyzeToolChannel()" ); + + if ( iEventHandler ) + { + // Cancel all processing that we may be doing + DoCancel(); + + // Client code should use Close() instead the operator delete + // to destroy the event handler. + TInt error( iEventHandler->Close() ); + if ( KErrNone != error ) + { + LOGSTR2( "ATDD iEventHandler->Close(%d)", error ); + } + } + #ifdef __WINSCW__ + iCodeSeg.Close(); + #endif // __WINSCW__ + + // Destroy the queqe + if ( iOwnDfcQ ) + { + iOwnDfcQ->Destroy(); + } + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::DoControl() +// Handles a client request. +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolChannel::DoControl( TInt aFunction, + TAny* a1, + TAny* /*a2*/, + TThreadMessage& aMessage ) + { + LOGSTR1( "ATDD DAnalyzeToolChannel::Request()" ); + + TInt ret( KErrNone ); + + // Check the requested function + switch (aFunction) + { + case RAnalyzeTool::EGetProcessInfo: + ret = GetProcessInfo( a1, aMessage ); + break; + + case RAnalyzeTool::EGetCodesegInfo: + ret = GetCodesegInfo( a1, aMessage ); + break; + + case RAnalyzeTool::EGetLibraryInfo: + ret = GetLibraryInfo( a1, aMessage ); + break; + + case RAnalyzeTool::ECancelLibraryEvent: + iEventHandler->CancelInformLibraryEvent(); + break; + + case RAnalyzeTool::ECurrentClientCount: + ret = ClientCount( a1, aMessage ); + break; + + case RAnalyzeTool::EMainThreadAlloctor: + ret = MainThreadAllocator( a1, aMessage ); + break; + + case RAnalyzeTool::EThreadStack: + ret = ThreadStack( a1, aMessage ); + break; + + case RAnalyzeTool::EGetProcessHandle: + ret = GetProcessHandleInfo( a1, aMessage ); + break; + + case RAnalyzeTool::EGetCurrentHandles: + ret = GetCurrentHandleCount( a1, aMessage ); + break; + case RAnalyzeTool::EGetMemoryModel: + ret = GetMemoryModel( a1, aMessage ); + break; + + // Unsupported function. Panic + default: + Kern::PanicCurrentThread( KClientPanic, EPanicUnsupportedRequest ); + break; + } + + return ret; + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::DoRequest() +// Handles a client asynchronous request. +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolChannel::DoRequest( TInt aFunction, + TRequestStatus* aStatus, + TAny* a1, + TAny* /*a2*/, + TThreadMessage& aMessage ) + { + LOGSTR1( "ATDD DAnalyzeToolChannel::DoRequest()" ); + + // Check the requested function + switch (aFunction) + { + case RAnalyzeTool::ELibraryEvent: + iEventHandler->InformLibraryEvent( aStatus, a1, aMessage ); + break; + + // Unsupported function. Panic + default: + aMessage.PanicClient( KClientPanic, EPanicUnsupportedRequest ); + break; + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::DoCancel() +// Cancels outstanding asynchronous request. +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolChannel::DoCancel() + { + LOGSTR1( "ATDD DAnalyzeToolChannel::DoCancel()" ); + + iEventHandler->CancelInformLibraryEvent(); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::HandleMsg() +// Processes a message for this logical channel. +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolChannel::HandleMsg(TMessageBase* aMsg) + { + LOGSTR1( "ATDD DAnalyzeToolChannel::HandleMsg()" ); + + TThreadMessage& message = *(TThreadMessage*)aMsg; + + // Get message type + TInt id = message.iValue; + + // Decode the message type and dispatch it to the relevent handler function... + if ( id == (TInt) ECloseMsg ) + { + // Channel Close + DoCancel(); + message.Complete( KErrNone, EFalse ); + } + else if ( id == KMaxTInt ) + { + // DoCancel + DoCancel(); + message.Complete( KErrNone, ETrue ); + } + else if ( id < 0 ) + { + // DoRequest + TRequestStatus* status = (TRequestStatus*) message.Ptr0(); + TInt error = DoRequest( ~id, status, message.Ptr1(), message.Ptr2(), message ); + if ( KErrNone != error ) + { + Kern::RequestComplete( message.Client(), status, error); + } + message.Complete(KErrNone, ETrue ); + } + else + { + // DoControl + TInt ret = DoControl( id, message.Ptr0(), message.Ptr1(), message ); + message.Complete( ret, ETrue ); + } + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::GetProcessInfo() +// Acquires current process information +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolChannel::GetProcessInfo( TAny* aProcessInfo, + TThreadMessage& aMessage ) + { + LOGSTR1( "ATDD DAnalyzeToolChannel::GetProcessInfo()" ); + + // Variable for reading parameters from user side + TProcessIdentityParamsBuf params; + + // Reads a descriptor from a thread's process. + TInt error = Kern::ThreadDesRead( aMessage.Client(), aProcessInfo, params, 0 ); + + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesRead error %d", error ); + return error; + } + + // Gets the current process + Kern::Containers()[ EProcess ]->Wait(); + DProcess& process = *Kern::ProcessFromId( params().iProcessId ); + Kern::Containers()[ EProcess ]->Signal(); + + if ( NULL == &process ) + { + return KErrNotFound; + } + + // Temporary variable for collecting information from the process + TProcessIdentityParamsBuf info; + + // Collect needed information from the process + process.AppendName( info().iProcessName );//lint !e64 !e1514 + + // Gets the current thread + Kern::Containers()[ EThread ]->Wait(); + DThread& thread = *Kern::ThreadFromId( params().iThreadId ); + Kern::Containers()[ EThread ]->Signal(); + + if ( NULL == &thread ) + { + return KErrNotFound; + } + + // Stack address of the main thread + info().iStackAddress = thread.iUserStackRunAddress; + info().iStackSize = thread.iUserStackSize; + + // Enters thread critical section and acquires code segment mutex. + Kern::AccessCode(); + + // Collect needed information from the process + info().iDynamicCount = process.iDynamicCode.Count(); + + // Temporary queue for acquiring the count of codesegments + SDblQue queue; + + // Acquire the count of codesegments + TInt codesegCount = process.TraverseCodeSegs( &queue, + NULL, + DCodeSeg::EMarkDebug, + DProcess::ETraverseFlagAdd ); + + #ifndef __WINSCW__ + info().iCodesegCount = codesegCount; + #else + // Reset codesegment array + iCodeSeg.Reset(); + + if ( codesegCount > 0 ) + { + SDblQueLink* link = queue.iA.iNext; + TCodesegInfo codeinfo; + // Iterate through codesegments + for ( TInt i = 0; i < codesegCount; ++i, link = link->iNext ) + { + DWin32CodeSeg* codeseg = + (DWin32CodeSeg*)_LOFF( link, DCodeSeg, iTempLink ); + + // Aqcuire codeseg information + codeinfo.iFileEntryPoint = codeseg->iFileEntryPoint; + codeinfo.iSize = codeseg->iSize; + codeinfo.iFullName.Copy( codeseg->iRootName ); + codeinfo.iRunAddress = codeseg->iRunAddress; + iCodeSeg.Append( codeinfo ); + } + } + + // Add dependency codesegments + DWin32CodeSeg* pcodeSeg = (DWin32CodeSeg*)process.iCodeSeg; + + // Get dependency codesegments + GetModuleDependencies( pcodeSeg->iModuleHandle ); + + // Set codesegment count + info().iCodesegCount = iCodeSeg.Count(); + #endif + + // Removes all code segments from a queue and clear specified mark(s) + DCodeSeg::EmptyQueue( queue, DCodeSeg::EMarkDebug ); + + // Exits thread critical section and releases code segment mutex. + Kern::EndAccessCode(); + + // Writes a descriptor to a thread's process. + error = Kern::ThreadDesWrite( aMessage.Client(), aProcessInfo, info, 0 ); + + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesWrite error %d", error ); + return error; + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::GetCodesegInfo() +// Acquires codeseg information. +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolChannel::GetCodesegInfo( TAny* aCodesegInfo, + TThreadMessage& aMessage ) + { + LOGSTR1( "ATDD DAnalyzeToolChannel::GetCodesegInfo()" ); + + // Temporary variable for collecting information from the codeseg + TCodesegInfoBuf params; + + TInt error( KErrArgument ); + + // Reads a descriptor from a thread's process. + error = Kern::ThreadDesRead( aMessage.Client(), aCodesegInfo, params, 0 ); + + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesRead error %d", error ); + return error; + } + + if ( params().iIndex < 0 ) + { + return KErrArgument; + } + + // Gets the current process + Kern::Containers()[ EProcess ]->Wait(); + DProcess& process = *Kern::ProcessFromId( params().iProcessId ); + Kern::Containers()[ EProcess ]->Signal(); + + if ( NULL == &process ) + { + return KErrNotFound; + } + + // Temporary variable for collecting information + TCodesegInfoBuf output; + + // Enters thread critical section and acquires code segment mutex. + Kern::AccessCode(); + + #ifndef __WINSCW__ + // Temporary queue for acquiring the codesegments + SDblQue queue; + + // Acquire the codesegments + TInt actcount = process.TraverseCodeSegs( &queue, + NULL, + DCodeSeg::EMarkDebug, + DProcess::ETraverseFlagAdd ); + if ( actcount >= params().iIndex ) + { + LOGSTR1( "ATDD DAnalyzeToolChannel::GetCodesegInfo() - actcount >= params.iIndex" ); + SDblQueLink* link = queue.iA.iNext; + + // Iterate through codesegments + for (TInt i = 0; i < actcount; ++i, link = link->iNext) + { + DCodeSeg* codeseg = _LOFF( link, DCodeSeg, iTempLink ); + + // Is the codesegments which information client wants + if ( i == params().iIndex ) + { + // Aqcuire codeseg information + output().iFileEntryPoint = codeseg->iFileEntryPoint; + output().iSize = codeseg->iSize; + output().iFullName.Copy( codeseg->iRootName ); + output().iRunAddress = codeseg->iRunAddress; + error = codeseg->GetMemoryInfo( output().iMemoryInfo, &process ); + + if ( KErrNone == error ) + { + // Writes a descriptor to a thread's process. + error = Kern::ThreadDesWrite( aMessage.Client(), + aCodesegInfo, + output, + 0 ); + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesWrite error %d", error ); + } + } + break; + } + } + } + // Removes all code segments from a queue and clear specified mark(s). + DCodeSeg::EmptyQueue( queue, DCodeSeg::EMarkDebug ); + + // Exits thread critical section and releases code segment mutex. + Kern::EndAccessCode(); + + return error; + #else // WINSCW + + if ( iCodeSeg.Count() > params().iIndex ) + { + // Aqcuire codeseg information + output().iSize = iCodeSeg[params().iIndex].iSize; + output().iFullName.Copy( iCodeSeg[params().iIndex].iFullName ); + output().iRunAddress = iCodeSeg[params().iIndex].iRunAddress; + + // Writes a descriptor to a thread's process. + error = Kern::ThreadDesWrite( aMessage.Client(), aCodesegInfo, output, 0 ); + + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesWrite error %d", error ); + } + } + + // Exits thread critical section and releases code segment mutex. + Kern::EndAccessCode(); + + return error; + #endif + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::GetLibraryInfo() +// Acquires library information. +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolChannel::GetLibraryInfo( TAny* aLibraryInfo, + TThreadMessage& aMessage ) + { + LOGSTR1( "ATDD DAnalyzeToolChannel::GetLibraryInfo()" ); + + // Temporary variable for reading informationfrom the user side + TLibraryInfoBuf params; + + // Reads a descriptor from a thread's process. + TInt error = Kern::ThreadDesRead( aMessage.Client(), aLibraryInfo, params, 0 ); + + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesRead error %d", error ); + return error; + } + + if ( params().iIndex < 0 ) + { + return KErrArgument; + } + + // Gets the current process + Kern::Containers()[ EProcess ]->Wait(); + DProcess& process = *Kern::ProcessFromId( params().iProcessId ); + Kern::Containers()[ EProcess ]->Signal(); + + if ( NULL == &process ) + { + return KErrNotFound; + } + + // Temporary variable for collecting information from the library + TLibraryInfoBuf output; + + // Enters thread critical section and acquires code segment mutex. + Kern::AccessCode(); + + // Iterate to find the right library + if ( params().iIndex < process.iDynamicCode.Count() ) + { + // Acquire entry to the codeseg + SCodeSegEntry entry = process.iDynamicCode[ params().iIndex ]; + + // Acquire library information + entry.iLib->AppendName( output().iLibraryName );//lint !e64 !e1514 + output().iRunAddress = entry.iSeg->iRunAddress; + output().iSize = entry.iSeg->iSize; + + // Writes a descriptor to a thread's process. + error = Kern::ThreadDesWrite( aMessage.Client(), aLibraryInfo, output, 0 ); + + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesWrite error %d", error ); + } + + // Exits thread critical section and releases code segment mutex. + Kern::EndAccessCode(); + + return error; + } + else + { + // Exits thread critical section and releases code segment mutex. + Kern::EndAccessCode(); + + return KErrArgument; + } + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::MainThreadAllocator() +// Acquires information about process main thread RAllocator +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolChannel::MainThreadAllocator( TAny* aMainThreadParams, + TThreadMessage& aMessage ) + { + LOGSTR1( "ATDD DAnalyzeToolChannel::MainThreadAllocator()" ); + + // Temporary variable for reading client side parameters + TMainThreadParamsBuf params; + + // Reads a descriptor from a thread's process. + TInt error = Kern::ThreadDesRead( aMessage.Client(), + aMainThreadParams, + params, + 0 ); + + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesRead error %d", error ); + return error; + } + + // Gets the current process + Kern::Containers()[ EProcess ]->Wait(); + DProcess& process = *Kern::ProcessFromId( params().iProcessId ); + Kern::Containers()[ EProcess ]->Signal(); + + if ( NULL == &process ) + { + return KErrNotFound; + } + + // Gets the current process + Kern::AccessCode(); + + // Temporary variable for collecting information from the RAllocator + TMainThreadParamsBuf output; + + // Aqcuire a reference to the main thread RAllocator + output().iAllocator = process.FirstThread()->iAllocator; + + // Is this only thread in the process + output().iAlone = process.iThreadQ.First()->Alone(); + + // Exits thread critical section and releases code segment mutex. + Kern::EndAccessCode(); + + // Writes a descriptor to a thread's process. + error = Kern::ThreadDesWrite( aMessage.Client(), + aMainThreadParams, + output, + 0 ); + + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesWrite error %d", error ); + } + + return error; + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::ThreadStack() +// Acquires main thread stack address +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolChannel::ThreadStack( TAny* aThreadStack, + TThreadMessage& aMessage ) + { + LOGSTR1( "ATDD DAnalyzeToolChannel::ThreadStack()" ); + + // Temporary variable for reading client side parameters + TThreadParamsBuf params; + + // Reads a descriptor from a thread's process. + TInt error = Kern::ThreadDesRead( aMessage.Client(), + aThreadStack, + params, + 0 ); + + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesRead error %d", error ); + return error; + } + + // Gets the current process + Kern::Containers()[ EThread ]->Wait(); + DThread& thread = *Kern::ThreadFromId( params().iThreadId ); + Kern::Containers()[ EThread ]->Signal(); + + if ( NULL == &thread ) + { + return KErrNotFound; + } + + // Gets the current process + Kern::AccessCode(); + + // Temporary variable for collecting information from the RAllocator + TThreadParamsBuf output; + + // Stack address of the main thread + output().iStackAddress = thread.iUserStackRunAddress; + output().iStackSize = thread.iUserStackSize; + + // Exits thread critical section and releases code segment mutex. + Kern::EndAccessCode(); + + // Writes a descriptor to a thread's process. + error = Kern::ThreadDesWrite( aMessage.Client(), + aThreadStack, + output, + 0 ); + + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesWrite error %d", error ); + } + + return error; + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::GetProcessHandleInfo() +// Acquires information about process global handles +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolChannel::GetProcessHandleInfo( TAny* aProcessHandleInfo, + TThreadMessage& aMessage ) + { + LOGSTR1( "ATDD DAnalyzeToolChannel::GetProcessHandleInfo()" ); + + // Temporary variable for collecting information from the codeseg + TProcessHandleInfoBuf params; + + // Reads a descriptor from a thread's process. + TInt error = Kern::ThreadDesRead( aMessage.Client(), + aProcessHandleInfo, + params, + 0 ); + + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesRead error %d", error ); + return error; + } + + // Gets the current process + Kern::Containers()[ EProcess ]->Wait(); + DProcess& process = *Kern::ProcessFromId( params().iProcessId ); + Kern::Containers()[ EProcess ]->Signal(); + + if ( NULL == &process ) + { + return KErrNotFound; + } + + // Variable holding wanted information + TProcessHandleInfoBuf output; + + // Enters thread critical section and acquires code segment mutex. + Kern::AccessCode(); + + // Get the process thread queue. + SDblQue queue = process.iThreadQ; + error = KErrNotFound; + + // Tests whether this doubly linked list is empty. + if ( !queue.IsEmpty() ) + { + // Gets a pointer to the first item in this doubly linked list. + SDblQueLink* link = queue.First(); + DThread* thread = _LOFF( link, DThread, iProcessLink ); + + if ( thread ) + { + +#ifdef MCL_ROBJECTIX + TInt threadHandles( thread->iHandles.ActiveCount() ); +#else + TInt threadHandles( thread->iHandles->ActiveCount() ); +#endif + + // Aqcuire thread information + //thread->AppendName( output.iThreadName ); + output().iUserStackRunAddress = thread->iUserStackRunAddress; + output().iUserStackSize = thread->iUserStackSize; + output().iThreadHandleCount = threadHandles; + +#ifdef MCL_ROBJECTIX + RObjectIx objectIx = process.iHandles; + output().iProcessHandleCount = objectIx.ActiveCount(); +#else + DObjectIx* objectIx = process.iHandles; + output().iProcessHandleCount = objectIx->ActiveCount(); +#endif + + // Writes a descriptor to a thread's process. + error = Kern::ThreadDesWrite( aMessage.Client(), + aProcessHandleInfo, + output, + 0 ); + + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesWrite error %d", error ); + } + } + } + + // Exits thread critical section and releases code segment mutex. + Kern::EndAccessCode(); + + return error; + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::GetCurrentHandleCount() +// Acquires a process's current handle count +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolChannel::GetCurrentHandleCount( TAny* aProcessHandles, + TThreadMessage& aMessage ) + { + LOGSTR1( "ATDD DAnalyzeToolChannel::GetCurrentHandleCount()" ); + + // Temporary variable for collecting information from the codeseg + TATProcessHandlesBuf params; + + // Reads a descriptor from a thread's process. + TInt error = Kern::ThreadDesRead( aMessage.Client(), + aProcessHandles, + params, + 0 ); + + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesRead error %d", error ); + return error; + } + + // Gets the current process + Kern::Containers()[ EProcess ]->Wait(); + DProcess* process = Kern::ProcessFromId( params().iProcessId ); + Kern::Containers()[ EProcess ]->Signal(); + + if ( NULL == process ) + { + return KErrNotFound; + } + + // Variable holding wanted information + TATProcessHandlesBuf output; + + // Enters thread critical section and acquires code segment mutex. + Kern::AccessCode(); + + SDblQue queue = process->iThreadQ; + SDblQueLink* link = queue.First(); + TInt threadHandles( 0 ); + + // Iterate through current processes's threads + while ( link != queue.Last() ) + { + DThread* thread = _LOFF( link, DThread, iProcessLink ); + +#ifdef MCL_ROBJECTIX + threadHandles += thread->iHandles.ActiveCount(); +#else + threadHandles += thread->iHandles->ActiveCount(); +#endif + + link = link->iNext; + } + + if ( link == queue.Last() ) + { + DThread* thread = _LOFF( link, DThread, iProcessLink ); + +#ifdef MCL_ROBJECTIX + threadHandles += thread->iHandles.ActiveCount(); +#else + threadHandles += thread->iHandles->ActiveCount(); +#endif + } + + output().iCurrentHandleCount = threadHandles; + + // Writes a descriptor to a thread's process. + error = Kern::ThreadDesWrite( aMessage.Client(), + aProcessHandles, + output, + 0 ); + + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesWrite error %d", error ); + } + + // Exits thread critical section and releases code segment mutex. + Kern::EndAccessCode(); + + return error; + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::ClientCount() +// Acquires the count of current device driver users. +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolChannel::ClientCount( TAny* aClientCount, + TThreadMessage& aMessage ) + { + LOGSTR1( "ATDD DAnalyzeToolChannel::ClientCount()" ); + + // Enters thread critical section and acquires code segment mutex. + Kern::AccessCode(); + + // Variable holding wanted information + TClientCountBuf output; + + // Get the number of DLogicalChannelBase objects currently in existence which + // have been created from this LDD. + output().iClientCount = DLogicalChannelBase::iDevice->iOpenChannels; + LOGSTR2( "ATDD > iOpenChannels count: %d", output().iClientCount ); + + // Writes a descriptor to a thread's process. + TInt error = Kern::ThreadDesWrite( aMessage.Client(), + aClientCount, + output, + 0 ); + + if ( KErrNone != error ) + { + LOGSTR2( "ATDD ThreadDesWrite error %d", error ); + } + + // Exits thread critical section and releases code segment mutex. + Kern::EndAccessCode(); + + return error; + } + +#ifdef __WINSCW__ +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::GetModuleDependencies() +// Get module dependencies +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolChannel::GetModuleDependencies( HMODULE aModule ) + { + LOGSTR1( "ATDD DAnalyzeToolChannel::GetModuleDependencies()" ); + + Emulator::TModule etm( aModule ); + TUint32 dllSize( 0 ); + // Temporary variable for collecting information from the codeseg + TCodesegInfo info; + TBool found( EFalse ); + + const IMAGE_IMPORT_DESCRIPTOR* imports = etm.Imports(); + while( imports->Characteristics != 0 ) + { + // Reset flag + found = EFalse; + + // Get dll name + const TUint8* nameAddr = ( const TUint8* )( imports->Name + ( TInt )etm.iBase ); + TPtrC8 namePtr( nameAddr ); + + // Get dll run address + Emulator::TModule imp_etm( ( PCSTR )etm.Translate( imports->Name ) ); + const TUint8* runAddr = ( const TUint8* )imp_etm.iBase; + + // Get dll size + const IMAGE_NT_HEADERS32* ntHeader = imp_etm.NtHeader(); + dllSize = ntHeader->OptionalHeader.SizeOfImage; + + // Check if DLL already exists in codesegment list + for( TInt i = 0; i < iCodeSeg.Count(); i++ ) + { + if ( iCodeSeg[i].iFullName.Compare( namePtr ) == KErrNone ) + { + found = ETrue; + break; + } + } + + if ( !found ) + { + info.iSize = dllSize; + info.iFullName.Copy( namePtr ); + info.iRunAddress = (TUint32) runAddr; + // Append codesegment to array + iCodeSeg.Append( info ); + } + imports++; + } + } + +#endif // __WINSCW__ + +// ----------------------------------------------------------------------------- +// DAnalyzeToolChannel::GetMemoryModel() +// Acquires memory model system uses. +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolChannel::GetMemoryModel(TAny* aMemoryModel, + TThreadMessage& aMessage) + { + LOGSTR1( "ATDD DAnalyzeToolChannel::GetMemoryModel()" ); + + // Model buffer. + TATMemoryModelBuf model; + // Get current model. + model().iMemoryModel = (TUint32) Kern::HalFunction( EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL ); + model().iMemoryModel &= EMemModelTypeMask; // Mask out other stuff. + // Write it to client side. + TInt error = Kern::ThreadDesWrite( aMessage.Client(), + aMemoryModel, + model, + 0); + if ( error != KErrNone ) + { + LOGSTR2( "ATDD ThreadDesWrite error %d", error ); + } + return error; + } +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/kerneleventhandler/src/analyzetooldevice.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/kerneleventhandler/src/analyzetooldevice.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,93 @@ +/* +* 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 DAnalyzeToolDevice. +* +*/ + + +// INCLUDE FILES +#include "analyzetooldevice.h" +#include "analyzetoolchannel.h" +#include "atlog.h" + +// ================= MEMBER FUNCTIONS ========================================= + +// ----------------------------------------------------------------------------- +// DAnalyzeToolDevice::DAnalyzeToolDevice() +// C++ default constructor. +// ----------------------------------------------------------------------------- +// +DAnalyzeToolDevice::DAnalyzeToolDevice() + { + LOGSTR1( "ATDD DAnalyzeToolDevice::DAnalyzeToolDevice()" ); + // Set version number + iVersion = KAnalyzeToolLddVersion(); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolDevice::Install() +// Second stage constructor. +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolDevice::Install() + { + LOGSTR1( "ATDD DAnalyzeToolDevice::Install()" ); + // Set device name + return SetName( &KAnalyzeToolLddName ); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolDevice::GetCaps() +// Gets the driver's capabilities. +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolDevice::GetCaps( TDes8& /*aDes*/ ) const + { + LOGSTR1( "ATDD DAnalyzeToolDevice::GetCaps()" ); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolDevice::Create() +// Creates the logical channel. +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolDevice::Create( DLogicalChannelBase*& aChannel ) + { + LOGSTR1( "ATDD DAnalyzeToolDevice::Create()" ); + + // create new channel + aChannel = new DAnalyzeToolChannel; + + // check that everything is OK + return ( aChannel != NULL ) ? KErrNone : KErrNoMemory; + } + +// ----------------------------------------------------------------------------- +// DECLARE_STANDARD_LDD +// Defines the entry point for a standard logical device driver (LDD), +// and declares the ordinal 1 export function for creating +// the LDD factory object +// ----------------------------------------------------------------------------- +// +DECLARE_STANDARD_LDD() + { + LOGSTR1( "ATDD DECLARE_STANDARD_LDD()" ); + return new DAnalyzeToolDevice; + } + +// ================= OTHER EXPORTED FUNCTIONS ================================= + +// None + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/kerneleventhandler/src/analyzetooleventhandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/kerneleventhandler/src/analyzetooleventhandler.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,427 @@ +/* +* 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 DAnalyzeToolEventHandler. +* +*/ + + +// INCLUDE FILES +#include "analyzetooleventhandler.h" +#include <kernel/kern_priv.h> + +// CONSTANTS + +// The handler mutex literal +_LIT( KHandlerMutexName, "AnalyzeToolHandlerMutex" ); + +// The handle data mutex literal +_LIT( KDataMutexName, "AnalyzeToolDataMutex" ); + + +// ================= MEMBER FUNCTIONS ========================================= + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::Create() +// C++ default constructor. +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolEventHandler::Create( DLogicalDevice* aDevice, + const TUint aProcessId ) + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::Create()" ); + TInt ret( KErrNone ); + + // Store owner process ID + iProcessId = aProcessId; + LOGSTR2( "ATDD DAnalyzeToolEventHandler::Create > iProcessId %d", + iProcessId ); + + // Open the device + ret = aDevice->Open(); + if ( ret != KErrNone ) + return ret; + iDevice = aDevice; + + // Create mutex for the handler + ret = Kern::MutexCreate( iHandlerMutex, KHandlerMutexName, KMutexOrdDebug ); + if ( ret != KErrNone ) + return ret; + // Create mutex for the data + ret = Kern::MutexCreate( iDataMutex, KDataMutexName, KMutexOrdDebug-1 ); + if ( ret != KErrNone ) + return ret; + + // Add handler to the handler queue + return Add(); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::~DAnalyzeToolEventHandler() +// C++ default constructor. +// ----------------------------------------------------------------------------- +// +DAnalyzeToolEventHandler::~DAnalyzeToolEventHandler() + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::~DAnalyzeToolEventHandler()" ); + + CancelInformLibraryEvent(); + + // Close the data mutex + if ( iDataMutex ) + { + iDataMutex->Close( NULL ); + } + + // Close the handler mutex + if ( iHandlerMutex ) + { + iHandlerMutex->Close( NULL ); + } + + // Close the device mutex + if ( iDevice ) + { + iDevice->Close( NULL ); + } + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::EventHandler() +// Function for receiving kernel events +// ----------------------------------------------------------------------------- +// +TUint DAnalyzeToolEventHandler::EventHandler( TKernelEvent aEvent, + TAny* a1, TAny* a2, TAny* aThis ) + { + + // Clarify the event type + switch ( aEvent) + { + case EEventRemoveLibrary: + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::EventHandler() - EEventRemoveLibrary" ); + // Cast the pointer to the handler + DAnalyzeToolEventHandler* handler = + ( ( DAnalyzeToolEventHandler* ) aThis ); + // Create variable for library information + TLibraryEventInfo info; + // Set as library remove event + info.iEventType = TLibraryEventInfo::ELibraryRemoved; + // Handle the event + handler->HandleLibraryEvent( ( DLibrary* ) a1, ( DThread* ) a2, info ); + break; + } + case EEventAddLibrary: + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::EventHandler() - EEventAddLibrary" ); + // Cast the pointer to the handler + DAnalyzeToolEventHandler* handler = + ( ( DAnalyzeToolEventHandler* ) aThis ); + // Create variable for library information + TLibraryEventInfo info; + // Set as library remove event + info.iEventType = TLibraryEventInfo::ELibraryAdded; + // Handle the event + handler->HandleLibraryEvent( ( DLibrary* ) a1, ( DThread* ) a2, info ); + break; + } + case EEventHwExc: + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::EventHandler() - EEventHwExc" ); + break; + } + case EEventSwExc: + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::EventHandler() - EEventSwExc" ); + break; + } + case EEventRemoveThread: + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::EventHandler() - EEventRemoveThread" ); + break; + } + case EEventKillThread: + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::EventHandler() - EEventKillThread" ); + + // Cast the pointer to the handler + DAnalyzeToolEventHandler* handler = + ( ( DAnalyzeToolEventHandler* ) aThis ); + + // Create variable for library information + TLibraryEventInfo info; + + // Set as kill thread event + info.iEventType = TLibraryEventInfo::EKillThread; + // Handle the event + handler->HandleKillThreadEvent( ( DThread* ) a1, info ); + break; + } + default: + { + } + break; + } + return ERunNext; + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::HandleLibraryEvent() +// Handles the EEventAddLibrary and EEventRemoveLibrary events. +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolEventHandler::HandleLibraryEvent( DLibrary* aLib, + DThread* aThread, TLibraryEventInfo& aInfo ) + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::HandleLibraryEvent()" ); + + // Aqcuire the handler mutex + Kern::MutexWait( *iHandlerMutex ); + + // Aqcuire the data mutex + Kern::MutexWait( *iDataMutex ); + + TBool addInfo( EFalse ); + + // Check the library event type + if ( aInfo.iEventType == TLibraryEventInfo::ELibraryAdded ) + { + if ( aThread != NULL ) + { + if ( iProcessId == aThread->iOwningProcess->iId ) + { + LOGSTR1( "ATDD > Process id match" ); + aInfo.iProcessId = aThread->iOwningProcess->iId; + addInfo = ETrue; + } + } + } + else if ( aInfo.iEventType == TLibraryEventInfo::ELibraryRemoved ) + { + if ( aThread != NULL ) + { + aInfo.iProcessId = aThread->iOwningProcess->iId; + } + else + { + aInfo.iProcessId = 0; + } + addInfo = ETrue; + } + + if ( addInfo ) + { + // Store lib info + aLib->AppendName( aInfo.iLibraryName );//lint !e64 !e1514 + aInfo.iSize = aLib->iCodeSeg->iSize; + aInfo.iRunAddress = aLib->iCodeSeg->iRunAddress; + // Store library event info to the array + iEventArray.Append( aInfo ); + LOGSTR2( "ATDD > iEventArray.Count() = %d", iEventArray.Count() ); + + // if client has subscribed the event it is queued + if ( iClientThread != NULL ) + { + iEventDfc.Enque(); + } + } + + // Release the data mutex + Kern::MutexSignal( *iDataMutex ); + + // Release the handler mutex + Kern::MutexSignal( *iHandlerMutex ); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::InformLibraryEvent() +// Subscribes library event. +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolEventHandler::InformLibraryEvent( TRequestStatus* aStatus, + TAny* aLibraryInfo, + TThreadMessage& aMessage ) + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::InformLibraryEvent()" ); + + // Aqcuire the data mutex + Kern::MutexWait( *iDataMutex ); + + // Check if request from client which is already pending + DThread* current = aMessage.Client(); + + LOGSTR2( "ATDD > Current Thread ID = %d", current->iId ); + + // Ensure that client doesn't subscribe service when there is a pending + // subscription + if ( NULL != iClientThread ) + { + aMessage.PanicClient( KClientPanic, EPanicRequestPending ); + } + else + { + // Store the client variable pointers + iClientThread = current; + iClientRequestStatus = aStatus; + iClientInfo = aLibraryInfo; + } + + // Release the data mutex + Kern::MutexSignal( *iDataMutex ); + + // Queue the event since now the client has subscribed it + iEventDfc.Enque(); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::CancelInformLibraryEvent +// Cancels subscription of the library event. +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolEventHandler::CancelInformLibraryEvent() + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::CancelInformLibraryEvent()" ); + + iEventDfc.Cancel(); + + // Aqcuire the data mutex + Kern::MutexWait( *iDataMutex ); + + if ( NULL != iClientThread && iEventArray.Count() > 0 ) + { + // Signal the request as complete + Kern::RequestComplete( iClientThread, + iClientRequestStatus, + KErrCancel ); + + iClientThread = NULL; + iClientRequestStatus = NULL; + iClientInfo = NULL; + + // Reset the event array + iEventArray.Reset(); + } + + // Release the data mutex + Kern::MutexSignal( *iDataMutex ); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::HandleKillThreadEvent() +// Handles the EEventKillThread events. +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolEventHandler::HandleKillThreadEvent( DThread* aThread, + TLibraryEventInfo& aInfo ) + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::HandleKillThreadEvent()" ); + + // Aqcuire the handler mutex + Kern::MutexWait( *iHandlerMutex ); + + // Aqcuire the data mutex + Kern::MutexWait( *iDataMutex ); + + aInfo.iProcessId = aThread->iOwningProcess->iId; + TBool alone( aThread->iOwningProcess->iThreadQ.First()->Alone() ); + LOGSTR2( "ATDD > Is alone = %d", alone ); + + // Check if this our process and is the only thread item. + if ( aInfo.iProcessId == iProcessId && !alone ) + { + if ( aThread ) + { + // Set current Thread id + LOGSTR2( "ATDD > Thread ID = %d", aThread->iId ); + aInfo.iThreadId = aThread->iId; + // Append event to array (beginning of the array) + iEventArray.Insert( aInfo, 0 ); + + // if client has subscribed the event it is queued + if ( iClientThread != NULL ) + { + iEventDfc.Enque(); + } + } + } + + // Release the data mutex + Kern::MutexSignal( *iDataMutex ); + + // Release the handler mutex + Kern::MutexSignal( *iHandlerMutex ); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::DoEventComplete() +// Informs client about the occured event. +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolEventHandler::DoEventComplete() + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::DoEventComplete()" ); + + // Aqcuire the handler mutex + Kern::MutexWait( *iHandlerMutex ); + + // Aqcuire the data mutex + Kern::MutexWait( *iDataMutex ); + + if ( NULL != iClientThread && iEventArray.Count() > 0 ) + { + TInt ret = Kern::ThreadRawWrite( iClientThread, + iClientInfo, + &iEventArray[0], + sizeof( iEventArray[0] ) ); + + LOGSTR2( "ATDD > ThreadRawWrite err = %d", ret ); + + // Signal the request as complete + Kern::RequestComplete( iClientThread, + iClientRequestStatus, + ret ); + + // Remove first item to array + iEventArray.Remove( 0 ); + + // Compresses the array down to a minimum + iEventArray.Compress(); + + // Ensure that pointers are set to NULL + iClientThread = NULL; + iClientRequestStatus = NULL; + iClientInfo = NULL; + + LOGSTR2( "ATDD > iEventArray = %d", iEventArray.Count() ); + } + + // Release the data mutex + Kern::MutexSignal( *iDataMutex ); + + // Release the handler mutex + Kern::MutexSignal( *iHandlerMutex ); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::EventDfc() +// Static function for DFC events. +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolEventHandler::EventDfc(TAny* aPtr) + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::EventDfc()" ); + ( (DAnalyzeToolEventHandler*) aPtr )->DoEventComplete(); + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/rom/analyzetool.iby --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/rom/analyzetool.iby Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2008 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: +* +*/ + + +#ifndef __ANALYZETOOL_IBY__ +#define __ANALYZETOOL_IBY__ + +// Stub +data=ZSYSTEM\Install\analyzetool_stub.sis \system\install\analyzetool_stub.sis + +#endif // __ANALYZETOOL_IBY__ diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/rom/analyzetool_rom.iby --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/rom/analyzetool_rom.iby Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2008 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: +* +*/ + + +#ifndef __ANALYZETOOL_ROM_IBY__ +#define __ANALYZETOOL_ROM_IBY__ + + +// Kernel event handler +device[VARID]=ABI_DIR\BUILD_DIR\atoolkerneleventhandler.ldd SHARED_LIB_DIR\atoolkerneleventhandler.ldd + +// Memory hook +file=ABI_DIR\BUILD_DIR\atoolmemoryhook.dll SHARED_LIB_DIR\atoolmemoryhook.dll + +// Cleaner +file=ABI_DIR\BUILD_DIR\atoolcleaner.dll SHARED_LIB_DIR\atoolcleaner.dll + +// Storage server +file=ABI_DIR\BUILD_DIR\atoolstorageserver.exe PROGRAMS_DIR\atoolstorageserver.exe +file=ABI_DIR\BUILD_DIR\atoolstorageserverclnt.dll SHARED_LIB_DIR\atoolstorageserverclnt.dll + + +#endif // __ANALYZETOOL_ROM_IBY__ diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/sis/AnalyzeTool.pkg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/sis/AnalyzeTool.pkg Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,42 @@ +; +; 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: +; + +;Language - standard language definitions +&EN + +; standard SIS file header +#{"AnalyzeTool"},(0x20012432),1,9,1,TYPE=SA, RU + +;Localised Vendor name +%{"Nokia Corporation"} + +;Unique Vendor name +:"Nokia Corporation" + +;Supports Series 60 v 3.1 +[0x102032BE], 0, 0, 0, {"Series60ProductID"} + +;Supports S60 release 5.0 +[0x1028315F], 0, 0, 0, {"Series60ProductID"} + +"\epoc32\release\armv5\urel\atoolkerneleventhandler.ldd" -"!:\sys\bin\atoolkerneleventhandler.ldd" +"\epoc32\release\armv5\urel\atoolmemoryhook.dll" -"!:\sys\bin\atoolmemoryhook.dll" +"\epoc32\release\armv5\urel\atoolstorageserver.exe" -"!:\sys\bin\atoolstorageserver.exe" +"\epoc32\release\armv5\urel\atoolstorageserverclnt.dll" -"!:\sys\bin\atoolstorageserverclnt.dll" +"\epoc32\release\armv5\urel\atoolcleaner.dll" -"!:\sys\bin\atoolcleaner.dll" + +; Install console application +"\epoc32\release\armv5\urel\atool.exe"-"!:\sys\bin\atool.exe" \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/sis/AnalyzeTool_udeb.pkg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/sis/AnalyzeTool_udeb.pkg Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,42 @@ +; +; 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: +; + +;Language - standard language definitions +&EN + +; standard SIS file header +#{"AnalyzeTool"},(0x20012432),1,9,1,TYPE=SA, RU + +;Localised Vendor name +%{"Nokia Corporation"} + +;Unique Vendor name +:"Nokia Corporation" + +;Supports Series 60 v 3.1 +[0x102032BE], 0, 0, 0, {"Series60ProductID"} + +;Supports S60 release 5.0 +[0x1028315F], 0, 0, 0, {"Series60ProductID"} + +"\epoc32\release\armv5\udeb\atoolkerneleventhandler.ldd" -"!:\sys\bin\atoolkerneleventhandler.ldd" +"\epoc32\release\armv5\udeb\atoolmemoryhook.dll" -"!:\sys\bin\atoolmemoryhook.dll" +"\epoc32\release\armv5\udeb\atoolstorageserver.exe" -"!:\sys\bin\atoolstorageserver.exe" +"\epoc32\release\armv5\udeb\atoolstorageserverclnt.dll" -"!:\sys\bin\atoolstorageserverclnt.dll" +"\epoc32\release\armv5\urel\atoolcleaner.dll" -"!:\sys\bin\atoolcleaner.dll" + +; Install console application +"\epoc32\release\armv5\udeb\atool.exe"-"!:\sys\bin\atool.exe" \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/sis/analyzeTool_stub.pkg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/sis/analyzeTool_stub.pkg Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,36 @@ +; +; 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: +; + +;Languages +&EN + +;Header +#{"AnalyzeTool"}, (0x20012432), 1,9,1 + +; Non-localised vendor name +:"Nokia Corporation" + +; Localised vendor names +%{"Nokia Corporation"} + +; AnalyzeTool binaries +""-"z:\sys\bin\atoolkerneleventhandler.ldd" +""-"z:\sys\bin\atoolmemoryhook.dll" +""-"z:\sys\bin\atoolstorageserver.exe" +""-"z:\sys\bin\atoolstorageserverclnt.dll" +""-"z:\sys\bin\atoolcleaner.dll" + +""-"z:\sys\bin\atool.exe" \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/staticlib/group/atoolstaticlib.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/staticlib/group/atoolstaticlib.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,34 @@ +/* +* 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: The .mmp file for AToolStaticLib. +* +*/ + +#include <platform_paths.hrh> + +TARGET atoolstaticlib.lib +TARGETTYPE lib +UID 0x1000008d 0x20018421//0x02DF7F96 +CAPABILITY ALL -TCB + +SMPSAFE + +USERINCLUDE ../../inc +SOURCEPATH ../src +SOURCE atoolstaticlib.cpp + +OS_LAYER_SYSTEMINCLUDE + + + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/staticlib/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/staticlib/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,27 @@ +/* +* 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: +* +*/ + +#include <platform_paths.hrh> + +PRJ_PLATFORMS +ARMV5 WINSCW + +PRJ_EXPORTS +../../dynamicmemoryhook/inc/customuser.h OS_LAYER_PLATFORM_EXPORT_PATH(analyzetool/customuser.h) + +PRJ_MMPFILES +atoolstaticlib.mmp diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/staticlib/src/atoolstaticlib.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/staticlib/src/atoolstaticlib.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,122 @@ +/* +* 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: The file contains declarations of extern methods and definitions +* of overloaded User methods. +* +*/ + + +#include <analyzetool/customuser.h> +#include "atlog.h" + +// ----------------------------------------------------------------------------- +// GetInt() +// Extern function for acquiring all integer values +// ----------------------------------------------------------------------------- +// +GLREF_C TInt GetInt( const TUint8 aType ); + +// ----------------------------------------------------------------------------- +// GetString() +// Extern function for acquiring all string values +// ----------------------------------------------------------------------------- +// +GLREF_C TPtrC GetString( const TUint8 aType ); + +// ----------------------------------------------------------------------------- +// User::Exit() +// Overloaded User::Exit() function +// ----------------------------------------------------------------------------- +// +void User::Exit( TInt aReason ) + { + LOGSTR2( "ATMH User::Exit %i", aReason ); + CustomUser::Exit( aReason ); + } + +// ----------------------------------------------------------------------------- +// User::Panic() +// Overloaded User::Panic() function +// ----------------------------------------------------------------------------- +// +void User::Panic( const TDesC& aCategory, TInt aReason ) + { + LOGSTR3( "ATMH User::Panic() %S %i", &aCategory, aReason ); + CustomUser::Panic( aCategory, aReason ); + } + +// ----------------------------------------------------------------------------- +// User::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. +// ----------------------------------------------------------------------------- +// +TInt User::SetCritical( TCritical aCritical ) + { + LOGSTR2( "ATMH User::SetCritical() %i", aCritical ); + return CustomUser::SetCritical( aCritical ); + } + +// ----------------------------------------------------------------------------- +// User::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. +// ----------------------------------------------------------------------------- +// +TInt User::SetProcessCritical( TCritical aCritical ) + { + LOGSTR2( "ATMH User::SetProcessCritical() %i", aCritical ); + return CustomUser::SetProcessCritical( aCritical ); + } + +// ----------------------------------------------------------------------------- +// UserHeap::SetupThreadHeap() +// Overloaded UserHeap::SetupThreadHeap function +// ----------------------------------------------------------------------------- +// +TInt UserHeap::SetupThreadHeap( TBool aNotFirst, + SStdEpocThreadCreateInfo& aInfo ) + { + LOGSTR1( "ATMH UserHeap::SetupThreadHeap()" ); + + // Check validity of parameters + TInt logOption( GetInt( (TUint8) CustomUser::ELogOption ) ); + if ( logOption < 0 ) + logOption = KATDefaultLogOption; + + TInt debug( GetInt( (TUint8) CustomUser::EDebug ) ); + if ( debug < 0 ) + debug = KATDefaultDebug; + + TInt allocCallStack( GetInt( (TUint8) CustomUser::EAllocCallStackSize ) ); + if ( allocCallStack < 0 ) + allocCallStack = KATDefaultAllocCallStackSize; + + TInt freeCallStack( GetInt( (TUint8) CustomUser::EFreeCallStackSize ) ); + if ( freeCallStack < 0 ) + freeCallStack = KATDefaultFreeCallStackSize; + + return CustomUser::SetupThreadHeap( aNotFirst, aInfo, + GetString( (TUint8) CustomUser::ELogFileName ), + (TUint32) logOption, (TUint32) debug, + GetString( (TUint8) CustomUser::EVersion ), + (TUint32) allocCallStack, (TUint32) freeCallStack, + KATArgumentList ); + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/client/bwins/atoolstorageserverclntu.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/client/bwins/atoolstorageserverclntu.def Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,26 @@ +EXPORTS + ??0RATStorageServer@@QAE@XZ @ 1 NONAME ; RATStorageServer::RATStorageServer(void) + ?CancelLogging@RATStorageServer@@QAEHI@Z @ 2 NONAME ; int RATStorageServer::CancelLogging(unsigned int) + ?CheckMemoryAddress@RATStorageServer@@QBEHK@Z @ 3 NONAME ; int RATStorageServer::CheckMemoryAddress(unsigned long) const + ?Close@RATStorageServer@@QAEXXZ @ 4 NONAME ; void RATStorageServer::Close(void) + ?Connect@RATStorageServer@@QAEHXZ @ 5 NONAME ; int RATStorageServer::Connect(void) + ?GetCurrentAllocsL@RATStorageServer@@QAEHIAAK0@Z @ 6 NONAME ; int RATStorageServer::GetCurrentAllocsL(unsigned int, unsigned long &, unsigned long &) + ?GetLoadedDllsL@RATStorageServer@@QAEHIAAV?$RArray@V?$TBuf8@$0DM@@@@@@Z @ 7 NONAME ; int RATStorageServer::GetLoadedDllsL(unsigned int, class RArray<class TBuf8<60> > &) + ?GetLoggingFileL@RATStorageServer@@QAEHIAAVTDes8@@@Z @ 8 NONAME ; int RATStorageServer::GetLoggingFileL(unsigned int, class TDes8 &) + ?GetLoggingModeL@RATStorageServer@@QAEHIAAW4TATLogOption@@@Z @ 9 NONAME ; int RATStorageServer::GetLoggingModeL(unsigned int, enum TATLogOption &) + ?GetMaxAllocsL@RATStorageServer@@QAEHIAAK0@Z @ 10 NONAME ; int RATStorageServer::GetMaxAllocsL(unsigned int, unsigned long &, unsigned long &) + ?GetProcessesL@RATStorageServer@@QAEHAAV?$RArray@VTATProcessInfo@@@@@Z @ 11 NONAME ; int RATStorageServer::GetProcessesL(class RArray<class TATProcessInfo> &) + ?GetUdebL@RATStorageServer@@QAEHIAAK@Z @ 12 NONAME ; int RATStorageServer::GetUdebL(unsigned int, unsigned long &) + ?IsMemoryAdded@RATStorageServer@@QAEHK@Z @ 13 NONAME ; int RATStorageServer::IsMemoryAdded(unsigned long) + ?LogDllLoaded@RATStorageServer@@QAEHABVTDesC8@@KK@Z @ 14 NONAME ; int RATStorageServer::LogDllLoaded(class TDesC8 const &, unsigned long, unsigned long) + ?LogDllUnloaded@RATStorageServer@@QAEHABVTDesC8@@KK@Z @ 15 NONAME ; int RATStorageServer::LogDllUnloaded(class TDesC8 const &, unsigned long, unsigned long) + ?LogMemoryAllocated@RATStorageServer@@QAEHKAAV?$TFixedArray@K$0BAA@@@H@Z @ 16 NONAME ; int RATStorageServer::LogMemoryAllocated(unsigned long, class TFixedArray<unsigned long, 256> &, int) + ?LogMemoryFreed@RATStorageServer@@QAEHKAAV?$TFixedArray@K$0BAA@@@@Z @ 17 NONAME ; int RATStorageServer::LogMemoryFreed(unsigned long, class TFixedArray<unsigned long, 256> &) + ?LogProcessEnded@RATStorageServer@@QAEHII@Z @ 18 NONAME ; int RATStorageServer::LogProcessEnded(unsigned int, unsigned int) + ?LogProcessStarted@RATStorageServer@@QAEHABVTDesC16@@ABVTDesC8@@IKK@Z @ 19 NONAME ; int RATStorageServer::LogProcessStarted(class TDesC16 const &, class TDesC8 const &, unsigned int, unsigned long, unsigned long) + ?StartSubTest@RATStorageServer@@QAEHABVTDesC8@@@Z @ 20 NONAME ; int RATStorageServer::StartSubTest(class TDesC8 const &) + ?StartSubTest@RATStorageServer@@QAEHIABVTDesC8@@H@Z @ 21 NONAME ; int RATStorageServer::StartSubTest(unsigned int, class TDesC8 const &, int) + ?StopSubTest@RATStorageServer@@QAEHABVTDesC8@@@Z @ 22 NONAME ; int RATStorageServer::StopSubTest(class TDesC8 const &) + ?StopSubTest@RATStorageServer@@QAEHIABVTDesC8@@H@Z @ 23 NONAME ; int RATStorageServer::StopSubTest(unsigned int, class TDesC8 const &, int) + ?Version@RATStorageServer@@QBE?AVTVersion@@XZ @ 24 NONAME ; class TVersion RATStorageServer::Version(void) const + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/client/eabi/atoolstorageserverclntu.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/client/eabi/atoolstorageserverclntu.def Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,27 @@ +EXPORTS + _ZN16RATStorageServer11StopSubTestERK6TDesC8 @ 1 NONAME + _ZN16RATStorageServer11StopSubTestEjRK6TDesC8i @ 2 NONAME + _ZN16RATStorageServer12LogDllLoadedERK6TDesC8mm @ 3 NONAME + _ZN16RATStorageServer12StartSubTestERK6TDesC8 @ 4 NONAME + _ZN16RATStorageServer12StartSubTestEjRK6TDesC8i @ 5 NONAME + _ZN16RATStorageServer13CancelLoggingEj @ 6 NONAME + _ZN16RATStorageServer13GetMaxAllocsLEjRmS0_ @ 7 NONAME + _ZN16RATStorageServer13GetProcessesLER6RArrayI14TATProcessInfoE @ 8 NONAME + _ZN16RATStorageServer13IsMemoryAddedEm @ 9 NONAME + _ZN16RATStorageServer14GetLoadedDllsLEjR6RArrayI5TBuf8ILi60EEE @ 10 NONAME + _ZN16RATStorageServer14LogDllUnloadedERK6TDesC8mm @ 11 NONAME + _ZN16RATStorageServer14LogMemoryFreedEmR11TFixedArrayImLi256EE @ 12 NONAME + _ZN16RATStorageServer15GetLoggingFileLEjR5TDes8 @ 13 NONAME + _ZN16RATStorageServer15GetLoggingModeLEjR12TATLogOption @ 14 NONAME + _ZN16RATStorageServer15LogProcessEndedEjj @ 15 NONAME + _ZN16RATStorageServer17GetCurrentAllocsLEjRmS0_ @ 16 NONAME + _ZN16RATStorageServer17LogProcessStartedERK7TDesC16RK6TDesC8jmm @ 17 NONAME + _ZN16RATStorageServer18LogMemoryAllocatedEmR11TFixedArrayImLi256EEi @ 18 NONAME + _ZN16RATStorageServer5CloseEv @ 19 NONAME + _ZN16RATStorageServer7ConnectEv @ 20 NONAME + _ZN16RATStorageServer8GetUdebLEjRm @ 21 NONAME + _ZN16RATStorageServerC1Ev @ 22 NONAME + _ZN16RATStorageServerC2Ev @ 23 NONAME + _ZNK16RATStorageServer18CheckMemoryAddressEm @ 24 NONAME + _ZNK16RATStorageServer7VersionEv @ 25 NONAME + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/client/group/atoolstorageserverclnt.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/client/group/atoolstorageserverclnt.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,41 @@ +/* +* 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: The .mmp file for the client side of AToolStorageServer +* +*/ + +#include <platform_paths.hrh> + +TARGET atoolstorageserverclnt.dll +TARGETTYPE dll +UID 0x1000008d 0x20012431 +CAPABILITY ALL -TCB + +SMPSAFE + +SOURCEPATH ../src + +SOURCE atstorageserverclnt.cpp + +USERINCLUDE ../inc +USERINCLUDE ../../inc +USERINCLUDE ../../server/inc +USERINCLUDE ../../../inc + +OS_LAYER_SYSTEMINCLUDE + +LIBRARY euser.lib +LIBRARY flogger.lib + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/client/inc/atstorageserverclnt.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/client/inc/atstorageserverclnt.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,371 @@ +/* +* 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: Declaration of the client side handle class RATStorageServer +* +*/ + + + +#ifndef ATSTORAGESERVERCLNT_H +#define ATSTORAGESERVERCLNT_H + + +// INCLUDES +#include <e32base.h> +#include <analyzetool/atcommon.h> + + +// CONSTANTS +// Constants for the lowest version of the server with which the +// client is compatible +const TUint KLowestVersionNumberMaj = 0; +const TUint KLowestVersionNumberMin = 1; +const TUint KLowestVersionNumberBld = 1; + + +// FORWARD DECLARATIONS +class TATProcessInfo; + + +// CLASS DECLARATION + +/** +* The main class of the Storage Server client. Objects of this class work as handles +* to the Storage Server's server side. Use Connect() to connect a client to the server, +* and Close() to end an opened session. +*/ +class RATStorageServer: public RSessionBase + { + public: // Constructor and destructor + + /** + * C++ default constructor. + */ + IMPORT_C RATStorageServer(); + + public: // New functions + + /** + * Creates a new process for the server, if that doesn't already exist, and + * connects a client to the server by creating a new session with it, and + * initializes the client for use. To end the server session, use Close(). + * @return KErrNone, if successful; otherwise one of the other + * system-wide error codes. + */ + IMPORT_C TInt Connect(); + + /** + * Closes a handle to a server session. This has also the effect of destroying + * the associated server side session object. Also, the server itself and the + * process where it is running are destroyed, if there are no other open sessions + * left. + */ + IMPORT_C void Close(); + + /** + * This method is called to initialize the server for logging and it is to be + * called as the first method after connecting to the server. The method informs + * the server that a new process has been started. The method cannot be called + * again without a call to the LogProcessEnded() first. Otherwise a STSEClient: 3 + * panic is raised. A KERN-EXEC: 0 panic is raised if the client is not connected + * to the server. + * @param aFileName The name of the logging file used when the system is logging + * to a file (the logging mode is EATLogToFile). The length of aFileName must not be + * greater than KMaxFileName, otherwise the method raises a STSEClient: 2 panic. + * @param aProcessName The name of the new process started. The length of this + * descriptor must not be greater than KMaxProcessName, otherwise the method + * raises a STSEClient: 2 panic. + * @param aProcessId The ID of the process started. + * @param aLogOption An option telling the logging mode. + * @param aIsDebug Determines whether a binary is UDEB or UREL + * @return KErrNone, if successful; otherwise one of the other + * system-wide error codes. + */ + IMPORT_C TInt LogProcessStarted( const TDesC& aFileName, + const TDesC8& aProcessName, + TUint aProcessId, + TUint32 aLogOption, TUint32 aIsDebug ); + + /** + * Asks the server to log that a new DLL has been loaded. Note, the method + * LogProcessStarted() has to be previously called. Otherwise a STSEClient: 3 + * panic is raised. A KERN-EXEC: 0 panic is raised if the client is not connected + * to the server. + * @param aDllName The name of the new DLL loaded. The length of this descriptor + * must not be greater than KMaxLibraryName, otherwise the method raises a + * STSEClient: 2 panic. + * @param aStartAddress The start address of the DLL loaded. + * @param aEndAddress The end address of the DLL loaded. + * @return KErrNone, if successful; otherwise one of the other + * system-wide error codes. + */ + IMPORT_C TInt LogDllLoaded( const TDesC8& aDllName, TUint32 aStartAddress, + TUint32 aEndAddress ); + + /** + * Asks the server to log that a new DLL has been unloaded. Note, the method + * LogProcessStarted() has to be previously called. Otherwise a STSEClient: 3 + * panic is raised. A KERN-EXEC: 0 panic is raised if the client is not connected + * to the server. If the method is called with illegal parameter values, a + * STSEClient: 2 panic is raised. + * @param aDllName The name of the DLL to be unloaded. The length of this + * descriptor must not be greater than KMaxLibraryName, otherwise the method + * raises a STSEClient: 2 panic. + * @param aStartAddress The start address of the DLL to be unloaded. + * @param aEndAddress The end address of the DLL to be unloaded. + * @return KErrNone, if successful; otherwise one of the other + * system-wide error codes. + */ + IMPORT_C TInt LogDllUnloaded( const TDesC8& aDllName, TUint32 aStartAddress, + TUint32 aEndAddress ); + + /** + * Informs the server that a memory allocation has occured at the specified + * address. Sends also the current call stack to the server. Note, the method + * LogProcessStarted() has to be previously called. Otherwise a STSEClient: 3 + * panic is raised. A KERN-EXEC: 0 panic is raised if the client is not connected + * to the server. + * @param aMemAddress The memory location where memory has been allocated. + * @param aCallstack An array including the current call stack. + * @param aSize The size of the newly allocated memory chunk. + * @return KErrNone, if successful; otherwise one of the other + * system-wide error codes. + */ + IMPORT_C TInt LogMemoryAllocated( TUint32 aMemAddress, + TFixedArray<TUint32, KATMaxCallstackLength>& aCallstack, + TInt aSize ); + + /** + * Informs the server that memory was released at the specified address. Note, + * the method LogProcessStarted() has to be previously called. Otherwise a + * STSEClient: 3 panic is raised. A KERN-EXEC: 0 panic is raised if the client is + * not connected to the server. + * @param aMemAddress The memory location where memory has been deallocated. + * @param aFreeCallstack An array including the current call stack. + * @return KErrNone, if successful; otherwise one of the other + * system-wide error codes. + */ + IMPORT_C TInt LogMemoryFreed( TUint32 aMemAddress, + TFixedArray<TUint32, KATMaxFreeCallstackLength>& aFreeCallstack ); + + /** + * Tells the server that the process under test has been ended. Prints information + * related to process ending, such as possibly occured memory leaks (when file + * logging mode used), and possibly occured handle leaks. Note, the method + * LogProcessStarted() has to be previously called. Otherwise a STSEClient: + * 3 panic is raised. A call to this method also closes the file opened for + * the current process. So, no further logging is possible without a new call + * to the method LogProcessStarted(). A KERN-EXEC: 0 panic is raised if the client + * is not connected to the server. + * @param aProcessId The ID number of the process ended. + * @param aHandleLeaks Amount of handle leaks. + * @return KErrNone, if successful; otherwise one of the other + * system-wide error codes. + */ + IMPORT_C TInt LogProcessEnded( TUint aProcessId, + TUint aHandleLeaks ); + + /** + * Gives the lowest version number of the server needed for this client. + * @return The lowest version of the server needed for this client. + */ + IMPORT_C TVersion Version() const; + + /** + * Checks if the current process has allocated, but not freed, the given memory + * address. Note, the method LogProcessStarted() has to be previously called. + * Otherwise a STSEClient: 3 panic is raised. A KERN-EXEC: 0 panic is raised if + * the client is not connected to the server. + * @param aMemAddress The memory location to check. + * @return When the system is logging into a file: the index of a found + * memory address or KErrNotFound, if a matching memory address cannot + * be found. When the system is not logging into a file: always KErrNone. + */ + IMPORT_C TInt CheckMemoryAddress( TUint32 aMemAddress ) const; + + /** + * Gets all the processes with currently open logging sessions. + * @param aProcesses A reference to a process array to be filled by the server. + * @return KErrNone, if successful; otherwise one of the other + * system wide error codes. + */ + IMPORT_C TInt GetProcessesL( RArray<TATProcessInfo>& aProcesses ); + + /** + * Gets all the DLLs loaded by the given process. + * @param aProcessId The ID of the process whose DLLs will be fetched. + * @param aDlls An array that after this function call includes names of + * the given process's dlls + * @return KErrNone, if successful; KErrNotFound, if the requested process was + * not found; otherwise one of the other system wide error codes. + */ + IMPORT_C TInt GetLoadedDllsL( TUint aProcessId, + RArray< TBuf8<KMaxLibraryName> >& aDlls ); + + /** + * Gets the logging mode of the given process. + * @param aProcessId The ID of the process whose logging mode is being asked. + * @param aLoggingMode An enumeration telling the logging mode after a call + * to this function. + * @return KErrNone, if successful; KErrNotFound, if the requested process was + * not found; otherwise one of the other system wide error codes. + */ + IMPORT_C TInt GetLoggingModeL( TUint aProcessId, TATLogOption& aLoggingMode ); + + /** + * Starts a sub test for the given process. + * @param aProcessId The ID of the process for which to start a sub test. + * @param aSubtestId The name identifying this particular sub test. The length + * of this descriptor must not be greater than KATMaxSubtestIdLength, or + * otherwise the method raises a STSEClient: 2 panic. + * @param aHandleCount The current handle count of a particular process. + * @return KErrNone, if successful; KErrNotFound, if the requested process was not + * found; KErrNotSupported, if the requested process does not have a logging + * session ongoing or its logging mode is not EATLogToTrace; Otherwise one of the + * other system wide error codes. + */ + IMPORT_C TInt StartSubTest( TUint aProcessId, const TDesC8& aSubtestId, TInt aHandleCount = 0 ); + + /** + * Stops a sub test for the given process. + * @param aProcessId The ID of the process for which to stop a sub test. + * @param aSubtestId The name identifying this particular sub test. The length + * of this descriptor must not be greater than KATMaxSubtestIdLength, or + * otherwise the method raises a STSEClient: 2 panic. + * @param aHandleCount The current handle count of a particular process. + * @return KErrNone, if successful; KErrNotFound, if the requested process was not + * found; KErrNotSupported, if the requested process does not have a logging + * session ongoing or its logging mode is not EATLogToTrace; Otherwise one of the + * other system wide error codes. + */ + IMPORT_C TInt StopSubTest( TUint aProcessId, const TDesC8& aSubtestId, TInt aHandleCount = 0 ); + + /** + * Gets the number and total size of the memory chunks currently allocated by the + * requested process. + * @param aProcessId The ID of the process whose information is requested. + * @param aNumber On return contains the number of memory chunks currenlty + * allocated by the requested process. + * @param aSize On return contains the amount of memory currently allocated + * by the requested process. + * @return KErrNone, if successful; KErrNotFound, if the requested process was not + * found; Otherwise one of the other system wide error codes. + */ + IMPORT_C TInt GetCurrentAllocsL( TUint aProcessId, TUint32& aNumber, TUint32& aSize ); + + /** + * Gets the maximum number and total size of the memory chunks allocated by the + * requested process. + * @param aProcessId The ID of the process whose information is requested. + * @param aNumber On return contains the maximum number of memory chunks + * allocated by the requested process during the test run. + * @param aSize On return contains the maximum amount of memory allocated + * by the requested process during the test run. + * @return KErrNone, if successful; KErrNotFound, if the requested process was not + * found; Otherwise one of the other system wide error codes. + */ + IMPORT_C TInt GetMaxAllocsL( TUint aProcessId, TUint32& aNumber, TUint32& aSize ); + + /** + * Starts a sub test for the calling process. + * @param aSubtestId The name identifying this particular sub test. The length + * of this descriptor must not be greater than KATMaxSubtestIdLength, or + * otherwise the method raises a STSEClient: 2 panic. + * @return KErrNone, if successful; KErrNotSupported, if the calling process + * does not have a logging session ongoing or its logging mode is not + * EATLogToTrace; Otherwise one of the other system wide error codes. + */ + IMPORT_C TInt StartSubTest( const TDesC8& aSubtestId ); + + /** + * Stops a sub test for the calling process + * @param aSubtestId The name identifying this particular sub test. The length + * of this descriptor must not be greater than KATMaxSubtestIdLength, or + * otherwise the method raises a STSEClient: 2 panic. + * @return KErrNone, if successful; KErrNotSupported, if the calling process + * does not have a logging session ongoing or its logging mode is not + * EATLogToTrace; Otherwise one of the other system wide error codes. + */ + IMPORT_C TInt StopSubTest( const TDesC8& aSubtestId ); + + /** + * Cancels logging for the requested process. After logging of a given process + * has been cancelled, the session associated with that process will not be + * usable anymore. If a process wants to start logging again, it needs to close + * the handle and open it again in order to create a new session. Until then, most + * of the client's methods will return KErrCancel. + * @param aProcessId The process ID of the process whose logging is requested to + * be cancelled. + * @return KErrNone, if successful; KErrNotFound, if the requested process was + * not found; otherwise one of the other system wide error codes. + */ + IMPORT_C TInt CancelLogging( TUint aProcessId ); + + /** + * Gets the number and total size of the memory chunks currently allocated by the + * requested process. + * @param aProcessId The ID of the process whose information is requested. + * @param aIsUdeb On return contains an value greater than KErrNone if + * mode is UDEB. Else the mode is UREL + * @return KErrNone, if successful; KErrNotFound, if the requested process was not + * found; Otherwise one of the other system wide error codes. + */ + IMPORT_C TInt GetUdebL( TUint aProcessId, TUint32& aIsUdeb ); + + /** + * Gets the number and total size of the memory chunks currently allocated by the + * requested process. + * @param aProcessId The ID of the process whose information is requested. + * @param aFileName On return contains logging filename for the process. + * @return KErrNone, if successful; KErrNotFound, if the requested process was not + * found; Otherwise one of the other system wide error codes. + */ + IMPORT_C TInt GetLoggingFileL( TUint aProcessId, TDes8& aFileName ); + + /** + * Check a memory allocation (memory address) from an internal array. + * @param aMemAddress The memory address to be check + * @return KErrNone, if memory address found in array; + * KErrNotFound, if the requested memory address was not found. + */ + IMPORT_C TInt IsMemoryAdded( TUint32 aMemAddress ); + + protected: // New functions + + /** + * Creates a new process for the server, if it does not already exist. + * @return KErrNone, if successful; otherwise one of the other + * system-wide error codes. + */ + TInt CreateProcess(); + + private: // Internal functions + + /** + * Creates two buffers: one for storing call stack memory addresses and one for + * handle leaks. Internally used by this class. May leave, if there is + * insufficient memory. + */ + void ConstructBuffersL(); + + private: // Data + + /** A pointer to a buffer of call stack's memory addresses */ + CBufFlat* iStackBuf; + }; + +#endif // ATSTORAGESERVERCLNT_H + + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/client/src/atstorageserverclnt.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/client/src/atstorageserverclnt.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,930 @@ +/* +* 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 client side handle class RATStorageServer +* +*/ + + + +// INCLUDE FILES +#include "atstorageserverclnt.h" +#include "atstorageserver.h" +#include "atlog.h" +#include "atstorageservercommon.h" + + +// CONSTANTS + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// RATStorageServer::RATStorageServer +// C++ default constructor. +// ----------------------------------------------------------------------------- +// +EXPORT_C RATStorageServer::RATStorageServer() : + RSessionBase(), iStackBuf( NULL ) + { + LOGSTR1( "STSE RATStorageServer::RATStorageServer()" ); + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::Connect +// A function for connecting to the server +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::Connect() + { + LOGSTR1( "STSE TInt RATStorageServer::Connect()" ); + + TInt errorCode( KErrNone ); + errorCode = CreateProcess(); + + // If process's creation failed, return the error code + if ( errorCode != KErrNone ) + { + return errorCode; + } + + // Otherwise create a new session + errorCode = CreateSession( KStorageServerName, Version() ); + + // If creation of a new session failed, return the error code + if ( errorCode != KErrNone ) + { + return errorCode; + } + + // Construct a buffer for call stack's memory addresses. If the function leaves, + // the leave code is put in "errorCode". + TRAP( errorCode, ConstructBuffersL() ); + + return errorCode; + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::Close +// Destroys all memory reserved by this class, and calls RSessionBase::Close() +// ----------------------------------------------------------------------------- +// +EXPORT_C void RATStorageServer::Close() + { + LOGSTR1( "STSE void RATStorageServer::Close()" ); + + // Delete iStackBuf + delete iStackBuf; + iStackBuf = NULL; + + // Call the base class' Close() + RSessionBase::Close(); + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::LogProcessStarted +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::LogProcessStarted( const TDesC& aFileName, + const TDesC8& aProcessName, + TUint aProcessId, + TUint32 aLogOption, TUint32 aIsDebug ) + { + LOGSTR1( "STSE TInt RATStorageServer::LogProcessStarted()" ); + + // Panic always if aFileName or aProcessName are longer than allowed. + __ASSERT_ALWAYS( aFileName.Length() <= KMaxFileName && + aProcessName.Length() <= KMaxProcessName, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + // Panic (in debug builds) if aProcessId is KNullProcessId + __ASSERT_DEBUG( aProcessId != KNullProcessId, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + // This information is optional -> ignoring error + // Must be before EProcessStarted in order to append udeb/urel + // information to LogProcessStarted + TIpcArgs ipcArgs2( aIsDebug ); + SendReceive( CATStorageServer::EProcessUdeb, ipcArgs2 ); + + TIpcArgs ipcArgs( &aFileName, &aProcessName, aProcessId, aLogOption ); + TInt error( 0 ); + + error = SendReceive( CATStorageServer::EProcessStarted, ipcArgs ); + + // Return, if error is not KErrNone. + if ( error != KErrNone ) + { + return error; + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::LogDllLoaded +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::LogDllLoaded( const TDesC8& aDllName, + TUint32 aStartAddress, + TUint32 aEndAddress ) + { + LOGSTR1( "STSE TInt RATStorageServer::LogDllLoaded()" ); + + // Panic always if aDllName is longer than allowed. + __ASSERT_ALWAYS( aDllName.Length() <= KMaxLibraryName, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + // Panic (in debug builds) if aStartAddress is greater than aEndAddress + __ASSERT_DEBUG( aStartAddress <= aEndAddress, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + TIpcArgs ipcArgs( &aDllName, aStartAddress, aEndAddress ); + + return SendReceive( CATStorageServer::EDllLoaded, ipcArgs ); + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::LogDllUnloaded +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::LogDllUnloaded( const TDesC8& aDllName, + TUint32 aStartAddress, + TUint32 aEndAddress ) + { + LOGSTR1( "STSE TInt RATStorageServer::LogDllUnloaded()" ); + + // Panic always if aDllName is longer than allowed. + __ASSERT_ALWAYS( aDllName.Length() <= KMaxLibraryName, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + // Panic (in debug builds) if aStartAddress is greater than aEndAddress + __ASSERT_DEBUG( aStartAddress <= aEndAddress, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + TIpcArgs ipcArgs( &aDllName, aStartAddress, aEndAddress ); + + return SendReceive( CATStorageServer::EDllUnloaded, ipcArgs ); + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::LogMemoryAllocated +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::LogMemoryAllocated( TUint32 aMemAddress, + TFixedArray<TUint32, KATMaxCallstackLength>& aCallstack, + TInt aSize ) + { + LOGSTR1( "STSE TInt RATStorageServer::LogMemoryAllocated()" ); + + TInt count=0; + // The number of memory addresses in aCallstack + for ( TInt i = 0; i < KATMaxCallstackLength; i++ ) + { + if( aCallstack[i] == 0 ) + { + break; + } + count++; + } + + LOGSTR2( "STSE The number of memory addresses in the current call stack: %d", count ); + + // The maximum number of call stack's memory addresses this server can handle + // is KMaxCallstackLength + if ( count > KATMaxCallstackLength ) + { + count = KATMaxCallstackLength; + } + + // Panic (in debug builds) if the parameters are faulty + __ASSERT_DEBUG( aMemAddress != 0 && count >= 0 && aSize >= 0, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + // Buffer position + TInt pos = 0; + TUint32 callStackAddr; + + // Write the number of memory addresses of aCallstack (one word) into + // the beginning of the call stack buffer + iStackBuf->Write( pos, &count, KWordSize ); + + // Increase the position by one word + pos += KWordSize; + + // Write all the memory addresses of aCallStack into the buffer + for ( TInt i = 0; i < count; i++ ) + { + callStackAddr = aCallstack[i]; + + // Write the current memory address (the length of an address is one word) + iStackBuf->Write( pos, &callStackAddr, KWordSize ); + + // Move the pos variable one word (4 bytes) onwards. + pos += KWordSize; + } + + TPtr8 bufPtr( iStackBuf->Ptr(0) ); + + TIpcArgs ipcArgs( aMemAddress, &bufPtr, aSize ); + + return SendReceive( CATStorageServer::EMemoryAllocated, ipcArgs ); + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::LogMemoryFreed +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::LogMemoryFreed( TUint32 aMemAddress, + TFixedArray<TUint32, KATMaxFreeCallstackLength>& aFreeCallstack ) + { + LOGSTR1( "STSE TInt RATStorageServer::LogMemoryFreed()" ); + + TInt count=0; + // The number of memory addresses in aFreeCallstack + for ( TInt i = 0; i < KATMaxCallstackLength; i++ ) + { + if( aFreeCallstack[i] == 0 ) + { + break; + } + count++; + } + LOGSTR3( "STSE > aFreeCallstack.Count() ( %i ), address( %x )", + count, aMemAddress ); + + // The maximum number of call stack's memory addresses this server can handle + // is KMaxCallstackLength + if ( count > KATMaxFreeCallstackLength ) + { + count = KATMaxFreeCallstackLength; + } + + // Buffer position + TInt pos = 0; + TUint32 callStackAddr; + + // Write the number of memory addresses of aFreeCallstack (one word) into + // the beginning of the call stack buffer + iStackBuf->Write( pos, &count, KWordSize ); + + // Increase the position by one word + pos += KWordSize; + + // Write all the memory addresses of aFreeCallstack into the buffer + for ( TInt i = 0; i < count; i++ ) + { + callStackAddr = aFreeCallstack[i]; + + // Write the current memory address (the length of an address is one word) + iStackBuf->Write( pos, &callStackAddr, KWordSize ); + + // Move the pos variable one word (4 bytes) onwards. + pos += KWordSize; + } + + TPtr8 bufPtr( iStackBuf->Ptr( 0 ) ); + TIpcArgs ipcArgs( aMemAddress, &bufPtr ); + + return SendReceive( CATStorageServer::EMemoryFreed, ipcArgs ); + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::LogProcessEnded +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::LogProcessEnded( TUint aProcessId, + TUint aHandleLeaks ) + { + LOGSTR1( "STSE TInt RATStorageServer::LogProcessEnded()" ); + + // Panic (in debug builds) if the parameters are faulty + __ASSERT_DEBUG( aProcessId != KNullProcessId, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + TIpcArgs ipcArgs( aProcessId, aHandleLeaks ); + + return SendReceive( CATStorageServer::EProcessEnded, ipcArgs ); + } + +//----------------------------------------------------------------------------- +// RATStorageServer::Version() +// Returns the version number. +//----------------------------------------------------------------------------- +// +EXPORT_C TVersion RATStorageServer::Version() const + { + LOGSTR1( "STSE TInt RATStorageServer::Version()" ); + + return TVersion(KLowestVersionNumberMaj, KLowestVersionNumberMin, + KLowestVersionNumberBld); + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::CheckMemoryAddress +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::CheckMemoryAddress( TUint32 aMemAddress ) const + { + LOGSTR1( "STSE TInt RATStorageServer::CheckMemoryAddress()" ); + + // Panic (in debug builds) if the parameters are faulty + __ASSERT_DEBUG( aMemAddress != 0, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + TIpcArgs ipcArgs( aMemAddress ); + + return SendReceive( CATStorageServer::EMemoryCheck, ipcArgs ); + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::GetProcessesL +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::GetProcessesL( RArray<TATProcessInfo>& aProcesses ) + { + LOGSTR1( "STSE TInt RATStorageServer::GetProcessesL()" ); + + TInt error( KErrNone ); + TInt sizeOfProcessInfo = sizeof( TATProcessInfo ); + + // Reset the sent array + aProcesses.Reset(); + + // Calculate the length of the buffer to be constructed for processes. + // One word will be reserved for the length of the array. + TInt bufferLength = KWordSize + KATMaxProcesses * sizeOfProcessInfo; + + CBufFlat* processBuf; + // Construct processBuf and expand it before the beginning (index 0) + processBuf = CBufFlat::NewL( bufferLength ); + CleanupStack::PushL( processBuf ); + processBuf->ExpandL( 0, bufferLength ); + + TPtr8 bufPtr( processBuf->Ptr(0) ); + + // Send the buffer to the server, which will fill it. + TIpcArgs ipcArgs( &bufPtr ); + error = SendReceive( CATStorageServer::EGetProcesses, ipcArgs ); + // Return with the error code if the operation failed + if ( error != KErrNone ) + { + CleanupStack::PopAndDestroy( processBuf ); + return error; + } + + // A variable for the number of TATProcessInfo objects + TInt count( 0 ); + // A variable for the position + TInt pos( 0 ); + + // Read the value for count + processBuf->Read( pos, &count, KWordSize ); + + // Return if we got an illegal value for count + if ( count < 0 || count > KATMaxProcesses ) + { + CleanupStack::PopAndDestroy( processBuf ); + return KErrGeneral; + } + + // Move the position one word onwards. + pos += KWordSize; + + TATProcessInfo processInfo; + + // Go through all TATProcessInfo objects sent to the server + for ( TInt j = 0; j < count; j++ ) + { + // Read one of the TATProcessInfo objects stored in the buffer. + processBuf->Read( pos, &processInfo, sizeOfProcessInfo ); + + // Append this processInfo to the array + error = aProcesses.Append( processInfo ); + + if ( error != KErrNone ) + { + CleanupStack::PopAndDestroy( processBuf ); + return error; + } + + // Move the pos variable one word onwards. + pos += sizeOfProcessInfo; + } + + CleanupStack::PopAndDestroy( processBuf ); + return error; + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::GetLoadedDllsL +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::GetLoadedDllsL( TUint aProcessId, + RArray< TBuf8<KMaxLibraryName> >& aDlls ) + { + LOGSTR1( "STSE TInt RATStorageServer::GetLoadedDllsL()" ); + + // Panic (in debug builds) if aProcessId is faulty + __ASSERT_DEBUG( aProcessId != KNullProcessId, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + TInt error( KErrNone ); + + // Size of a DLL descriptor + TInt sizeOfDllDesc = sizeof( TBuf8<KMaxLibraryName> ); + + // Reset the sent array + aDlls.Reset(); + + // Calculate the length of the buffer to be constructed for DLL names. + // One word will be reserved for the length of the array. + TInt bufferLength = KWordSize + KATMaxDlls * sizeOfDllDesc; + + CBufFlat* dllBuf; + // Construct dllBuf and expand it before the beginning (index 0) + dllBuf = CBufFlat::NewL( bufferLength ); + CleanupStack::PushL( dllBuf ); + dllBuf->ExpandL( 0, bufferLength ); + + TPtr8 bufPtr( dllBuf->Ptr(0) ); + + // Call the server with the given arguments + TIpcArgs ipcArgs( aProcessId, &bufPtr ); + error = SendReceive( CATStorageServer::EGetDlls, ipcArgs ); + + // Return, if error is not KErrNone. + if ( error != KErrNone ) + { + CleanupStack::PopAndDestroy( dllBuf ); + return error; + } + + // A variable for the number of objects in the buffer + TInt count( 0 ); + + // A variable for the position + TInt pos( 0 ); + + // Read the value for count + dllBuf->Read( pos, &count, KWordSize ); + + // Return if we got an illegal value for count + if ( count < 0 || count > KATMaxDlls ) + { + CleanupStack::PopAndDestroy( dllBuf ); + return KErrGeneral; + } + + // Move the position one word onwards. + pos += KWordSize; + + TBuf8<KMaxLibraryName> dllName; + + // Go through all DLL names objects sent to the server + for ( TInt j = 0; j < count; j++ ) + { + // Read one of the DLL names stored in the buffer. + dllBuf->Read( pos, &dllName, sizeOfDllDesc ); + + // Append this DLL name to the array + error = aDlls.Append( dllName ); + + if ( error != KErrNone ) + { + return error; + } + + // Move the pos variable one word onwards. + pos += sizeOfDllDesc; + } + + CleanupStack::PopAndDestroy( dllBuf ); + return error; + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::GetLoggingModeL +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::GetLoggingModeL( TUint aProcessId, + TATLogOption& aLoggingMode ) + { + LOGSTR1( "STSE TInt RATStorageServer::GetLoggingModeL()" ); + + // Panic (in debug builds) if aProcessId is illegal + __ASSERT_DEBUG( aProcessId != KNullProcessId, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + TInt error(0); + + // The length of the buffer to be constructed for logging mode + TInt bufferLength = KWordSize; + + CBufFlat* loggingModeBuf; + // Construct allocInfoBuf and expand it before the beginning (index 0) + loggingModeBuf = CBufFlat::NewL( bufferLength ); + CleanupStack::PushL( loggingModeBuf ); + loggingModeBuf->ExpandL( 0, bufferLength ); + + TPtr8 bufPtr( loggingModeBuf->Ptr(0) ); + + // Call the server + TIpcArgs ipcArgs( aProcessId, &bufPtr ); + error = SendReceive( CATStorageServer::EGetLoggingMode, ipcArgs ); + + // Return if an error occured. + if ( error ) + { + CleanupStack::PopAndDestroy( loggingModeBuf ); + return error; + } + + // A variable for the position + TInt pos( 0 ); + + // Read the value for aNumber + loggingModeBuf->Read( pos, &aLoggingMode, KWordSize ); + + CleanupStack::PopAndDestroy( loggingModeBuf ); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::StartSubTest +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::StartSubTest( TUint aProcessId, + const TDesC8& aSubtestId, TInt aHandleCount ) + { + LOGSTR1( "STSE TInt RATStorageServer::StartSubTest()" ); + + // Panic if the parameters are faulty + __ASSERT_ALWAYS( aSubtestId.Length() <= KATMaxSubtestIdLength, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + // Panic (in debug builds) if the parameters are faulty + __ASSERT_DEBUG( aProcessId != KNullProcessId, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + TIpcArgs ipcArgs( aProcessId, &aSubtestId, aHandleCount ); + + return SendReceive( CATStorageServer::ESubtestStart, ipcArgs ); + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::StopSubTest +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::StopSubTest( TUint aProcessId, + const TDesC8& aSubtestId, TInt aHandleCount ) + { + LOGSTR1( "STSE TInt RATStorageServer::StopSubTest()" ); + + // Panic if the parameters are faulty + __ASSERT_ALWAYS( aSubtestId.Length() <= KATMaxSubtestIdLength, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + // Panic (in debug builds) if the parameters are faulty + __ASSERT_DEBUG( aProcessId != KNullProcessId, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + TIpcArgs ipcArgs( aProcessId, &aSubtestId, aHandleCount ); + + return SendReceive( CATStorageServer::ESubtestStop, ipcArgs ); + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::GetCurrentAllocsL +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::GetCurrentAllocsL( TUint aProcessId, + TUint32& aNumber, + TUint32& aSize ) + { + LOGSTR1( "STSE TInt RATStorageServer::GetCurrentAllocsL()" ); + + // Panic (in debug builds) if aProcessId is illegal + __ASSERT_DEBUG( aProcessId != KNullProcessId, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + TInt error(0); + + // The length of the buffer to be constructed for allocation number and size + TInt bufferLength = KWordSize + KWordSize; + + CBufFlat* allocInfoBuf; + // Construct allocInfoBuf and expand it before the beginning (index 0) + allocInfoBuf = CBufFlat::NewL( bufferLength ); + CleanupStack::PushL( allocInfoBuf ); + allocInfoBuf->ExpandL( 0, bufferLength ); + + TPtr8 bufPtr( allocInfoBuf->Ptr(0) ); + + // Call the server + TIpcArgs ipcArgs( aProcessId, &bufPtr ); + error = SendReceive( CATStorageServer::EGetCurrentAllocs, ipcArgs ); + + // Return if error is not KErrNone. + if ( error != KErrNone ) + { + CleanupStack::PopAndDestroy( allocInfoBuf ); + return error; + } + + // A variable for the position + TInt pos( 0 ); + + // Read the value for aNumber + allocInfoBuf->Read( pos, &aNumber, KWordSize ); + + pos += KWordSize; + + // Read the value for aSize + allocInfoBuf->Read( pos, &aSize, KWordSize ); + + CleanupStack::PopAndDestroy( allocInfoBuf ); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::GetMaxAllocsL +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::GetMaxAllocsL( TUint aProcessId, + TUint32& aNumber, + TUint32& aSize ) + { + LOGSTR1( "STSE TInt RATStorageServer::GetMaxAllocsL()" ); + + // Panic (in debug builds) if aProcessId is illegal + __ASSERT_DEBUG( aProcessId != KNullProcessId, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + TInt error(0); + + // The length of the buffer to be constructed for allocation number and size + TInt bufferLength = KWordSize + KWordSize; + + CBufFlat* allocInfoBuf; + // Construct allocInfoBuf and expand it before the beginning (index 0) + allocInfoBuf = CBufFlat::NewL( bufferLength ); + CleanupStack::PushL( allocInfoBuf ); + allocInfoBuf->ExpandL( 0, bufferLength ); + + TPtr8 bufPtr( allocInfoBuf->Ptr(0) ); + + // Call the server + TIpcArgs ipcArgs( aProcessId, &bufPtr ); + error = SendReceive( CATStorageServer::EGetMaxAllocs, ipcArgs ); + + // Return, if error is not KErrNone. + if ( error != KErrNone ) + { + CleanupStack::PopAndDestroy( allocInfoBuf ); + return error; + } + + // A variable for the position + TInt pos( 0 ); + + // Read the value for aNumber + allocInfoBuf->Read( pos, &aNumber, KWordSize ); + + pos += KWordSize; + + // Read the value for aSize + allocInfoBuf->Read( pos, &aSize, KWordSize ); + + CleanupStack::PopAndDestroy( allocInfoBuf ); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::StartSubTest +// An overloaded version without a PID parameter +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::StartSubTest( const TDesC8& aSubtestId ) + { + LOGSTR1( "STSE TInt RATStorageServer::StartSubTest()" ); + + // Panic if the parameters are faulty + __ASSERT_ALWAYS( aSubtestId.Length() <= KATMaxSubtestIdLength, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + TIpcArgs ipcArgs( &aSubtestId ); + + return SendReceive( CATStorageServer::ESubtestStart2, ipcArgs ); + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::StopSubTest +// An overloaded version without a PID parameter +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::StopSubTest( const TDesC8& aSubtestId ) + { + LOGSTR1( "STSE TInt RATStorageServer::StopSubTest()" ); + + // Panic if the parameters are faulty + __ASSERT_ALWAYS( aSubtestId.Length() <= KATMaxSubtestIdLength, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + TIpcArgs ipcArgs( &aSubtestId ); + + return SendReceive( CATStorageServer::ESubtestStop2, ipcArgs ); + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::CancelLogging +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::CancelLogging( TUint aProcessId ) + { + LOGSTR1( "STSE TInt RATStorageServer::CancelLogging()" ); + + // Panic (in debug builds) if aProcessId is illegal + __ASSERT_DEBUG( aProcessId != KNullProcessId, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + TIpcArgs ipcArgs( aProcessId ); + + return SendReceive( CATStorageServer::ECancelLogging, ipcArgs ); + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::CreateProcess +// Checks if the server already exists. If it doesn't, creates a new process +// for it. +// ----------------------------------------------------------------------------- +// +TInt RATStorageServer::CreateProcess() + { + LOGSTR1( "STSE TInt RATStorageServer::CreateProcess()" ); + + TInt errorCode( KErrNone ); + + // Check if the server already exists + TFindServer findServer( KStorageServerName ); + TFullName fullName; + + errorCode = findServer.Next( fullName ); + + // Return KErrNone if the server is already running + if ( errorCode == KErrNone ) + { + return KErrNone; + } + + // Otherwise initiate starting the server by creating first a new process for it. + // The second argument of the Create() method call is an empty descriptor, because + // we don't need to pass any data to the thread function of the new process's main + // thread. + RProcess process; + errorCode = process.Create( KStorageServerFile, KNullDesC ); + + // Return the error code if the creation of the process failed + if ( errorCode != KErrNone ) + { + return errorCode; + } + + TRequestStatus status; + process.Rendezvous( status ); + + // If the status is not KRequestPending, abort the project creation + // and return KErrGeneral + if ( status != KRequestPending ) + { + process.RendezvousCancel( status ); + process.Kill( KErrGeneral ); + process.Close(); + return KErrGeneral; + } + + // Otherwise make the first thread of the new process eligible for execution + process.Resume(); + + // Wait for a signal from the server + User::WaitForRequest( status ); + + // Close the process handle + process.Close(); + + // Return the error code + return status.Int(); + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::ConstructBuffersL +// Allocates buffers from heap. Called when connecting to the server +// ----------------------------------------------------------------------------- +// +void RATStorageServer::ConstructBuffersL() + { + LOGSTR1( "STSE void RATStorageServer::ConstructBuffersL()" ); + + // Calculate the length of the buffer to be constructed for call stack. + // One word will be reserved for the length of the array + TInt bufferLength = ( (1 + KATMaxCallstackLength) * KWordSize ); + + // Construct iStackBuf and expand it before the beginning (index 0) + iStackBuf = CBufFlat::NewL( bufferLength ); + iStackBuf->ExpandL( 0, bufferLength ); + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::GetLoggingFileL +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::GetLoggingFileL( TUint aProcessId, + TDes8& aFileName ) + { + LOGSTR1( "STSE TInt RATStorageServer::GetLoggingFileL()" ); + + // Panic (in debug builds) if aProcessId is illegal + __ASSERT_DEBUG( aProcessId != KNullProcessId, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + TInt error(0); + + TBuf8<KMaxFileName> fileBuf; + // Call the server + TIpcArgs ipcArgs( aProcessId, &fileBuf ); + error = SendReceive( CATStorageServer::EGetLoggingFile, ipcArgs ); + + // Return, if an error occured. + if ( error ) + { + return error; + } + + aFileName.Copy( fileBuf ); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::GetUdebL +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::GetUdebL( TUint aProcessId, TUint32& aIsUdeb ) + { + LOGSTR1( "STSE TInt RATStorageServer::GetUdebL()" ); + + // Panic (in debug builds) if aProcessId is illegal + __ASSERT_DEBUG( aProcessId != KNullProcessId, + StorageServerPanic( KCategoryClient, EAToolBadArgument ) ); + + TInt error(0); + TBuf8<KMaxVersionName> isUdeb; + _LIT8( KUdeb, "UDEB" ); + // Call the server + TIpcArgs ipcArgs( aProcessId, &isUdeb ); + error = SendReceive( CATStorageServer::EGetUdeb, ipcArgs ); + + // Return, if an error occured. + if ( error != KErrNone ) + { + return error; + } + + if ( isUdeb.Compare( KUdeb() ) == 0 ) + { + LOGSTR1( "STSE TInt RATStorageServer::GetUdebL() - Is UDEB" ); + aIsUdeb = 1; + } + else + { + LOGSTR1( "STSE TInt RATStorageServer::GetUdebL() - Is UREL" ); + aIsUdeb = 0; + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// RATStorageServer::IsMemoryAdded +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RATStorageServer::IsMemoryAdded( TUint32 aMemAddress ) + { + LOGSTR1( "STSE TInt RATStorageServer::IsMemoryAdded()" ); + + TIpcArgs ipcArgs( aMemAddress ); + return SendReceive( CATStorageServer::EIsMemoryAdded, ipcArgs ); + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,31 @@ +/* +* 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: +* +*/ + +#include <platform_paths.hrh> + +PRJ_PLATFORMS +ARMV5 WINSCW + +PRJ_EXPORTS +../client/inc/atstorageserverclnt.h OS_LAYER_PLATFORM_EXPORT_PATH(analyzetool/atstorageserverclnt.h) + +PRJ_MMPFILES +../server/group/atoolstorageserver.mmp +../client/group/atoolstorageserverclnt.mmp + +PRJ_TESTMMPFILES +../internal/tsrc/group/storageservertest.mmp diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/inc/atstorageservercommon.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/inc/atstorageservercommon.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,77 @@ +/* +* 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: Includes common constants and enums for the AnalyzeTool +* StorageServer client and server. +* +*/ + + + +#ifndef ATSTORAGESERVERCOMMON_H +#define ATSTORAGESERVERCOMMON_H + + +// INCLUDES + +#include <e32base.h> + + +// CONSTANTS + +// Server's file name +_LIT(KStorageServerFile, "AToolStorageServer.exe"); + +// server name +_LIT(KStorageServerName,"AToolStorageServer"); + + +// The path of the storage file +#ifdef __WINS__ +_LIT( KATDataFilePath, ":\\logs\\analyzetool\\" ); +#else +_LIT( KATDataFilePath, ":\\analyzetool\\" ); +_LIT( KATDataFilePath2, ":\\data\\analyzetool\\" ); +#endif + +// The word size in the current system is 32 bits, which is 4 bytes. +const TInt KWordSize = 4; + +// Leak array granularity value +const TInt KLeakArrayGranularity = 100; + +// DATA TYPES + +/** Storage Server panic codes */ +enum TStorageServerPanics + { + EAToolBadRequest = 1, // An undefined operation request from the client + EAToolBadArgument, // Illegal arguments / function parameters + EAToolNotAllowed, // An operation is not allowed in the current program state + EAToolInternalError, // An internal error has occured + EAToolIllegalLogOption // An undefined log option has been requested + }; + + +/** Panic categories */ +_LIT(KCategoryServer,"STSEServer"); +_LIT(KCategoryClient,"STSEClient"); + +inline void StorageServerPanic( const TDesC &aCategory, TStorageServerPanics aReason ) + { + User::Panic(aCategory, aReason); + } + +#endif // ATSTORAGESERVERCOMMON_H + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/server/group/atoolstorageserver.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/server/group/atoolstorageserver.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,50 @@ +/* +* 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: The .mmp file for the server side of AToolStorageServer +* +*/ + +#include <platform_paths.hrh> + +TARGET atoolstorageserver.exe +TARGETTYPE exe +UID 0x0 0x20012430 +CAPABILITY NONE + +SMPSAFE + +EPOCHEAPSIZE 0x10000 0x800000 + +SOURCEPATH ../src + +SOURCE atstorageserver.cpp +SOURCE atstorageserversession.cpp +SOURCE atmemoryentry.cpp +SOURCE atdynprocessinfo.cpp +SOURCE atdriveinfo.cpp +SOURCE atdllinfo.cpp + +USERINCLUDE ../inc +USERINCLUDE ../../inc +USERINCLUDE ../../../inc + +OS_LAYER_SYSTEMINCLUDE + +LIBRARY euser.lib +LIBRARY efsrv.lib +LIBRARY flogger.lib +LIBRARY charconv.lib +LIBRARY platformenv.lib + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/server/inc/atdllinfo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/server/inc/atdllinfo.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,96 @@ +/* +* 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: Declaration of the class TATDllInfo. +* +*/ + + +#ifndef ATDLLINFO_H +#define ATDLLINFO_H + +// INCLUDES +#include <u32std.h> + +/** +* Stores information of process loaded library +*/ +class TATDllInfo + { + + public: // Constructors + + /** + * C++ default constructor. + * @param aStartAddress Start address of the library + * @param aEndAddress The end address of the library + * @param aLoadTime The current time in a 64-bit form. + * @param aDllName The name of the library + */ + TATDllInfo( const TUint32 aStartAddress, const TUint32 aEndAddress, + const TInt64& aLoadTime, const TDesC8& aDllName ); + + public: // New functions + + /** + * Returs library start address + * @return TUint32 start address of the library + */ + TUint32 StartAddress(); + + /** + * Returns library end address + * @return TUint32 end address of the library + */ + TUint32 EndAddress(); + + /** + * Gets specific library name + * return TDes8 Name of the library + */ + TDes8& Name(); + + /** + * Returns library load time + * @return TInt64 library load time + */ + TInt64 LibraryLoadTime(); + + /** + * Checks if two objects of this class match based on the objects's + * saved library name. + * @param aFirst Library object + * @param aSecond Library object + * return TBool ETrue, if the two objects match. EFalse otherwise. + */ + static TBool Match( const TATDllInfo& aFirst, const TATDllInfo& aSecond ); + + public: // Member variables + + /* Start address of the loaded dll */ + const TUint32 iStartAddress; + + /* End address of the loaded dll */ + const TUint32 iEndAddress; + + /* Loaded dll name */ + TBuf8<KMaxLibraryName> iName; + + /** For storing the time when DLL has loaded. */ + const TInt64 iLoadTime; + }; + +#endif // ATDLLINFO_H + +// End of File + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/server/inc/atdriveinfo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/server/inc/atdriveinfo.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,67 @@ +/* +* 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: Declaration of the class TATDriveInfo. +* +*/ + + + +#ifndef ATDRIVEINFO_H +#define ATDRIVEINFO_H + +#include <f32file.h> + +/** +* Check what drives exists and creates file full path. +*/ +class TATDriveInfo + { + public: // Constructors + + /** + * C++ default constructor. + */ + TATDriveInfo(); + + public: // New functions + + /** + * Create the file full path. + * @param aPath Full path. + * @param aFileName Filename. + * @param aFs A handle to a file server. + * @return KErrNone or KErrAlreadyExists, if successful; + * Otherwise one of the other system wide error codes. + */ + static TInt CreatePath( TDes& aPath, const TDesC& aFileName, RFs& aFs ); + + private: // New functions + + /** + * Get the available drive character. + * @param aDrive The drive letter. + * @param aDriveNumber The drive number. + * @param aFs A handle to a file server. + * @param aDriveType Drive type. + * @return KErrNone, if successful; otherwise KErrNotFound + */ + static TInt GetDrive( TChar& aDrive, TInt& aDriveNumber, + RFs& aFs, const TUint aDriveType ); + + }; + +#endif // ATDRIVEINFO_H + +// End of File + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/server/inc/atdynprocessinfo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/server/inc/atdynprocessinfo.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,102 @@ +/* +* 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: Declaration of the class CATDynProcessInfo +* +*/ + + +#ifndef ATDYNPROCESSINFO_H +#define ATDYNPROCESSINFO_H + + +// INCLUDES +#include <e32base.h> +#include <analyzetool/atcommon.h> +#include "atdllinfo.h" + +// FORWARD DECLARATIONS +class CATStorageServerSession; + +// CLASS DECLARATION + +/** +* A class that can store different process related information. The information +* is associated to a particular process wiht a member telling a process ID. +* All the other information but the process ID and the pointer to this process's +* associated session object can be subject to change dynamically, run-time. +*/ +class CATDynProcessInfo : public CBase + { + public: // Constructor + + /** + * Constructor. + */ + CATDynProcessInfo(); + + /** + * Constructor. + * @param aProcessId A process ID. + * @param aSessionObject A pointer to this process's associated session object. + * @param aDlls The loaded DLLs of the associated process. + */ + CATDynProcessInfo( TUint aProcessId, + CATStorageServerSession* aSessionObject, + const RArray<TATDllInfo>& aDlls ); + + /** + * Constructor. + * @param aProcessId A process ID. + * @param aSessionObject A pointer to this process's associated session object. + */ + CATDynProcessInfo( TUint aProcessId, + CATStorageServerSession* aSessionObject ); + + /** + * Constructor. + * @param aProcessId A process ID. + */ + CATDynProcessInfo( TUint aProcessId ); + + /** + * Destructor + */ + virtual ~CATDynProcessInfo(); + + public: + + /** + * Compares two objects of this class based on the process ID. + * @param aFirst The first object of this class to be compared. + * @param aSecond The second object of this class to be compared. + * @return Zero, if the two objects are equal. A negative value, + * if the first object is less than the second. A positive value, + * if the first object is greater than the second. + */ + static TInt Compare( const CATDynProcessInfo& aFirst, + const CATDynProcessInfo& aSecond ); + + public: + + /** The ID of the process. */ + const TUint iProcessId; + + /** A pointer to the session object associated with this process. */ + CATStorageServerSession* const iSessionObject; + + /** The DLLs loaded by the associated process */ + RArray<TATDllInfo> iDlls; + }; + +#endif // ATDYNPROCESSINFO_H diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/server/inc/atmemoryentry.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/server/inc/atmemoryentry.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,98 @@ +/* +* 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: Declaration of the class CATMemoryEntry +* +*/ + + +#ifndef ATMEMORYENTRY_H +#define ATMEMORYENTRY_H + + +// INCLUDES +#include <e32base.h> + + +// CLASS DECLARATION + +/** +* A class for storing memory entries when the server is informed that memory has been +* allocated. The class stores the memory address of a new allocation and a pointer to +* a buffer including the current call stack. It also stores a time stamp, and the size +* of the allocation. +* The class has member methods for evaluating two different objects of this class +* with each other. In the construction the class takes a pointer to the call stack +* buffer, but it does not create the buffer itself. However, it is responsible for +* deleting the buffer in the destruction. +*/ +class CATMemoryEntry : public CBase + { + public: // Constructor + + /** + * Constructor. + * @param aMemAddress An address to allocated memory. + * @param aCallstackBuf A pointer to a buffer containing call stack's memory + * addresses. + * @param aAllocTime The current time in a 64-bit form. + * @param aAllocSize The size of an allocated memory chunk. + */ + CATMemoryEntry( TUint32 aMemAddress, const CBufFlat* aCallstackBuf, + const TInt64& aAllocTime, TInt aAllocSize ); + + /** + * Destructor + */ + virtual ~CATMemoryEntry(); + + public: + /** + * Compares two objects of this class based on the allocation time. + * @param aFirst The first object of this class to be compared. + * @param aSecond The second object of this class to be compared. + * @return Zero, if the two objects are equal. A negative value, + * if the first object is less than the second. A positive value, + * if the first object is greater than the second. + */ + static TInt Compare( const CATMemoryEntry& aFirst, + const CATMemoryEntry& aSecond ); + + /** + * Checks if two objects of this class match based on the objects's + * saved memory allocation addresses. + * @param aFirst The first object of this class to be evaluated. + * @param aSecond The second object of this class to be evaluated. + * @return ETrue, if the two objects match. EFalse otherwise. + */ + static TBool Match( const CATMemoryEntry& aFirst, + const CATMemoryEntry& aSecond ); + + public: + + /** For storing an address of a memory allocation. */ + const TUint32 iMemAddress; + + /** A pointer to an array for storing the current call stack. */ + const CBufFlat* const iCallstackBuf; + + /** For storing the time when an allocation has occured. */ + const TInt64 iAllocTime; + + /** For storing the size of an allocation. */ + const TInt iAllocSize; + + }; + + +#endif // ATMEMORYENTRY_H diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/server/inc/atstorageserver.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/server/inc/atstorageserver.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,218 @@ +/* +* 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: Declaration of the server side main class CATStorageServer +* +*/ + + +#ifndef ATSTORAGESERVER_H +#define ATSTORAGESERVER_H + + +// INCLUDES +#include <e32base.h> +#include <analyzetool/atcommon.h> +#include "atdllinfo.h" + +// CONSTANTS +// Constants for the server's version +const TUint KVersionNumberMaj = 0; +const TUint KVersionNumberMin = 1; +const TUint KVersionNumberBld = 1; + +// DATA TYPES + +// FORWARD DECLARATIONS +class TATProcessInfo; +class CATDynProcessInfo; +class CATStorageServerSession; + +// CLASS DECLARATION + +/** +* The main class of the Storage Server. +* When a client connects to the server, a new session object +* is created by an object of this class. If the server does not exist when +* connecting, a new process and an object of this class are created first. +*/ +class CATStorageServer : public CPolicyServer + { + + public: // Enumerations + + // opcodes used in message passing between client and server + enum TStorageServerReq + { + EProcessStarted, + EDllLoaded, + EDllUnloaded, + EMemoryAllocated, + EMemoryFreed, + EProcessEnded, + EMemoryCheck, + EGetProcesses, + EGetDlls, + ESetLoggingMode, + EGetLoggingMode, + ESubtestStart, + ESubtestStop, + ESubtestStart2, + ESubtestStop2, + EGetCurrentAllocs, + EGetMaxAllocs, + ECancelLogging, + EGetUdeb, + EGetLoggingFile, + EProcessUdeb, + EIsMemoryAdded, + EOutOfBounds + }; + + + public: // Constructors and destructor + + /** + * Two-phased constructor that can leave. + * @return A new instance of this class + */ + static CATStorageServer* NewL(); + + /** + * Two-phased constructor that can leave and leaves a pointer + * on the cleanup stack. + * @return A new instance of this class + */ + static CATStorageServer* NewLC(); + + /** + * Destructor + */ + virtual ~CATStorageServer(); + + public: // New functions + + + /** + * Creates a new server object and starts the server. + */ + static void RunServerL(); + + /** + * Increments the count of active sessions for this server. + */ + void IncSessionCount(); + + /** + * Decrements the count of active sessions for this server. + */ + void DecSessionCount(); + + /** + * Adds a new process into the server's arrays. + * @param aProcessName The name of the process to be added. + * @param aProcessId The ID of the process to be added. + * @param aSessionObject A pointer to the current process's associated session + * object. + * @param aStartTime The starting time of the process to be added. It represents + * time as a number of microseconds since midnight, January 1st, 0 AD nominal + * Gregorian. This is the representation used by, e.g., the TTime class. + * @return KErrNone, if the operation is successful; KErrAlreadyExists, if + * an attempt is being made to insert a duplicate process; otherwise one of + * the other system wide error codes. + */ + TInt AddProcessL( const TDesC8& aProcessName, + TUint aProcessId, + CATStorageServerSession* aSessionObject, + const TInt64& aStartTime ); + + /** + * Removes a process from the server's arrays. + * @param aProcessId The ID of the process to be removed. + * @return KErrNone, if successful; KErrNotFound, if a process with + * the specified process ID could not be found in the array. + */ + TInt RemoveProcessL( TUint aProcessId ); + + /** + * Adds a DLL for a given process to the dynamic process info array of this class. + * @param aProcessId The ID of the process that has loaded the DLL to be added. + * @param aDllInfo Information of the DLL. + * @return KErrNone, if successful; KErrNotFound, if a process with the given + * process ID could not be found; KErrAlreadyExists, if a DLL with the given + * name was already stored; otherwise one of the other system wide error codes. + */ + TInt AddDllL( TUint aProcessId, const TATDllInfo aDllInfo ); + + /** + * Removes a DLL associated with the given process from the dynamic process + * info array of this class. + * @param aProcessId The ID of the process that has loaded the DLL to be removed. + * @param aDllName The name of the DLL to be removed. + * @return KErrNone, if successful; KErrNotFound, if a process with + * the specified process ID could not be found, or if a DLL with the specified + * name could not be found. + */ + TInt RemoveDllL( TUint aProcessId, const TDesC8& aDllName ); + + /** + * Gives a reference to the process info array of this class. + * @return A reference to iProcesses array + */ + const RArray<TATProcessInfo>& ProcessInfoArray(); + + /** + * Gives a reference to the dynamic process info array of this class. + * @return A reference to iProcessesDyn array + */ + const RPointerArray<CATDynProcessInfo>& DynProcessInfoArray(); + + public: // Functions from base classes + + /** + * From CPolicyServer. + * Creates a new server-side session object. + * @param aVersion The version of this server + * @param aMessage A message from the client + * @return A pointer to a new session object. + */ + CSession2* NewSessionL( const TVersion& aVersion, const RMessage2& aMessage ) const; + + private: + + /** + * C++ default constructor. + * @param aPriority A priority for this active object + */ + CATStorageServer( TInt aPriority ); + + /** + * Symbian 2nd phase constructor. + */ + void ConstructL(); + + private: // Data + + /** The number of active sessions */ + TInt iSessionCount; + + /** An array for storing TATProcessInfo objects */ + RArray<TATProcessInfo> iProcesses; + + /** An array for storing CATDynProcessInfo pointers */ + RPointerArray<CATDynProcessInfo> iProcessesDyn; + }; + +#endif // ATSTORAGESERVER_H + +// End of File \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/server/inc/atstorageserversession.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/server/inc/atstorageserversession.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,588 @@ +/* +* 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: Declaration of the server side session class CATStorageServerSession +* +*/ + + +#ifndef ATSTORAGESERVERSESSION_H +#define ATSTORAGESERVERSESSION_H + + +// INCLUDES +#include <e32base.h> +#include <f32file.h> +#include <analyzetool/atcommon.h> + +// FORWARD DECLARATIONS +class CATStorageServer; +class CATMemoryEntry; + +// CLASS DECLARATIONS + +/** +* A class for storing memory addresses and sizes of allocations. +* Needed for giving allocation information for the configuration UI. +*/ +class TAllocInfo + { + public: + + // Constructor + TAllocInfo( TUint32 aMemAddress, TInt aAllocSize ); + + /** Address of a memory allocation. */ + const TUint32 iMemAddress; + + /** Size of the associated allocation. */ + const TInt iAllocSize; + }; + + +/** +* The session class for Storage Server. +* When the Storage Server client connects to the server, a new object of this +* class is constructed. So, for every client there is an associated object +* of this class. CATStorageServer forwards all client messages to their associated +* session objects. +*/ +class CATStorageServerSession : public CSession2 + { + public: // Enumerations + + public: // Constructors and destructor + + /** + * Two-phased constructor that can leave. + * @return A new instance of this class + */ + static CATStorageServerSession* NewL( CATStorageServer& aStorageServer ); + + /** + * Two-phased constructor that can leave and leaves a pointer + * on the cleanup stack. + * @return A new instance of this class + */ + static CATStorageServerSession* NewLC( CATStorageServer& aStorageServer ); + + /** + * Destructor + */ + virtual ~CATStorageServerSession(); + + public: // Functions from base classes + + /** + * Receives messages sent by a client. + * @param aMessage A message from a client + */ + virtual void ServiceL( const RMessage2& aMessage ); + + protected: // new functions + + /** + * Initializes this session for logging. This includes opening a logging file + * with a requested name. The method is to be called as the first method after + * connecting to the server. The method logs information on process starting into + * the just opened logging file. + * If a logging session is already ongoing, the method makes the client raise an + * STSEClient: 3 panic, and returns KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrCancel, if a logging session is already + * ongoing. Otherwise one of the other system wide error codes. + */ + TInt LogProcessStartedL( const RMessage2& aMessage ); + + /** + * Initializes this session for logging. The method is to be called as the first + * method after connecting to the server. The method logs information on process + * starting into debug channel. + * If a logging session is already ongoing, the method makes the client raise an + * STSEClient: 3 panic, and returns KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrCancel, if a logging session is already + * ongoing. Otherwise one of the other system wide error codes. + */ + TInt LogProcessStartTraceL( const RMessage2& aMessage ); + + /** + * Logs information on a DLL load into the opened file. + * If a logging session is not ongoing, the method makes the client raise an + * STSEClient: 3 panic, and returns KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrCancel, if a logging session is not + * currently ongoing; Otherwise one of the other system wide error codes. + */ + TInt LogDllLoadedL( const RMessage2& aMessage ); + + /** + * Logs information on a DLL load into debug channel. + * If a logging session is not ongoing, the method makes the client raise an + * STSEClient: 3 panic, and returns KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrCancel, if a logging session is not + * currently ongoing; Otherwise one of the other system wide error codes. + */ + TInt LogDllLoadTraceL( const RMessage2& aMessage ); + + /** + * Logs information on a DLL unload into the opened file. + * If a logging session is not ongoing, the method makes the client raise an + * STSEClient: 3 panic, and returns KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrCancel, if a logging session is not + * currently ongoing; Otherwise one of the other system wide error codes. + */ + TInt LogDllUnloadedL( const RMessage2& aMessage ); + + /** + * Logs information on a DLL unload into debug channel. + * If a logging session is not ongoing, the method makes the client raise an + * STSEClient: 3 panic, and returns KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrCancel, if a logging session is not + * currently ongoing; Otherwise one of the other system wide error codes. + */ + TInt LogDllUnloadTraceL( const RMessage2& aMessage ); + + /** + * Stores a memory allocation (memory address, current call stack, allocation + * time and allocation size) in an internal array. + * If a logging session is not ongoing, the method makes the client raise an + * STSEClient: 3 panic, and returns KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrCancel, if a logging session is not + * currently ongoing; KErrAlreadyExists, if an attempt is being made to allocate + * again an already allocated memory area; Otherwise one of the other system + * wide error codes. + */ + TInt LogMemoryAllocatedL( const RMessage2& aMessage ); + + /** + * Logs information on a memory allocation into debug channel. + * If a logging session is not ongoing, the method makes the client raise an + * STSEClient: 3 panic, and returns KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrCancel, if a logging session is not + * currently ongoing; KErrAlreadyExists, if an attempt is being made to allocate + * again an already allocated memory area; Otherwise one of the other system + * wide error codes. + */ + TInt LogMemoryAllocTraceL( const RMessage2& aMessage ); + + /** + * Check a memory allocation (memory address) from an internal array. + * If a logging session is not ongoing, the method makes the client raise an + * STSEClient: 3 panic, and returns KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @param aRemoveAlloc Boolean to enable removing the found address from allocations. + * @return KErrNone, if memory address found in array; + * KErrNotFound, if the requested memory address was not found. + */ + TInt IsMemoryAdded( const RMessage2& aMessage, const TBool aRemoveAlloc = EFalse ); + + /** + * Removes a memory allocation (memory address, current call stack, allocation + * time and allocation size) from an internal array. + * If a logging session is not ongoing, the method makes the client raise an + * STSEClient: 3 panic, and returns KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrCancel, if a logging session is not + * currently ongoing; KErrNotFound, if the requested memory address was not + * found; Otherwise one of the other system wide error codes. + */ + TInt LogMemoryFreedL( const RMessage2& aMessage ); + + /** + * Logs information on freeing of a memory allocatin into debug channel. + * If a logging session is not ongoing, the method makes the client raise an + * STSEClient: 3 panic, and returns KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrCancel, if a logging session is not + * currently ongoing; KErrNotFound, if the requested memory address was not + * found; Otherwise one of the other system wide error codes. + */ + TInt LogMemoryFreedTraceL( const RMessage2& aMessage ); + + /** + * Logs all non-released memory allocations into the opened file as memory leaks. + * Then the method logs a number of possibly occured handle leaks into the file. + * Next, the method logs information on process ending into the logging file. + * Finally, this method closes the logging file opened for the connected process, + * and ends the current logging session. However, this method does not end the + * actual client-server session. + * If a logging session is not ongoing, the method makes the client raise an + * STSEClient: 3 panic, and returns KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrCancel, if a logging session is not + * currently ongoing; KErrNotSupported if this method is called with a wrong + * process id from the client. Otherwise one of the other system wide error + * codes. + */ + TInt LogProcessEndedL( const RMessage2& aMessage ); + + /** + * Logs a number of possibly occured handle leaks into debug channel. Then, the method + * logs information on process ending into debug channel. The method also + * ends the current logging session. However, this method does not end the actual + * client-server session. + * If a logging session is not ongoing, the method makes the client raise an + * STSEClient: 3 panic, and returns KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrCancel, if a logging session is not + * currently ongoing; KErrNotSupported if this method is called with a wrong + * process id from the client. Otherwise one of the other system wide error + * codes. + */ + TInt LogProcessEndTraceL( const RMessage2& aMessage ); + + /** + * Checks if a given memory address can be found. + * If a logging session is not ongoing, the method makes the client raise an + * STSEClient: 3 panic, and returns KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @return When the system is logging into a file: the index of a found + * memory address, or KErrNotFound, if a matching memory address cannot + * be found. KErrNone, when the system is not logging into a file. + * KErrCancel, if a logging session is not currently ongoing. + */ + TInt CheckMemoryAddressL( const RMessage2& aMessage ); + + /** + * Checks if a given memory address can be found. + * If a logging session is not ongoing, the method makes the client raise an + * STSEClient: 3 panic, and returns KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @return When the system is logging into a file: the index of a found + * memory address, or KErrNotFound, if a matching memory address cannot + * be found. KErrNone, when the system is not logging into a file. + * KErrCancel, if a logging session is not currently ongoing. + */ + TInt CheckMemoryAddressTrace( const RMessage2& aMessage ); + + /** + * Gets all the processes currently logging with AnalyzeTool + * @param aMessage A message that includes parameters sent by the client. + * On return a buffer including all the currently logging processes is written + * into this message. + * @return KErrNone, if successful; otherwise one of the other system wide error + * codes. + */ + TInt GetProcessesL( const RMessage2& aMessage ); + + /** + * Gets all the DLLs loaded by the process determined by the parameters. + * @param aMessage A message that includes parameters sent by the client. + * A buffer including all the DLLs loaded by the requested process is + * written into this message. + * @return KErrNone, if successful; KErrNotFound, if the requested process was + * not found; otherwise one of the other system wide error codes. + */ + TInt GetDllsL( const RMessage2& aMessage ); + + /** + * Gets the logging mode of the process determined by the parameters. + * @param aMessage A message that includes parameters sent by the client. + * On return, the logging mode is written into this message. + * @return KErrNone, if successful; KErrNotFound, if the requested process was + * not found; otherwise one of the other system wide error codes. + */ + TInt GetLoggingModeL( const RMessage2& aMessage ); + + /** + * Starts a sub test for the given process. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrNotFound, if the requested process is not + * found; KErrNotSupported, if the requested process does not have a logging + * session ongoing or its logging mode is not EATLogToTrace; Otherwise one of the + * other system wide error codes. + */ + TInt StartSubtestL( const RMessage2& aMessage ); + + /** + * Stops a sub test for the given process. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrNotFound, if the requested process is not + * found; KErrNotSupported, if the requested process does not have a logging + * session ongoing or its logging mode is not EATLogToTrace; Otherwise one of the + * other system wide error codes. + */ + TInt StopSubtestL( const RMessage2& aMessage ); + + /** + * Starts a sub test for the calling process. Does not need a PID from the client. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrNotSupported, if the calling process + * does not have a logging session ongoing or its logging mode is not + * EATLogToTrace; Otherwise one of the other system wide error codes. + */ + TInt StartSubtest2L( const RMessage2& aMessage ); + + /** + * Stops a sub test for the calling process. Does not need a PID from the client. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrNotSupported, if the calling process + * does not have a logging session ongoing or its logging mode is not + * EATLogToTrace; Otherwise one of the other system wide error codes. + */ + TInt StopSubtest2( const RMessage2& aMessage ); + + /** + * Gets the number and total size of the current memory chunks allocated by the + * requested process. + * @param aMessage A message that includes parameters sent by the client. The + * requested information is written into this message. + * @return KErrNone, if successful; KErrNotFound, if the requested process was + * not found; otherwise one of the other system wide error codes. + */ + TInt GetCurrentAllocsL( const RMessage2& aMessage ); + + /** + * Gets the maximum number of memory chunks and the maximum amount of memory + * allocated by the requested process during the test run. + * @param aMessage A message that includes parameters sent by the client. The + * requested information is written into this message. + * @return KErrNone, if successful; KErrNotFound, if the requested process was + * not found; otherwise one of the other system wide error codes. + */ + TInt GetMaxAllocsL( const RMessage2& aMessage ); + + /** + * Cancels logging for the requested process. After logging of a given process + * has been cancelled, the session associated with that process will not be + * usable anymore. If a process wants to start logging again, it needs to close + * the handle and open it again in order to create a new session. Until then, any + * of the server's methods that can be called by the client will return + * KErrCancel. + * @param aMessage A message that includes parameters sent by the client. + * @return KErrNone, if successful; KErrNotFound, if the requested process was + * not found; otherwise one of the other system wide error codes. + */ + TInt CancelLoggingL( const RMessage2& aMessage ); + + /** + * Gets the logging file of the process determined by the parameters. + * @param aMessage A message that includes parameters sent by the client. + * On return, the logging file is written into this message. + * @return KErrNone, if successful; KErrNotFound, if the requested process was + * not found; otherwise one of the other system wide error codes. + */ + TInt GetLoggingFileL( const RMessage2& aMessage ); + + /** + * Gets the mode of the process determined by the parameters. + * @param aMessage A message that includes parameters sent by the client. + * On return, the logging file is written into this message. + * @return KErrNone, if successful; KErrNotFound, if the requested process was + * not found; otherwise one of the other system wide error codes. + */ + TInt GetUdebL( const RMessage2& aMessage ); + + /** + * Sets the mode of the process determined by the parameters. + * @param aMessage A message that includes parameters sent by the client. + */ + void SetUdeb( const RMessage2& aMessage ); + + private: // New functions for internal use + + /** + * Releases the resources reserved by this object, and before closing the logging + * file and file server session, the method logs information on the occured error + * into the logging file. + * @param aError The error code to be logged. + */ + void HandleError( TInt aError ); + + /** + * Releases the resources reserved by this object, and logs information on the + * occured error into debug channel. + * @param aError The error code to be logged. + */ + void HandleErrorTrace( TInt aError ); + + /** + * Opens a file server session and a file with the name specified. + * @param aFileName The name of the file into which to log. + * @param aProcessName Current process name. + * @return KErrNone, if successful; otherwise one of the other system wide + * error codes. + */ + TInt OpenFsAndFile( const TDesC& aFileName, const TDesC8& aProcessName ); + + /** + * Method is used to parse file name extension. + * @param aFileName The name of the file into which to log. + * @param aExtension Parsed file extension. + */ + void ParseExtension( TDes& aFileName, TDes& aExtension ); + + /** + * Called internally when need generate new file name. + * @param aFileName The name of the file into which to log. + * @param aProcessName Current process name. + */ + void GenerateNewFileName( TDes& aFileName, const TDesC8& aProcessName ); + + /** + * Method is used to check that file exists and is valid. + * @param aFileName The name of the file into which to log. + */ + void CheckIfFileAlreadyExist( const TDes& aFileName ); + + /** + * Method is used to check file version. + * @param aFileName The name of the file into which to log. + */ + void CheckFileVersion( const TDes& aFileName ); + + /** + * Closes the handles to the file server session and to the file (if currently open). + */ + void CloseFsAndFile(); + + /** + * Writes the memory leaks stored in the iLeakArray member array into the + * logging file opened for the current logging session. If the method is + * called in a wrong program state (logging session is not ongoing, or the + * logging mode is not EATLogToFile), STSEClient: 4, and STSEServer: 4 + * panics are raised. + * @param aMessage The current message from the client. + * @return KErrNone, if successful; otherwise one of the other system wide + * error codes. + */ + TInt PrintLeaksL( const RMessage2& aMessage ); + + /** + * Sets the server's mode of operation. The operation mode is determined with + * an enumeration value, which is received from the client. If the method is + * called in a wrong program state (logging session is ongoing), STSEClient: 4, + * and STSEServer: 4 panics are raised. + * @param aMessage The current message from the client. + */ + void SetLogOption( const RMessage2& aMessage ); + + /** + * Logs the given descriptor through debug channel. + * @param aLogString The descriptor to be logged. + * @return KErrNone, if successful; KErrNotSupported, if a logging session is not + * ongoing, or the logging mode is not EATLogToTrace; + */ + TInt LogThroughTrace( const TDesC& aLogString ) const; + + /** + * Gives a reference to the allocation info array of this class. + * @return A reference to iAllocInfoArray array + */ + RArray<TAllocInfo>& AllocInfoArray(); + + /** + * Creates a panic in the associated client's code. + * @param aPanic The panic code + * @param aMessage The message associated with this panic. + */ + void PanicClient( TInt aPanic, const RMessage2& aMessage ); + + /** + * Logs the abnormal end to the debug channel (If logging mode is EATLogToTrace) + * and to the file(If logging mode is EATLogToFile). + */ + void LogAbnormalEnd(); + + /** + * Get the current universal time. + * @return Time + */ + TInt64 GetTime(); + + private: // Constructors + + /** + * C++ default constructor. + */ + CATStorageServerSession( CATStorageServer& aStorageServer ); + + /** + * Symbian 2nd phase constructor. + */ + void ConstructL(); + + private: // Data + + /** A reference to the CATStorageServer object that has created this session */ + CATStorageServer& iStorageServer; + + /** A handle to a file server */ + RFs iFileServer; + + /** A handle to a file */ + RFile iFile; + + /** A member variable for storing results of server function calls. */ + TInt iError; + + /** An object for getting time stamps */ + TTime iTime; + + /** + * An array for storing CATMemoryEntry pointers. Used when logging + * to an S60 file. + */ + RPointerArray<CATMemoryEntry> iLeakArray; + + /** + * An array for storing TAllocInfo objects. Used for keeping records on memory + * allocations and their sizes. + */ + RArray<TAllocInfo> iAllocInfoArray; + + /** The ID of the process associated with this session. */ + TUint iProcessId; + + /** + * A boolean telling whether this session has been initialized for logging + * ( whether the client's LogProcessStarted() method has been called ) or not. + */ + TBool iLoggingOngoing; + + /** + * A variable telling the number of microseconds from January 1st, 0 AD + * nominal Gregorian to January 1st, 1970 AD nominal Gregorian. + */ + TInt64 iMicroSecondsAt1970; + + /** + * An enumeration that tells the current operation mode of the Storage Server. + */ + TATLogOption iLogOption; + + /** The total size of all the current allocations of this process */ + TUint32 iCurAllocSize; + + /** The maximum number of allocations of this process */ + TUint32 iMaxAllocs; + + /** The maximum total size of allocations of this process */ + TUint32 iMaxAllocSize; + + /** The logging file of this process */ + TBuf8<KMaxFileName> iLogFile; + + /** The mode of the session. Default is 1 = UDEB */ + TUint32 iIsUdeb; + }; + +#endif // ATSTORAGESERVERSESSION_H + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/server/src/atdllinfo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/server/src/atdllinfo.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,102 @@ +/* +* 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 TATDllInfo. +* +*/ + +// INCLUDE FILES +#include "atdllinfo.h" +#include "atlog.h" + +// ----------------------------------------------------------------------------- +// TATDllInfo::TATDllInfo +// C++ default constructor. +// ----------------------------------------------------------------------------- +// +TATDllInfo::TATDllInfo( const TUint32 aStartAddress, const TUint32 aEndAddress, + const TInt64& aLoadTime, const TDesC8& aDllName ) + : iStartAddress( aStartAddress ), iEndAddress( aEndAddress ), + iLoadTime( aLoadTime ) + { + LOGSTR3( "STSE TATDllInfo::TATDllInfo() %x - %x", iStartAddress, iEndAddress ); + + iName.Copy( aDllName ); + } + +// ----------------------------------------------------------------------------- +// TATDllInfo::StartAddress +// Returns library start address +// ----------------------------------------------------------------------------- +// +TUint32 TATDllInfo::StartAddress() + { + LOGSTR2( "STSE TATDllInfo::StartAddress( %x )", iStartAddress ); + + return iStartAddress; + } + +// ----------------------------------------------------------------------------- +// TATDllInfo::EndAddress +// Returns library end address +// ----------------------------------------------------------------------------- +// +TUint32 TATDllInfo::EndAddress() + { + LOGSTR2( "STSE TATDllInfo::EndAddress( %x )", iEndAddress ); + + return iEndAddress; + } + +// ----------------------------------------------------------------------------- +// TATDllInfo::Name +// Gets specific library name +// ----------------------------------------------------------------------------- +// +TDes8& TATDllInfo::Name() + { + LOGSTR1( "STSE TATDllInfo::Name()" ); + + return iName; + } + +// ----------------------------------------------------------------------------- +// TATDllInfo::LibraryLoadTime +// Returns library load time +// ----------------------------------------------------------------------------- +// +TInt64 TATDllInfo::LibraryLoadTime() + { + LOGSTR1( "STSE TATDllInfo::LibraryLoadTime()" ); + + return iLoadTime; + } + +// ----------------------------------------------------------------------------- +// TATDllInfo::Match +// Checks if two objects of this class match based on the objects's +// saved library name. +// ----------------------------------------------------------------------------- +// +TBool TATDllInfo::Match( const TATDllInfo& aFirst, const TATDllInfo& aSecond ) + { + LOGSTR1( "STSE TATDllInfo::Match()" ); + + if ( aFirst.iName.Compare( aSecond.iName ) == 0 ) + { + return ETrue; + } + return EFalse; + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/server/src/atdriveinfo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/server/src/atdriveinfo.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,188 @@ +/* +* 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 TATDriveInfo. +* +*/ + + + +// INCLUDE FILES +#include <f32file.h> +#include <driveinfo.h> +#include "atdriveinfo.h" +#include "atstorageservercommon.h" +#include "atlog.h" + +// ----------------------------------------------------------------------------- +// TATDriveInfo::TATDriveInfo +// C++ default constructor. +// ----------------------------------------------------------------------------- +// +TATDriveInfo::TATDriveInfo() + { + LOGSTR1( "TATD TATDriveInfo::TATDriveInfo()" ); + } + +// ----------------------------------------------------------------------------- +// TATDriveInfo::CreatePath() +// ----------------------------------------------------------------------------- +// +TInt TATDriveInfo::CreatePath( TDes& aPath, + const TDesC& aFileName, RFs& aFs ) + { + LOGSTR1( "TATD TInt TATDriveInfo::CreatePath()" ); + + // Drive letter + TChar driveLetter; + // Drive number + TInt dNumber( EDriveZ ); + TBool found( EFalse ); + // Drive type + TUint driveType( KDriveAttRemovable ); + TInt err( KErrNotFound ); + + while ( !found ) + { + // Get drive letter + if ( GetDrive( driveLetter, dNumber, aFs, driveType ) == KErrNotFound ) + { + if ( driveType == KDriveAttInternal ) + { + return KErrNotFound; + } + driveType = KDriveAttInternal; + dNumber = EDriveZ; + } + else + { + // Create path + aPath.Delete( 0, aPath.MaxLength() ); + aPath.Append( driveLetter ); + + + #ifdef __WINS__ + // For emulator the data file is stored to different location + aPath.Append( KATDataFilePath ); + #else + TDriveInfo driveInfo; + aFs.Drive( driveInfo, dNumber ); + // The drive is removable( memory card ) so we can log inside of root folder + if ( driveInfo.iDriveAtt & KDriveAttRemovable ) + { + aPath.Append( KATDataFilePath ); + } + // The drive is internal user can only access data folder so log into that + else + { + aPath.Append( KATDataFilePath2 ); + } + #endif + + // Make a directory for AToolStorageServer's logging data file + err = aFs.MkDir( aPath ); + LOGSTR2( "STSE > aFs.MkDir err = %i", err ); + + if ( !err || err == KErrAlreadyExists ) + { + if ( aFileName.Length() != 0 && + ( ( aPath.MaxLength() - aPath.Length() ) > aFileName.Length() ) ) + { + aPath.Append( aFileName ); + } + found = ETrue; + } + } + } + return err; + } + +// ----------------------------------------------------------------------------- +// TATDriveInfo::GetDrive() +// ----------------------------------------------------------------------------- +// +TInt TATDriveInfo::GetDrive( TChar& aDrive, TInt& aDriveNumber, RFs& aFs, + const TUint aDriveType ) + { + LOGSTR1( "TATD TInt TATDriveInfo::GetDrive()" ); + + // Contains drive information. + TDriveInfo driveInfo; + + for ( TInt i = aDriveNumber; i >= (TInt)EDriveA; i-- ) + { + // Gets information about a drive and the medium mounted on it. + // If error occured then skip to next drive. + if ( aFs.Drive( driveInfo, i ) != KErrNone ) + continue; + + // Test whether drive is available. If not, skip to next drive. + if ( driveInfo.iDriveAtt & KDriveAbsent || i == (TInt)EDriveD || + driveInfo.iDriveAtt & KDriveAttRom || + driveInfo.iMediaAtt & KMediaAttWriteProtected || + driveInfo.iDriveAtt & KDriveFileSysROFS ) + continue; + + // Maps a drive number to the corresponding character. + if ( aFs.DriveToChar( i, aDrive ) != KErrNone ) + continue; + + if ( driveInfo.iDriveAtt & aDriveType && + driveInfo.iType != EMediaNotPresent && + driveInfo.iType != EMediaCdRom ) + { + TUint status( 0 ); + + switch ( aDriveType ) + { + case KDriveAttRemovable: + { + // Get the drive status of the default removable mass storage. + if ( DriveInfo::GetDriveStatus( aFs, i, status ) == KErrNone ) + { + // To indicate that the drive is physically removable. + if ( status & DriveInfo::EDriveRemovable && + !( status & DriveInfo::EDriveCorrupt ) ) + { + aDriveNumber = --i; + return KErrNone; + } + } + } + break; + case KDriveAttInternal: + { + // Get the drive status of the default removable mass storage. + if ( DriveInfo::GetDriveStatus( aFs, i, status ) == KErrNone ) + { + // To indicate that the drive is internal and + // cannot be physically removed. + if ( status & DriveInfo::EDriveInternal && + !( status & DriveInfo::EDriveExternallyMountable ) ) + { + aDriveNumber = --i; + return KErrNone; + } + } + } + break; + + default: + break; + } + } + } + return KErrNotFound; + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/server/src/atdynprocessinfo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/server/src/atdynprocessinfo.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,94 @@ +/* +* 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 CATDynProcessInfo +* +*/ + + +// INCLUDE FILES +#include "atdynprocessinfo.h" + +// ============================ MEMBER FUNCTIONS =============================== + + +// ----------------------------------------------------------------------------- +// CATDynProcessInfo::CATDynProcessInfo +// ----------------------------------------------------------------------------- +// +CATDynProcessInfo::CATDynProcessInfo() : + iProcessId( KNullProcessId ), + iSessionObject( NULL ) + { + } + +// ----------------------------------------------------------------------------- +// CATDynProcessInfo::CATDynProcessInfo +// ----------------------------------------------------------------------------- +// +CATDynProcessInfo::CATDynProcessInfo( TUint aProcessId, + CATStorageServerSession* aSessionObject, + const RArray<TATDllInfo>& aDlls ) : + iProcessId( aProcessId ), + iSessionObject( aSessionObject ), + iDlls( aDlls ) + { + } + +// ----------------------------------------------------------------------------- +// CATDynProcessInfo::CATDynProcessInfo +// ----------------------------------------------------------------------------- +// +CATDynProcessInfo::CATDynProcessInfo( TUint aProcessId, + CATStorageServerSession* aSessionObject ) : + iProcessId( aProcessId ), iSessionObject( aSessionObject ) + { + } + +// ----------------------------------------------------------------------------- +// CATDynProcessInfo::CATDynProcessInfo +// ----------------------------------------------------------------------------- +// +CATDynProcessInfo::CATDynProcessInfo( TUint aProcessId ) : + iProcessId( aProcessId ), iSessionObject( NULL ) + { + } + +// Destructor +CATDynProcessInfo::~CATDynProcessInfo() + { + iDlls.Close(); + } + +// ----------------------------------------------------------------------------- +// CATDynProcessInfo::Compare +// ----------------------------------------------------------------------------- +// +TInt CATDynProcessInfo::Compare( const CATDynProcessInfo& aFirst, + const CATDynProcessInfo& aSecond ) + { + if ( aFirst.iProcessId < aSecond.iProcessId ) + { + return -1; + } + + if ( aFirst.iProcessId > aSecond.iProcessId ) + { + return 1; + } + + // else + return 0; + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/server/src/atmemoryentry.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/server/src/atmemoryentry.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,84 @@ +/* +* 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 CATMemoryEntry +* +*/ + + + +// INCLUDE FILES +#include "atmemoryentry.h" + + +// ============================ MEMBER FUNCTIONS =============================== + + +// ----------------------------------------------------------------------------- +// CATMemoryEntry::CATMemoryEntry +// C++ default constructor. +// ----------------------------------------------------------------------------- +// +CATMemoryEntry::CATMemoryEntry( TUint32 aMemAddress, + const CBufFlat* aCallstackBuf, + const TInt64& aAllocTime, + TInt aAllocSize ) : + iMemAddress( aMemAddress ), + iCallstackBuf( aCallstackBuf ), + iAllocTime( aAllocTime ), + iAllocSize( aAllocSize ) + { + } + +// Destructor +CATMemoryEntry::~CATMemoryEntry() + { + delete const_cast<CBufFlat*>( iCallstackBuf ); + } + +// ----------------------------------------------------------------------------- +// CATMemoryEntry::Compare +// ----------------------------------------------------------------------------- +// +TInt CATMemoryEntry::Compare( const CATMemoryEntry& aFirst, const CATMemoryEntry& aSecond ) + { + if ( aFirst.iAllocTime < aSecond.iAllocTime ) + { + return -1; + } + + if ( aFirst.iAllocTime > aSecond.iAllocTime ) + { + return 1; + } + + // else + return 0; + } + +// ----------------------------------------------------------------------------- +// CATMemoryEntry::Match +// ----------------------------------------------------------------------------- +// +TBool CATMemoryEntry::Match( const CATMemoryEntry& aFirst, const CATMemoryEntry& aSecond ) + { + if ( aFirst.iMemAddress == aSecond.iMemAddress ) + { + return ETrue; + } + + // else + return EFalse; + } + + diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/server/src/atstorageserver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/server/src/atstorageserver.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,452 @@ +/* +* 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 CATStorageServer. Includes also the +* entry point of the atoolstorageserver.exe executable. +* +*/ + + + + +// INCLUDE FILES + +#include "atstorageserver.h" +#include "atstorageserversession.h" +#include "atstorageservercommon.h" +#include "atlog.h" +#include "atdynprocessinfo.h" + + +// CONSTANTS + + +// The amount of different ranges of requests specified for this policy server. +// In a policy server, different actions can be determined for different ranges +// of requests. +const TUint8 KAmountOfRanges = 2; + + +const TInt ranges[KAmountOfRanges] = + { + CATStorageServer::EProcessStarted, + CATStorageServer::EOutOfBounds + }; + + +const TUint8 actionForRange[ KAmountOfRanges ] = + { 0, CPolicyServer::ENotSupported }; + + +const CPolicyServer::TPolicyElement elements[] = + { + + { _INIT_SECURITY_POLICY_C1( ECapability_None ), + CPolicyServer::EFailClient } + + }; + + +const CPolicyServer::TPolicy policy = + { + CPolicyServer::EAlwaysPass, // On connect + KAmountOfRanges, // Range count + ranges, + actionForRange, + elements, + }; + + + +// ENTRY POINT + +TInt E32Main() + { + LOGSTR1( "STSE TInt E32Main() in ATStorageServer.cpp" ); + + __UHEAP_MARK; + + // Create a cleanup stack + CTrapCleanup* cleanup = CTrapCleanup::New(); + + TInt errorCode( KErrNoMemory ); + + // If there was enough memory to create a cleanup stack, + // create and start the server. + if( cleanup ) + { + // If RunServerL() doesn't leave, errorCode will be set to KErrNone + TRAP( errorCode, CATStorageServer::RunServerL() ); + delete cleanup; + } + + // Signal the client that server creation failed, if a leave occured during + // the call to 'RunServerL()' function + if( errorCode != KErrNone ) + { + RProcess::Rendezvous( errorCode ); + } + + __UHEAP_MARKEND; + + return errorCode; + + } + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CATStorageServer::CATStorageServer +// C++ default constructor can NOT contain any code that +// might leave. +// ----------------------------------------------------------------------------- +// +CATStorageServer::CATStorageServer( TInt aPriority ) : + CPolicyServer( aPriority, policy, ESharableSessions ), + iSessionCount( 0 ) + { + LOGSTR1( "STSE CATStorageServer::CATStorageServer()" ); + } + +// ----------------------------------------------------------------------------- +// CATStorageServer::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CATStorageServer::ConstructL() + { + } + +// ----------------------------------------------------------------------------- +// CATStorageServer::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CATStorageServer* CATStorageServer::NewL() + { + CATStorageServer* self = NewLC(); + CleanupStack::Pop( self ); + + return self; + } + +// ----------------------------------------------------------------------------- +// CATStorageServer::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CATStorageServer* CATStorageServer::NewLC() + { + CATStorageServer* self = new ( ELeave ) CATStorageServer( EPriorityStandard ); + CleanupStack::PushL( self ); + self->ConstructL(); + self->StartL( KStorageServerName ); + return self; + } + +// Destructor +CATStorageServer::~CATStorageServer() + { + LOGSTR1( "STSE CATStorageServer::~CATStorageServer()" ); + + iProcesses.Close(); + iProcessesDyn.ResetAndDestroy(); + iProcessesDyn.Close(); + } + +// ----------------------------------------------------------------------------- +// CATStorageServer::NewSessionL +// Create a new server session. +// ----------------------------------------------------------------------------- +// +CSession2* CATStorageServer::NewSessionL( + const TVersion &aVersion, + const RMessage2& /*aMessage*/ ) const + { + LOGSTR1( "STSE CSession2* CATStorageServer::NewSessionL()" ); + + // The server's version + TVersion version( KVersionNumberMaj, KVersionNumberMin, + KVersionNumberBld ); + + // Check this is a high enough version of the server + if ( !User::QueryVersionSupported(version, aVersion) ) + { + User::Leave( KErrNotSupported ); + } + + // Construct and return a new session object + return CATStorageServerSession::NewL( const_cast<CATStorageServer&>(*this) ); + } + +// ----------------------------------------------------------------------------- +// CATStorageServer::RunServerL +// Create active scheduler and a server object +// ----------------------------------------------------------------------------- +// +void CATStorageServer::RunServerL() + { + LOGSTR1( "STSE void CATStorageServer::RunServerL()" ); + + // Create and install an active scheduler + CActiveScheduler* activeSched = new (ELeave) CActiveScheduler; + CleanupStack::PushL( activeSched ); + CActiveScheduler::Install( activeSched ); + + // Create server + CATStorageServer::NewLC(); + + // The initialization performed alright, signal the client + RProcess::Rendezvous( KErrNone ); + + // Start the active scheduler + CActiveScheduler::Start(); + + // Remove the server and active scheduler from the cleanup stack + CleanupStack::PopAndDestroy( 2, activeSched ); + } + +// ----------------------------------------------------------------------------- +// CATStorageServer::IncSessionCount +// Increments the count of active sessions for this server. +// ----------------------------------------------------------------------------- +// +void CATStorageServer::IncSessionCount() + { + LOGSTR1( "STSE void CATStorageServer::IncSessionCount()" ); + + iSessionCount++; + } + +// ----------------------------------------------------------------------------- +// CATStorageServer::DecSessionCount +// Decrements the count of active sessions for this server. +// ----------------------------------------------------------------------------- +// +void CATStorageServer::DecSessionCount() + { + LOGSTR1( "STSE void CATStorageServer::DecSessionCount()" ); + + iSessionCount--; + + // Cancels all outstanding messages and stops the active scheduler, + // if there are no other sessions open at the moment + if ( iSessionCount <= 0 ) + { + this->Cancel(); + CActiveScheduler::Stop(); + } + } + +// ----------------------------------------------------------------------------- +// CATStorageServer::AddProcessL +// ----------------------------------------------------------------------------- +// +TInt CATStorageServer::AddProcessL( const TDesC8& aProcessName, + TUint aProcessId, + CATStorageServerSession* aSessionObject, + const TInt64& aStartTime ) + { + LOGSTR1( "STSE TInt CATStorageServer::AddProcessL()" ); + + TInt error( KErrNone ); + TATProcessInfo processInfo; + + processInfo.iProcessId = aProcessId; + processInfo.iProcessName.Copy( aProcessName ); + processInfo.iStartTime = aStartTime; + + // Insert the static process info into the iProcesses array + error = iProcesses.InsertInUnsignedKeyOrder( processInfo ); + + // Return if an error occured + if ( error != KErrNone) + { + return error; + } + + // Construct a CATDynProcessInfo object with the given process ID and logging mode + CATDynProcessInfo* dynProcessInfo = + new (ELeave) CATDynProcessInfo( aProcessId, + aSessionObject ); + + // Insert the dynamic process info into the iProcessesDyn array + TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare ); + error = iProcessesDyn.InsertInOrder( dynProcessInfo, order ); + + return error; + } + +// ----------------------------------------------------------------------------- +// CATStorageServer::RemoveProcessL +// ----------------------------------------------------------------------------- +// +TInt CATStorageServer::RemoveProcessL( TUint aProcessId ) + { + LOGSTR1( "STSE TInt CATStorageServer::RemoveProcessL()" ); + + TATProcessInfo processInfo; + processInfo.iProcessId = aProcessId; + + TInt index = iProcesses.FindInUnsignedKeyOrder( processInfo ); + + // Return, if a process with the requested process ID was not found + if ( index == KErrNotFound ) + { + return index; + } + + // Remove the TATProcessInfo object at "index" from the array + iProcesses.Remove( index ); + + // Now, start removing the associated dynamic process info object + + // Construct a CATDynProcessInfo object with the given process ID + CATDynProcessInfo* dynProcessInfo = + new (ELeave) CATDynProcessInfo( aProcessId ); + + // Find the index of a CATDynProcessInfo object with the given ID in the array + TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare ); + index = iProcessesDyn.FindInOrder( dynProcessInfo, order ); + delete dynProcessInfo; + dynProcessInfo = NULL; + + // Return, if a process with the requested process ID was not found + if ( index == KErrNotFound ) + { + return index; + } + + // Otherwise, delete the object and remove the pointer at "index" + delete iProcessesDyn[index]; + iProcessesDyn.Remove( index ); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CATStorageServer::AddDllL +// ----------------------------------------------------------------------------- +// +TInt CATStorageServer::AddDllL( TUint aProcessId, + const TATDllInfo aDllInfo ) + { + LOGSTR1( "STSE TInt CATStorageServer::AddDllL()" ); + + // Construct a CATDynProcessInfo object with the given process ID + CATDynProcessInfo* dynProcessInfo = + new (ELeave) CATDynProcessInfo( aProcessId ); + + // Find out if a process with this ID can be found in the dynamic process array + TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare ); + TInt index = iProcessesDyn.FindInOrder( dynProcessInfo, order ); + delete dynProcessInfo; + dynProcessInfo = NULL; + + // Return, if a process with the requested process ID was not found + if ( index == KErrNotFound ) + { + return index; + } + + // If we are here, the wanted process was found at index => append a DLL for it + dynProcessInfo = iProcessesDyn[index]; + + // Get the DLL array from this dynamic process info object + RArray<TATDllInfo>& dllArray = dynProcessInfo->iDlls; + + // Let's see if the DLL to be added already exists + TIdentityRelation<TATDllInfo> matcher( TATDllInfo::Match ); + index = dllArray.Find( aDllInfo, matcher ); + + // If so, return KErrAlreadyExists + if ( index != KErrNotFound ) + { + return KErrAlreadyExists; + } + + // Otherwise append this DLL to the array and return + return dynProcessInfo->iDlls.Append( aDllInfo ); + } + +// ----------------------------------------------------------------------------- +// CATStorageServer::RemoveDllL +// ----------------------------------------------------------------------------- +// +TInt CATStorageServer::RemoveDllL( TUint aProcessId, + const TDesC8& aDllName ) + { + LOGSTR1( "STSE TInt CATStorageServer::RemoveDllL()" ); + + // Construct a CATDynProcessInfo object with the given process ID + CATDynProcessInfo* dynProcessInfo = + new (ELeave) CATDynProcessInfo( aProcessId ); + + // Find out if a process with this ID can be found in the dynamic process array + TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare ); + TInt index = iProcessesDyn.FindInOrder( dynProcessInfo, order ); + delete dynProcessInfo; + dynProcessInfo = NULL; + + // Return, if a process with the requested process ID was not found + if ( index == KErrNotFound ) + { + return index; + } + + // If we are here, the wanted process was found at index + dynProcessInfo = iProcessesDyn[index]; + + // Get the DLL array from this dynamic process info object + RArray<TATDllInfo>& dllArray = dynProcessInfo->iDlls; + + // Try to find wanted DLL + TIdentityRelation<TATDllInfo> matcher( TATDllInfo::Match ); + index = dllArray.Find( TATDllInfo( 0, 0, 0, aDllName ), matcher ); + + // Return, if a process with the requested process ID was not found + if ( index == KErrNotFound ) + { + return index; + } + + // Otherwise remove the found DLL at "index" + dllArray.Remove( index ); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CATStorageServer::ProcessInfoArray +// ----------------------------------------------------------------------------- +// +const RArray<TATProcessInfo>& CATStorageServer::ProcessInfoArray() + { + LOGSTR1( "STSE RArray<TATProcessInfo>& CATStorageServer::ProcessInfoArray()" ); + + return iProcesses; + } + +// ----------------------------------------------------------------------------- +// CATStorageServer::DynProcessInfoArray +// ----------------------------------------------------------------------------- +// +const RPointerArray<CATDynProcessInfo>& CATStorageServer::DynProcessInfoArray() + { + LOGSTR1( "STSE RPointerArray<CATDynProcessInfo>& CATStorageServer::DynProcessInfoArray()" ); + + return iProcessesDyn; + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/server/src/atstorageserversession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/server/src/atstorageserversession.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,3397 @@ +/* +* 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 and constants for the class CATStorageServerSession +* +*/ + + + +// INCLUDE FILES +#include <utf.h> +#include <analyzetool/analyzetooltraceconstants.h> +#include "atstorageserversession.h" +#include "atstorageserver.h" +#include "atstorageservercommon.h" +#include "atmemoryentry.h" +#include "atlog.h" +#include "atdynprocessinfo.h" +#include "atdriveinfo.h" + +// CONSTANTS + +// New file name start and end index. +const TInt KNameIndexStart = 1; +const TInt KNameIndexEnd = 100; + +// ==================== MEMBER FUNCTIONS for TAllocInfo ======================== + +// ----------------------------------------------------------------------------- +// TAllocInfo::TAllocInfo +// Implementation for the constructor of the class TAllocInfo +// ----------------------------------------------------------------------------- +// +TAllocInfo::TAllocInfo( TUint32 aMemAddress, TInt aAllocSize ) : + iMemAddress( aMemAddress ), + iAllocSize( aAllocSize ) + { + } + + +// ============== MEMBER FUNCTIONS for CATStorageServerSession ================= + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::CATStorageServerSession +// C++ default constructor. It Does not contain any code that +// might leave. +// ----------------------------------------------------------------------------- +// +CATStorageServerSession::CATStorageServerSession( CATStorageServer& aStorageServer ) : + iStorageServer( aStorageServer ), + iError( 0 ), + iLeakArray( KLeakArrayGranularity ), + iProcessId( KNullProcessId ), + iLoggingOngoing( EFalse ), + iLogOption( KDefaultLoggingMode ), + iCurAllocSize( 0 ), + iMaxAllocs( 0 ), + iMaxAllocSize( 0 ), + iLogFile( KEmpty() ), + iIsUdeb( 1 ) + { + LOGSTR1( "STSE CATStorageServerSession::CATStorageServerSession()" ); + + // Initialize iMicroSecondsAt1970 + TTime time( KJanuaryFirst1970 ); + iMicroSecondsAt1970 = time.Int64(); + + // Increment the server's session count by one (1) + iStorageServer.IncSessionCount(); + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CATStorageServerSession::ConstructL() + { + // Intentionally left empty + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CATStorageServerSession* CATStorageServerSession::NewL( CATStorageServer& aStorageServer ) + { + CATStorageServerSession* self = NewLC( aStorageServer ); + CleanupStack::Pop( self ); + + return self; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CATStorageServerSession* CATStorageServerSession::NewLC( CATStorageServer& aStorageServer ) + { + CATStorageServerSession* self = new ( ELeave ) CATStorageServerSession( aStorageServer ); + + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::~CATStorageServerSession +// Destructor +// ----------------------------------------------------------------------------- +CATStorageServerSession::~CATStorageServerSession() + { + LOGSTR1( "STSE CATStorageServerSession::~CATStorageServerSession()" ); + + // Empty the array and delete the referenced objects + iLeakArray.ResetAndDestroy(); + + // Close the leak array + iLeakArray.Close(); + + // Close the allocation info array + iAllocInfoArray.Close(); + + // Check if process closed abnormal + if ( iProcessId != KNullProcessId && + iLoggingOngoing && iLogOption != EATLoggingOff && + iError != KErrNoMemory ) + { + LogAbnormalEnd(); + } + + // Close the file and the handle to the file server + CloseFsAndFile(); + + // Remove the process with the current PID from the server's array of processes + TRAP_IGNORE( iStorageServer.RemoveProcessL( iProcessId ) ); + + // Decrement the server's session count by one (1) + iStorageServer.DecSessionCount(); + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::ServiceL +// This function is called by the client/server framework +// ----------------------------------------------------------------------------- +// +void CATStorageServerSession::ServiceL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE void CATStorageServerSession::ServiceL()" ); + + // If logging has been cancelled for this session, return immediately + if( iLogOption == EATLoggingOff ) + { + aMessage.Complete( KErrCancel ); + return; + } + + switch ( aMessage.Function() ) + { + case CATStorageServer::EProcessStarted: + { + // If logging is not ongoing, set the log option + if( !iLoggingOngoing ) + { + // Set the operation mode + SetLogOption( aMessage ); + } + + switch ( iLogOption ) + { + case EATLogToTrace: + { + iError = LogProcessStartTraceL( aMessage ); + } + break; + + case EATLogToFile: + { + iError = LogProcessStartedL( aMessage ); + } + break; + + default: + { + // Panic the client and set iError KErrCancel, because being + // here implies that an illegal log option has been given. + PanicClient( EAToolIllegalLogOption, aMessage ); + iError = KErrCancel; + } + break; + } + } + break; + + + case CATStorageServer::EDllLoaded: + { + switch ( iLogOption ) + { + case EATLogToTrace: + { + iError = LogDllLoadTraceL( aMessage ); + } + break; + + case EATLogToFile: + { + iError = LogDllLoadedL( aMessage ); + } + break; + + default: + { + // Panic the client and set iError KErrCancel, because being + // here implies that an illegal log option has been given. + PanicClient( EAToolIllegalLogOption, aMessage ); + iError = KErrCancel; + } + break; + } + } + break; + + + case CATStorageServer::EDllUnloaded: + { + switch ( iLogOption ) + { + case EATLogToTrace: + { + iError = LogDllUnloadTraceL( aMessage ); + } + break; + + case EATLogToFile: + { + iError = LogDllUnloadedL( aMessage ); + } + break; + + default: + { + // Panic the client and set iError KErrCancel, because being + // here implies that an illegal log option has been given. + PanicClient( EAToolIllegalLogOption, aMessage ); + iError = KErrCancel; + } + break; + } + } + break; + + + case CATStorageServer::EMemoryAllocated: + { + switch ( iLogOption ) + { + case EATLogToTrace: + { + iError = LogMemoryAllocTraceL( aMessage ); + } + break; + + case EATLogToFile: + { + iError = LogMemoryAllocatedL( aMessage ); + } + break; + + default: + { + // Panic the client and set iError KErrCancel, because being + // here implies that an illegal log option has been given. + PanicClient( EAToolIllegalLogOption, aMessage ); + iError = KErrCancel; + } + break; + } + } + break; + + + case CATStorageServer::EMemoryFreed: + { + switch ( iLogOption ) + { + case EATLogToTrace: + { + iError = LogMemoryFreedTraceL( aMessage ); + } + break; + + case EATLogToFile: + { + iError = LogMemoryFreedL( aMessage ); + } + break; + + default: + { + // Panic the client and set iError KErrCancel, because being + // here implies that an illegal log option has been given. + PanicClient( EAToolIllegalLogOption, aMessage ); + iError = KErrCancel; + } + break; + } + } + break; + + + case CATStorageServer::EProcessEnded: + { + switch ( iLogOption ) + { + case EATLogToTrace: + { + iError = LogProcessEndTraceL( aMessage ); + } + break; + + case EATLogToFile: + { + iError = LogProcessEndedL( aMessage ); + } + break; + + default: + { + // Panic the client and set iError KErrCancel, because being + // here implies that an illegal log option has been given. + PanicClient( EAToolIllegalLogOption, aMessage ); + iError = KErrCancel; + } + break; + } + } + break; + + + case CATStorageServer::EMemoryCheck: + { + switch ( iLogOption ) + { + case EATLogToTrace: + { + iError = CheckMemoryAddressTrace( aMessage ); + } + break; + + case EATLogToFile: + { + iError = CheckMemoryAddressL( aMessage ); + } + break; + + default: + { + // Panic the client and set iError KErrCancel, because being + // here implies that an illegal log option has been given. + PanicClient( EAToolIllegalLogOption, aMessage ); + iError = KErrCancel; + } + break; + } + } + break; + + + case CATStorageServer::EGetProcesses: + { + iError = GetProcessesL( aMessage ); + } + break; + + + case CATStorageServer::EGetDlls: + { + iError = GetDllsL( aMessage ); + } + break; + + case CATStorageServer::EGetLoggingMode: + { + iError = GetLoggingModeL( aMessage ); + } + break; + + case CATStorageServer::ESubtestStart: + { + iError = StartSubtestL( aMessage ); + } + break; + + case CATStorageServer::ESubtestStop: + { + iError = StopSubtestL( aMessage ); + } + break; + + case CATStorageServer::ESubtestStart2: + { + iError = StartSubtest2L( aMessage ); + } + break; + + case CATStorageServer::ESubtestStop2: + { + iError = StopSubtest2( aMessage ); + } + break; + + case CATStorageServer::EGetCurrentAllocs: + { + iError = GetCurrentAllocsL( aMessage ); + } + break; + + case CATStorageServer::EGetMaxAllocs: + { + iError = GetMaxAllocsL( aMessage ); + } + break; + + case CATStorageServer::ECancelLogging: + { + iError = CancelLoggingL( aMessage ); + } + break; + + case CATStorageServer::EGetUdeb: + { + iError = GetUdebL( aMessage ); + } + break; + + case CATStorageServer::EGetLoggingFile: + { + iError = GetLoggingFileL( aMessage ); + } + break; + + case CATStorageServer::EProcessUdeb: + { + SetUdeb( aMessage ); + } + break; + + case CATStorageServer::EIsMemoryAdded: + { + iError = IsMemoryAdded( aMessage ); + LOGSTR2( "STSE > IsMemoryAdded err = %i", iError ); + } + break; + + default: + { + // Panic both the client and server, because being here implies + // that there is an internal error in the client/server. + PanicClient( EAToolBadRequest, aMessage ); + StorageServerPanic( KCategoryServer, EAToolBadRequest ); + } + break; + + } + + // Complete the message, if it has not been already cancelled. + if ( iError != KErrCancel ) + { + // Log the error code. Only KErrNoMemory errors are logged. + if ( iLogOption == EATLogToFile && iError == KErrNoMemory ) + { + HandleError( iError ); + } + else if ( iLogOption == EATLogToTrace && iError == KErrNoMemory ) + { + HandleErrorTrace( iError ); + } + + // Complete serving the message + aMessage.Complete( iError ); + } + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::LogProcessStartedL() +// Opens a logging file with the requested name and then writes information +// on process start into the file. +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::LogProcessStartedL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::LogProcessStartedL()" ); + + // Panic the client and return, if this method has already been called for this + // session object (and a logging file has been opened) + if ( iLoggingOngoing ) + { + PanicClient( EAToolNotAllowed, aMessage ); + return KErrCancel; + } + + iError = KErrNone; + + LOGMEM; + + // READ THE FIRST ARGUMENT (descriptor) + + // Length of the first argument (index 0) + TInt length = aMessage.GetDesLength( 0 ); + + LOGSTR2( "STSE length of the fileName: %i", length ); + + // Return if errors + if ( length == KErrArgument || length == KErrBadDescriptor ) + { + return length; + } + + // Construct a buffer for file name, and leave the pointer on Cleanup Stack + HBufC* fileName = HBufC::NewLC( length ); + TPtr fileNamePtr( fileName->Des() ); + + // Read the client side's descriptor at index 0 + iError = aMessage.Read( 0, fileNamePtr ); + + if ( iError != KErrNone ) + { + CleanupStack::PopAndDestroy( fileName ); + return iError; + } + + // READ THE SECOND ARGUMENT (descriptor) + + // Length of the second argument (index 1) + length = aMessage.GetDesLength( 1 ); + + LOGSTR2( "STSE length of the processName: %i", length ); + + // Return if errors + if ( length == KErrArgument || length == KErrBadDescriptor ) + { + CleanupStack::PopAndDestroy( fileName ); + return length; + } + + HBufC8* processName = HBufC8::NewL( length ); + TPtr8 bufPtr( processName->Des() ); + + // Read the client side's descriptor at index 1 + iError = aMessage.Read( 1, bufPtr ); + + if ( iError != KErrNone ) + { + delete processName; + CleanupStack::PopAndDestroy( fileName ); + return iError; + } + + // READ THE THIRD ARGUMENT (integer, a process ID) + TInt processId = aMessage.Int2(); + + // Open a file server session and a file. The file + // will be opened with the name received from the client + iError = OpenFsAndFile( *fileName, *processName ); + CleanupStack::PopAndDestroy( fileName ); + // Return without logging, if an error occured + if ( iError != KErrNone ) + { + // Delete the local objects + delete processName; + return iError; + } + + // Get the home time for the configuration UI + iTime.HomeTime(); + + // Add the process into the server's array of processes + iError = iStorageServer.AddProcessL( *processName, + processId, + this, + iTime.Int64() ); + + // Return without logging, if an error occured + if ( iError ) + { + // Remove, if something was added regardless of the error + // However, we must not remove an existing process + if ( iError != KErrAlreadyExists ) + { + iStorageServer.RemoveProcessL( processId ); + } + return iError; + } + + // Make a buffer that will be logged into the opened logging file + TBuf8<KProcessStartBufLength> loggingBuf; + loggingBuf.Format( KProcessStart, processName, processId ); + + delete processName; + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + loggingBuf.AppendNum( timeFrom1970, EHex ); + + // Append udeb/urel information to the process start + loggingBuf.Append( KSpace ); + loggingBuf.AppendNum( iIsUdeb, EHex ); + + // Append trace version information + loggingBuf.Append( KSpace ); + loggingBuf.AppendNum( KATTraceVersion, EHex ); + + // Append a new line + loggingBuf.Append( KNewLine ); + + // Write the buffer into the file + iError = iFile.Write( loggingBuf ); + + // Return, if an error occured + if ( iError ) + { + iStorageServer.RemoveProcessL( processId ); + return iError; + } + + LOGMEM; + + // Set the process ID value for this logging session + iProcessId = processId; + // Set logging session started + iLoggingOngoing = ETrue; + + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::LogProcessStartTraceL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::LogProcessStartTraceL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::LogProcessStartTraceL()" ); + + // Panic the client and return, if this method has already been called for this + // session object + if ( iLoggingOngoing ) + { + PanicClient( EAToolNotAllowed, aMessage ); + return KErrCancel; + } + + iError = KErrNone; + + LOGMEM; + + // READ THE SECOND ARGUMENT (descriptor) + // The first argument, file name, is ignored when logging thru trace + + // Length of the second argument (index 1) + TInt length = aMessage.GetDesLength( 1 ); + + LOGSTR2( "STSE length of the processName: %i", length ); + + // Return if errors + if ( length == KErrArgument || length == KErrBadDescriptor ) + { + return length; + } + + HBufC8* processName = HBufC8::NewL( length ); + TPtr8 bufPtr( processName->Des() ); + + // Read the client side's descriptor at index 1 + iError = aMessage.Read( 1, bufPtr ); + + if ( iError != KErrNone ) + { + // Delete local objects and return + delete processName; + return iError; + } + + // READ THE THIRD ARGUMENT (integer, a process ID) + TInt processId = aMessage.Int2(); + + // Get the home time for the configuration UI + iTime.HomeTime(); + + // Add the process into the server's array of processes + iError = iStorageServer.AddProcessL( *processName, processId, this, + iTime.Int64() ); + + // Return without logging, if an error occured + if ( iError ) + { + // Remove, if something was added regardless of the error + // However, we must not remove an existing process + if ( iError != KErrAlreadyExists ) + { + iStorageServer.RemoveProcessL( processId ); + } + return iError; + } + + // Make a buffer that will be logged + TBuf8<KProcessStartBufLength> loggingBuf; + + loggingBuf.Format( KProcessStart, processName, processId ); + + delete processName; + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + loggingBuf.AppendNum( timeFrom1970, EHex ); + + // Append udeb/urel information to the process start + loggingBuf.Append( KSpace ); + loggingBuf.AppendNum( iIsUdeb, EHex ); + + // Append version number + loggingBuf.Append( KSpace ); + loggingBuf.AppendNum( KATTraceVersion, EHex ); + + // Append a new line + loggingBuf.Append( KNewLine ); + + // Log to trace + TBuf<KProcessStartBufLength> traceBuf; + traceBuf.Copy( loggingBuf ); + RDebug::Print( KTraceMessage, processId ,&traceBuf ); + + LOGMEM; + + // Set the process ID value for this logging session + iProcessId = processId; + // Set logging session started + iLoggingOngoing = ETrue; + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::LogDllLoadedL() +// Logs to the file opened by the function LogProcessStartedL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::LogDllLoadedL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::LogDllLoadedL()" ); + + // Panic the client and return, if a logging session is not ongoing + // ( can be started by calling the client's LogProcessStarted() ) + if ( !iLoggingOngoing ) + { + PanicClient( EAToolNotAllowed, aMessage ); + return KErrCancel; + } + + iError = KErrNone; + + // Read the length of the first argument (index 0) + TInt length = aMessage.GetDesLength( 0 ); + + // Return if errors + if ( length == KErrArgument || length == KErrBadDescriptor ) + { + return length; + } + + HBufC8* dllName = HBufC8::NewL( length ); + TPtr8 bufPtr( dllName->Des() ); + + // Read the client side's descriptor (the argument 0) + iError = aMessage.Read( 0, bufPtr ); + + if ( iError != KErrNone ) + { + delete dllName; + return iError; + } + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Add this dll into the server's array + TUint32 startAddress( aMessage.Int1() ); + TUint32 endAddress( aMessage.Int2() ); + iError = iStorageServer.AddDllL( iProcessId, + TATDllInfo( startAddress, endAddress, timeFrom1970, *dllName ) ); + + // Return without logging, if an error occured + if ( iError ) + { + delete dllName; + return iError; + } + + // Make a buffer that will be logged into the opened logging file + TBuf8<KDllLoadBufLength> loggingBuf; + loggingBuf.Format( KDllLoad, dllName, timeFrom1970, startAddress, endAddress ); + + delete dllName; + + // Write the buffer into a file and return the error code + return iFile.Write( loggingBuf ); + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::LogDllLoadTraceL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::LogDllLoadTraceL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::LogDllLoadTraceL()" ); + + // Panic the client and return, if a logging session is not ongoing + // ( can be started by calling the client's LogProcessStarted() ) + if ( !iLoggingOngoing ) + { + PanicClient( EAToolNotAllowed, aMessage ); + return KErrCancel; + } + + iError = KErrNone; + + // Read the length of the first argument (index 0) + TInt length = aMessage.GetDesLength( 0 ); + + // Return if errors + if ( length == KErrArgument || length == KErrBadDescriptor ) + { + return length; + } + + HBufC8* dllName = HBufC8::NewL( length ); + TPtr8 bufPtr( dllName->Des() ); + + // Read the client side's descriptor (the argument 0) + iError = aMessage.Read( 0, bufPtr ); + + if ( iError != KErrNone ) + { + delete dllName; + return iError; + } + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + TUint32 startAddress( aMessage.Int1() ); + TUint32 endAddress( aMessage.Int2() ); + + // Add this dll into the server's array + iError = iStorageServer.AddDllL( iProcessId, + TATDllInfo( startAddress, endAddress, timeFrom1970, *dllName ) ); + + // Return without logging, if an error occured + if ( iError ) + { + delete dllName; + return iError; + } + + // Make a buffer that will be logged + TBuf8<KDllLoadBufLength> loggingBuf; + loggingBuf.Format( KDllLoad, dllName, timeFrom1970, startAddress, endAddress ); + + delete dllName; + + TBuf<KDllLoadBufLength> traceBuf; + traceBuf.Copy( loggingBuf ); + RDebug::Print( KTraceMessage, iProcessId ,&traceBuf ); + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::LogDllUnloadedL() +// Logs to the file opened by the function LogProcessStartedL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::LogDllUnloadedL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::LogDllUnloadedL()" ); + + // Panic the client and return, if a logging session is not ongoing + // ( can be started by calling the client's LogProcessStarted() ) + if ( !iLoggingOngoing ) + { + PanicClient( EAToolNotAllowed, aMessage ); + return KErrCancel; + } + + iError = KErrNone; + + // Read the length of the first argument (index 0) + TInt length = aMessage.GetDesLength( 0 ); + + LOGSTR2( "STSE length %i", length ); + + // Return if errors + if ( length == KErrArgument || length == KErrBadDescriptor ) + { + return length; + } + + HBufC8* dllName = HBufC8::NewL( length ); + TPtr8 bufPtr( dllName->Des() ); + + // Read the client side's descriptor (the argument 0) + iError = aMessage.Read( 0, bufPtr ); + + if ( iError != KErrNone ) + { + delete dllName; + return iError; + } + + TUint32 startAddress = aMessage.Int1(); + TUint32 endAddress = aMessage.Int2(); + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Make a buffer that will be logged into the opened logging file + TBuf8<KDllUnloadBufLength> loggingBuf; + loggingBuf.Format( KDllUnload, dllName, timeFrom1970, startAddress, endAddress ); + + // Remove this dll from the server's array + iError = iStorageServer.RemoveDllL( iProcessId, bufPtr ); + + delete dllName; + + // Return without logging, if an error occured + if ( iError ) + { + return iError; + } + + // Write the buffer into a file and return the error code + return iFile.Write( loggingBuf ); + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::LogDllUnloadTraceL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::LogDllUnloadTraceL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::LogDllUnloadTraceL()" ); + + // Panic the client and return, if a logging session is not ongoing + // ( can be started by calling the client's LogProcessStarted() ) + if ( !iLoggingOngoing ) + { + PanicClient( EAToolNotAllowed, aMessage ); + return KErrCancel; + } + + iError = KErrNone; + + // Read the length of the first argument (index 0) + TInt length = aMessage.GetDesLength( 0 ); + + LOGSTR2( "STSE length %i", length ); + + // Return if errors + if ( length == KErrArgument || length == KErrBadDescriptor ) + { + return length; + } + + HBufC8* dllName = HBufC8::NewL( length ); + TPtr8 bufPtr( dllName->Des() ); + + // Read the client side's descriptor (the argument 0) + iError = aMessage.Read( 0, bufPtr ); + + if ( iError != KErrNone ) + { + delete dllName; + return iError; + } + + TUint32 startAddress = aMessage.Int1(); + TUint32 endAddress = aMessage.Int2(); + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Make a buffer that will be logged + TBuf8<KDllUnloadBufLength> loggingBuf; + loggingBuf.Format( KDllUnload, dllName, timeFrom1970, startAddress, endAddress ); + + // Remove this dll from the server's array + iError = iStorageServer.RemoveDllL( iProcessId, bufPtr ); + + delete dllName; + + // Return without logging, if an error occured + if ( iError ) + { + return iError; + } + + TBuf<KDllLoadBufLength> traceBuf; + traceBuf.Copy( loggingBuf ); + RDebug::Print( KTraceMessage, iProcessId ,&traceBuf ); + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::LogMemoryAllocatedL() +// Constructs a CATMemoryEntry object and appends it into iLeakArray. +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::LogMemoryAllocatedL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::LogMemoryAllocatedL()" ); + + // Panic the client and return, if a logging session is not ongoing + // ( can be started by calling the client's LogProcessStarted() ) + if ( !iLoggingOngoing ) + { + PanicClient( EAToolNotAllowed, aMessage ); + return KErrCancel; + } + + // A pointer to a buffer of call stack's memory addresses + CBufFlat* stackBuf = NULL; + + iError = KErrNone; + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Read the first argument (index 0) + TUint32 memAddress = aMessage.Int0(); + if ( memAddress == 0 ) + { + return KErrNotSupported; + } + + // Read the length of the descriptor argument (index 1) that should include + // call stack memory addresses associated with this memory allocation + TInt bufferLength = aMessage.GetDesLength( 1 ); + + // Construct a buffer for aCallstack + stackBuf = CBufFlat::NewL( bufferLength ); + CleanupStack::PushL( stackBuf ); + + // Buffer position + TInt pos = 0; + + stackBuf->ExpandL( pos, bufferLength ); + + TPtr8 bufPtr = stackBuf->Ptr( pos ); + + // Read the descriptor argument into the buffer + aMessage.ReadL( 1, bufPtr ); + + // Read the third argument (index 2) that tells the size of this allocation + TInt size = aMessage.Int2(); + + // Construct a new CATMemoryEntry object. + // The ownership of the current stackBuf object is given to the "entry" object. + CATMemoryEntry* entry = + new (ELeave) CATMemoryEntry( memAddress, stackBuf, timeFrom1970, size ); + + // Pop stackBuf from CleanupStack and set it to NULL, because it is not used anymore. + CleanupStack::Pop( stackBuf ); + stackBuf = NULL; + + // Make sure that the same memory area is not tryed to be allocated a second time + TIdentityRelation<CATMemoryEntry> matcher( CATMemoryEntry::Match ); + + TInt index = iLeakArray.Find( entry, matcher ); + + if ( index == KErrNotFound ) + { + TLinearOrder<CATMemoryEntry> order( CATMemoryEntry::Compare ); + + // Insert the "entry" object into "iLeakArray". The ownership of + // the "entry" object is given to the array. + iError = iLeakArray.InsertInOrderAllowRepeats( entry, order ); + + // If an insertion to the array was not successful, delete the created + // entry manually and return. + if ( iError ) + { + delete entry; + return iError; + } + + // Make a TAllocInfo object, and give values for its members. + TAllocInfo allocInfo( memAddress, size ); + + // Insert the allocInfo object into iAllocInfoArray + iError = iAllocInfoArray.InsertInUnsignedKeyOrder( allocInfo ); + + // If an insertion to the array was not successful, delete the created entry + // and remove its pointer from iLeakArray. + if ( iError ) + { + index = iLeakArray.Find( entry, matcher ); + // Delete the entry object and remove remove the pointer from the array + delete entry; + // The index should be in a legal range, because the earlier insertion of + // the entry was successful + iLeakArray.Remove( index ); + } + + // Otherwise update the iCurAllocSize, iMaxAllocs and iMaxAllocSize variables + + iCurAllocSize += size; + + // The count can never be negative => associate it to an unsigned int + TUint allocCount = iAllocInfoArray.Count(); + if ( allocCount > iMaxAllocs ) + { + iMaxAllocs = allocCount; + } + + if ( iCurAllocSize > iMaxAllocSize ) + { + iMaxAllocSize = iCurAllocSize; + } + + return iError; + } + + // This shouldn't happen, because the same memory area shouldn't be allocated + // more than once (without deallocating it first) + else + { + delete entry; + return KErrAlreadyExists; + } + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::LogMemoryAllocTraceL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::LogMemoryAllocTraceL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::LogMemoryAllocTraceL()" ); + + // Panic the client and return, if a logging session is not ongoing + // ( can be started by calling the client's LogProcessStarted() ) + if ( !iLoggingOngoing ) + { + PanicClient( EAToolNotAllowed, aMessage ); + return KErrCancel; + } + + // Read the first argument (index 0) + TUint32 memAddress = aMessage.Int0(); + if ( memAddress == 0 ) + { + return KErrNotSupported; + } + + // Read the third argument (index 2) that tells the size of this allocation + TInt size = aMessage.Int2(); + + // Append this allocation into the iAllocInfoArray array. This array is for + // providing the configuration UI with information on allocations + + // Make a TAllocInfo object, and give values for its members. + TAllocInfo allocInfo( memAddress, size ); + + // Insert the allocInfo object into iAllocInfoArray + iError = iAllocInfoArray.InsertInUnsignedKeyOrder( allocInfo ); + + // Log debug message if duplicated allocation. + if ( iError == KErrAlreadyExists ) + { + LOGSTR2( "STSE TInt CATStorageServerSession::LogMemoryAllocTraceL() Error, duplicate allocation :%i", memAddress ); + } + + // A pointer to a buffer of call stack's memory addresses + CBufFlat* stackBuf = NULL; + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Read the length of the descriptor argument (index 1) that should include + // call stack memory addresses associated with this memory allocation + TInt bufferLength = aMessage.GetDesLength( 1 ); + + // Construct a buffer for aCallstack + stackBuf = CBufFlat::NewL( bufferLength ); + CleanupStack::PushL( stackBuf ); + + // Buffer position + TInt pos( 0 ); + stackBuf->ExpandL( pos, bufferLength ); + + TPtr8 bufPtr = stackBuf->Ptr( pos ); + + // Read the descriptor argument (index 1) into the buffer + aMessage.ReadL( 1, bufPtr ); + + // Variable for the number of memory addresses in the call stack + TInt addrCount( 0 ); + TUint32 callStackAddr; + + // Read the first word of the buffer. This includes the number of + // memory addresses stored in the current stackBuf + stackBuf->Read( pos, &addrCount, KWordSize ); + + // Move the position one word onwards. + pos += KWordSize; + + // Create a 16-bit buffer, and a pointer descriptor for it + // ALLOCH <Memory address> <Time stamp> <Allocation size> <Call stack address count> + // <Call stack address> <Call stack address> ... + HBufC* traceBuf = HBufC::NewL( KMemAllocBufLength ); + TPtr tracePtr( traceBuf->Des() ); + + // Pop stackBuf from CleanupStack, since no leavable operations will be done + // anymore + CleanupStack::Pop( stackBuf ); + + // Append the tag implying a memory allocation line in the data file + tracePtr.Append( KMemoryAllocHeader ); + + // Append the start address of this allocation in the 32-bit (max 8 characters) + // hexadecimal text format. + tracePtr.AppendNum( memAddress, EHex ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + tracePtr.Append( KSpaceTrace ); + tracePtr.AppendNum( timeFrom1970, EHex ); + + // Append the size of the allocation in the 32-bit (max 8 characters) hexadecimal + // text format. + tracePtr.Append( KSpaceTrace ); + tracePtr.AppendNum( size, EHex ); + + // Append call stack address count + tracePtr.Append( KSpaceTrace ); + tracePtr.AppendNum( addrCount, EHex ); + + // Calculate last item length + TInt lastItemLength( KTraceMessage().Length() + KHexa32Length + + KSpaceLength + KNewlineLength ); + + TUint packetNumber( 1 ); + + // Go through all call stack's memory addresses associated with + // this memory allocation + for ( TInt j = 0; j < addrCount; j++ ) + { + // ALLOCF <Memory address> <Time stamp> <Packet number> + // <Call stack address> <Call stack address> ... + if ( tracePtr.Length() <= 0 ) + { + // Create alloc fragment message header + tracePtr.Append( KMemoryAllocFragment ); + tracePtr.AppendNum( memAddress, EHex ); + tracePtr.Append( KSpaceTrace ); + tracePtr.AppendNum( timeFrom1970, EHex ); + tracePtr.Append( KSpaceTrace ); + tracePtr.AppendNum( packetNumber, EHex ); + // Increase packet number + packetNumber++; + } + + // Read the next call stack's memory address stored in the buffer. + stackBuf->Read( pos, &callStackAddr, KWordSize ); + + // Append the read memory address as a hexadecimal number + tracePtr.AppendFormat( KHexaNumberTrace, callStackAddr ); + + // Move the pos variable one word onwards. + pos += KWordSize; + + // Check if buffer max length exceed + if ( lastItemLength + tracePtr.Length() >= KMemAllocBufLength ) + { + tracePtr.Append( KNewLineTrace ); + // Log through debug channel + RDebug::Print( KTraceMessage, iProcessId, traceBuf ); + // Empty trace buffer + tracePtr.Delete( 0, tracePtr.MaxLength() ); + } + } + + // Send the last message if exists + if ( tracePtr.Length() > 0 ) + { + tracePtr.Append( KNewLineTrace ); + + // Log through debug channel + RDebug::Print( KTraceMessage, iProcessId, traceBuf ); + } + + delete traceBuf; + delete stackBuf; + + // Update the iCurAllocSize, iMaxAllocs and iMaxAllocSize variables + iCurAllocSize += size; + + // The count can never be negative => associate it to an unsigned int + TUint allocCount = iAllocInfoArray.Count(); + if ( allocCount > iMaxAllocs ) + { + iMaxAllocs = allocCount; + } + + if ( iCurAllocSize > iMaxAllocSize ) + { + iMaxAllocSize = iCurAllocSize; + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::LogMemoryFreedL() +// Removes a TATMemoryEntry object with the specified memory address from +// iLeakArray, if found. +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::LogMemoryFreedL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::LogMemoryFreedL()" ); + + // Panic the client and return, if a logging session is not ongoing + // ( can be started by calling the client's LogProcessStarted() ) + if ( !iLoggingOngoing ) + { + PanicClient( EAToolNotAllowed, aMessage ); + return KErrCancel; + } + + // Get the memory address + TUint32 memAddress = aMessage.Int0(); + + // Remove this memory allocation from the leak array + TIdentityRelation<CATMemoryEntry> matcher( CATMemoryEntry::Match ); + CATMemoryEntry* entry = new (ELeave) CATMemoryEntry( memAddress, NULL, 0, 0 ); + TInt index = iLeakArray.Find( entry, matcher ); + delete entry; + + // Return, if the requested memory address was not found + // (had not been allocated) + if ( index == KErrNotFound ) + { + return index; + } + + // Delete the CATMemoryEntry object at "index" and remove from the array + delete iLeakArray[index]; + iLeakArray.Remove( index ); + + // Remove this memory allocation also from the allocation info array + // Make a TAllocInfo object for a "find" operation + TAllocInfo allocInfo( memAddress, 0 ); + index = iAllocInfoArray.FindInUnsignedKeyOrder( allocInfo ); + + // The index should not be KErrNotFound, because an object with this memory address + // was found in the iLeakArray array. If the index is out of range, something is + // badly wrong, so it would be alright to panic in that case. + if ( index == KErrNotFound ) + { + PanicClient( EAToolInternalError, aMessage ); + return KErrCancel; + } + + // Decrease the current alloc size and remove the requested allocation + // from iAllocInfoArray + iCurAllocSize -= iAllocInfoArray[index].iAllocSize; + iAllocInfoArray.Remove( index ); + + // If we are here, everything has gone alright + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::IsMemoryAdded() +// Check a memory allocation (memory address) from an internal array. +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::IsMemoryAdded( const RMessage2& aMessage, + const TBool aRemoveAlloc ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::IsMemoryAdded()" ); + + // Panic the client and return, if a logging session is not ongoing + // ( can be started by calling the client's LogProcessStarted() ) + if ( !iLoggingOngoing ) + { + PanicClient( EAToolNotAllowed, aMessage ); + return KErrCancel; + } + + // Read the first argument (index 0) + TUint32 memAddress = aMessage.Int0(); + + // Try to find this memory allocation from the allocation info array + + // Make a TAllocInfo object for a "find" operation + TAllocInfo allocInfo( memAddress, 0 ); + TInt index( iAllocInfoArray.FindInUnsignedKeyOrder( allocInfo ) ); + + if ( index == KErrNotFound ) + { + return index; + } + else if ( aRemoveAlloc ) + { + // Otherwise decrease the current alloc size and remove the requested allocation + // from iAllocInfoArray + iCurAllocSize -= iAllocInfoArray[index].iAllocSize; + iAllocInfoArray.Remove( index ); + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::LogMemoryFreedTraceL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::LogMemoryFreedTraceL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::LogMemoryFreedTraceL()" ); + + // Panic the client and return, if a logging session is not ongoing + // ( can be started by calling the client's LogProcessStarted() ) + if ( !iLoggingOngoing ) + { + PanicClient( EAToolNotAllowed, aMessage ); + return KErrCancel; + } + + // A pointer to a buffer of call stack's memory addresses + CBufFlat* stackBuf = NULL; + iError = KErrNone; + + // Read the first argument (index 0) + TUint32 memAddress = aMessage.Int0(); + + // Remove address from allocation table and its size from alloc size, + // if found from table. + TAllocInfo allocInfo( memAddress, 0 ); // Dummy info for search. + TInt index( iAllocInfoArray.FindInUnsignedKeyOrder( allocInfo ) ); + if ( index != KErrNotFound ) + { + // Decrease the current alloc size and remove the requested allocation + // from table. + iCurAllocSize -= iAllocInfoArray[index].iAllocSize; + iAllocInfoArray.Remove( index ); + } + else + { + LOGSTR2( "STSE TInt CATStorageServerSession::LogMemoryFreedTrace() Error, cannot find alloc for free: %i", memAddress ); + } + + // Read the length of the descriptor argument (index 1) that should include + // call stack memory addresses associated with this memory allocation + TInt bufferLength = aMessage.GetDesLength( 1 ); + + // Construct a buffer for aCallstack + stackBuf = CBufFlat::NewL( bufferLength ); + CleanupStack::PushL( stackBuf ); + + // Buffer position + TInt pos = 0; + + stackBuf->ExpandL( pos, bufferLength ); + + TPtr8 bufPtr = stackBuf->Ptr( pos ); + + // Read the descriptor argument (index 1) into the buffer + aMessage.ReadL( 1, bufPtr ); + + // Variable for the number of memory addresses in the call stack + TInt addrCount( 0 ); + TUint32 callStackAddr( 0 ); + + // Read the first word of the buffer. This includes the number of + // memory addresses stored in the current stackBuf + stackBuf->Read( pos, &addrCount, KWordSize ); + + // Move the position one word onwards. + pos += KWordSize; + + // Create a 16-bit buffer, and a pointer descriptor for it + HBufC* traceBuf = HBufC::NewL( KMemFreedBufLength ); + TPtr tracePtr( traceBuf->Des() ); + + // Pop stackBuf from CleanupStack, since no leavable operations will be done + // anymore + CleanupStack::Pop( stackBuf ); + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Memory deallocation header message. + // FREEH <Memory address> <Time stamp> <Call stack address count> <Call stack address> + // <Call stack address> ... + + // Append the tag implying a memory free line in the data file + tracePtr.Append( KMemoryFreedHeader ); + + // Append the start address of this allocation in the 32-bit (max 8 characters) + // hexadecimal text format. + tracePtr.AppendNum( memAddress, EHex ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + tracePtr.Append( KSpaceTrace ); + tracePtr.AppendNum( timeFrom1970, EHex ); + + // Append call stack address count + tracePtr.Append( KSpaceTrace ); + tracePtr.AppendNum( addrCount, EHex ); + + // Packet number + TUint packetNumber( 1 ); + + // Calculate last item length + TInt lastItemLength( KTraceMessage().Length() + KHexa32Length + + KSpaceLength + KNewlineLength ); + + // Go through all call stack's memory addresses associated with + // this memory allocation + for ( TInt j = 0; j < addrCount; j++ ) + { + if ( tracePtr.Length() <= 0 ) + { + // Memory deallocation fragment message. + // FREEF <Memory address> <Time stamp> <Packet number> <Call stack address count> + // <Call stack address>... + // Create free fragment message header + tracePtr.Append( KMemoryFreedFragment ); + tracePtr.AppendNum( memAddress, EHex ); + tracePtr.Append( KSpaceTrace ); + tracePtr.AppendNum( timeFrom1970, EHex ); + tracePtr.Append( KSpaceTrace ); + tracePtr.AppendNum( packetNumber, EHex ); + // Increase packet number + packetNumber++; + } + + // Read the next call stack's memory address stored in the buffer. + stackBuf->Read( pos, &callStackAddr, KWordSize ); + + // Append the read memory address as a hexadecimal number + tracePtr.AppendFormat( KHexaNumberTrace, callStackAddr ); + + // Move the pos variable one word onwards. + pos += KWordSize; + + // Check if buffer max length exceed + if ( lastItemLength + tracePtr.Length() >= KMemFreedBufLength ) + { + tracePtr.Append( KNewLineTrace ); + // Log through debug channel + RDebug::Print( KTraceMessage, iProcessId, traceBuf ); + // Empty trace buffer + tracePtr.Delete( 0, tracePtr.MaxLength() ); + } + } + + // Send the last message if exists + if ( tracePtr.Length() > 0 ) + { + tracePtr.Append( KNewLineTrace ); + + // Log through debug channel + RDebug::Print( KTraceMessage, iProcessId, traceBuf ); + } + + delete traceBuf; + delete stackBuf; + // If we are here, everything has gone alright + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::LogProcessEndedL() +// Prints memory leaks and information on process end into a file opened by the +// function LogProcessStartedL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::LogProcessEndedL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::LogProcessEndedL()" ); + + // Panic the client and return, if a logging session is not ongoing + // ( can be started by calling the client's LogProcessStarted() ) + if ( !iLoggingOngoing ) + { + PanicClient( EAToolNotAllowed, aMessage ); + return KErrCancel; + } + + iError = KErrNone; + + // Read the sent process ID + TUint processId = aMessage.Int0(); + + // The process ID got from the client should equal iProcessId. + // If it does not, return KErrNotSupported + if ( processId != iProcessId ) + { + return KErrNotSupported; + } + + ////////////////////////////////////////////// + // Log memory leaks + ////////////////////////////////////////////// + + // Print the information on the memory allocations that were never freed + iError = PrintLeaksL( aMessage ); + + if ( iError != KErrNone ) + { + return iError; + } + + ////////////////////////////////////////////// + // Log handle leaks + ////////////////////////////////////////////// + + TUint handleLeakCount = aMessage.Int1(); + + if( handleLeakCount == 0 ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::LogProcessEndedL() No handle leaks to report" ); + } + else + { + // Make a buffer that will be logged + TBuf8<KHandleLeakBufLength> loggingBuf; + + // Set handle leak module name to unknown since it can not be defined. + // Write the handle leak count from aMessage. + loggingBuf.Format( KHandleLeak, &KUnknownModule, handleLeakCount ); + + // Write the constructed string into the data file and return if error + iError = iFile.Write( loggingBuf ); + + if ( iError != KErrNone ) + { + return iError; + } + } + + ////////////////////////////////////////////// + // Log process end + ////////////////////////////////////////////// + + // Make a buffer that will be logged into the opened logging file + TBufC8<KProcessEndBufLength> processEndBuf; + + TPtr8 bufPtr = processEndBuf.Des(); + + bufPtr.AppendFormat( KProcessEnd, iProcessId ); + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + bufPtr.AppendNum( timeFrom1970, EHex ); + + // Append a new line + bufPtr.Append( KNewLine ); + + // Write the buffer into a file and return the error code + iError = iFile.Write( processEndBuf ); + + // Close the file and the handle to the file server + CloseFsAndFile(); + + // Remove the process from the server's array of processes + iError = iStorageServer.RemoveProcessL( processId ); + + // Reset iProcesssId and set the logging flag false + iProcessId = KNullProcessId; + iLoggingOngoing = EFalse; + + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::LogProcessEndTraceL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::LogProcessEndTraceL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::LogProcessEndTraceL()" ); + + // Panic the client and return, if a logging session is not ongoing + // ( can be started by calling the client's LogProcessStarted() ) + if ( !iLoggingOngoing ) + { + PanicClient( EAToolNotAllowed, aMessage ); + return KErrCancel; + } + + iError = KErrNone; + + // Read the sent process ID + TUint processId = aMessage.Int0(); + + // The process ID got from the client should equal iProcessId. + // If it does not, return KErrNotSupported + if ( processId != iProcessId ) + { + return KErrNotSupported; + } + + ////////////////////////////////////////////// + // Log handle leaks + ////////////////////////////////////////////// + + TUint handleLeakCount = aMessage.Int1(); + + if( handleLeakCount == 0 ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::LogProcessEndTraceL() No handle leaks to report" ); + } + else + { + // Make a buffer that will be logged + TBuf8<KHandleLeakBufLength> loggingBuf; + + // Make a 16-bit buffer that can be logged using RDebug + TBuf<KHandleLeakBufLength> traceBuf; + + // Set handle leak module name to unknown since it can not be defined. + // Write the handle leak count from aMessage. + loggingBuf.Format( KHandleLeak, &KUnknownModule, handleLeakCount ); + + traceBuf.Copy( loggingBuf ); + + // Log through debug channel + RDebug::Print( KTraceMessage, iProcessId , &traceBuf ); + } + + ////////////////////////////////////////////// + // Log process end + ////////////////////////////////////////////// + + // Make a buffer that will be logged + TBuf<KProcessEndBufLength> processEndBuf; + processEndBuf.AppendFormat( KProcessEndTrace, iProcessId ); + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + processEndBuf.AppendNum( timeFrom1970, EHex ); + + // Append a new line + processEndBuf.Append( KNewLineTrace ); + + // Log through debug channel + RDebug::Print( KTraceMessage, iProcessId, &processEndBuf ); + + // Remove the process from the server's array of processes + iError = iStorageServer.RemoveProcessL( iProcessId ); + + // Reset iProcesssId and set the logging flag false + iProcessId = KNullProcessId; + iLoggingOngoing = EFalse; + + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::CheckMemoryAddressL() +// Checks if given memory address can be found +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::CheckMemoryAddressL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::CheckMemoryAddressL()" ); + + // Panic the client and return, if a logging session is not ongoing + // ( can be started by calling the client's LogProcessStarted() ) + if ( !iLoggingOngoing ) + { + PanicClient( EAToolNotAllowed, aMessage ); + return KErrCancel; + } + + iError = KErrNone; + + // Check if memory address can be found in iLeakArray + TUint32 memAddress = aMessage.Int0(); + TIdentityRelation<CATMemoryEntry> matcher( CATMemoryEntry::Match ); + CATMemoryEntry* entry = new (ELeave) CATMemoryEntry( memAddress, NULL, 0, 0 ); + + // Get the index or an error code + iError = iLeakArray.Find( entry, matcher ); + delete entry; + + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::CheckMemoryAddressTrace() +// Checks if some memory address can be found +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::CheckMemoryAddressTrace( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::CheckMemoryAddressTrace()" ); + + // Panic the client and return, if a logging session is not ongoing + // ( can be started by calling the client's LogProcessStarted() ) + if ( !iLoggingOngoing ) + { + PanicClient( EAToolNotAllowed, aMessage ); + return KErrCancel; + } + + // Always return KErrNone in this mode + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::GetProcessesL() +// Checks if some memory address can be found +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::GetProcessesL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::GetProcessesL()" ); + + iError = KErrNone; + + TInt processInfoSize = sizeof( TATProcessInfo ); + + CBufFlat* processInfoBuf; + + // Buffer position + TInt pos( 0 ); + + // Calculate the length of the buffer to be constructed for processes + // One word will be reserved for the length of the array. + TInt bufferLength = KWordSize + KATMaxProcesses * processInfoSize; + + // Construct processInfoBuf and expand it before the beginning (index 0) + processInfoBuf = CBufFlat::NewL( bufferLength ); + CleanupStack::PushL( processInfoBuf ); + processInfoBuf->ExpandL( pos, bufferLength ); + + RArray<TATProcessInfo> processArray = iStorageServer.ProcessInfoArray(); + + // Variable for the number of TATProcessInfo objects in processArray + TInt count = processArray.Count(); + + // The count cannot be greater than KATMaxProcesses, because the client + // has reserved a buffer of this size to be filled by the server + if ( count > KATMaxProcesses ) + { + count = KATMaxProcesses; + } + + // Write the count (4 bytes) into the beginning of processInfoBuf + processInfoBuf->Write( pos, &count, KWordSize ); + + // Move the position one word onwards. + pos += KWordSize; + + // Write all the process info objects into the buffer + for ( TInt i = 0; i < count; i++ ) + { + TATProcessInfo& processInfo = processArray[i]; + + // Write the current process info into the buffer + processInfoBuf->Write( pos, &processInfo, processInfoSize ); + + // Move the pos variable onwards. + pos += processInfoSize; + } + + // Make a pointer descriptor pointing to the start of processInfoBuf + TPtr8 bufPtr( processInfoBuf->Ptr(0) ); + + // Write the buffer into aMessage at index 0 for the client + aMessage.WriteL( 0, bufPtr ); + + CleanupStack::PopAndDestroy( processInfoBuf ); + + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::GetDllsL() +// Checks if some memory address can be found +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::GetDllsL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::GetDllsL()" ); + + // Read the process ID at index 0 + TUint processId = aMessage.Int0(); + + // Size of a DLL descriptor + TInt sizeOfDllDesc = sizeof( TBuf8<KMaxLibraryName> ); + + // Buffer position + TInt pos( 0 ); + + // Calculate the length of the buffer to be constructed for DLL names. + // One word will be reserved for the length of the array. + TInt bufferLength = KWordSize + KATMaxDlls * sizeOfDllDesc; + + CBufFlat* dllBuf; + // Construct dllBuf and expand it before the beginning (index 0) + dllBuf = CBufFlat::NewL( bufferLength ); + CleanupStack::PushL( dllBuf ); + dllBuf->ExpandL( pos, bufferLength ); + + RPointerArray<CATDynProcessInfo> dynProcessArray = + iStorageServer.DynProcessInfoArray(); + + // Construct a CATDynProcessInfo object with the given process ID for searching + CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId ); + + // Find the index of a CATDynProcessInfo object with the given process ID + TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare ); + TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order ); + delete dynProcessInfo; + dynProcessInfo = NULL; + + // Return, if a process with the requested process ID was not found + if ( index == KErrNotFound ) + { + CleanupStack::PopAndDestroy( dllBuf ); + return index; + } + + // Get the wanted dynamic process info + dynProcessInfo = dynProcessArray[index]; + + // Fetch a reference to the desired DLL array + RArray<TATDllInfo>& dllArray = dynProcessInfo->iDlls; + + // Take the count of names in the array + TInt count = dllArray.Count(); + + // The count cannot be greater than KATMaxDlls, because the client + // has reserved a buffer of this size to be filled by the server + if ( count > KATMaxDlls ) + { + count = KATMaxDlls; + } + + // Write the count (4 bytes) into the beginning of dllBuf + dllBuf->Write( pos, &count, KWordSize ); + + // Move the position one word onwards. + pos += KWordSize; + + // Go through all DLL names objects sent to the server + for ( TInt i = 0; i < count; i++ ) + { + TBuf8<KMaxLibraryName>& dllName = dllArray[i].iName; + + // Write the current DLL name into the buffer + dllBuf->Write( pos, &dllName, sizeOfDllDesc ); + + // Move the pos variable onwards. + pos += sizeOfDllDesc; + } + + // Make a pointer descriptor pointing to the start of dllBuf + TPtr8 bufPtr( dllBuf->Ptr(0) ); + + // Write the whole buffer into aMessage at index 1 for the client + aMessage.WriteL( 1, bufPtr ); + + CleanupStack::PopAndDestroy( dllBuf ); + + // The dynProcessInfo object will not be deleted, because it is still owned by the + // server object's dynamic process info array. + dynProcessInfo = NULL; + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::GetLoggingModeL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::GetLoggingModeL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::GetLoggingModeL()" ); + + iError = KErrNone; + + // Read the process ID at index 0 + TUint processId = aMessage.Int0(); + + // Buffer position + TInt pos( 0 ); + + // The length of the buffer to be constructed for logging mode + TInt bufferLength = KWordSize; + + // Get the dynamic process info array + RPointerArray<CATDynProcessInfo> dynProcessArray = + iStorageServer.DynProcessInfoArray(); + + // Construct a CATDynProcessInfo object with the given process ID for searching + CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId ); + + // Find the index of a CATDynProcessInfo object with the given process ID + TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare ); + TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order ); + delete dynProcessInfo; + dynProcessInfo = NULL; + + // Return, if a process with the requested process ID was not found + if ( index == KErrNotFound ) + { + return index; + } + + // Otherwise get the wanted dynamic process info + dynProcessInfo = dynProcessArray[index]; + + // Get the desired process's associated session object + CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject; + CBufFlat* loggingModeBuf; + // Construct allocInfoBuf and expand it before the beginning (index 0) + loggingModeBuf = CBufFlat::NewL( bufferLength ); + CleanupStack::PushL( loggingModeBuf ); + loggingModeBuf->ExpandL( 0, bufferLength ); + + // Write the current logging mode of the requested process into the buffer. + loggingModeBuf->Write( pos, &sessionObject->iLogOption, KWordSize ); + + // Make a pointer descriptor that points to the data of allocInfoBuf + TPtr8 bufPtr( loggingModeBuf->Ptr(0) ); + + // Write the whole buffer into aMessage at index 1 for the client + aMessage.WriteL( 1, bufPtr ); + + CleanupStack::PopAndDestroy( loggingModeBuf ); + + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::StartSubtestL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::StartSubtestL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::StartSubtestL()" ); + + iError = KErrNone; + + // Read the process ID at index 0 + TUint processId = aMessage.Int0(); + + // Read the sub test ID at index 1 + TBuf8<KATMaxSubtestIdLength> subTestName; + iError = aMessage.Read( 1, subTestName ); + + // Return if reading was not successful + if ( iError != KErrNone ) + { + return iError; + } + + // Create another (non-8-bit) descriptor for logging to trace + // and copy the contents + TBuf<KATMaxSubtestIdLength> subTestNameTrace; + subTestNameTrace.Copy( subTestName ); + + // Read the handle count at index 2 + TInt handleCount = aMessage.Int2(); + + // FIND THE REQUESTED PROCESS + + // Get the dynamic process array + RPointerArray<CATDynProcessInfo> dynProcessArray = + iStorageServer.DynProcessInfoArray(); + + // Construct a CATDynProcessInfo object with the given process ID for searching + CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId ); + + // Find the index of a CATDynProcessInfo object with the given process ID + TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare ); + TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order ); + delete dynProcessInfo; + dynProcessInfo = NULL; + + // Return, if a process with the requested process ID was not found + if ( index == KErrNotFound ) + { + return index; + } + + // Get the wanted dynamic process info + dynProcessInfo = dynProcessArray[index]; + + // Get the desired process's associated session object + const CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject; + + // Make a buffer for logging thru trace + TBuf<KTestStartBufLength> loggingBuf; + + // Copy the line tag into the buffer + loggingBuf.Copy( KSubtestStart ); + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + loggingBuf.AppendNum( timeFrom1970, EHex ); + + // Append a space + loggingBuf.Append( KSpaceTrace ); + + // Append the sub test ID + loggingBuf.Append( subTestNameTrace ); + + // Append a space + loggingBuf.Append( KSpaceTrace ); + + // Append current handle leak count + loggingBuf.AppendNum( handleCount ); + + // Append a new line + loggingBuf.Append( KNewLineTrace ); + + // Log the string through trace + iError = sessionObject->LogThroughTrace( loggingBuf ); + + // ******************* + // Send loaded DLL's + // ******************* + + // Fetch a reference to the desired DLL array + RArray<TATDllInfo>& dllArray = dynProcessInfo->iDlls; + + // Take the count of dll info items + TInt count( dllArray.Count() ); + LOGSTR2( "STSE > dllArray.Count( %i )", count ); + + // Create buffers + TBuf<KDllLoadBufLength> traceBuf; + TBuf8<KDllLoadBufLength> dllBuf; + + for ( TInt x = 0; x < count; x++ ) + { + dllBuf.Format( KDllLoad, &dllArray[x].iName, dllArray[x].iLoadTime, + dllArray[x].iStartAddress, dllArray[x].iEndAddress ); + traceBuf.Copy( dllBuf ); + + // Log the string through trace + iError = sessionObject->LogThroughTrace( traceBuf ); + if ( iError != KErrNone ) + { + LOGSTR2( "STSE > LogThroughTrace() err( %i )", iError ); + } + } + sessionObject = NULL; + + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::StopSubtestL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::StopSubtestL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::StopSubtestL()" ); + + iError = KErrNone; + + // Read the process ID at index 0 + TUint processId = aMessage.Int0(); + + // Read the sub test ID at index 1 + TBuf8<KATMaxSubtestIdLength> subTestName; + iError = aMessage.Read( 1, subTestName ); + + // Return if reading was not successful + if ( iError != KErrNone ) + { + return iError; + } + + // Create another (non-8-bit) descriptor for logging to trace, + // and copy the contents + TBuf<KATMaxSubtestIdLength> subTestNameTrace; + subTestNameTrace.Copy( subTestName ); + + // Read the handle count at index 2 + TInt handleCount = aMessage.Int2(); + + // FIND THE REQUESTED PROCESS + + // Get the dynamic process array + RPointerArray<CATDynProcessInfo> dynProcessArray = + iStorageServer.DynProcessInfoArray(); + + // Construct a CATDynProcessInfo object with the given process ID for searching + CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId ); + + // Find the index of a CATDynProcessInfo object with the given process ID + TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare ); + TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order ); + delete dynProcessInfo; + dynProcessInfo = NULL; + + // Return, if a process with the requested process ID was not found + if ( index == KErrNotFound ) + { + return index; + } + + // Get the wanted dynamic process info + dynProcessInfo = dynProcessArray[index]; + + // Get the desired process's associated session object + const CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject; + + // Make a buffer for logging thru trace + TBuf<KTestEndBufLength> loggingBuf; + + // Copy the line tag into the buffer + loggingBuf.Copy( KSubtestEnd ); + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + loggingBuf.AppendNum( timeFrom1970, EHex ); + + // Append a space + loggingBuf.Append( KSpaceTrace ); + + // Append the sub test ID + loggingBuf.Append( subTestNameTrace ); + + // Append a space + loggingBuf.Append( KSpaceTrace ); + + // Append current handle leak count + loggingBuf.AppendNum( handleCount ); + + // Append a new line + loggingBuf.Append( KNewLineTrace ); + + // Log the string through trace + iError = sessionObject->LogThroughTrace( loggingBuf ); + + sessionObject = NULL; + + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::StartSubtest2L() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::StartSubtest2L( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::StartSubtest2L()" ); + + iError = KErrNone; + + // Read the sub test ID at index 0 + TBuf8<KATMaxSubtestIdLength> subTestName; + iError = aMessage.Read( 0, subTestName ); + + // Return if reading was not successful + if ( iError != KErrNone ) + { + return iError; + } + + // Create another (non-8-bit) descriptor for logging to trace + // and copy the contents + TBuf<KATMaxSubtestIdLength> subTestNameTrace; + subTestNameTrace.Copy( subTestName ); + + // Make a buffer for logging thru trace + TBuf<KTestStartBufLength> loggingBuf; + + // Copy the line tag into the buffer + loggingBuf.Copy( KSubtestStart ); + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + loggingBuf.AppendNum( timeFrom1970, EHex ); + + // Append a space + loggingBuf.Append( KSpaceTrace ); + + // Append the sub test ID + loggingBuf.Append( subTestNameTrace ); + + // Append a new line + loggingBuf.Append( KNewLineTrace ); + + // Log the string through trace + iError = LogThroughTrace( loggingBuf ); + + // ******************* + // Send loaded DLL's + // ******************* + + // Get the dynamic process array + RPointerArray<CATDynProcessInfo> dynProcessArray = + iStorageServer.DynProcessInfoArray(); + + // Construct a CATDynProcessInfo object with the given process ID for searching + CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( iProcessId ); + + // Find the index of a CATDynProcessInfo object with the given process ID + TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare ); + TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order ); + delete dynProcessInfo; + dynProcessInfo = NULL; + + // Return, if a process with the requested process ID was not found + if ( index == KErrNotFound ) + { + return index; + } + + // Get the wanted dynamic process info + dynProcessInfo = dynProcessArray[index]; + + // Fetch a reference to the desired DLL array + RArray<TATDllInfo>& dllArray = dynProcessInfo->iDlls; + + // Take the count of dll info items + TInt count( dllArray.Count() ); + LOGSTR2( "STSE > dllArray.Count( %i )", count ); + + // Create buffers + TBuf<KDllLoadBufLength> traceBuf; + TBuf8<KDllLoadBufLength> dllBuf; + + for ( TInt x = 0; x < count; x++ ) + { + dllBuf.Format( KDllLoad, &dllArray[x].iName, dllArray[x].iLoadTime, + dllArray[x].iStartAddress, dllArray[x].iEndAddress ); + traceBuf.Copy( dllBuf ); + + // Log the string through trace + iError = LogThroughTrace( traceBuf ); + if ( iError != KErrNone ) + { + LOGSTR2( "STSE > LogThroughTrace() err( %i )", iError ); + } + } + + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::StopSubtest2() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::StopSubtest2( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::StopSubtest2()" ); + + iError = KErrNone; + + // Read the sub test ID at index 0 + TBuf8<KATMaxSubtestIdLength> subTestName; + iError = aMessage.Read( 0, subTestName ); + + // Return if reading was not successful + if ( iError != KErrNone ) + { + return iError; + } + + // Create another (non-8-bit) descriptor for logging to trace, + // and copy the contents + TBuf<KATMaxSubtestIdLength> subTestNameTrace; + subTestNameTrace.Copy( subTestName ); + + // Make a buffer for logging thru trace + TBuf<KTestEndBufLength> loggingBuf; + + // Copy the line tag into the buffer + loggingBuf.Copy( KSubtestEnd ); + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + loggingBuf.AppendNum( timeFrom1970, EHex ); + + // Append a space + loggingBuf.Append( KSpaceTrace ); + + // Append the sub test ID + loggingBuf.Append( subTestNameTrace ); + + // Append a new line + loggingBuf.Append( KNewLineTrace ); + + // Log the string through trace + iError = LogThroughTrace( loggingBuf ); + + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::GetCurrentAllocsL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::GetCurrentAllocsL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::GetCurrentAllocsL()" ); + + iError = KErrNone; + + // Read the process ID at index 0 + TUint processId = aMessage.Int0(); + TUint32 allocNumber( 0 ); + TUint32 allocSize( 0 ); + + // Buffer position + TInt pos( 0 ); + + // The length of the buffer to be constructed for allocation number and size + TInt bufferLength = KWordSize + KWordSize; + + // Get the dynamic process info array + RPointerArray<CATDynProcessInfo> dynProcessArray = + iStorageServer.DynProcessInfoArray(); + + // Construct a CATDynProcessInfo object with the given process ID for searching + CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId ); + + // Find the index of a CATDynProcessInfo object with the given process ID + TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare ); + TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order ); + delete dynProcessInfo; + dynProcessInfo = NULL; + + // Return, if a process with the requested process ID was not found + if ( index == KErrNotFound ) + { + return index; + } + + // Otherwise get the wanted dynamic process info + dynProcessInfo = dynProcessArray[index]; + + // Get the desired process's associated session object + CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject; + + // Get the alloc info array of that session object + RArray<TAllocInfo> allocInfo = sessionObject->AllocInfoArray(); + + // Get the values for current allocations number and size + allocNumber = allocInfo.Count(); + + // Calculate the total size of the current allocations + for ( TUint32 i = 0; i < allocNumber; i++ ) + { + allocSize += allocInfo[i].iAllocSize; + } + + LOGSTR2( "STSE allocSize: %u", allocSize ); + LOGSTR2( "STSE iCurAllocSize: %u", iCurAllocSize ); + + CBufFlat* allocInfoBuf; + // Construct allocInfoBuf and expand it before the beginning (index 0) + allocInfoBuf = CBufFlat::NewL( bufferLength ); + CleanupStack::PushL( allocInfoBuf ); + allocInfoBuf->ExpandL( 0, bufferLength ); + + // Write the current number of allocations of the requested process into the buffer. + allocInfoBuf->Write( pos, &allocNumber, KWordSize ); + + // Move the position one word onwards + pos += KWordSize; + + // Write the current total size of the allocations of the requested process into the + // buffer. + allocInfoBuf->Write( pos, &allocSize, KWordSize ); + + // Make a pointer descriptor that points to the data of allocInfoBuf + TPtr8 bufPtr( allocInfoBuf->Ptr(0) ); + + // Write the whole buffer into aMessage at index 1 for the client + aMessage.WriteL( 1, bufPtr ); + + CleanupStack::PopAndDestroy( allocInfoBuf ); + + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::GetMaxAllocsL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::GetMaxAllocsL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::GetMaxAllocsL()" ); + + iError = KErrNone; + + // Read the process ID at index 0 + TUint processId = aMessage.Int0(); + TUint32 allocNumber( 0 ); + TUint32 allocSize( 0 ); + + // Buffer position + TInt pos( 0 ); + + // The length of the buffer to be constructed for allocation number and size + TInt bufferLength = KWordSize + KWordSize; + + // Get the dynamic process info array + RPointerArray<CATDynProcessInfo> dynProcessArray = + iStorageServer.DynProcessInfoArray(); + + // Construct a CATDynProcessInfo object with the given process ID for searching + CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId ); + + // Find the index of a CATDynProcessInfo object with the given process ID + TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare ); + TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order ); + delete dynProcessInfo; + dynProcessInfo = NULL; + + // Return, if a process with the requested process ID was not found + if ( index == KErrNotFound ) + { + return index; + } + + // Otherwise get the wanted dynamic process info + dynProcessInfo = dynProcessArray[index]; + + // Get the desired process's associated session object + CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject; + + // Get values for the maximum allocations number and size + allocNumber = sessionObject->iMaxAllocs; + allocSize = sessionObject->iMaxAllocSize; + + CBufFlat* allocInfoBuf; + // Construct allocInfoBuf and expand it before the beginning (index 0) + allocInfoBuf = CBufFlat::NewL( bufferLength ); + CleanupStack::PushL( allocInfoBuf ); + allocInfoBuf->ExpandL( 0, bufferLength ); + + // Write the maximum number of allocations of the requested process into the buffer. + allocInfoBuf->Write( pos, &allocNumber, KWordSize ); + + // Move the position one word onwards + pos += KWordSize; + + // Write the maximum total size of the allocations of the requested process into the + // buffer. + allocInfoBuf->Write( pos, &allocSize, KWordSize ); + + // Make a pointer descriptor that points to the data of allocInfoBuf + TPtr8 bufPtr( allocInfoBuf->Ptr(0) ); + + // Write the whole buffer into aMessage at index 1 for the client + aMessage.WriteL( 1, bufPtr ); + + CleanupStack::PopAndDestroy( allocInfoBuf ); + + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::CancelLoggingL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::CancelLoggingL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::CancelLoggingL()" ); + + iError = KErrNone; + + // Read the process ID at index 0 + TUint processId = aMessage.Int0(); + + // FIND THE REQUESTED PROCESS + + // Get the dynamic process array + RPointerArray<CATDynProcessInfo> dynProcessArray = + iStorageServer.DynProcessInfoArray(); + + // Construct a CATDynProcessInfo object with the given process ID for searching + CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId ); + + // Find the index of a CATDynProcessInfo object with the given process ID + TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare ); + TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order ); + delete dynProcessInfo; + dynProcessInfo = NULL; + + // Return, if a process with the requested process ID was not found + if ( index == KErrNotFound ) + { + return index; + } + + // Otherwise get the wanted dynamic process info + dynProcessInfo = dynProcessArray[index]; + + // Get the session object of the requested process + CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject; + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Make a buffer for logging "logging cancelled" + TBuf8<KCancelBufLength> loggingBuf; + + // Copy the "logging cancelled" tag into the buffer with the current time + loggingBuf.AppendFormat( KLoggingCancelled, timeFrom1970 ); + + // Log the buffer eather to a file or to debug channel depending on the current + // logging mode + + if ( sessionObject->iLoggingOngoing && + sessionObject->iLogOption == EATLogToFile ) + { + // Write the buffer into the file + sessionObject->iFile.Write( loggingBuf ); + } + + else if ( sessionObject->iLoggingOngoing && + sessionObject->iLogOption == EATLogToTrace ) + { + // Make a buffer for logging to trace + TBuf<KCancelBufLength> traceBuf; + traceBuf.Copy( loggingBuf ); + + // Write the buffer into the debug channel + RDebug::Print( KTraceMessage, processId ,&traceBuf ); + } + + // Switch off logging of the requested process + sessionObject->iLogOption = EATLoggingOff; + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::HandleError +// Internally used for handling error situations. +// ----------------------------------------------------------------------------- +// +void CATStorageServerSession::HandleError( TInt aError ) + { + LOGSTR1( "STSE void CATStorageServerSession::HandleError()" ); + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Make a buffer that will be logged into the opened logging file + TBufC8<KErrOccuredBufLength> loggingBuf; + + TPtr8 bufPtr( loggingBuf.Des() ); + + // Write the error code to the buffer + bufPtr.Format( KErrorOccured, aError ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + bufPtr.AppendNum( timeFrom1970, EHex ); + + // Append a new line + bufPtr.Append( KNewLine ); + + // Write the buffer into a file (if possible in the current condition) + iFile.Write( loggingBuf ); + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::HandleErrorTrace() +// Internally used for handling error situations. +// ----------------------------------------------------------------------------- +// +void CATStorageServerSession::HandleErrorTrace( TInt aError ) + { + LOGSTR1( "STSE void CATStorageServerSession::HandleErrorTrace()" ); + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + // Make a buffer that will be logged + TBuf<KErrOccuredBufLength> traceBuf; + + // Write the error code to the buffer + traceBuf.Format( KErrorOccuredTrace, aError ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + traceBuf.AppendNum( timeFrom1970, EHex ); + + // Append a new line + traceBuf.Append( KNewLineTrace ); + + RDebug::Print( KTraceMessage, iProcessId , &traceBuf ); + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::OpenFsAndFile +// Internally used for opening a handle to the file server and a file +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::OpenFsAndFile( const TDesC& aFileName, + const TDesC8& aProcessName ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::OpenFsAndFile()" ); + + // Connect file server, return if error occured + iError = iFileServer.Connect(); + if ( iError ) + { + iFileServer.Close(); + return iError; + } + + // Open a file + TBuf<KMaxFileName> fileNameBuf; + iError = TATDriveInfo::CreatePath( fileNameBuf, aFileName, iFileServer ); + + // Return, if an error occured, and it + // is not KErrAlreadyExists + if ( iError && iError != KErrAlreadyExists ) + { + iFileServer.Close(); + return iError; + } + + // Save the file name for this session + CnvUtfConverter::ConvertFromUnicodeToUtf8( iLogFile, fileNameBuf ); + + // Try to open file + CheckIfFileAlreadyExist( fileNameBuf ); + + // If a data file with the requested name already existed, and was opened + // successfully, check the version of the file. If the line telling the version of + // the file is not the expected, replace the file + // If cannot open the file(error is KErrInUse), generate new filename and + // then try to create new file. + if ( iError == KErrNone ) + { + CheckFileVersion( fileNameBuf ); + } + else if ( iError == KErrInUse ) + { + GenerateNewFileName( fileNameBuf, aProcessName ); + + // Save the file name for this session + CnvUtfConverter::ConvertFromUnicodeToUtf8( iLogFile, fileNameBuf ); + } + LOGSTR2( "STSE > iError(%i)", iError ); + + // If the file does not exist, create it. Write also the version number of + // the file at the beginning of the new file + if ( iError == KErrNotFound ) + { + iError = iFile.Create( iFileServer, fileNameBuf, EFileWrite ); + + if ( !iError ) + { + iError = iFile.Write( KDataFileVersion ); + } + } + + if ( iError ) + { + iFile.Close(); + iFileServer.Close(); + return iError; + } + + // Seek the end of the file and set the current file position there + TInt offset = 0; + iError = iFile.Seek( ESeekEnd, offset ); + + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::GenerateNewFileName +// Called internally when need generate new file name. +// ----------------------------------------------------------------------------- +// +void CATStorageServerSession::GenerateNewFileName( TDes& aFileName, + const TDesC8& aProcessName ) + { + LOGSTR1( "STSE void CATStorageServerSession::GenerateNewFileName()" ); + + // Extension + TBuf<KExtensionLength> extension; + + // Parse file extension + ParseExtension( aFileName, extension ); + + // Try to find UID3 from current process name + TInt uidErr( KErrBadName ); + TBuf<KMaxFileName> unicodeFile; + + // Converts text encoded using the Unicode transformation format UTF-8 + // into the Unicode UCS-2 character set. + CnvUtfConverter::ConvertToUnicodeFromUtf8( unicodeFile, aProcessName ); + LOGSTR2( "STSE > unicodeFile(%S)", &unicodeFile ); + + // Find square brackets + TInt sPos( unicodeFile.Find( KOpenSquareBracket ) ); + TInt ePos( unicodeFile.Find( KCloseSquareBracket ) ); + LOGSTR3( "STSE > sPos(%i), ePos(%i)", sPos, ePos ); + + if ( sPos != KErrNotFound && ePos != KErrNotFound ) + { + TBuf<KProcessUidLength> processUid; + TInt pEnd( ePos - sPos - KOpenSquareBracket().Length() ); + LOGSTR2( "STSE > pEnd(%i)", pEnd ); + + // Copy UID value + if ( pEnd > 0 ) + { + processUid.Copy( unicodeFile.Mid( + sPos + KOpenSquareBracket().Length(), pEnd ) ); + LOGSTR2( "STSE > processUid(%S)", &processUid ); + } + + if ( aFileName.Find( processUid ) == KErrNotFound ) + { + // UID not exist, create new filename + // Append uid to filename (<file name>_<uid>.<extension>) + aFileName.Append( KUnderLine ); + aFileName.Append( processUid ); + aFileName.Append( extension ); + // Try to open file + CheckIfFileAlreadyExist( aFileName ); + + if ( iError == KErrNone ) + { + uidErr = KErrNone; + CheckFileVersion( aFileName ); + } + } + } + + if ( uidErr == KErrBadName && iError != KErrNotFound ) + { + // Need re-create file name, add end off file _xx (xx=01, 02...) + LOGSTR2( "STSE > Re-create file name, aFileName(%S)", &aFileName ); + + // Parse file extension if exists. + ParseExtension( aFileName, extension ); + + // Temp file name + TBuf<KMaxFileName> tempName; + + for ( TInt i = KNameIndexStart; i < KNameIndexEnd; i++ ) + { + tempName.Delete( 0, tempName.MaxLength() ); + tempName.Format( KFormat, &aFileName, &KUnderLine, i, &extension ); + LOGSTR2( "STSE > tempName(%S)", &tempName ); + // Try to open file + CheckIfFileAlreadyExist( tempName ); + + if ( iError == KErrNone || iError == KErrNotFound ) + { + aFileName.Copy( tempName ); + break; + } + } + } + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::ParseExtension +// Method is used to parse file name extension. +// ----------------------------------------------------------------------------- +// +void CATStorageServerSession::ParseExtension( + TDes& aFileName, TDes& aExtension ) + { + LOGSTR2( "STSE void CATStorageServerSession::ParseExtension(%S)", + &aFileName ); + + // Parse current file name + TParse parse; + // Set up the TParse object + parse.Set( aFileName, NULL, NULL ); + + // Tests whether an extension is present. + if ( parse.ExtPresent() ) + { + // Gets the extension + aExtension.Copy( parse.Ext() ); + // Remove extension from file name + TInt pos( aFileName.Find( aExtension ) ); + aFileName.Delete( pos, aFileName.Length() ); + LOGSTR3( "STSE > aFileName(%S), aExtension(%S)", + &aFileName, &aExtension ); + } + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::CheckIfFileAlreadyExist +// Method is used to check that file exists and is valid. +// ----------------------------------------------------------------------------- +// +void CATStorageServerSession::CheckIfFileAlreadyExist( + const TDes& aFileName ) + { + LOGSTR2( "STSE void CATStorageServerSession::CheckIfFileAlreadyExist(%S)", + &aFileName ); + + iError = iFile.Open( iFileServer, aFileName, EFileWrite ); + LOGSTR2( "STSE > iError(%i)", iError ); + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::CheckFileVersion +// Method is used to check file version. +// ----------------------------------------------------------------------------- +// +void CATStorageServerSession::CheckFileVersion( + const TDes& aFileName ) + { + LOGSTR2( "STSE void CATStorageServerSession::CheckFileVersion(%S)", + &aFileName ); + + TBuf8<KVersionStringLength> versionString; + + // Read version information from the beginning of the file (offset 0) + iFile.Read( 0, versionString, KVersionStringLength ); + + // Delete the existing file, if the version string read from the file does not + // match with KDataFileVersion. + if ( versionString.Compare( KDataFileVersion ) != 0 ) + { + // Close the existing, opened file, and delete it + iFile.Close(); + iError = iFileServer.Delete( aFileName ); + + // If the deletion was successful, set iError = KErrNotFound, so a new + // file will be created in the next few lines + if ( iError == KErrNone ) + { + iError = KErrNotFound; + } + } + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::CloseFsAndFile +// Internally used for closing a handle to the file server and a file +// ----------------------------------------------------------------------------- +// +void CATStorageServerSession::CloseFsAndFile() + { + LOGSTR1( "STSE void CATStorageServerSession::CloseFsAndFile()" ); + + // Close the file + iFile.Close(); + + // Close the server session and return the error code + iFileServer.Close(); + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::PrintLeaksL() +// Called internally when a process is closed. Prints possible memory leaks +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::PrintLeaksL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::PrintLeaksL()" ); + + // Panic both the client and the server, if this method is called in a wrong + // state (logging should be ongoing, and the system should be logging into a file, + // not into debug channel) + if ( !iLoggingOngoing || iLogOption != EATLogToFile ) + { + PanicClient( EAToolInternalError, aMessage ); + StorageServerPanic( KCategoryServer, EAToolInternalError ); + } + + LOGMEM; + + // A pointer to a buffer of call stack's memory addresses + CBufFlat* stackBuf = NULL; + + iError = KErrNone; + + TUint32 callStackAddr; + + // Number of leaks + TInt leakCount = iLeakArray.Count(); + + // Variable for the number of memory addresses in the call stack + TInt addrCount( 0 ); + + // Buffer position + TInt pos( 0 ); + + // Go through all the leaks + for ( TInt i = 0; i < leakCount; i++ ) + { + pos = 0; + + // Get the call stack buffer of the the leak i. + stackBuf = const_cast<CBufFlat*>( iLeakArray[i]->iCallstackBuf ); + + // Read the first word of the buffer. This includes the number of + // memory addresses stored in the current stackBuf + stackBuf->Read( pos, &addrCount, KWordSize ); + + // Move the position one word onwards. + pos += KWordSize; + + // Construct a buffer for the string to be written into the logging file + // because of this memory leak. MEM_LEAK: <Memory address> <Time stamp> + // <Allocation size> <Call stack address> <Call stack address> ... + HBufC8* leakString = + HBufC8::NewL( KMemleakLength + + KHexa32Length + + KSpaceLength + KHexa64Length + + KSpaceLength + KHexa32Length + + ( addrCount * (KSpaceLength + KHexa32Length) ) + + KNewlineLength + ); + + // Make a pointer descriptor that points to leakString + TPtr8 leakStringPtr( leakString->Des() ); + + // Append the tag implying a memory leak line in the data file + leakStringPtr.Append( KMemoryLeak ); + + // Append the address of the memory leak + TUint32 memAddress = iLeakArray[i]->iMemAddress; + leakStringPtr.AppendNum( memAddress, EHex ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + leakStringPtr.Append( KSpace ); + TInt64 allocTime = iLeakArray[i]->iAllocTime; + leakStringPtr.AppendNum( allocTime, EHex ); + + // Append the size of the allocation in the 32-bit (max 8 characters) hexadecimal + // text format. + leakStringPtr.Append( KSpace ); + TInt allocSize = iLeakArray[i]->iAllocSize; + leakStringPtr.AppendNum( allocSize, EHex ); + + // Go through all call stack's memory addresses associated with + // the current memory leak + for ( TInt j = 0; j < addrCount; j++ ) + { + // Read the next call stack's memory address stored in the buffer. + stackBuf->Read( pos, &callStackAddr, KWordSize ); + + // Append the read memory address as a hexadecimal number + leakStringPtr.AppendFormat( KHexaNumber, callStackAddr ); + + // Move the pos variable one word onwards. + pos += KWordSize; + } + + leakStringPtr.Append( KNewLine ); + + // Set stackBuf to NULL, because it is not used anymore. + stackBuf = NULL; + + // Write the constructed string into the data file and return if error + iError = iFile.Write( *leakString ); + + delete leakString; + + if ( iError != KErrNone ) + { + return iError; + } + + } // The outer for + + LOGSTR1( "STSE End of CATStorageServerSession::PrintLeaks()" ); + LOGMEM; + + // Empty the leak array and delete the referenced objects + iLeakArray.ResetAndDestroy(); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::SetLogOption() +// For setting the logging mode. +// ----------------------------------------------------------------------------- +// +void CATStorageServerSession::SetLogOption( const RMessage2& aMessage ) + { + LOGSTR1( "STSE void CATStorageServerSession::SetLogOption()" ); + + // Panic both the client and the server, if this method is called in a wrong + // state (logging must not be ongoing when changing the mode of operation). + // So, the mode cannot be changed "on the fly". + if ( iLoggingOngoing ) + { + PanicClient( EAToolInternalError, aMessage ); + StorageServerPanic( KCategoryServer, EAToolInternalError ); + } + + iLogOption = static_cast<TATLogOption>( aMessage.Int3() ); + + // The default is EATLogToFile + if ( iLogOption == EATUseDefault ) + { + iLogOption = KDefaultLoggingMode; + } + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::LogThroughTrace() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::LogThroughTrace( const TDesC& aLogString ) const + { + LOGSTR1( "STSE TInt CATStorageServerSession::LogThroughTrace()" ); + + // Return KErrNotSupported, if a logging session is not currently ongoing, or + // the logging mode is not EATLogToTrace + if ( !iLoggingOngoing || iLogOption != EATLogToTrace) + { + return KErrNotSupported; + } + + RDebug::Print( KTraceMessage, iProcessId, &aLogString ); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::AllocInfoArray +// ----------------------------------------------------------------------------- +// +RArray<TAllocInfo>& CATStorageServerSession::AllocInfoArray() + { + LOGSTR1( "STSE RArray<TAllocInfo>& CATStorageServerSession::AllocInfoArray()" ); + + return iAllocInfoArray; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::PanicClient +// Creates a panic in the associated client's code. +// ----------------------------------------------------------------------------- +// +void CATStorageServerSession::PanicClient( TInt aPanic, const RMessage2& aMessage ) + { + LOGSTR1( "STSE void CATStorageServerSession::PanicClient()" ); + + aMessage.Panic( KCategoryClient, aPanic ); + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::GetLoggingFileL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::GetLoggingFileL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::GetLoggingFileL()" ); + + iError = KErrNone; + + // Read the process ID at index 0 + TUint processId = aMessage.Int0(); + + // Get the dynamic process info array + RPointerArray<CATDynProcessInfo> dynProcessArray = + iStorageServer.DynProcessInfoArray(); + + // Construct a CATDynProcessInfo object with the given process ID for searching + CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId ); + + // Find the index of a CATDynProcessInfo object with the given process ID + TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare ); + TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order ); + delete dynProcessInfo; + dynProcessInfo = NULL; + + // Return, if a process with the requested process ID was not found + if ( index == KErrNotFound ) + { + return index; + } + + // Otherwise get the wanted dynamic process info + dynProcessInfo = dynProcessArray[index]; + + // Get the desired process's associated session object + CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject; + + // Write the whole buffer into aMessage at index 1 for the client + aMessage.WriteL( 1, sessionObject->iLogFile ); + + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::GetUdebL() +// ----------------------------------------------------------------------------- +// +TInt CATStorageServerSession::GetUdebL( const RMessage2& aMessage ) + { + LOGSTR1( "STSE TInt CATStorageServerSession::GetUdebL()" ); + + iError = KErrNone; + + // Read the process ID at index 0 + TUint processId = aMessage.Int0(); + + // Get the dynamic process info array + RPointerArray<CATDynProcessInfo> dynProcessArray = + iStorageServer.DynProcessInfoArray(); + + // Construct a CATDynProcessInfo object with the given process ID for searching + CATDynProcessInfo* dynProcessInfo = new (ELeave) CATDynProcessInfo( processId ); + + // Find the index of a CATDynProcessInfo object with the given process ID + TLinearOrder<CATDynProcessInfo> order( CATDynProcessInfo::Compare ); + TInt index = dynProcessArray.FindInOrder( dynProcessInfo, order ); + delete dynProcessInfo; + dynProcessInfo = NULL; + + // Return, if a process with the requested process ID was not found + if ( index == KErrNotFound ) + { + return index; + } + + // Otherwise get the wanted dynamic process info + dynProcessInfo = dynProcessArray[index]; + + // Get the desired process's associated session object + CATStorageServerSession* sessionObject = dynProcessInfo->iSessionObject; + + TBuf8<KMaxVersionName> isUdeb; + if ( sessionObject->iIsUdeb == 1 ) + { + isUdeb.Copy( KUdeb() ); + } + else if ( sessionObject->iIsUdeb == 0 ) + { + isUdeb.Copy( KUrel() ); + } + else + { + return KErrNotFound; + } + // Write the whole buffer into aMessage at index 1 for the client + aMessage.WriteL( 1, isUdeb ); + + return iError; + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::SetUdeb() +// ----------------------------------------------------------------------------- +// +void CATStorageServerSession::SetUdeb( const RMessage2& aMessage ) + { + LOGSTR1( "STSE void CATStorageServerSession::SetUdeb()" ); + + iIsUdeb = aMessage.Int0(); + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::LogAbnormalEnd() +// ----------------------------------------------------------------------------- +// +void CATStorageServerSession::LogAbnormalEnd() + { + LOGSTR1( "STSE void CATStorageServerSession::LogAbnormalEnd()" ); + + // Get the current universal time + TInt64 timeFrom1970( GetTime() ); + + switch ( iLogOption ) + { + case EATLogToTrace: + { + // Make a buffer that will be logged + TBuf<KEndAbnormalBufLength> traceBuf; + + // Write the process id to the buffer + traceBuf.Format( KProcessEndAbnormalTrace, iProcessId ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + traceBuf.AppendNum( timeFrom1970, EHex ); + + // Append a new line + traceBuf.Append( KNewLineTrace ); + + // Write the buffer into the debug channel + RDebug::Print( KTraceMessage, iProcessId, &traceBuf ); + } + break; + + case EATLogToFile: + { + // Make a buffer that will be logged + TBuf8<KEndAbnormalBufLength> loggingBuf; + + // Write the process id to the buffer + loggingBuf.Format( KProcessEndAbnormal, iProcessId ); + + // Append the current time in the 64-bit (max 16 characters) hexadecimal text + // format + loggingBuf.AppendNum( timeFrom1970, EHex ); + + // Append a new line + loggingBuf.Append( KNewLine ); + + // Write the buffer into a file (if possible in the current condition) + iFile.Write( loggingBuf ); + } + break; + + default: + break; + } + } + +// ----------------------------------------------------------------------------- +// CATStorageServerSession::GetTime() +// Get the current universal time +// ----------------------------------------------------------------------------- +// +TInt64 CATStorageServerSession::GetTime() + { + LOGSTR1( "STSE void CATStorageServerSession::GetTime()" ); + + // Get the current universal time + iTime.UniversalTime(); + + // Change the time format that tells the number of microseconds from January First, + // 0 AD nominal Gregorian, into a format that tells the number of microseconds from + // January First, 1970 AD nominal Gregorian. This is a more generic format and + // can be directly exploited by the PC code parsing the data file that this + // server generates. + return ( iTime.Int64() - iMicroSecondsAt1970 ); + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/sis/atstorageserver.pkg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/sis/atstorageserver.pkg Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,37 @@ +; +; 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: +; +; +; An installation file for AnalyzeTool StorageServer +; + +;Language - standard language definitions +&EN + +; standard SIS file header +#{"ATStorageServer"},(0xA22E6C80),1,8,1 + +;Localised Vendor name +%{"Vendor-EN"} + +;Unique Vendor name +:"Vendor" + +;Supports Series 60 v 3.0 +[0x101F7961], 0, 0, 0, {"Series60ProductID"} + +; 4 Files to install +"\epoc32\release\armv5\urel\atoolstorageserver.exe"-"!:\sys\bin\atoolstorageserver.exe" +"\epoc32\release\armv5\urel\atoolstorageserverclnt.dll"-"!:\sys\bin\atoolstorageserverclnt.dll" diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/storageserver/sis/atstorageserver_udeb.pkg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/storageserver/sis/atstorageserver_udeb.pkg Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,37 @@ +; +; 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: +; +; +; An installation file for AnalyzeTool StorageServer +; + +;Language - standard language definitions +&EN + +; standard SIS file header +#{"ATStorageServer"},(0xA22E6C80),1,8,1 + +;Localised Vendor name +%{"Vendor-EN"} + +;Unique Vendor name +:"Vendor" + +;Supports Series 60 v 3.0 +[0x101F7961], 0, 0, 0, {"Series60ProductID"} + +; 4 Files to install +"\epoc32\release\armv5\udeb\atoolstorageserver.exe"-"!:\sys\bin\atoolstorageserver.exe" +"\epoc32\release\armv5\udeb\atoolstorageserverclnt.dll"-"!:\sys\bin\atoolstorageserverclnt.dll" diff -r ccab7f1f8266 -r a71a3e32a2ae analyzetool/symbian_version.hrh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/symbian_version.hrh Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,43 @@ +/* +* 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: Symbian version configuration file +* +*/ + +#ifndef __SYMBIAN_VERSION_HRH +#define __SYMBIAN_VERSION_HRH + +// S60 and Symbian version number enumeration definitions + +#define S60_30 30 +#define S60_31 31 +#define S60_32 32 +#define S60_50 50 +#define S60_51 91 +#define S60_52 92 +#define SYMBIAN_1 50 +#define SYMBIAN_2 91 +#define SYMBIAN_3 92 +#define SYMBIAN_4 101 + + +/** + * Defines the S60 or Symbian version used by this component. This flag can be + * used to variate the source code based on the SDK in use. The value of the + * flag should be always changed to reflect the current build environment. + */ +#define SYMBIAN_VERSION_SUPPORT SYMBIAN_4 + + +#endif // __SYMBIAN_VERSION_HRH diff -r ccab7f1f8266 -r a71a3e32a2ae group/bld.inf --- a/group/bld.inf Mon May 03 13:58:41 2010 +0300 +++ b/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -21,4 +21,6 @@ #include "../osrndtools_plat/group/bld.inf" #include "../stif/group/bld.inf" #include "../memspy/group/bld.inf" -#include "../hti/group/bld.inf" \ No newline at end of file +#include "../hti/group/bld.inf" +#include "../piprofiler/group/bld.inf" +#include "../analyzetool/group/bld.inf" \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae hti/hti_plat/hti_api/inc/HtiCommPluginInterface.h --- a/hti/hti_plat/hti_api/inc/HtiCommPluginInterface.h Mon May 03 13:58:41 2010 +0300 +++ b/hti/hti_plat/hti_api/inc/HtiCommPluginInterface.h Thu May 13 23:59:27 2010 +0300 @@ -113,6 +113,6 @@ TUid iDtor_ID_Key; }; -#include <HTICommPluginInterface.inl> +#include <HtiCommPluginInterface.inl> #endif diff -r ccab7f1f8266 -r a71a3e32a2ae hti/hti_plat/hti_api/inc/HtiServicePluginInterface.h --- a/hti/hti_plat/hti_api/inc/HtiServicePluginInterface.h Mon May 03 13:58:41 2010 +0300 +++ b/hti/hti_plat/hti_api/inc/HtiServicePluginInterface.h Thu May 13 23:59:27 2010 +0300 @@ -110,6 +110,6 @@ TUid iDtor_ID_Key; }; -#include <HTIServicePluginInterface.inl> +#include <HtiServicePluginInterface.inl> #endif diff -r ccab7f1f8266 -r a71a3e32a2ae hti/hti_plat/hti_api/inc/HtiVersion.h --- a/hti/hti_plat/hti_api/inc/HtiVersion.h Mon May 03 13:58:41 2010 +0300 +++ b/hti/hti_plat/hti_api/inc/HtiVersion.h Thu May 13 23:59:27 2010 +0300 @@ -25,13 +25,13 @@ // CONSTANTS const TUint8 KHtiVersionMajor = 2; -const TUint8 KHtiVersionMinor = 18; +const TUint8 KHtiVersionMinor = 22; const TUint8 KHtiVersionBuild = 0; const TUint16 KHtiVersionYear = 2010; -const TUint8 KHtiVersionMonth = 3; -const TUint8 KHtiVersionWeek = 9; -const TUint8 KHtiVersionDay = 5; +const TUint8 KHtiVersionMonth = 4; +const TUint8 KHtiVersionWeek = 17; +const TUint8 KHtiVersionDay = 30; // MACROS diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/CommandLine/Source/MemSpyCommandLine.cpp --- a/memspy/CommandLine/Source/MemSpyCommandLine.cpp Mon May 03 13:58:41 2010 +0300 +++ b/memspy/CommandLine/Source/MemSpyCommandLine.cpp Thu May 13 23:59:27 2010 +0300 @@ -390,26 +390,49 @@ TInt err = KErrGeneral; RProcess proc; + + // Try to run server first + err = proc.Create( KMemSpyProcessName0, KNullDesC ); + if ( err == KErrNone ) + { + TRACE( RDebug::Printf( "[MemSpyCmdLine] CMemSpyCommandLine::LaunchMemSpyL() - Create server process successfully... - this: 0x%08x", this ) ); - // First try with s60 UI - err = proc.Create( KMemSpyProcessName1, KNullDesC ); - if ( err == KErrNone ) - { - TFullName fullName; - proc.FullName( fullName ); - TRACE( RDebug::Print( _L("[MemSpyCmdLine] CMemSpyCommandLine::LaunchMemSpyL() - Create S60 UI process successfully... - this: 0x%08x, name: %S"), this, &fullName ) ); + TRequestStatus status; + proc.Rendezvous( status ); + proc.Resume(); + + TRACE( RDebug::Printf( "[MemSpyCmdLine] CMemSpyCommandLine::LaunchMemSpyL() - MemSpy resumed, waiting for Rendezvous... - this: 0x%08x", this ) ); + + User::WaitForRequest( status ); + err = status.Int(); + proc.Close(); + + TRACE( RDebug::Printf( "[MemSpyCmdLine] CMemSpyCommandLine::LaunchMemSpyL() - Rendezvous complete: %d, this: 0x%08x", err, this ) ); + } - TRequestStatus status; - proc.Rendezvous( status ); - proc.Resume(); - - TRACE( RDebug::Printf( "[MemSpyCmdLine] CMemSpyCommandLine::LaunchMemSpyL() - MemSpy resumed, waiting for Rendezvous... - this: 0x%08x", this ) ); - User::WaitForRequest( status ); - err = status.Int(); - proc.Close(); - - TRACE( RDebug::Printf( "[MemSpyCmdLine] CMemSpyCommandLine::LaunchMemSpyL() - Rendezvous complete: %d, this: 0x%08x", err, this ) ); - } + // If server is not available, try with s60 UI + if ( err != KErrNone ) + { + err = proc.Create( KMemSpyProcessName1, KNullDesC ); + if ( err == KErrNone ) + { + TFullName fullName; + proc.FullName( fullName ); + TRACE( RDebug::Print( _L("[MemSpyCmdLine] CMemSpyCommandLine::LaunchMemSpyL() - Create S60 UI process successfully... - this: 0x%08x, name: %S"), this, &fullName ) ); + + TRequestStatus status; + proc.Rendezvous( status ); + proc.Resume(); + + TRACE( RDebug::Printf( "[MemSpyCmdLine] CMemSpyCommandLine::LaunchMemSpyL() - MemSpy resumed, waiting for Rendezvous... - this: 0x%08x", this ) ); + User::WaitForRequest( status ); + err = status.Int(); + proc.Close(); + + TRACE( RDebug::Printf( "[MemSpyCmdLine] CMemSpyCommandLine::LaunchMemSpyL() - Rendezvous complete: %d, this: 0x%08x", err, this ) ); + } + } + if ( err != KErrNone ) { // Try console UI diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/Console/Include/ConsoleMenu.h --- a/memspy/Console/Include/ConsoleMenu.h Mon May 03 13:58:41 2010 +0300 +++ b/memspy/Console/Include/ConsoleMenu.h Thu May 13 23:59:27 2010 +0300 @@ -26,22 +26,22 @@ // Engine includes #include <memspy/engine/memspyengine.h> #include <memspy/engine/memspyengineobserver.h> - +#include <memspysession.h> // User includes #include "ConsoleConstants.h" // Classes referenced class CConsoleBase; - +class RMemSpySession; class CMemSpyConsoleMenu : public CActive, public MMemSpyEngineObserver { public: - static CMemSpyConsoleMenu* NewLC( CMemSpyEngine& aEngine, CConsoleBase& aConsole ); + static CMemSpyConsoleMenu* NewLC( RMemSpySession& aSession, CConsoleBase& aConsole ); ~CMemSpyConsoleMenu(); private: - CMemSpyConsoleMenu( CMemSpyEngine& aEngine, CConsoleBase& aConsole ); + CMemSpyConsoleMenu( RMemSpySession& aEngine, CConsoleBase& aConsole ); void ConstructL(); public: // API @@ -74,8 +74,10 @@ void InitiateMemSpyClientServerOperationL( TInt aOpCode ); private: // Data members - CMemSpyEngine& iEngine; + RMemSpySession& iSession; CConsoleBase& iConsole; + + TMemSpyOutputType iOutputType; // TBuf<KMemSpyMaxInputBufferLength> iCommandBuffer; TPoint iCommandPromptPos; diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/Console/Source/ConsoleDWOperation.cpp --- a/memspy/Console/Source/ConsoleDWOperation.cpp Mon May 03 13:58:41 2010 +0300 +++ b/memspy/Console/Source/ConsoleDWOperation.cpp Thu May 13 23:59:27 2010 +0300 @@ -56,7 +56,7 @@ #endif iWaiter = new(ELeave) CActiveSchedulerWait(); - iOperation = CMemSpyDeviceWideOperations::NewL( iEngine, *this, aOperation ); + //iOperation = CMemSpyDeviceWideOperations::NewL( iEngine, *this, aOperation ); #ifdef _DEBUG RDebug::Printf("[MCon] CMemSpyDeviceWideOperationWaiter::ExecuteL() - starting scheduler wait..." ); diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/Console/Source/ConsoleMain.cpp --- a/memspy/Console/Source/ConsoleMain.cpp Mon May 03 13:58:41 2010 +0300 +++ b/memspy/Console/Source/ConsoleMain.cpp Thu May 13 23:59:27 2010 +0300 @@ -26,6 +26,7 @@ // Engine includes #include <memspy/engine/memspyengine.h> +#include <memspysession.h> // User includes #include "ConsoleMenu.h" @@ -54,11 +55,12 @@ CleanupStack::PushL( console ); // Engine - CMemSpyEngine* engine = CMemSpyEngine::NewL( fsSession ); - CleanupStack::PushL( engine ); + RMemSpySession session; + User::LeaveIfError(session.Connect()); + CleanupClosePushL(session); // Menu & event handler AO - CMemSpyConsoleMenu::NewLC( *engine, *console ); + CMemSpyConsoleMenu::NewLC( session, *console ); // Play nicely with external processes RProcess::Rendezvous( KErrNone ); diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/Console/Source/ConsoleMenu.cpp --- a/memspy/Console/Source/ConsoleMenu.cpp Mon May 03 13:58:41 2010 +0300 +++ b/memspy/Console/Source/ConsoleMenu.cpp Thu May 13 23:59:27 2010 +0300 @@ -39,18 +39,17 @@ #include "ConsoleDWOperation.h" -CMemSpyConsoleMenu::CMemSpyConsoleMenu( CMemSpyEngine& aEngine, CConsoleBase& aConsole ) -: CActive( EPriorityHigh ), iEngine( aEngine ), iConsole( aConsole ) +CMemSpyConsoleMenu::CMemSpyConsoleMenu( RMemSpySession& aSession, CConsoleBase& aConsole ) +: CActive( EPriorityHigh ), iSession( aSession ), iConsole( aConsole ), iOutputType(EOutputTypeDebug) { CActiveScheduler::Add( this ); - iEngine.SetObserver( this ); + // TODO: iEngine.SetObserver( this ); } CMemSpyConsoleMenu::~CMemSpyConsoleMenu() { Cancel(); - iEngine.SetObserver( NULL ); } @@ -61,9 +60,9 @@ } -CMemSpyConsoleMenu* CMemSpyConsoleMenu::NewLC( CMemSpyEngine& aEngine, CConsoleBase& aConsole ) +CMemSpyConsoleMenu* CMemSpyConsoleMenu::NewLC( RMemSpySession& aSession, CConsoleBase& aConsole ) { - CMemSpyConsoleMenu* self = new(ELeave) CMemSpyConsoleMenu( aEngine, aConsole ); + CMemSpyConsoleMenu* self = new(ELeave) CMemSpyConsoleMenu( aSession, aConsole ); CleanupStack::PushL( self ); self->ConstructL(); return self; @@ -76,7 +75,7 @@ // First line - sink type (defaults to file) _LIT( KLine1, "1 or T. Toggle output mode between file or trace [%S]" ); - if ( iEngine.SinkType() == ESinkTypeDebug ) + if ( iOutputType == EOutputTypeDebug ) { _LIT( KLine1Trace, "Trace" ); iConsole.Printf( KLine1, &KLine1Trace ); @@ -204,14 +203,7 @@ void CMemSpyConsoleMenu::OnCmdSinkTypeToggleL() { - if ( iEngine.SinkType() == ESinkTypeDebug ) - { - iEngine.InstallSinkL( ESinkTypeFile ); - } - else - { - iEngine.InstallSinkL( ESinkTypeDebug ); - } + iOutputType = iOutputType == EOutputTypeFile ? EOutputTypeDebug : EOutputTypeFile; } @@ -224,7 +216,7 @@ _LIT( KMsg, "Ouputting Kernel data..." ); RedrawStatusMessage( KMsg ); - iEngine.HelperHeap().OutputHeapDataKernelL(); + iSession.OutputKernelHeapDataL( iOutputType ); RedrawStatusMessage( KNullDesC ); } @@ -239,14 +231,7 @@ _LIT( KMsg, "Ouputting Kernel Object listing..." ); RedrawStatusMessage( KMsg ); // - CMemSpyEngineHelperKernelContainers& kernelContainerManager = iEngine.HelperKernelContainers(); - CMemSpyEngineGenericKernelObjectContainer* model = kernelContainerManager.ObjectsAllL(); - CleanupStack::PushL( model ); - // - CMemSpyEngineOutputSink& sink = iEngine.Sink(); - model->OutputL( sink ); - // - CleanupStack::PopAndDestroy( model ); + iSession.OutputKernelObjectsL( iOutputType ); RedrawStatusMessage( KNullDesC ); } @@ -258,7 +243,7 @@ RDebug::Printf( "[MCon] CMemSpyConsoleMenu::OnCmdCSVListingStackL() - START" ); #endif - iEngine.HelperStack().OutputStackInfoForDeviceL(); + iSession.OutputCompactStackInfoL( iOutputType ); } @@ -268,7 +253,7 @@ RDebug::Printf( "[MCon] CMemSpyConsoleMenu::OnCmdCSVListingHeapL() - START" ); #endif - iEngine.HelperHeap().OutputHeapInfoForDeviceL(); + iSession.OutputCompactHeapInfoL( iOutputType ); } @@ -296,44 +281,34 @@ TPtr pCmdBuf( cmdBuf->Des() ); pCmdBuf.Copy( iCommandBuffer ); pCmdBuf.Append( KMemSpyConsoleWildcardCharacter ); - // - CMemSpyEngineObjectContainer& container = iEngine.Container(); - const TInt count = container.Count(); - TFullName fullThreadName; + + TInt err; + TProcessId procId; + TRAP(err, procId = iSession.GetProcessIdByNameL(pCmdBuf)); // - TInt index = 0; -#ifdef _DEBUG - RDebug::Printf( "[MCon] CMemSpyConsoleMenu::OnCmdHeapDataUserL() - procCount: %d", count ); -#endif - - while( index < count ) - { - CMemSpyProcess& process = container.At( index ); - const TPtrC processName( process.Name() ); -#ifdef _DEBUG - RDebug::Print( _L("[MCon] CMemSpyConsoleMenu::OnCmdHeapDataUserL() - procName: 0x%08x %S"), &process, &processName ); -#endif - - // - if ( processName.MatchF( pCmdBuf ) >= 0 ) - { - _LIT( KProcessingRequest, "** Dumping Heap Data for thread: %S" ); - const TInt threadCount = process.Count(); - for( TInt i=0; i<threadCount; i++ ) + if (err == KErrNone) + { + RArray<CMemSpyApiThread*> threads; + + TRAP(err, iSession.GetThreadsL(procId, threads)); + if (err == KErrNone) + { + _LIT( KProcessingRequest, "** Dumping Heap Data for thread: %S" ); + TFullName fullThreadName; + + for( TInt i=0; i<threads.Count(); i++ ) { - CMemSpyThread& thread = process.At( i ); + CMemSpyApiThread* thread = threads[i]; // - fullThreadName = thread.FullName(); + fullThreadName = thread->Name(); iConsole.Printf( KProcessingRequest, &fullThreadName ); iConsole.Write( KMemSpyConsoleNewLine ); // - TRAP_IGNORE( iEngine.HelperHeap().OutputHeapDataUserL( thread ) ); + TRAP_IGNORE( iSession.OutputThreadHeapDataL(iOutputType, thread->Id()) ); + + delete thread; } - - break; } - - ++index; } CleanupStack::PopAndDestroy( cmdBuf ); @@ -369,38 +344,36 @@ TPtr pCmdBuf( cmdBuf->Des() ); pCmdBuf.Copy( iCommandBuffer ); pCmdBuf.Append( KMemSpyConsoleWildcardCharacter ); - // - CMemSpyEngineObjectContainer& container = iEngine.Container(); - const TInt count = container.Count(); - TFullName fullThreadName; - // - TInt index = 0; - while( index < count ) - { - CMemSpyProcess& process = container.At( index ); - const TPtrC processName( process.Name() ); - // - if ( processName.MatchF( pCmdBuf ) >= 0 ) - { - _LIT( KProcessingRequest, "** Dumping Heap Cell List for thread: %S" ); - const TInt threadCount = process.Count(); - for( TInt i=0; i<threadCount; i++ ) - { - CMemSpyThread& thread = process.At( i ); - // - fullThreadName = thread.FullName(); - iConsole.Printf( KProcessingRequest, &fullThreadName ); - iConsole.Write( KMemSpyConsoleNewLine ); - // - TRAP_IGNORE( iEngine.HelperHeap().OutputCellListingUserL( thread ) ); - } - - break; - } - - ++index; - } - + + TInt err; + TProcessId procId; + TRAP(err, procId = iSession.GetProcessIdByNameL(pCmdBuf)); + // + if (err == KErrNone) + { + RArray<CMemSpyApiThread*> threads; + + TRAP(err, iSession.GetThreadsL(procId, threads)); + if (err == KErrNone) + { + _LIT( KProcessingRequest, "** Dumping Heap Cell List for thread: %S" ); + TFullName fullThreadName; + + for( TInt i=0; i<threads.Count(); i++ ) + { + CMemSpyApiThread* thread = threads[i]; + // + fullThreadName = thread->Name(); + iConsole.Printf( KProcessingRequest, &fullThreadName ); + iConsole.Write( KMemSpyConsoleNewLine ); + // + TRAP_IGNORE( iSession.OutputThreadCellListL(iOutputType, thread->Id()) ); + + delete thread; + } + } + } + CleanupStack::PopAndDestroy( cmdBuf ); DrawMenuL(); } @@ -604,71 +577,72 @@ void CMemSpyConsoleMenu::InitiateMemSpyClientServerOperationL( TInt aOpCode ) { -#ifdef _DEBUG - RDebug::Printf( "[MCon] CMemSpyConsoleMenu::InitiateMemSpyClientServerOperationL() - START - aOpCode: %d, iRunningDeviceWideOperation: %d", aOpCode, iRunningDeviceWideOperation ); -#endif - // - if ( aOpCode == EMemSpyClientServerOpExit ) - { - // Exit console app UI - CActiveScheduler::Stop(); - } - else - { - CMemSpyDeviceWideOperations::TOperation op = CMemSpyDeviceWideOperations::EPerEntityGeneralSummary; - switch( aOpCode ) - { - case EMemSpyClientServerOpSummaryInfo: - op = CMemSpyDeviceWideOperations::EPerEntityGeneralSummary; - break; - case EMemSpyClientServerOpSummaryInfoDetailed: - op = CMemSpyDeviceWideOperations::EPerEntityGeneralDetailed; - break; - // - case EMemSpyClientServerOpHeapInfo: - op = CMemSpyDeviceWideOperations::EPerEntityHeapInfo; - break; - case EMemSpyClientServerOpHeapCellListing: - op = CMemSpyDeviceWideOperations::EPerEntityHeapCellListing; - break; - case EMemSpyClientServerOpHeapData: - op = CMemSpyDeviceWideOperations::EPerEntityHeapData; - break; - // - case EMemSpyClientServerOpStackInfo: - op = CMemSpyDeviceWideOperations::EPerEntityStackInfo; - break; - case EMemSpyClientServerOpStackDataUser: - op = CMemSpyDeviceWideOperations::EPerEntityStackDataUser; - break; - case EMemSpyClientServerOpStackDataKernel: - op = CMemSpyDeviceWideOperations::EPerEntityStackDataKernel; - break; - - // These are not supported by the console UI - default: - case EMemSpyClientServerOpBitmapsSave: - case EMemSpyClientServerOpSendToBackground: - case EMemSpyClientServerOpBringToForeground: - User::Leave( KErrNotSupported ); - break; - } - - if ( iRunningDeviceWideOperation ) - { - User::Leave( KErrInUse ); - } - else - { - iRunningDeviceWideOperation = ETrue; - TRAP_IGNORE( CMemSpyDeviceWideOperationWaiter::ExecuteLD( iEngine, op ) ); - iRunningDeviceWideOperation = EFalse; - } - } - -#ifdef _DEBUG - RDebug::Printf( "[MCon] CMemSpyConsoleMenu::InitiateMemSpyClientServerOperationL() - END - aOpCode: %d", aOpCode ); -#endif + // TODO: .... +//#ifdef _DEBUG +// RDebug::Printf( "[MCon] CMemSpyConsoleMenu::InitiateMemSpyClientServerOperationL() - START - aOpCode: %d, iRunningDeviceWideOperation: %d", aOpCode, iRunningDeviceWideOperation ); +//#endif +// // +// if ( aOpCode == EMemSpyClientServerOpExit ) +// { +// // Exit console app UI +// CActiveScheduler::Stop(); +// } +// else +// { +// CMemSpyDeviceWideOperations::TOperation op = CMemSpyDeviceWideOperations::EPerEntityGeneralSummary; +// switch( aOpCode ) +// { +// case EMemSpyClientServerOpSummaryInfo: +// op = CMemSpyDeviceWideOperations::EPerEntityGeneralSummary; +// break; +// case EMemSpyClientServerOpSummaryInfoDetailed: +// op = CMemSpyDeviceWideOperations::EPerEntityGeneralDetailed; +// break; +// // +// case EMemSpyClientServerOpHeapInfo: +// op = CMemSpyDeviceWideOperations::EPerEntityHeapInfo; +// break; +// case EMemSpyClientServerOpHeapCellListing: +// op = CMemSpyDeviceWideOperations::EPerEntityHeapCellListing; +// break; +// case EMemSpyClientServerOpHeapData: +// op = CMemSpyDeviceWideOperations::EPerEntityHeapData; +// break; +// // +// case EMemSpyClientServerOpStackInfo: +// op = CMemSpyDeviceWideOperations::EPerEntityStackInfo; +// break; +// case EMemSpyClientServerOpStackDataUser: +// op = CMemSpyDeviceWideOperations::EPerEntityStackDataUser; +// break; +// case EMemSpyClientServerOpStackDataKernel: +// op = CMemSpyDeviceWideOperations::EPerEntityStackDataKernel; +// break; +// +// // These are not supported by the console UI +// default: +// case EMemSpyClientServerOpBitmapsSave: +// case EMemSpyClientServerOpSendToBackground: +// case EMemSpyClientServerOpBringToForeground: +// User::Leave( KErrNotSupported ); +// break; +// } +// +// if ( iRunningDeviceWideOperation ) +// { +// User::Leave( KErrInUse ); +// } +// else +// { +// iRunningDeviceWideOperation = ETrue; +// TRAP_IGNORE( CMemSpyDeviceWideOperationWaiter::ExecuteLD( iEngine, op ) ); +// iRunningDeviceWideOperation = EFalse; +// } +// } +// +//#ifdef _DEBUG +// RDebug::Printf( "[MCon] CMemSpyConsoleMenu::InitiateMemSpyClientServerOperationL() - END - aOpCode: %d", aOpCode ); +//#endif } diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/Console/group/MemSpyConsole.mmp --- a/memspy/Console/group/MemSpyConsole.mmp Mon May 03 13:58:41 2010 +0300 +++ b/memspy/Console/group/MemSpyConsole.mmp Thu May 13 23:59:27 2010 +0300 @@ -25,8 +25,8 @@ #include "../../group/MemSpyCapabilities.mmh" -EPOCSTACKSIZE 0x4000 -EPOCHEAPSIZE 0x100000 0x4000000 +//EPOCSTACKSIZE 0x4000 +//EPOCHEAPSIZE 0x100000 0x4000000 SOURCEPATH ../Source @@ -41,6 +41,4 @@ LIBRARY euser.lib LIBRARY efsrv.lib -LIBRARY memspydriverclient.lib -LIBRARY memspyengine.lib - +LIBRARY MemSpyClient.lib diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/Engine/BWINS/MemSpyEngineu.def --- a/memspy/Engine/BWINS/MemSpyEngineu.def Mon May 03 13:58:41 2010 +0300 +++ b/memspy/Engine/BWINS/MemSpyEngineu.def Thu May 13 23:59:27 2010 +0300 @@ -384,24 +384,32 @@ ?Type@CMemSpyThreadInfoItemBase@@QBE?AW4TMemSpyThreadInfoItemType@@XZ @ 383 NONAME ; enum TMemSpyThreadInfoItemType CMemSpyThreadInfoItemBase::Type(void) const ?TypeAsString@CMemSpyEngineGenericKernelObjectList@@SA?AVTPtrC16@@W4TMemSpyDriverContainerType@@@Z @ 384 NONAME ; class TPtrC16 CMemSpyEngineGenericKernelObjectList::TypeAsString(enum TMemSpyDriverContainerType) ?VID@CMemSpyProcess@@QBEKXZ @ 385 NONAME ; unsigned long CMemSpyProcess::VID(void) const - ?MdcaCount@CMemSpyEngineWindowGroupList@@UBEHXZ @ 386 NONAME ABSENT ; int CMemSpyEngineWindowGroupList::MdcaCount(void) const - ?GetWindowGroupListL@CMemSpyEngineHelperWindowServer@@QAEXAAV?$RArray@VTMemSpyEngineWindowGroupInfo@@@@@Z @ 387 NONAME ABSENT ; void CMemSpyEngineHelperWindowServer::GetWindowGroupListL(class RArray<class TMemSpyEngineWindowGroupInfo> &) - ??1CMemSpyEngineWindowGroupList@@UAE@XZ @ 388 NONAME ABSENT ; CMemSpyEngineWindowGroupList::~CMemSpyEngineWindowGroupList(void) - ?Count@CMemSpyEngineWindowGroupList@@QBEHXZ @ 389 NONAME ABSENT ; int CMemSpyEngineWindowGroupList::Count(void) const - ?ItemIndex@CMemSpyEngineWindowGroupList@@QBEHABVTMemSpyEngineWindowGroupInfo@@@Z @ 390 NONAME ABSENT ; int CMemSpyEngineWindowGroupList::ItemIndex(class TMemSpyEngineWindowGroupInfo const &) const - ?WindowGroupListL@CMemSpyEngineHelperWindowServer@@QAEPAVCMemSpyEngineWindowGroupList@@XZ @ 391 NONAME ABSENT ; class CMemSpyEngineWindowGroupList * CMemSpyEngineHelperWindowServer::WindowGroupListL(void) - ?HelperWindowServer@CMemSpyEngine@@QAEAAVCMemSpyEngineHelperWindowServer@@XZ @ 392 NONAME ABSENT ; class CMemSpyEngineHelperWindowServer & CMemSpyEngine::HelperWindowServer(void) - ?MdcaPoint@CMemSpyEngineWindowGroupList@@UBE?AVTPtrC16@@H@Z @ 393 NONAME ABSENT ; class TPtrC16 CMemSpyEngineWindowGroupList::MdcaPoint(int) const - ?At@CMemSpyEngineWindowGroupList@@QBEABVTMemSpyEngineWindowGroupInfo@@H@Z @ 394 NONAME ABSENT ; class TMemSpyEngineWindowGroupInfo const & CMemSpyEngineWindowGroupList::At(int) const - ?ItemIndex@CMemSpyEngineWindowGroupList@@QBEHABVTMemSpyEngineWindowGroupBasicInfo@@@Z @ 395 NONAME ABSENT ; int CMemSpyEngineWindowGroupList::ItemIndex(class TMemSpyEngineWindowGroupBasicInfo const &) const - ?At@CMemSpyEngineWindowGroupList@@QBEABVTMemSpyEngineWindowGroupBasicInfo@@H@Z @ 396 NONAME ABSENT ; class TMemSpyEngineWindowGroupBasicInfo const & CMemSpyEngineWindowGroupList::At(int) const - ?GetWindowGroupListL@CMemSpyEngineHelperWindowServer@@QAEXAAV?$RArray@VTMemSpyEngineWindowGroupBasicInfo@@@@@Z @ 397 NONAME ABSENT ; void CMemSpyEngineHelperWindowServer::GetWindowGroupListL(class RArray<class TMemSpyEngineWindowGroupBasicInfo> &) - ?GetWindowGroupDetailsL@CMemSpyEngineHelperWindowServer@@QAEXHAAVTMemSpyEngineWindowGroupDetails@@@Z @ 398 NONAME ABSENT ; void CMemSpyEngineHelperWindowServer::GetWindowGroupDetailsL(int, class TMemSpyEngineWindowGroupDetails &) - ?SwitchToL@CMemSpyEngineHelperWindowServer@@QAEXH@Z @ 399 NONAME ABSENT ; void CMemSpyEngineHelperWindowServer::SwitchToL(int) + __E32Dll @ 386 NONAME ABSENT ; int CMemSpyEngineWindowGroupList::MdcaCount(void) const + __E32Dll @ 387 NONAME ABSENT ; void CMemSpyEngineHelperWindowServer::GetWindowGroupListL(class RArray<class TMemSpyEngineWindowGroupInfo> &) + __E32Dll @ 388 NONAME ABSENT ; CMemSpyEngineWindowGroupList::~CMemSpyEngineWindowGroupList(void) + __E32Dll @ 389 NONAME ABSENT ; int CMemSpyEngineWindowGroupList::Count(void) const + __E32Dll @ 390 NONAME ABSENT ; int CMemSpyEngineWindowGroupList::ItemIndex(class TMemSpyEngineWindowGroupInfo const &) const + __E32Dll @ 391 NONAME ABSENT ; class CMemSpyEngineWindowGroupList * CMemSpyEngineHelperWindowServer::WindowGroupListL(void) + __E32Dll @ 392 NONAME ABSENT ; class CMemSpyEngineHelperWindowServer & CMemSpyEngine::HelperWindowServer(void) + __E32Dll @ 393 NONAME ABSENT ; class TPtrC16 CMemSpyEngineWindowGroupList::MdcaPoint(int) const + __E32Dll @ 394 NONAME ABSENT ; class TMemSpyEngineWindowGroupInfo const & CMemSpyEngineWindowGroupList::At(int) const + __E32Dll @ 395 NONAME ABSENT ; int CMemSpyEngineWindowGroupList::ItemIndex(class TMemSpyEngineWindowGroupBasicInfo const &) const + __E32Dll @ 396 NONAME ABSENT ; class TMemSpyEngineWindowGroupBasicInfo const & CMemSpyEngineWindowGroupList::At(int) const + __E32Dll @ 397 NONAME ABSENT ; void CMemSpyEngineHelperWindowServer::GetWindowGroupListL(class RArray<class TMemSpyEngineWindowGroupBasicInfo> &) + __E32Dll @ 398 NONAME ABSENT ; void CMemSpyEngineHelperWindowServer::GetWindowGroupDetailsL(int, class TMemSpyEngineWindowGroupDetails &) + __E32Dll @ 399 NONAME ABSENT ; void CMemSpyEngineHelperWindowServer::SwitchToL(int) ?Capabilities@CMemSpyProcess@@QBE?AUSCapabilitySet@@XZ @ 400 NONAME ; struct SCapabilitySet CMemSpyProcess::Capabilities(void) const ?UIDs@CMemSpyProcess@@QBE?AVTUidType@@XZ @ 401 NONAME ; class TUidType CMemSpyProcess::UIDs(void) const ?HelperCondVar@CMemSpyEngine@@QAEAAVCMemSpyEngineHelperCondVar@@XZ @ 402 NONAME ; class CMemSpyEngineHelperCondVar & CMemSpyEngine::HelperCondVar(void) ?GetCondVarSuspendedThreadsL@CMemSpyEngineHelperCondVar@@QAEXABVTMemSpyDriverHandleInfoGeneric@@AAV?$RArray@VTMemSpyDriverCondVarSuspendedThreadInfo@@@@@Z @ 403 NONAME ; void CMemSpyEngineHelperCondVar::GetCondVarSuspendedThreadsL(class TMemSpyDriverHandleInfoGeneric const &, class RArray<class TMemSpyDriverCondVarSuspendedThreadInfo> &) ?HelperWindowServer@CMemSpyEngine@@QAEAAVMMemSpyEngineHelperWindowServer@@XZ @ 404 NONAME ; class MMemSpyEngineHelperWindowServer & CMemSpyEngine::HelperWindowServer(void) ?IsHelperWindowServerSupported@CMemSpyEngine@@QAEHXZ @ 405 NONAME ; int CMemSpyEngine::IsHelperWindowServerSupported(void) + __E32Dll @ 406 NONAME ABSENT ; int CMemSpyEngineGenericKernelObjectList::Size(void) const + __E32Dll @ 407 NONAME ABSENT ; int CMemSpyEngineGenericKernelObjectList::Size(void) + ?Size@CMemSpyEngineGenericKernelObjectList@@QBEHXZ @ 408 NONAME ; int CMemSpyEngineGenericKernelObjectList::Size(void) const + ?NewHeapRawInfo@CMemSpyEngineHelperHeap@@QAEAAVTMemSpyHeapData@@ABVTMemSpyHeapInfo@@@Z @ 409 NONAME ABSENT ; class TMemSpyHeapData & CMemSpyEngineHelperHeap::NewHeapRawInfo(class TMemSpyHeapInfo const &) + ?NewHeapRawInfo@CMemSpyEngineHelperHeap@@QAE?AVTMemSpyHeapData@@ABVTMemSpyHeapInfo@@@Z @ 410 NONAME ; class TMemSpyHeapData CMemSpyEngineHelperHeap::NewHeapRawInfo(class TMemSpyHeapInfo const &) + ?ItemsCount@CMemSpyEngineGenericKernelObjectList@@QBEHXZ @ 411 NONAME ; int CMemSpyEngineGenericKernelObjectList::ItemsCount(void) const + ?Priority@CMemSpyThread@@QBE?AW4TThreadPriority@@XZ @ 412 NONAME ; enum TThreadPriority CMemSpyThread::Priority(void) const + ?NewL@CMemSpyEngine@@SAPAV1@AAVRFs@@H@Z @ 413 NONAME ; class CMemSpyEngine * CMemSpyEngine::NewL(class RFs &, int) diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/Engine/Include/ClientServer/MemSpyEngineServer.h --- a/memspy/Engine/Include/ClientServer/MemSpyEngineServer.h Mon May 03 13:58:41 2010 +0300 +++ b/memspy/Engine/Include/ClientServer/MemSpyEngineServer.h Thu May 13 23:59:27 2010 +0300 @@ -63,6 +63,8 @@ private: // Internal methods void DoServiceL( const RMessage2& aMessage ); + void DoUiServiceL( const RMessage2& aMessage ); + void DoCmdServiceL( const RMessage2& aMessage ); static TInt ValidateFunction( TInt aFunction, TBool aIncludesThreadId, TBool aIncludesThreadName ); void HandleThreadSpecificOpL( TInt aFunction, const TThreadId& aThreadId ); void HandleThreadSpecificOpL( TInt aFunction, const TDesC& aThreadName ); diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/Engine/Source/ClientServer/MemSpyEngineServer.cpp --- a/memspy/Engine/Source/ClientServer/MemSpyEngineServer.cpp Mon May 03 13:58:41 2010 +0300 +++ b/memspy/Engine/Source/ClientServer/MemSpyEngineServer.cpp Thu May 13 23:59:27 2010 +0300 @@ -19,6 +19,9 @@ // System includes #include <e32svr.h> +#include <w32std.h> +#include <APGTASK.H> +#include <APGWGNAM.H> // User includes #include <memspy/engine/memspyengine.h> @@ -38,6 +41,12 @@ #include <memspy/engine/memspyenginehelpersysmemtracker.h> #include <memspy/engine/memspyenginehelpersysmemtrackerconfig.h> #include <memspy/engine/memspyenginehelperkernelcontainers.h> +#include <memspy/engine/memspyengineobjectthreadinfocontainer.h> + +#include <memspy/engine/memspyprocessdata.h> +#include <memspy/engine/memspythreaddata.h> +#include <memspy/engine/memspykernelobjectdata.h> +#include <memspy/engine/memspythreadinfoitemdata.h> CMemSpyEngineServer::CMemSpyEngineServer( CMemSpyEngine& aEngine ) @@ -167,8 +176,551 @@ TRACE( RDebug::Print( _L("[MemSpy] CMemSpyEngineSession::ServiceL() - END - this: 0x%08x, fn: 0x%08x, id: %4d, client: %S"), this, aMessage.Function(), iClientThreadId, iClientThreadName ) ); } +// --------------------------------------------------------- +// DoServiceL( const RMessage2& aMessage ) +// --------------------------------------------------------- +// +void CMemSpyEngineSession::DoServiceL( const RMessage2& aMessage ) + { + TInt function = aMessage.Function() & KMemSpyOpFlagsTypeMask; + if (function >= EMemSpyClientServerOpMarkerUiFirst && + function < EMemSpyClientServerOpMarkerUiLast) + + DoUiServiceL(aMessage); + else + DoCmdServiceL(aMessage); + } -void CMemSpyEngineSession::DoServiceL( const RMessage2& aMessage ) +// --------------------------------------------------------- +// DoUiServiceL( const RMessage2& aMessage ) +// --------------------------------------------------------- +// +void CMemSpyEngineSession::DoUiServiceL( const RMessage2& aMessage ) + { + switch (aMessage.Function() & KMemSpyOpFlagsTypeMask) + { + case EMemSpyClientServerOpGetProcessCount: + { + aMessage.WriteL(0, TPckgBuf<TInt>(iEngine.Container().Count())); + break; + } + case EMemSpyClientServerOpGetProcesses: + { + CMemSpyEngineObjectContainer& list = iEngine.Container(); + + TPckgBuf<TInt> a0; + aMessage.ReadL(0, a0); + TInt realCount = Min(a0(), list.Count()); + + for(TInt i=0, offset = 0; i<realCount; i++, offset += sizeof(TMemSpyProcessData)) + { + CMemSpyProcess& process = iEngine.Container().At(i); + TMemSpyProcessData data; + data.iId = process.Id(); + data.iName.Copy(process.Name()); + + TPckgBuf<TMemSpyProcessData> buffer(data); + aMessage.WriteL(1, buffer, offset); + } + + a0 = list.Count(); + aMessage.WriteL(0, a0); + + break; + } + case EMemSpyClienServerOpGetProcessIdByName: + { + TFullName processName; + aMessage.ReadL(0, processName); + + TBool found(EFalse); + + for (TInt i=0; i<iEngine.Container().Count(); i++) + { + CMemSpyProcess& process = iEngine.Container().At(i); + if (process.Name().FindF(processName) >= 0) + { + found = ETrue; + TPckgBuf<TProcessId> procId(process.Id()); + aMessage.WriteL(1, procId); + } + } + + if (!found) + { + User::Leave(KErrNotFound); + } + + break; + } + case EMemSpyClientServerOpProcessSystemPermanentOrCritical: + { + TBool ret = EFalse; + TPckgBuf<TProcessId> id; + aMessage.ReadL( 0, id ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess& process = container.ProcessByIdL( id() ); + + process.Open(); + + if ( process.IsSystemPermanent() || process.IsSystemCritical() ) + { + ret = ETrue; + } + TPckgBuf<TBool> retBuf( ret ); + aMessage.WriteL( 1, retBuf ); + + break; + } + case EMemSpyClientServerOpEndProcess: + { + TPckgBuf<TProcessId> id; + aMessage.ReadL( 0, id ); + TPckgBuf<TMemSpyEndType> type; + aMessage.ReadL( 1, type ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess& process = container.ProcessByIdL( id() ); + + switch ( type() ) + { + case ETerminate: + { + process.TerminateL(); + break; + } + case EPanic: + { + process.PanicL(); + break; + } + case EKill: + { + process.KillL(); + break; + } + } + break; + } + case EMemSpyClientServerOpSwitchToProcess: + {/* + TInt wgCount; + RWsSession wsSession; + User::LeaveIfError( wsSession.Connect() ); + CleanupClosePushL( wsSession ); + User::LeaveIfError( wgCount = wsSession.NumWindowGroups() ); + RArray<RWsSession::TWindowGroupChainInfo> wgArray; + CleanupClosePushL( wgArray ); + User::LeaveIfError( wsSession.WindowGroupList( &wgArray ) ); + TApaTask task( wsSession ); + TBool brought( EFalse ); + TInt wgId( KErrNotFound ); + TThreadId threadId; + + TPckgBuf<TProcessId> id; + aMessage.ReadL( 0, id ); + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess& process = container.ProcessByIdL( id() ); + + // loop trough threads in a process + for ( TInt i = 0; i < process.MdcaCount(); i++ ) + { + TInt wgCountLocal = wgCount; + + // loop trough all window groups and see if a thread id matches + while( !brought && wgCountLocal-- ) + { + wgId = wgArray[wgCountLocal].iId; + User::LeaveIfError( wsSession.GetWindowGroupClientThreadId( wgId, threadId ) ); + if ( threadId == process.At( i ).Id() ) + { + CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC( wsSession, wgId ); + task.SetWgId( wgId ); + if ( !wgName->Hidden() && task.Exists() ) + { + task.BringToForeground(); + brought = ETrue; + } + CleanupStack::PopAndDestroy( wgName ); + } + } + } + + TPckgBuf<TBool> ret( brought ); + aMessage.WriteL( 1, ret ); + + break;*/ + } + case EMemSpyClientServerOpGetThreadCount: + { + TPckgBuf<TProcessId> pid; + aMessage.ReadL(1, pid); + CMemSpyProcess& process = iEngine.Container().ProcessByIdL(pid()); + process.Open(); + aMessage.WriteL(0, TPckgBuf<TInt>(process.Count())); + process.Close(); + break; + } + case EMemSpyClientServerOpGetThreads: + { + TPckgBuf<TProcessId> pid; + aMessage.ReadL(2, pid); + + CMemSpyProcess& list = iEngine.Container().ProcessByIdL(pid()); + list.Open(); + + TPckgBuf<TInt> a0; + aMessage.ReadL(0, a0); + TInt realCount = Min(a0(), list.Count()); + + for(TInt i=0, offset = 0; i<realCount; i++, offset += sizeof(TMemSpyThreadData)) + { + CMemSpyThread& thread = list.At(i); + thread.Open(); + + TMemSpyThreadData data; + data.iId = thread.Id(); + data.iName.Copy(thread.Name()); + data.iThreadPriority = thread.Priority(); + + TPckgBuf<TMemSpyThreadData> buffer(data); + aMessage.WriteL(1, buffer, offset); + + thread.Close(); + } + + a0 = list.Count(); + aMessage.WriteL(0, a0); + + list.Close(); + + break; + } + case EMemSpyClientServerOpSetThreadPriority: + { + TPckgBuf<TThreadId> tid; + TPckgBuf<TInt> priority; + aMessage.ReadL(0, tid); + aMessage.ReadL(1, priority); + + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError(iEngine.Container().ProcessAndThreadByThreadId(tid(), process, thread)); + + if (thread) + { + thread->Open(); + thread->SetPriorityL(static_cast<TThreadPriority>(priority())); + thread->Close(); + } + break; + } + case EMemSpyClientServerOpThreadSystemPermanentOrCritical: + { + TBool ret = EFalse; + TPckgBuf<TThreadId> id; + aMessage.ReadL( 0, id ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id(), process, thread ) ); + + if ( thread ) + { + thread->Open(); + + if ( thread->IsSystemPermanent() || thread->IsSystemCritical() ) + { + ret = ETrue; + } + thread->Close(); + } + TPckgBuf<TBool> retBuf( ret ); + aMessage.WriteL( 1, retBuf ); + + break; + } + case EMemSpyClientServerOpEndThread: + { + TPckgBuf<TThreadId> id; + aMessage.ReadL( 0, id ); + TPckgBuf<TMemSpyEndType> type; + aMessage.ReadL( 1, type ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id(), process, thread ) ); + + if( thread ) + { + switch ( type() ) + { + case ETerminate: + { + thread->TerminateL(); + break; + } + case EPanic: + { + thread->PanicL(); + break; + } + case EKill: + { + thread->KillL(); + break; + } + } + } + break; + } + case EMemSpyClientServerOpSwitchToThread: + { + TInt wgCount; + RWsSession wsSession; + User::LeaveIfError( wsSession.Connect() ); + CleanupClosePushL( wsSession ); + User::LeaveIfError( wgCount = wsSession.NumWindowGroups() ); + RArray<RWsSession::TWindowGroupChainInfo> wgArray; + CleanupClosePushL( wgArray ); + User::LeaveIfError( wsSession.WindowGroupList( &wgArray ) ); + TApaTask task( wsSession ); + TBool brought( EFalse ); + TInt wgId( KErrNotFound ); + TThreadId threadId; + + TPckgBuf<TThreadId> id; + aMessage.ReadL( 0, id ); + + // loop trough all window groups and see if a thread id matches + while( !brought && wgCount-- ) + { + wgId = wgArray[wgCount].iId; + User::LeaveIfError( wsSession.GetWindowGroupClientThreadId( wgId, threadId ) ); + if ( threadId == id() ) + { + CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC( wsSession, wgId ); + task.SetWgId( wgId ); + if ( !wgName->Hidden() && task.Exists() ) + { + task.BringToForeground(); + brought = ETrue; + } + CleanupStack::PopAndDestroy( wgName ); + } + } + TPckgBuf<TBool> ret( brought ); + aMessage.WriteL( 1, ret ); + + break; + } + case EMemSpyClientServerOpGetInfoItemType: + { + TPckgBuf<TInt> index; + aMessage.ReadL( 0, index ); + TPckgBuf<TThreadId> id; + aMessage.ReadL( 1, id); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; //not needed + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id(), process, thread ) ); + + thread->Open(); + process->Open(); + + CMemSpyThreadInfoContainer& threadInfoContainer = thread->InfoContainerForceSyncronousConstructionL(); + TMemSpyThreadInfoItemType retType = threadInfoContainer.Item( index() ).Type(); + + TPckgBuf<TMemSpyThreadInfoItemType> ret( retType ); + aMessage.WriteL( 2, ret ); + + thread->Close(); + process->Close(); + + break; + } + case EMemSpyClientServerOpGetThreadInfoItemsCount: + { + TPckgBuf<TThreadId> id; + aMessage.ReadL( 0, id ); + TPckgBuf<TMemSpyThreadInfoItemType> type; + aMessage.ReadL( 1, type ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + + container.ProcessAndThreadByThreadId( id(), process, thread ); + + thread->Open(); + process->Open(); + + CMemSpyThreadInfoContainer& threadInfoContainer = thread->InfoContainerForceSyncronousConstructionL(); + + CMemSpyThreadInfoItemBase& threadInfoItemBase = threadInfoContainer.Item( type() ); + + TInt count = threadInfoItemBase.MdcaCount(); + TPckgBuf<TInt> tempret( count ); + aMessage.WriteL( 2, tempret ); + + thread->Close(); + process->Close(); + + break; + } + case EMemSpyClientServerOpGetThreadInfoItems: + { + TPckgBuf<TInt> count; + aMessage.ReadL( 0, count ); + TPckgBuf<TThreadId> id; + aMessage.ReadL( 1, id ); + TPckgBuf<TMemSpyThreadInfoItemType> type; + aMessage.ReadL( 2, type ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id() , process, thread ) ); + + process->Open(); + thread->Open(); + + CMemSpyThreadInfoContainer& threadInfoContainer = thread->InfoContainerForceSyncronousConstructionL(); + + CMemSpyThreadInfoItemBase& threadInfoItemBase = threadInfoContainer.Item( type() ); //get ThreadInfoItemBaseByType + + TInt itemCount = Min(count(), threadInfoItemBase.MdcaCount()); + + for( TInt i=0, offset = 0; i<itemCount; i++, offset += sizeof( TMemSpyThreadInfoItemData ) ) + { + TMemSpyThreadInfoItemData data; + + TPtrC caption(threadInfoItemBase.MdcaPoint(i).Mid(1)); + TInt tabPos = caption.Locate('\t'); + if (tabPos != KErrNotFound) + caption.Set(caption.Left(tabPos)); + + TPtrC value(threadInfoItemBase.MdcaPoint(i)); + tabPos = value.LocateReverse('\t'); + if (tabPos != KErrNotFound) + value.Set(value.Mid(tabPos + 1)); + + data.iCaption.Copy( caption ); + data.iValue.Copy( value ); + + TPckgBuf<TMemSpyThreadInfoItemData> buffer(data); + aMessage.WriteL(3, buffer, offset); + } + aMessage.WriteL(0, count); + + thread->Close(); + process->Close(); + + break; + } + // --- KernelObjects related functions --- + case EMemSpyClientServerOpGetKernelObjectCount: + { + TInt iCount = EMemSpyDriverContainerTypeLast - EMemSpyDriverContainerTypeFirst; + TPckgBuf<TInt> ret( iCount ); + aMessage.WriteL(0, ret); + break; + } + case EMemSpyClientServerOpGetKernelObjects: + { + TPckgBuf<TInt> count; + aMessage.ReadL(0, count); + + CMemSpyEngineGenericKernelObjectContainer* model = iEngine.HelperKernelContainers().ObjectsAllL(); //contains all the objects + CleanupStack::PushL( model ); + + for( TInt i=0, offset = 0; i<count(); i++, offset += sizeof( TMemSpyKernelObjectData ) ) + { + TMemSpyKernelObjectData data; + + TPtrC name(model->At(i).Name().Mid(1)); + TInt tabPos = name.Locate('\t'); + if (tabPos != KErrNotFound) + name.Set(name.Left(tabPos)); + + data.iName.Copy(name); + data.iType = model->At(i).Type(); + data.iCount = model->At(i).Count(); + data.iSize = model->At(i).Count() * model->At(i).Count(); + + TPckgBuf<TMemSpyKernelObjectData> buffer(data); + aMessage.WriteL(1, buffer, offset); + } + aMessage.WriteL(0, count); + CleanupStack::PopAndDestroy( model ); + break; + } + case EMemSpyClientServerOpGetKernelObjectItemCount: + { + TPckgBuf<TMemSpyDriverContainerType> tempType; + aMessage.ReadL(1, tempType); //get type of kernel object + TMemSpyDriverContainerType type = tempType(); + + CMemSpyEngineHelperKernelContainers& kernelContainerManager = iEngine.HelperKernelContainers(); + CMemSpyEngineGenericKernelObjectList* iObjectList = kernelContainerManager.ObjectsForSpecificContainerL( type ); + CleanupStack::PushL( iObjectList ); + + TInt count = iObjectList->Count(); + TPckgBuf<TInt> ret( count ); + aMessage.WriteL( 0, ret ); + + CleanupStack::PopAndDestroy( iObjectList ); + break; + } + case EMemSpyClientServerOpGetKernelObjectItems: + { + TPckgBuf<TInt> count; + TPckgBuf<TMemSpyDriverContainerType> tempType; + aMessage.ReadL( 0, count ); //get count of items + aMessage.ReadL(1, tempType); //get type of kernel object + TInt c = count(); + + CMemSpyEngineHelperKernelContainers& kernelContainerManager = iEngine.HelperKernelContainers(); + CMemSpyEngineGenericKernelObjectList* iObjectList = kernelContainerManager.ObjectsForSpecificContainerL( tempType() ); + CleanupStack::PushL( iObjectList ); + + for( TInt i=0, offset = 0; i<c; i++, offset += sizeof( TMemSpyDriverHandleInfoGeneric ) ) + { + TMemSpyDriverHandleInfoGeneric data; + + data = iObjectList->At( i ); + + TPckgBuf<TMemSpyDriverHandleInfoGeneric> buffer(data); + aMessage.WriteL(2, buffer, offset); + } + + CleanupStack::PopAndDestroy( iObjectList ); + break; + } + // --- Kernel Heap related functions --- + case EMemSpyClientServerOpGetHeap: + { + TMemSpyHeapInfo heapInfo; + iEngine.HelperHeap().GetHeapInfoKernelL( heapInfo ); + TMemSpyHeapData data = iEngine.HelperHeap().NewHeapRawInfo( heapInfo ); + + TPckgBuf<TMemSpyHeapData> buffer(data); + aMessage.WriteL(0, buffer); + + break; + } + } + } + +// --------------------------------------------------------- +// DoCmdServiceL( const RMessage2& aMessage ) +// --------------------------------------------------------- +// +void CMemSpyEngineSession::DoCmdServiceL( const RMessage2& aMessage ) { TInt error = KErrNone; diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/Engine/Source/Helpers/MemSpyEngineHelperKernelContainers.cpp --- a/memspy/Engine/Source/Helpers/MemSpyEngineHelperKernelContainers.cpp Mon May 03 13:58:41 2010 +0300 +++ b/memspy/Engine/Source/Helpers/MemSpyEngineHelperKernelContainers.cpp Thu May 13 23:59:27 2010 +0300 @@ -247,6 +247,16 @@ { return iType; } + +EXPORT_C TInt CMemSpyEngineGenericKernelObjectList::Size() const + { + return iSize; + } + +EXPORT_C TInt CMemSpyEngineGenericKernelObjectList::ItemsCount() const + { + return iItems.Count(); + } EXPORT_C TPtrC CMemSpyEngineGenericKernelObjectList::TypeAsString( TMemSpyDriverContainerType aType ) @@ -392,7 +402,7 @@ AddItemL( aItem.iHandle ); iItems.AppendL( aItem ); // - UpdateNameL(); + //UpdateNameL(); } diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/Engine/Source/MemSpyEngine.cpp --- a/memspy/Engine/Source/MemSpyEngine.cpp Mon May 03 13:58:41 2010 +0300 +++ b/memspy/Engine/Source/MemSpyEngine.cpp Thu May 13 23:59:27 2010 +0300 @@ -43,14 +43,14 @@ } -void CMemSpyEngine::ConstructL( RFs& aFsSession ) +void CMemSpyEngine::ConstructL( RFs& aFsSession, TBool aStartServer ) { #ifdef _DEBUG RDebug::Printf( "CMemSpyEngine::ConstructL() - START" ); #endif iImp = new(ELeave) CMemSpyEngineImp( aFsSession, *this ); - iImp->ConstructL(); + iImp->ConstructL(aStartServer); #ifdef _DEBUG RDebug::Printf( "CMemSpyEngine::ConstructL() - END" ); @@ -60,9 +60,14 @@ EXPORT_C CMemSpyEngine* CMemSpyEngine::NewL( RFs& aFsSession ) { + return NewL(aFsSession, ETrue ); + } + +EXPORT_C CMemSpyEngine* CMemSpyEngine::NewL( RFs& aFsSession, TBool aStartServer ) + { CMemSpyEngine* self = new(ELeave) CMemSpyEngine(); CleanupStack::PushL( self ); - self->ConstructL( aFsSession ); + self->ConstructL( aFsSession, aStartServer ); CleanupStack::Pop( self ); return self; } diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/Engine/Source/MemSpyEngineImp.cpp --- a/memspy/Engine/Source/MemSpyEngineImp.cpp Mon May 03 13:58:41 2010 +0300 +++ b/memspy/Engine/Source/MemSpyEngineImp.cpp Thu May 13 23:59:27 2010 +0300 @@ -74,7 +74,7 @@ RDebug::Printf( "CMemSpyEngineImp::~CMemSpyEngineImp() - deleting helpers..." ); #endif delete iHelperSysMemTracker; - delete iServer; + //delete iServer; delete iHelperKernelContainers; delete iHelperFbServ; delete iHelperHeap; @@ -127,7 +127,7 @@ } -void CMemSpyEngineImp::ConstructL() +void CMemSpyEngineImp::ConstructL( TBool aStartServer ) { #ifdef _DEBUG RDebug::Printf( "CMemSpyEngineImp::ConstructL() - START" ); @@ -138,8 +138,11 @@ // Starting the server before the driver connection is made // ensures that only one instance of MemSpy can run (either the S60 // UI or the console UI ). - iServer = CMemSpyEngineServer::NewL( iEngine ); - // + if (aStartServer) + { + iServer = CMemSpyEngineServer::NewL( iEngine ); + } + iMemSpyDriver = new(ELeave) RMemSpyDriverClient(); const TInt error = Driver().Open(); User::LeaveIfError( error ); diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/Engine/Source/ThreadAndProcess/MemSpyEngineObjectProcess.cpp --- a/memspy/Engine/Source/ThreadAndProcess/MemSpyEngineObjectProcess.cpp Mon May 03 13:58:41 2010 +0300 +++ b/memspy/Engine/Source/ThreadAndProcess/MemSpyEngineObjectProcess.cpp Thu May 13 23:59:27 2010 +0300 @@ -515,6 +515,25 @@ return iInfo->VID(); } +EXPORT_C TProcessPriority CMemSpyProcess::Priority() const + { + return iPriority; + } + +EXPORT_C TExitCategoryName CMemSpyProcess::ExitCategory() const + { + return iExitCategory; + } + +EXPORT_C TInt CMemSpyProcess::ExitReason() const + { + return iExitReason; + } + +EXPORT_C TExitType CMemSpyProcess::ExitType() const + { + return iExitType; + } EXPORT_C TUidType CMemSpyProcess::UIDs() const { diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/Engine/Source/ThreadAndProcess/MemSpyEngineObjectThreadInfoObjects.cpp --- a/memspy/Engine/Source/ThreadAndProcess/MemSpyEngineObjectThreadInfoObjects.cpp Mon May 03 13:58:41 2010 +0300 +++ b/memspy/Engine/Source/ThreadAndProcess/MemSpyEngineObjectThreadInfoObjects.cpp Thu May 13 23:59:27 2010 +0300 @@ -123,6 +123,17 @@ return TPtrC( item->Combined() ); } +EXPORT_C TPtrC CMemSpyThreadInfoItemBase::Caption(TInt aIndex ) const + { + CItem* item = iItems[ aIndex ]; + return TPtrC( item->Caption() ); + } + +EXPORT_C TPtrC CMemSpyThreadInfoItemBase::Value(TInt aIndex ) const + { + CItem* item = iItems[ aIndex ]; + return TPtrC( item->Value() ); + } EXPORT_C CMemSpyEngine& CMemSpyThreadInfoItemBase::Engine() const { diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/Engine/eabi/MemSpyEngineu.def --- a/memspy/Engine/eabi/MemSpyEngineu.def Mon May 03 13:58:41 2010 +0300 +++ b/memspy/Engine/eabi/MemSpyEngineu.def Thu May 13 23:59:27 2010 +0300 @@ -536,4 +536,15 @@ _ZTI49CMemSpyEngineHelperSysMemTrackerEntryWindowServer @ 535 NONAME ; #<TI># _ZTV49CMemSpyEngineHelperSysMemTrackerEntryWindowServer @ 536 NONAME ; #<VT># _ZN13CMemSpyEngine29IsHelperWindowServerSupportedEv @ 537 NONAME + _ZN23CMemSpyEngineHelperHeap14NewHeapRawInfoERK15TMemSpyHeapInfo @ 538 NONAME + _ZNK36CMemSpyEngineGenericKernelObjectList10ItemsCountEv @ 539 NONAME + _ZNK36CMemSpyEngineGenericKernelObjectList4SizeEv @ 540 NONAME + _ZNK13CMemSpyThread8PriorityEv @ 541 NONAME + _ZN13CMemSpyEngine4NewLER3RFsi @ 542 NONAME + _ZNK14CMemSpyProcess10ExitReasonEv @ 543 NONAME + _ZNK14CMemSpyProcess12ExitCategoryEv @ 544 NONAME + _ZNK14CMemSpyProcess8ExitTypeEv @ 545 NONAME + _ZNK14CMemSpyProcess8PriorityEv @ 546 NONAME + _ZNK25CMemSpyThreadInfoItemBase5ValueEi @ 547 NONAME + _ZNK25CMemSpyThreadInfoItemBase7CaptionEi @ 548 NONAME diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/Engine/group/MemSpyEngine.mmp --- a/memspy/Engine/group/MemSpyEngine.mmp Mon May 03 13:58:41 2010 +0300 +++ b/memspy/Engine/group/MemSpyEngine.mmp Thu May 13 23:59:27 2010 +0300 @@ -113,15 +113,18 @@ OS_LAYER_SYSTEMINCLUDE +APP_LAYER_SYSTEMINCLUDE + LIBRARY euser.lib LIBRARY MemSpyDriverClient.lib hal.lib estor.lib LIBRARY efsrv.lib bafl.lib fbscli.lib LIBRARY ecom.lib xmlframework.lib charconv.lib - +LIBRARY apgrfx.lib +LIBRARY ws32.lib #include "MemSpyEngine.config" +//EXPORTUNFROZEN - diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyClient/bwins/MemSpyClientu.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyClient/bwins/MemSpyClientu.def Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,121 @@ +EXPORTS + ?CpuUse@CMemSpyApiThread@@QBEHXZ @ 1 NONAME ; int CMemSpyApiThread::CpuUse(void) const + ?Name@CMemSpyApiKernelObjectItem@@QBEABVTDesC8@@XZ @ 2 NONAME ; class TDesC8 const & CMemSpyApiKernelObjectItem::Name(void) const + ?AccessCount@CMemSpyApiKernelObjectItem@@QBEHXZ @ 3 NONAME ; int CMemSpyApiKernelObjectItem::AccessCount(void) const + ?TotalOverhead@CMemSpyApiHeap@@QAEHXZ @ 4 NONAME ; int CMemSpyApiHeap::TotalOverhead(void) + ?UniqueID@CMemSpyApiKernelObjectItem@@QBEHXZ @ 5 NONAME ; int CMemSpyApiKernelObjectItem::UniqueID(void) const + ?SessionType@CMemSpyApiKernelObjectItem@@QBE?AW4TIpcSessionType@@XZ @ 6 NONAME ; enum TIpcSessionType CMemSpyApiKernelObjectItem::SessionType(void) const + ?VID@CMemSpyApiThread@@QBEHXZ @ 7 NONAME ; int CMemSpyApiThread::VID(void) const + ?MaxLength@CMemSpyApiHeap@@QAEHXZ @ 8 NONAME ; int CMemSpyApiHeap::MaxLength(void) + ?ProcessNumberUsing@CMemSpyApiThread@@QBEHXZ @ 9 NONAME ; int CMemSpyApiThread::ProcessNumberUsing(void) const + ?AddressOfKernelOwner@CMemSpyApiKernelObjectItem@@QAEPAEXZ @ 10 NONAME ; unsigned char * CMemSpyApiKernelObjectItem::AddressOfKernelOwner(void) + ?FreeCount@CMemSpyApiHeap@@QAEHXZ @ 11 NONAME ; int CMemSpyApiHeap::FreeCount(void) + ?ExitType@CMemSpyApiProcess@@QBE?AW4TExitType@@XZ @ 12 NONAME ; enum TExitType CMemSpyApiProcess::ExitType(void) const + ?TotalFree@CMemSpyApiHeap@@QAEHXZ @ 13 NONAME ; int CMemSpyApiHeap::TotalFree(void) + ?SwitchToThread@RMemSpySession@@QAEHVTThreadId@@H@Z @ 14 NONAME ; int RMemSpySession::SwitchToThread(class TThreadId, int) + ?FreeOverhead@CMemSpyApiHeap@@QAEHXZ @ 15 NONAME ; int CMemSpyApiHeap::FreeOverhead(void) + ?SlackFreeSpace@CMemSpyApiHeap@@QAEHXZ @ 16 NONAME ; int CMemSpyApiHeap::SlackFreeSpace(void) + ?Priority@CMemSpyApiKernelObjectItem@@QBEHXZ @ 17 NONAME ; int CMemSpyApiKernelObjectItem::Priority(void) const + ?EndThread@RMemSpySession@@QAEHVTThreadId@@W4TMemSpyEndType@@@Z @ 18 NONAME ; int RMemSpySession::EndThread(class TThreadId, enum TEndType) + ?ThreadCount@CMemSpyApiProcess@@QBEHXZ @ 19 NONAME ; int CMemSpyApiProcess::ThreadCount(void) const + ?RequestCount@CMemSpyApiThread@@QBEHXZ @ 20 NONAME ; int CMemSpyApiThread::RequestCount(void) const + ??1CMemSpyApiProcess@@QAE@XZ @ 21 NONAME ; CMemSpyApiProcess::~CMemSpyApiProcess(void) + ?SetThreadPriorityL@RMemSpySession@@QAEXVTThreadId@@H@Z @ 22 NONAME ; void RMemSpySession::SetThreadPriorityL(class TThreadId, int) + ?MinLength@CMemSpyApiHeap@@QAEHXZ @ 23 NONAME ; int CMemSpyApiHeap::MinLength(void) + ?Restrictions@CMemSpyApiKernelObjectItem@@QBEIXZ @ 24 NONAME ; unsigned int CMemSpyApiKernelObjectItem::Restrictions(void) const + ?Id@CMemSpyApiKernelObjectItem@@QBEHXZ @ 25 NONAME ; int CMemSpyApiKernelObjectItem::Id(void) const + ?Count@CMemSpyApiKernelObjectItem@@QBEHXZ @ 26 NONAME ; int CMemSpyApiKernelObjectItem::Count(void) const + ?ExitCategory@CMemSpyApiProcess@@QBE?AV?$TBuf@$0BA@@@XZ @ 27 NONAME ; class TBuf<16> CMemSpyApiProcess::ExitCategory(void) const + ?ControllingOwner@CMemSpyApiKernelObjectItem@@QBEIXZ @ 28 NONAME ; unsigned int CMemSpyApiKernelObjectItem::ControllingOwner(void) const + ?Count@CMemSpyApiKernelObject@@QBEHXZ @ 29 NONAME ; int CMemSpyApiKernelObject::Count(void) const + ?StartPos@CMemSpyApiKernelObjectItem@@QBEHXZ @ 30 NONAME ; int CMemSpyApiKernelObjectItem::StartPos(void) const + ?TimerState@CMemSpyApiKernelObjectItem@@QBE?AW4TMemSpyDriverTimerState@@XZ @ 31 NONAME ; enum TMemSpyDriverTimerState CMemSpyApiKernelObjectItem::TimerState(void) const + ?ExitType@CMemSpyApiThread@@QBE?AW4TExitType@@XZ @ 32 NONAME ; enum TExitType CMemSpyApiThread::ExitType(void) const + ?BaseAddress@CMemSpyApiHeap@@QAEHXZ @ 33 NONAME ; int CMemSpyApiHeap::BaseAddress(void) + ?Version@CMemSpyApiKernelObjectItem@@QBE?AVTVersion@@XZ @ 34 NONAME ; class TVersion CMemSpyApiKernelObjectItem::Version(void) const + ?SwitchToProcess@RMemSpySession@@QAEHVTProcessId@@H@Z @ 35 NONAME ; int RMemSpySession::SwitchToProcess(class TProcessId, int) + ?MaxSize@CMemSpyApiKernelObjectItem@@QBEHXZ @ 36 NONAME ; int CMemSpyApiKernelObjectItem::MaxSize(void) const + ?Type@CMemSpyApiHeap@@QAEAAVTDesC16@@XZ @ 37 NONAME ; class TDesC16 & CMemSpyApiHeap::Type(void) + ?AddressOfOwningProcess@CMemSpyApiKernelObjectItem@@QAEPAEXZ @ 38 NONAME ; unsigned char * CMemSpyApiKernelObjectItem::AddressOfOwningProcess(void) + ?Id@CMemSpyApiProcess@@QBE?AVTProcessId@@XZ @ 39 NONAME ; class TProcessId CMemSpyApiProcess::Id(void) const + ??1CMemSpyApiKernelObjectItem@@QAE@XZ @ 40 NONAME ; CMemSpyApiKernelObjectItem::~CMemSpyApiKernelObjectItem(void) + ?BiggestAllocation@CMemSpyApiHeap@@QAEHXZ @ 41 NONAME ; int CMemSpyApiHeap::BiggestAllocation(void) + ?ExitReason@CMemSpyApiProcess@@QBEHXZ @ 42 NONAME ; int CMemSpyApiProcess::ExitReason(void) const + ?MsgCount@CMemSpyApiKernelObjectItem@@QBEHXZ @ 43 NONAME ; int CMemSpyApiKernelObjectItem::MsgCount(void) const + ?AllocationsCount@CMemSpyApiHeap@@QAEHXZ @ 44 NONAME ; int CMemSpyApiHeap::AllocationsCount(void) + ?AllocationOverhead@CMemSpyApiHeap@@QAEHXZ @ 45 NONAME ; int CMemSpyApiHeap::AllocationOverhead(void) + ?NameOfOwner@CMemSpyApiKernelObjectItem@@QBEABVTDesC8@@XZ @ 46 NONAME ; class TDesC8 const & CMemSpyApiKernelObjectItem::NameOfOwner(void) const + ?WaitCount@CMemSpyApiKernelObjectItem@@QBEHXZ @ 47 NONAME ; int CMemSpyApiKernelObjectItem::WaitCount(void) const + ?ThreadSystemPermanentOrCritical@RMemSpySession@@QAEHVTThreadId@@H@Z @ 48 NONAME ; int RMemSpySession::ThreadSystemPermanentOrCritical(class TThreadId, int) + ?Protection@CMemSpyApiKernelObjectItem@@QBEIXZ @ 49 NONAME ; unsigned int CMemSpyApiKernelObjectItem::Protection(void) const + ?Attributes@CMemSpyApiThread@@QBEHXZ @ 50 NONAME ; int CMemSpyApiThread::Attributes(void) const + ?BiggestFree@CMemSpyApiHeap@@QAEHXZ @ 51 NONAME ; int CMemSpyApiHeap::BiggestFree(void) + ?Bottom@CMemSpyApiKernelObjectItem@@QBEHXZ @ 52 NONAME ; int CMemSpyApiKernelObjectItem::Bottom(void) const + ?Size@CMemSpyApiKernelObject@@QBE_JXZ @ 53 NONAME ; long long CMemSpyApiKernelObject::Size(void) const + ?ThreadHandles@CMemSpyApiThread@@QBEHXZ @ 54 NONAME ; int CMemSpyApiThread::ThreadHandles(void) const + ?SvrSessionType@CMemSpyApiKernelObjectItem@@QBEEXZ @ 55 NONAME ; unsigned char CMemSpyApiKernelObjectItem::SvrSessionType(void) const + ?TotalAllocations@CMemSpyApiHeap@@QAEHXZ @ 56 NONAME ; int CMemSpyApiHeap::TotalAllocations(void) + ?Name@CMemSpyApiProcess@@QBEABVTDesC16@@XZ @ 57 NONAME ; class TDesC16 const & CMemSpyApiProcess::Name(void) const + ?ChunkType@CMemSpyApiKernelObjectItem@@QBEIXZ @ 58 NONAME ; unsigned int CMemSpyApiKernelObjectItem::ChunkType(void) const + ?GetKernelObjects@RMemSpySession@@QAEHAAV?$RArray@PAVCMemSpyApiKernelObject@@@@@Z @ 59 NONAME ; int RMemSpySession::GetKernelObjects(class RArray<class CMemSpyApiKernelObject *> &) + ?HeaderSizeF@CMemSpyApiHeap@@QAEHXZ @ 60 NONAME ; int CMemSpyApiHeap::HeaderSizeF(void) + ?Id@CMemSpyApiThread@@QBE?AVTThreadId@@XZ @ 61 NONAME ; class TThreadId CMemSpyApiThread::Id(void) const + ?MsgLimit@CMemSpyApiKernelObjectItem@@QBEHXZ @ 62 NONAME ; int CMemSpyApiKernelObjectItem::MsgLimit(void) const + ?AddressOfDataBssStackChunk@CMemSpyApiKernelObjectItem@@QAEPAEXZ @ 63 NONAME ; unsigned char * CMemSpyApiKernelObjectItem::AddressOfDataBssStackChunk(void) + ?MapAttr@CMemSpyApiKernelObjectItem@@QBEIXZ @ 64 NONAME ; unsigned int CMemSpyApiKernelObjectItem::MapAttr(void) const + ?Top@CMemSpyApiKernelObjectItem@@QBEHXZ @ 65 NONAME ; int CMemSpyApiKernelObjectItem::Top(void) const + ?Resetting@CMemSpyApiKernelObjectItem@@QBEEXZ @ 66 NONAME ; unsigned char CMemSpyApiKernelObjectItem::Resetting(void) const + ?HeaderSizeA@CMemSpyApiHeap@@QAEHXZ @ 67 NONAME ; int CMemSpyApiHeap::HeaderSizeA(void) + ?EndProcess@RMemSpySession@@QAEHVTProcessId@@W4TMemSpyEndType@@@Z @ 68 NONAME ; int RMemSpySession::EndProcess(class TProcessId, enum TEndType) + ?AddressOfCodeSeg@CMemSpyApiKernelObjectItem@@QAEPAEXZ @ 69 NONAME ; unsigned char * CMemSpyApiKernelObjectItem::AddressOfCodeSeg(void) + ?TotalAccessCount@CMemSpyApiKernelObjectItem@@QBEGXZ @ 70 NONAME ; unsigned short CMemSpyApiKernelObjectItem::TotalAccessCount(void) const + ?GetThreadsL@RMemSpySession@@QAEXVTProcessId@@AAV?$RArray@PAVCMemSpyApiThread@@@@W4TSortType@@@Z @ 71 NONAME ; void RMemSpySession::GetThreadsL(class TProcessId, class RArray<class CMemSpyApiThread *> &, enum TSortType) + ?Changes@CMemSpyApiKernelObjectItem@@QBEIXZ @ 72 NONAME ; unsigned int CMemSpyApiKernelObjectItem::Changes(void) const + ?ProcessId@CMemSpyApiThread@@QBE?AVTProcessId@@XZ @ 73 NONAME ; class TProcessId CMemSpyApiThread::ProcessId(void) const + ??0RMemSpySession@@QAE@XZ @ 74 NONAME ; RMemSpySession::RMemSpySession(void) + ?Type@CMemSpyApiKernelObjectItem@@QBE?AW4TMemSpyDriverContainerType@@XZ @ 75 NONAME ; enum TMemSpyDriverContainerType CMemSpyApiKernelObjectItem::Type(void) const + ?AddressOfServer@CMemSpyApiKernelObjectItem@@QAEPAEXZ @ 76 NONAME ; unsigned char * CMemSpyApiKernelObjectItem::AddressOfServer(void) + ?Size@CMemSpyApiHeap@@QAEHXZ @ 77 NONAME ; int CMemSpyApiHeap::Size(void) + ??1CMemSpyApiKernelObject@@QAE@XZ @ 78 NONAME ; CMemSpyApiKernelObject::~CMemSpyApiKernelObject(void) + ??1CMemSpyApiHeap@@QAE@XZ @ 79 NONAME ; CMemSpyApiHeap::~CMemSpyApiHeap(void) + ?ChunkSize@CMemSpyApiHeap@@QAEHXZ @ 80 NONAME ; int CMemSpyApiHeap::ChunkSize(void) + ?UnitsMask@CMemSpyApiKernelObjectItem@@QBEIXZ @ 81 NONAME ; unsigned int CMemSpyApiKernelObjectItem::UnitsMask(void) const + ?Size@CMemSpyApiKernelObjectItem@@QBEKXZ @ 82 NONAME ; unsigned long CMemSpyApiKernelObjectItem::Size(void) const + ?State@CMemSpyApiKernelObjectItem@@QBEEXZ @ 83 NONAME ; unsigned char CMemSpyApiKernelObjectItem::State(void) const + ?Shared@CMemSpyApiHeap@@QAEHXZ @ 84 NONAME ; int CMemSpyApiHeap::Shared(void) + ?Type@CMemSpyApiKernelObject@@QBE?AW4TMemSpyDriverContainerType@@XZ @ 85 NONAME ; enum TMemSpyDriverContainerType CMemSpyApiKernelObject::Type(void) const + ?Fragmentation@CMemSpyApiHeap@@QAEHXZ @ 86 NONAME ; int CMemSpyApiHeap::Fragmentation(void) + ?Name@CMemSpyApiKernelObject@@QBEABVTDesC16@@XZ @ 87 NONAME ; class TDesC16 const & CMemSpyApiKernelObject::Name(void) const + ?TimerType@CMemSpyApiKernelObjectItem@@QBE?AW4TMemSpyDriverTimerType@@XZ @ 88 NONAME ; enum TMemSpyDriverTimerType CMemSpyApiKernelObjectItem::TimerType(void) const + ?ProcessSystemPermanentOrCritical@RMemSpySession@@QAEHVTProcessId@@H@Z @ 89 NONAME ; int RMemSpySession::ProcessSystemPermanentOrCritical(class TProcessId, int) + ?SecurityZone@CMemSpyApiKernelObjectItem@@QBEIXZ @ 90 NONAME ; unsigned int CMemSpyApiKernelObjectItem::SecurityZone(void) const + ?CreatorId@CMemSpyApiKernelObjectItem@@QBEIXZ @ 91 NONAME ; unsigned int CMemSpyApiKernelObjectItem::CreatorId(void) const + ?MapCount@CMemSpyApiKernelObjectItem@@QBEHXZ @ 92 NONAME ; int CMemSpyApiKernelObjectItem::MapCount(void) const + ?NameDetail@CMemSpyApiKernelObjectItem@@QBEABVTDesC8@@XZ @ 93 NONAME ; class TDesC8 const & CMemSpyApiKernelObjectItem::NameDetail(void) const + ?OpenChannels@CMemSpyApiKernelObjectItem@@QAEHXZ @ 94 NONAME ; int CMemSpyApiKernelObjectItem::OpenChannels(void) + ?Order@CMemSpyApiKernelObjectItem@@QBEEXZ @ 95 NONAME ; unsigned char CMemSpyApiKernelObjectItem::Order(void) const + ?ProcessPriority@CMemSpyApiThread@@QBE?AW4TProcessPriority@@XZ @ 96 NONAME ; enum TProcessPriority CMemSpyApiThread::ProcessPriority(void) const + ?GetProcessesL@RMemSpySession@@QAEXAAV?$RArray@PAVCMemSpyApiProcess@@@@W4TSortType@@@Z @ 97 NONAME ; void RMemSpySession::GetProcessesL(class RArray<class CMemSpyApiProcess *> &, enum TSortType) + ?Handle@CMemSpyApiKernelObjectItem@@QBEPAXXZ @ 98 NONAME ; void * CMemSpyApiKernelObjectItem::Handle(void) const + ?ParseMask@CMemSpyApiKernelObjectItem@@QBEIXZ @ 99 NONAME ; unsigned int CMemSpyApiKernelObjectItem::ParseMask(void) const + ?Attributes@CMemSpyApiKernelObjectItem@@QBEHXZ @ 100 NONAME ; int CMemSpyApiKernelObjectItem::Attributes(void) const + ?DebugAllocatorLibrary@CMemSpyApiHeap@@QAEHXZ @ 101 NONAME ; int CMemSpyApiHeap::DebugAllocatorLibrary(void) + ?ThreadNumberUsing@CMemSpyApiThread@@QBEHXZ @ 102 NONAME ; int CMemSpyApiThread::ThreadNumberUsing(void) const + ?Overhead@CMemSpyApiHeap@@QAEHXZ @ 103 NONAME ; int CMemSpyApiHeap::Overhead(void) + ?Connect@RMemSpySession@@QAEHXZ @ 104 NONAME ; int RMemSpySession::Connect(void) + ??1CMemSpyApiThread@@QAE@XZ @ 105 NONAME ; CMemSpyApiThread::~CMemSpyApiThread(void) + ?SID@CMemSpyApiThread@@QBEHXZ @ 106 NONAME ; int CMemSpyApiThread::SID(void) const + ?AddressOfOwningThread@CMemSpyApiKernelObjectItem@@QAEPAEXZ @ 107 NONAME ; unsigned char * CMemSpyApiKernelObjectItem::AddressOfOwningThread(void) + ?GetKernelObjectItems@RMemSpySession@@QAEHAAV?$RArray@PAVCMemSpyApiKernelObjectItem@@@@W4TMemSpyDriverContainerType@@@Z @ 108 NONAME ; int RMemSpySession::GetKernelObjectItems(class RArray<class CMemSpyApiKernelObjectItem *> &, enum TMemSpyDriverContainerType) + ?ProcessHandles@CMemSpyApiThread@@QBEHXZ @ 109 NONAME ; int CMemSpyApiThread::ProcessHandles(void) const + ?ThreadPriority@CMemSpyApiThread@@QBE?AW4TThreadPriority@@XZ @ 110 NONAME ; enum TThreadPriority CMemSpyApiThread::ThreadPriority(void) const + ?GetHeap@RMemSpySession@@QAEPAVCMemSpyApiHeap@@XZ @ 111 NONAME ; class CMemSpyApiHeap * RMemSpySession::GetHeap(void) + ?Name@CMemSpyApiThread@@QBEABVTDesC16@@XZ @ 112 NONAME ; class TDesC16 const & CMemSpyApiThread::Name(void) const + ?OutputThreadCellListL@RMemSpySession@@QAEXW4TMemSpyOutputType@@VTThreadId@@@Z @ 113 NONAME ; void RMemSpySession::OutputThreadCellListL(enum TMemSpyOutputType, class TThreadId) + ?OutputCompactHeapInfoL@RMemSpySession@@QAEXW4TMemSpyOutputType@@@Z @ 114 NONAME ; void RMemSpySession::OutputCompactHeapInfoL(enum TMemSpyOutputType) + ?GetProcessIdByNameL@RMemSpySession@@QAE?AVTProcessId@@ABVTDesC16@@@Z @ 115 NONAME ; class TProcessId RMemSpySession::GetProcessIdByNameL(class TDesC16 const &) + ?OutputThreadHeapDataL@RMemSpySession@@QAEXW4TMemSpyOutputType@@VTThreadId@@@Z @ 116 NONAME ; void RMemSpySession::OutputThreadHeapDataL(enum TMemSpyOutputType, class TThreadId) + ?OutputKernelHeapDataL@RMemSpySession@@QAEXW4TMemSpyOutputType@@@Z @ 117 NONAME ; void RMemSpySession::OutputKernelHeapDataL(enum TMemSpyOutputType) + ?OutputCompactStackInfoL@RMemSpySession@@QAEXW4TMemSpyOutputType@@@Z @ 118 NONAME ; void RMemSpySession::OutputCompactStackInfoL(enum TMemSpyOutputType) + ?OutputKernelObjectsL@RMemSpySession@@QAEXW4TMemSpyOutputType@@@Z @ 119 NONAME ; void RMemSpySession::OutputKernelObjectsL(enum TMemSpyOutputType) + diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyClient/eabi/MemSpyClientu.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyClient/eabi/MemSpyClientu.def Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,138 @@ +EXPORTS + _ZN14CMemSpyApiHeap11BaseAddressEv @ 1 NONAME + _ZN14CMemSpyApiHeap11BiggestFreeEv @ 2 NONAME + _ZN14CMemSpyApiHeap11HeaderSizeAEv @ 3 NONAME + _ZN14CMemSpyApiHeap11HeaderSizeFEv @ 4 NONAME + _ZN14CMemSpyApiHeap12FreeOverheadEv @ 5 NONAME + _ZN14CMemSpyApiHeap13FragmentationEv @ 6 NONAME + _ZN14CMemSpyApiHeap13TotalOverheadEv @ 7 NONAME + _ZN14CMemSpyApiHeap14SlackFreeSpaceEv @ 8 NONAME + _ZN14CMemSpyApiHeap16AllocationsCountEv @ 9 NONAME + _ZN14CMemSpyApiHeap16TotalAllocationsEv @ 10 NONAME + _ZN14CMemSpyApiHeap17BiggestAllocationEv @ 11 NONAME + _ZN14CMemSpyApiHeap18AllocationOverheadEv @ 12 NONAME + _ZN14CMemSpyApiHeap21DebugAllocatorLibraryEv @ 13 NONAME + _ZN14CMemSpyApiHeap4SizeEv @ 14 NONAME + _ZN14CMemSpyApiHeap4TypeEv @ 15 NONAME + _ZN14CMemSpyApiHeap6SharedEv @ 16 NONAME + _ZN14CMemSpyApiHeap8OverheadEv @ 17 NONAME + _ZN14CMemSpyApiHeap9ChunkSizeEv @ 18 NONAME + _ZN14CMemSpyApiHeap9FreeCountEv @ 19 NONAME + _ZN14CMemSpyApiHeap9MaxLengthEv @ 20 NONAME + _ZN14CMemSpyApiHeap9MinLengthEv @ 21 NONAME + _ZN14CMemSpyApiHeap9TotalFreeEv @ 22 NONAME + _ZN14CMemSpyApiHeapD1Ev @ 23 NONAME + _ZN14CMemSpyApiHeapD2Ev @ 24 NONAME + _ZN14RMemSpySession10EndProcessE10TProcessId14TMemSpyEndType @ 25 NONAME + _ZN14RMemSpySession11GetThreadsLE10TProcessIdR6RArrayIP16CMemSpyApiThreadE9TSortType @ 26 NONAME + _ZN14RMemSpySession13GetProcessesLER6RArrayIP17CMemSpyApiProcessE9TSortType @ 27 NONAME + _ZN14RMemSpySession14SwitchToThreadE9TThreadIdi @ 28 NONAME + _ZN14RMemSpySession15SwitchToProcessE10TProcessIdi @ 29 NONAME + _ZN14RMemSpySession16GetKernelObjectsER6RArrayIP22CMemSpyApiKernelObjectE @ 30 NONAME + _ZN14RMemSpySession20GetKernelObjectItemsER6RArrayIP26CMemSpyApiKernelObjectItemE26TMemSpyDriverContainerType @ 31 NONAME + _ZN14RMemSpySession31ThreadSystemPermanentOrCriticalE9TThreadIdi @ 32 NONAME + _ZN14RMemSpySession32ProcessSystemPermanentOrCriticalE10TProcessIdi @ 33 NONAME + _ZN14RMemSpySession7ConnectEv @ 34 NONAME + _ZN14RMemSpySession7GetHeapEv @ 35 NONAME + _ZN14RMemSpySession9EndThreadE9TThreadId14TMemSpyEndType @ 36 NONAME + _ZN14RMemSpySessionC1Ev @ 37 NONAME + _ZN14RMemSpySessionC2Ev @ 38 NONAME + _ZN16CMemSpyApiThreadD1Ev @ 39 NONAME + _ZN16CMemSpyApiThreadD2Ev @ 40 NONAME + _ZN17CMemSpyApiProcessD1Ev @ 41 NONAME + _ZN17CMemSpyApiProcessD2Ev @ 42 NONAME + _ZN22CMemSpyApiKernelObjectD1Ev @ 43 NONAME + _ZN22CMemSpyApiKernelObjectD2Ev @ 44 NONAME + _ZN26CMemSpyApiKernelObjectItem12OpenChannelsEv @ 45 NONAME + _ZN26CMemSpyApiKernelObjectItem15AddressOfServerEv @ 46 NONAME + _ZN26CMemSpyApiKernelObjectItem16AddressOfCodeSegEv @ 47 NONAME + _ZN26CMemSpyApiKernelObjectItem20AddressOfKernelOwnerEv @ 48 NONAME + _ZN26CMemSpyApiKernelObjectItem21AddressOfOwningThreadEv @ 49 NONAME + _ZN26CMemSpyApiKernelObjectItem22AddressOfOwningProcessEv @ 50 NONAME + _ZN26CMemSpyApiKernelObjectItem26AddressOfDataBssStackChunkEv @ 51 NONAME + _ZN26CMemSpyApiKernelObjectItemD1Ev @ 52 NONAME + _ZN26CMemSpyApiKernelObjectItemD2Ev @ 53 NONAME + _ZNK16CMemSpyApiThread10AttributesEv @ 54 NONAME + _ZNK16CMemSpyApiThread12RequestCountEv @ 55 NONAME + _ZNK16CMemSpyApiThread13ThreadHandlesEv @ 56 NONAME + _ZNK16CMemSpyApiThread14ProcessHandlesEv @ 57 NONAME + _ZNK16CMemSpyApiThread14ThreadPriorityEv @ 58 NONAME + _ZNK16CMemSpyApiThread15ProcessPriorityEv @ 59 NONAME + _ZNK16CMemSpyApiThread17ThreadNumberUsingEv @ 60 NONAME + _ZNK16CMemSpyApiThread18ProcessNumberUsingEv @ 61 NONAME + _ZNK16CMemSpyApiThread2IdEv @ 62 NONAME + _ZNK16CMemSpyApiThread3SIDEv @ 63 NONAME + _ZNK16CMemSpyApiThread3VIDEv @ 64 NONAME + _ZNK16CMemSpyApiThread4NameEv @ 65 NONAME + _ZNK16CMemSpyApiThread6CpuUseEv @ 66 NONAME + _ZNK16CMemSpyApiThread8ExitTypeEv @ 67 NONAME + _ZNK16CMemSpyApiThread9ProcessIdEv @ 68 NONAME + _ZNK17CMemSpyApiProcess10ExitReasonEv @ 69 NONAME + _ZNK17CMemSpyApiProcess11ThreadCountEv @ 70 NONAME + _ZNK17CMemSpyApiProcess12ExitCategoryEv @ 71 NONAME + _ZNK17CMemSpyApiProcess2IdEv @ 72 NONAME + _ZNK17CMemSpyApiProcess4NameEv @ 73 NONAME + _ZNK17CMemSpyApiProcess8ExitTypeEv @ 74 NONAME + _ZNK22CMemSpyApiKernelObject4NameEv @ 75 NONAME + _ZNK22CMemSpyApiKernelObject4SizeEv @ 76 NONAME + _ZNK22CMemSpyApiKernelObject4TypeEv @ 77 NONAME + _ZNK22CMemSpyApiKernelObject5CountEv @ 78 NONAME + _ZNK26CMemSpyApiKernelObjectItem10AttributesEv @ 79 NONAME + _ZNK26CMemSpyApiKernelObjectItem10NameDetailEv @ 80 NONAME + _ZNK26CMemSpyApiKernelObjectItem10ProtectionEv @ 81 NONAME + _ZNK26CMemSpyApiKernelObjectItem10TimerStateEv @ 82 NONAME + _ZNK26CMemSpyApiKernelObjectItem11AccessCountEv @ 83 NONAME + _ZNK26CMemSpyApiKernelObjectItem11NameOfOwnerEv @ 84 NONAME + _ZNK26CMemSpyApiKernelObjectItem11SessionTypeEv @ 85 NONAME + _ZNK26CMemSpyApiKernelObjectItem12RestrictionsEv @ 86 NONAME + _ZNK26CMemSpyApiKernelObjectItem12SecurityZoneEv @ 87 NONAME + _ZNK26CMemSpyApiKernelObjectItem14SvrSessionTypeEv @ 88 NONAME + _ZNK26CMemSpyApiKernelObjectItem16ControllingOwnerEv @ 89 NONAME + _ZNK26CMemSpyApiKernelObjectItem16TotalAccessCountEv @ 90 NONAME + _ZNK26CMemSpyApiKernelObjectItem2IdEv @ 91 NONAME + _ZNK26CMemSpyApiKernelObjectItem3TopEv @ 92 NONAME + _ZNK26CMemSpyApiKernelObjectItem4NameEv @ 93 NONAME + _ZNK26CMemSpyApiKernelObjectItem4SizeEv @ 94 NONAME + _ZNK26CMemSpyApiKernelObjectItem4TypeEv @ 95 NONAME + _ZNK26CMemSpyApiKernelObjectItem5CountEv @ 96 NONAME + _ZNK26CMemSpyApiKernelObjectItem5OrderEv @ 97 NONAME + _ZNK26CMemSpyApiKernelObjectItem5StateEv @ 98 NONAME + _ZNK26CMemSpyApiKernelObjectItem6BottomEv @ 99 NONAME + _ZNK26CMemSpyApiKernelObjectItem6HandleEv @ 100 NONAME + _ZNK26CMemSpyApiKernelObjectItem7ChangesEv @ 101 NONAME + _ZNK26CMemSpyApiKernelObjectItem7MapAttrEv @ 102 NONAME + _ZNK26CMemSpyApiKernelObjectItem7MaxSizeEv @ 103 NONAME + _ZNK26CMemSpyApiKernelObjectItem7VersionEv @ 104 NONAME + _ZNK26CMemSpyApiKernelObjectItem8MapCountEv @ 105 NONAME + _ZNK26CMemSpyApiKernelObjectItem8MsgCountEv @ 106 NONAME + _ZNK26CMemSpyApiKernelObjectItem8MsgLimitEv @ 107 NONAME + _ZNK26CMemSpyApiKernelObjectItem8PriorityEv @ 108 NONAME + _ZNK26CMemSpyApiKernelObjectItem8StartPosEv @ 109 NONAME + _ZNK26CMemSpyApiKernelObjectItem8UniqueIDEv @ 110 NONAME + _ZNK26CMemSpyApiKernelObjectItem9ChunkTypeEv @ 111 NONAME + _ZNK26CMemSpyApiKernelObjectItem9CreatorIdEv @ 112 NONAME + _ZNK26CMemSpyApiKernelObjectItem9ParseMaskEv @ 113 NONAME + _ZNK26CMemSpyApiKernelObjectItem9ResettingEv @ 114 NONAME + _ZNK26CMemSpyApiKernelObjectItem9TimerTypeEv @ 115 NONAME + _ZNK26CMemSpyApiKernelObjectItem9UnitsMaskEv @ 116 NONAME + _ZNK26CMemSpyApiKernelObjectItem9WaitCountEv @ 117 NONAME + _ZN14RMemSpySession18SetThreadPriorityLE9TThreadIdi @ 118 NONAME + _ZN14RMemSpySession19GetProcessIdByNameLERK7TDesC16 @ 119 NONAME + _ZN14RMemSpySession20OutputKernelObjectsLE17TMemSpyOutputType @ 120 NONAME + _ZN14RMemSpySession21OutputKernelHeapDataLE17TMemSpyOutputType @ 121 NONAME + _ZN14RMemSpySession21OutputThreadCellListLE17TMemSpyOutputType9TThreadId @ 122 NONAME + _ZN14RMemSpySession21OutputThreadHeapDataLE17TMemSpyOutputType9TThreadId @ 123 NONAME + _ZN14RMemSpySession22OutputCompactHeapInfoLE17TMemSpyOutputType @ 124 NONAME + _ZN14RMemSpySession23OutputCompactStackInfoLE17TMemSpyOutputType @ 125 NONAME + _ZN14RMemSpySession14DumpKernelHeapEv @ 126 NONAME + _ZN14RMemSpySession15GetInfoItemTypeEi9TThreadIdR25TMemSpyThreadInfoItemType @ 127 NONAME + _ZN14RMemSpySession18GetThreadInfoItemsER6RArrayIP24CMemSpyApiThreadInfoItemE9TThreadId25TMemSpyThreadInfoItemType @ 128 NONAME + _ZN14RMemSpySession26OutputAllContainerContentsEv @ 129 NONAME + _ZN24CMemSpyApiThreadInfoItemD1Ev @ 130 NONAME + _ZN24CMemSpyApiThreadInfoItemD2Ev @ 131 NONAME + _ZNK17CMemSpyApiProcess3SIDEv @ 132 NONAME + _ZNK17CMemSpyApiProcess3VIDEv @ 133 NONAME + _ZNK17CMemSpyApiProcess8PriorityEv @ 134 NONAME + _ZNK24CMemSpyApiThreadInfoItem5ValueEv @ 135 NONAME + _ZNK24CMemSpyApiThreadInfoItem7CaptionEv @ 136 NONAME + diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyClient/group/MemSpyClient.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyClient/group/MemSpyClient.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,55 @@ +/* +* 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: +* +*/ + +#include <data_caging_paths.hrh> +#include <platform_paths.hrh> + +TARGETTYPE dll +TARGET MemSpyClient.dll +UID 0 0x2002EA8E +VENDORID VID_DEFAULT +SMPSAFE + +CAPABILITY PowerMgmt SwEvent ReadUserData WriteUserData ReadDeviceData WriteDeviceData + +SOURCEPATH ../src +SOURCE memspysession.cpp +SOURCE memspyapiprocess.cpp +SOURCE memspyapikernelobject.cpp +SOURCE memspyapiheap.cpp +SOURCE memspyapikernelobjectitem.cpp +SOURCE memspyapithread.cpp +SOURCE memspyapithreadinfoitem.cpp + +USERINCLUDE ../inc + +OS_LAYER_SYSTEMINCLUDE + +LIBRARY euser.lib +LIBRARY ecom.lib +LIBRARY efsrv.lib +LIBRARY estor.lib +LIBRARY bafl.lib +LIBRARY ws32.lib +LIBRARY cone.lib +LIBRARY eikcore.lib +LIBRARY fbscli.lib +LIBRARY PlatformEnv.lib + +LIBRARY MemSpyEngine.lib + +EXPORTUNFROZEN \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyClient/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyClient/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,37 @@ +/* +* 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: +* +*/ + +#include <platform_paths.hrh> + +PRJ_EXPORTS +// Public API +../inc/memspysession.h OS_LAYER_PLATFORM_EXPORT_PATH(memspysession.h) +../inc/memspyprocessdata.h OS_LAYER_PLATFORM_EXPORT_PATH(memspy/engine/memspyprocessdata.h) +../inc/memspykernelobjectdata.h OS_LAYER_PLATFORM_EXPORT_PATH(memspy/engine/memspykernelobjectdata.h) +../inc/memspyheapdata.h OS_LAYER_PLATFORM_EXPORT_PATH(memspy/engine/memspyheapdata.h) +../inc/memspythreaddata.h OS_LAYER_PLATFORM_EXPORT_PATH(memspy/engine/memspythreaddata.h) +../inc/memspythreadinfoitemdata.h OS_LAYER_PLATFORM_EXPORT_PATH(memspy/engine/memspythreadinfoitemdata.h) + +../inc/memspyapiprocess.h OS_LAYER_PLATFORM_EXPORT_PATH(memspy/api/memspyapiprocess.h) +../inc/memspyapikernelobject.h OS_LAYER_PLATFORM_EXPORT_PATH(memspy/api/memspyapikernelobject.h) +../inc/memspyapikernelobjectitem.h OS_LAYER_PLATFORM_EXPORT_PATH(memspy/api/memspyapikernelobjectitem.h) +../inc/memspyapiheap.h OS_LAYER_PLATFORM_EXPORT_PATH(memspy/api/memspyapiheap.h) +../inc/memspyapithread.h OS_LAYER_PLATFORM_EXPORT_PATH(memspy/api/memspyapithread.h) +../inc/memspyapithreadinfoitem.h OS_LAYER_PLATFORM_EXPORT_PATH(memspy/api/memspyapithreadinfoitem.h) + +PRJ_MMPFILES +MemSpyClient.mmp \ No newline at end of file diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyClient/inc/memspyapiprocess.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyClient/inc/memspyapiprocess.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,65 @@ +/* +* 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: +* Contains the declaration of CMemSpyProcess class +*/ + +#ifndef MEMSPYAPIPROCESS_H +#define MEMSPYAPIPROCESS_H + +// System includes +#include <e32base.h> + +class TMemSpyProcessData; + +NONSHARABLE_CLASS( CMemSpyApiProcess ) + { +public: + IMPORT_C ~CMemSpyApiProcess(); + + static CMemSpyApiProcess* NewL(const TMemSpyProcessData& aData); + + static CMemSpyApiProcess* NewLC(const TMemSpyProcessData& aData); + +public: + IMPORT_C TProcessId Id() const; + + IMPORT_C const TDesC& Name() const; + + IMPORT_C TExitCategoryName ExitCategory() const; + + IMPORT_C TInt ExitReason() const; + + IMPORT_C TExitType ExitType() const; + + IMPORT_C TInt ThreadCount() const; + + IMPORT_C TUint32 SID() const; + + IMPORT_C TUint32 VID() const; + + IMPORT_C TProcessPriority Priority() const; + + +private: + CMemSpyApiProcess(); + + void ConstructL(const TMemSpyProcessData& aData); + +private: + TMemSpyProcessData *iProcessData; +}; + + +#endif // MEMSPYAPIPROCESS_H diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyClient/inc/memspyapithreadinfoitem.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyClient/inc/memspyapithreadinfoitem.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,50 @@ +/* +* 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: +* Contains the declaration of CMemSpyProcess class +*/ + +#ifndef MEMSPYAPITHREADINFOITEM_H +#define MEMSPYAPITHREADINFOITEM_H + +// System includes +#include <e32base.h> + +class TMemSpyThreadInfoItemData; + +NONSHARABLE_CLASS( CMemSpyApiThreadInfoItem ) + { +public: + IMPORT_C ~CMemSpyApiThreadInfoItem(); + + static CMemSpyApiThreadInfoItem* NewL(const TMemSpyThreadInfoItemData& aData); + + static CMemSpyApiThreadInfoItem* NewLC(const TMemSpyThreadInfoItemData& aData); + +public: + IMPORT_C const TDesC& Caption() const; + + IMPORT_C const TDesC& Value() const; + +private: + CMemSpyApiThreadInfoItem(); + + void ConstructL(const TMemSpyThreadInfoItemData& aData); + +private: + TMemSpyThreadInfoItemData *iInfoItem; +}; + + +#endif // MEMSPYAPITHREADINFOITEM_H diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyClient/inc/memspykernelobjectdata.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyClient/inc/memspykernelobjectdata.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,43 @@ +/* +* 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: +* Contains the declaration of TMemSpyProcessData class +*/ + +#ifndef MEMSPYKERNELOBJECTDATA_H +#define MEMSPYKERNELOBJECTDATA_H + +#include <memspy/driver/memspydriverenumerationsshared.h> + +// Constants +const TInt KBufSize = 128; + +// TMemSpyProcess data class holds data to be sent to the UI +class TMemSpyKernelObjectData + { +public: + //constructor & destructor + inline TMemSpyKernelObjectData() + : iCount(0), iSize(0) + { + } + +public: + TMemSpyDriverContainerType iType; + TFullName iName; + TInt iCount; + TInt64 iSize; + }; + +#endif // MEMSPYKERNELOBJECTDATA_H diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyClient/inc/memspyprocessdata.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyClient/inc/memspyprocessdata.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,46 @@ +/* +* 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: +* Contains the declaration of TMemSpyProcessData class +*/ + +#ifndef MEMSPYPROCESSDATA_H +#define MEMSPYPROCESSDATA_H + +#include <memspy/driver/memspydriverobjectsshared.h> + +// TMemSpyProcess data class holds data to be sent to the UI +class TMemSpyProcessData + { +public: + //constructor & destructor + inline TMemSpyProcessData() + : iId(0), iThreadCount(0), iExitCategory(0), iExitReason(0) + { + } + +public: + TProcessId iId; + TFullName iName; + TProcessPriority iPriority; + TExitCategoryName iExitCategory; + TInt iExitReason; + TExitType iExitType; + TInt iThreadCount; + TUint32 iSID; + TUint32 iVID; + //TMemSpyDriverProcessInfo iInfo; + }; + +#endif // MEMSPYPROCESSDATA_H diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyClient/inc/memspysession.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyClient/inc/memspysession.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,134 @@ +/* +* 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: +* +*/ + + +#ifndef MEMSPYSESSION_H +#define MEMSPYSESSION_H + + +// System includes +#include <e32base.h> +#include <u32std.h> + +//user includes +#include <memspy/engine/memspyprocessdata.h> //for Processes +#include <memspy/api/memspyapiprocess.h> + +#include <memspy/engine/memspythreaddata.h> //for Threads +#include <memspy/api/memspyapithread.h> +#include <memspy/api/memspyapithreadinfoitem.h> +#include <memspy/engine/memspythreadinfoitemdata.h> +#include <memspy/engine/memspyengineobjectthreadinfoobjects.h> + +#include <memspy/engine/memspykernelobjectdata.h> //for KernelObjects +#include <memspy/api/memspyapikernelobject.h> + +#include <memspy/api/memspyapikernelobjectitem.h> //for KernelObjectItems + +#include <memspy/engine/memspyheapdata.h> //for Heap +#include <memspy/api/memspyapiheap.h> + +#include <memspyengineclientinterface.h> + +// Constants +const TInt KMemSpyVersion = 2; + +enum TSortType + { + ESortProcById, + ESortProcByName, + ESortProcByThreadCount, + ESortProcByCodeSegs, + ESortProcByHeapUsage, + ESortProcByStackUsage + }; + +enum TMemSpyOutputType + { + EOutputTypeDebug = 0, + EOutputTypeFile + }; + + +NONSHARABLE_CLASS( RMemSpySession ) : public RSessionBase + { +public: + IMPORT_C RMemSpySession(); + IMPORT_C TInt Connect(); + +public: //API + IMPORT_C void OutputKernelHeapDataL(TMemSpyOutputType aOutputType); //EMemSpyClientServerOpHeapData + IMPORT_C void OutputThreadHeapDataL(TMemSpyOutputType aOutputType, TThreadId aThreadId); //EMemSpyClientServerOpHeapData + IMPORT_C void OutputThreadCellListL(TMemSpyOutputType aOutputType, TThreadId aThreadId);//EMemSpyClientServerOpHeapCellListing + IMPORT_C void OutputKernelObjectsL(TMemSpyOutputType aOutputType);// EMemSpyClientServerOpEnumerateKernelContainerAll + IMPORT_C void OutputCompactStackInfoL(TMemSpyOutputType aOutputType);// EMemSpyClientServerOpStackInfoCompact + IMPORT_C void OutputCompactHeapInfoL(TMemSpyOutputType aOutputType);// EMemSpyClientServerOpHeapInfoCompact + + IMPORT_C void GetProcessesL(RArray<CMemSpyApiProcess*> &aProcesses, TSortType aSortType = ESortProcById); + + IMPORT_C TProcessId GetProcessIdByNameL(const TDesC& aProcessName); + + IMPORT_C void GetThreadsL(TProcessId aProcessId, RArray<CMemSpyApiThread*> &aThreads, TSortType aSortType = ESortProcById); + + IMPORT_C TInt ProcessSystemPermanentOrCritical( TProcessId aId, TBool aValue ); //aValue -> return value + + IMPORT_C void SetThreadPriorityL(TThreadId aId, TInt aPriority); + IMPORT_C TInt EndProcess( TProcessId aId, TMemSpyEndType aType ); + + IMPORT_C TInt SwitchToProcess( TProcessId aId, TBool aBrought ); + + + //Threads operations + /** + * + */ + IMPORT_C void GetThreadsL(TProcessId aProcessId, RArray<CMemSpyApiProcess*> &aThreads, TSortType aSortType = ESortProcById); + + IMPORT_C TInt ThreadSystemPermanentOrCritical( TThreadId aId, TBool aValue ); + + IMPORT_C TInt EndThread( TThreadId aId, TMemSpyEndType aType ); + + IMPORT_C TInt SwitchToThread( TThreadId aId, TBool aBrought ); + + IMPORT_C TInt GetInfoItemType( TInt aIndex, TThreadId aId, TMemSpyThreadInfoItemType &aType ); + + IMPORT_C void GetThreadInfoItems( RArray<CMemSpyApiThreadInfoItem*> &aInfoItems, TThreadId aId, TMemSpyThreadInfoItemType aType ); + + //KernelObjects operations + /** + * + */ + IMPORT_C TInt GetKernelObjects( RArray<CMemSpyApiKernelObject*> &aKernelObjects ); + + IMPORT_C TInt GetKernelObjectItems( RArray<CMemSpyApiKernelObjectItem*> &aKernelObjectItems, TMemSpyDriverContainerType aForContainer ); + + IMPORT_C void OutputAllContainerContents(); + + /** + * + */ + IMPORT_C CMemSpyApiHeap* GetHeap(); + + IMPORT_C void DumpKernelHeap(); + +private: + TInt StartServer(); + + void SetOutputTypeL(TMemSpyOutputType aOutputType); + }; + +#endif // MEMSPYSESSION_H diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyClient/inc/memspythreadinfoitemdata.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyClient/inc/memspythreadinfoitemdata.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,39 @@ +/* +* 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: +* Contains the declaration of TMemSpyProcessData class +*/ + +#ifndef MEMSPYTHREADINFOITEMDATA_H +#define MEMSPYTHREADINFOITEMDATA_H + +#include <memspy/driver/memspydriverobjectsshared.h> + +const TInt KMaxBufSize = 32; + +// TMemSpyProcess data class holds data to be sent to the UI +class TMemSpyThreadInfoItemData + { +public: + //constructor & destructor + inline TMemSpyThreadInfoItemData() + { + } + +public: + TBuf<KMaxBufSize> iCaption; + TBuf<KMaxBufSize> iValue; + }; + +#endif // MEMSPYTHREADINFOITEMDATA_H diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyClient/src/memspyapiprocess.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyClient/src/memspyapiprocess.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,98 @@ +/* +* 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: +* +*/ + +#include <memspy/api/memspyapiprocess.h> +#include <memspy/engine/memspyengine.h> +#include <memspy/engine/memspyprocessdata.h> +#include <memspy/engine/memspyengineobjectprocess.h> +#include <memspy/engine/memspyengineobjectcontainer.h> + + +EXPORT_C CMemSpyApiProcess::~CMemSpyApiProcess() + { + delete iProcessData; + } + +EXPORT_C TProcessId CMemSpyApiProcess::Id() const + { + return iProcessData->iId; + } + +EXPORT_C const TDesC& CMemSpyApiProcess::Name() const + { + return iProcessData->iName; + } + +EXPORT_C TExitCategoryName CMemSpyApiProcess::ExitCategory() const + { + return iProcessData->iExitCategory; + } + +EXPORT_C TInt CMemSpyApiProcess::ExitReason() const + { + return iProcessData->iExitReason; + } + +EXPORT_C TExitType CMemSpyApiProcess::ExitType() const + { + return iProcessData->iExitType; + } + +EXPORT_C TInt CMemSpyApiProcess::ThreadCount() const + { + return iProcessData->iThreadCount; + } + +EXPORT_C TUint32 CMemSpyApiProcess::SID() const + { + return iProcessData->iSID; + } + +EXPORT_C TUint32 CMemSpyApiProcess::VID() const + { + return iProcessData->iSID; + } + +EXPORT_C TProcessPriority CMemSpyApiProcess::Priority() const + { + return iProcessData->iPriority; + } + +CMemSpyApiProcess::CMemSpyApiProcess() : iProcessData(0) + { + } + +void CMemSpyApiProcess::ConstructL(const TMemSpyProcessData& aData) + { + iProcessData = new (ELeave) TMemSpyProcessData(aData); + } + +CMemSpyApiProcess* CMemSpyApiProcess::NewL(const TMemSpyProcessData& aData) + { + CMemSpyApiProcess* self = CMemSpyApiProcess::NewLC(aData); + CleanupStack::Pop(self); + return (self); + } + +CMemSpyApiProcess* CMemSpyApiProcess::NewLC(const TMemSpyProcessData& aData) + { + CMemSpyApiProcess* self = new (ELeave) CMemSpyApiProcess; + CleanupStack::PushL(self); + self->ConstructL(aData); + return (self); + } + diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyClient/src/memspyapithreadinfoitem.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyClient/src/memspyapithreadinfoitem.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,60 @@ +/* +* 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: +* +*/ + +#include <memspy/api/memspyapithreadinfoitem.h> +#include <memspy/engine/memspyengine.h> +#include <memspy/engine/memspythreadinfoitemdata.h> + +EXPORT_C CMemSpyApiThreadInfoItem::~CMemSpyApiThreadInfoItem() + { + delete iInfoItem; + } + +EXPORT_C const TDesC& CMemSpyApiThreadInfoItem::Caption() const + { + return iInfoItem->iCaption; + } + +EXPORT_C const TDesC& CMemSpyApiThreadInfoItem::Value() const + { + return iInfoItem->iValue; + } + +CMemSpyApiThreadInfoItem::CMemSpyApiThreadInfoItem() : iInfoItem(0) + { + } + +void CMemSpyApiThreadInfoItem::ConstructL(const TMemSpyThreadInfoItemData& aData) + { + iInfoItem = new (ELeave) TMemSpyThreadInfoItemData(aData); + } + +CMemSpyApiThreadInfoItem* CMemSpyApiThreadInfoItem::NewL(const TMemSpyThreadInfoItemData& aData) + { + CMemSpyApiThreadInfoItem* self = CMemSpyApiThreadInfoItem::NewLC(aData); + CleanupStack::Pop(self); + return (self); + } + +CMemSpyApiThreadInfoItem* CMemSpyApiThreadInfoItem::NewLC(const TMemSpyThreadInfoItemData& aData) + { + CMemSpyApiThreadInfoItem* self = new (ELeave) CMemSpyApiThreadInfoItem; + CleanupStack::PushL(self); + self->ConstructL(aData); + return (self); + } + diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyClient/src/memspysession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyClient/src/memspysession.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,501 @@ +/* +* 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: +* +*/ + + +#include "memspysession.h" +#include <memspyengineclientinterface.h> + +#include <memspy/api/memspyapiprocess.h> +#include <memspy/api/memspyapikernelobject.h> +#include <memspy/api/memspyapikernelobjectitem.h> +#include <memspy/api/memspyapithreadinfoitem.h> +//KernelObjects +#include <memspy/driver/memspydriverenumerationsshared.h> +// IMPLEMENTATION + +EXPORT_C RMemSpySession::RMemSpySession() + { + } + + +EXPORT_C TInt RMemSpySession::Connect() + { + TInt error(KErrNone); + + for (TInt i=0; i<2; i++) // Two retries max + { + TInt error = CreateSession(KMemSpyServerName, TVersion(KMemSpyVersion, 0, 0)); + + if (error != KErrNotFound && error != KErrServerTerminated) + return error; + + error = StartServer(); + + if (error != KErrNone && error != KErrAlreadyExists) + return error; + } + + return error; + } + +TInt RMemSpySession::StartServer() + { + RProcess server; + _LIT(KCommand, "start"); + const TUid KServerUid3 = {0xE5883BC2}; + TInt error = server.Create(KMemSpyServerName, KCommand);//, KServerUid3); + + if (error != KErrNone) + return error; + + TRequestStatus startStatus, stopStatus; + server.Logon(stopStatus); + if (stopStatus != KRequestPending) + { + User::WaitForRequest(stopStatus); + server.Kill(0); + server.Close(); + return stopStatus.Int(); + } + + server.Rendezvous(startStatus); + server.Resume(); + User::WaitForRequest(startStatus, stopStatus); + if (startStatus == KRequestPending) + { + // not started yet, i.e. stopStatus was signaled + server.Close(); + return stopStatus.Int(); + } + + // Rendezvous was called - the server is ready + + // We first need to cancel Logon + server.LogonCancel(stopStatus); + // We don't need this anymore + server.Close(); + // Wait for LogonCancel to complete + User::WaitForRequest(stopStatus); + + // Everything went OK + return KErrNone; + } + +//inline void RMemSpySession::Close() +// { +// RSessionBase::Close(); +// } +// +//inline TMemSpySinkType RMemSpySession::GetSinkType() +// { +// TPckgBuf<TMemSpySinkType> OutBuf; +// TIpcArgs args( &OutBuf ); +// SendReceive( EGetSinkType, args ); +// return OutBuf(); +// } +// +//inline void RMemSpySession::OutputKernelObjects() +// { +// SendReceive( EOutputKernelObjects ); +// } +// +//inline void RMemSpySession::OutputToDebug() +// { +// SendReceive( EOutputToDebug ); +// } +// +//inline void RMemSpySession::OutputToFile() +// { +// SendReceive( EOutputToFile ); +// } +// +//inline void RMemSpySession::SetServerTimeOutStatus( TUint32 aValue, TBool aEnabled ) +// { +// TPckgBuf<TUint32> In1(aValue); +// TPckgBuf<TBool> In2(aEnabled); +// TIpcArgs args( &In1, &In2 ); +// SendReceive( ESetServerTimeOutStatus, args ); +// } + +//inline void RMemSpySession::OutputProcessInfo( TMemSpyProcess aProcess ) +// { +// TProcessId iId = aProcess.iId; +// TPckgBuf<TProcessId> In( iId ); +// TIpcArgs args( &In ); +// SendReceive( EOutputProcessInfo, args ); +// } + +////Processes operations +//inline TInt RMemSpySession::ProcessesCount() +// { +// TPckgBuf<TInt> Out; +// TIpcArgs args( &Out ); +// SendReceive( EProcessesCount, args ); +// return Out(); +// } +// +//inline TMemSpyProcess RMemSpySession::GetProcessByIndex( TInt aIndex ) +// { +// TPckgBuf<TInt> In( aIndex ); +// TPckgBuf<TMemSpyProcess> Out; +// TIpcArgs args( &In, &Out ); +// SendReceive( EProcessByIndex, args ); +// return Out(); +// } +// +//inline TInt RMemSpySession::ProcessIndexById( TProcessId aId ) +// { +// TPckgBuf<TProcessId> In( aId ); +// TPckgBuf<TInt> Out; +// TIpcArgs args( &In, &Out ); +// SendReceive( EProcessIndexById, args ); +// return Out(); +// } +// +//inline TBool RMemSpySession::ProcessIsDead( TMemSpyProcess aProcess ) +// { +// TProcessId iId = aProcess.iId; +// TPckgBuf<TProcessId> In( iId ); +// TPckgBuf<TBool> Out; +// TIpcArgs args( &In, &Out ); +// SendReceive( EProcessIsDead, args ); +// return Out(); +// } + +EXPORT_C void RMemSpySession::GetProcessesL(RArray<CMemSpyApiProcess*> &aProcesses, TSortType aSortType) + { + TPckgBuf<TInt> count; + User::LeaveIfError(SendReceive(EMemSpyClientServerOpGetProcessCount, TIpcArgs(&count))); + + TInt requestedCount = count(); + HBufC8* buffer = HBufC8::NewLC(requestedCount * sizeof(TMemSpyProcessData)); + TPtr8 bufferPtr(buffer->Des()); + + User::LeaveIfError(SendReceive(EMemSpyClientServerOpGetProcesses, TIpcArgs(&count, &bufferPtr))); + aProcesses.Reset(); + + TInt receivedCount = Min(count(), requestedCount); + for(TInt i=0, offset = 0; i<requestedCount; i++, offset+=sizeof(TMemSpyProcessData)) + { + TPckgBuf<TMemSpyProcessData> data; + data.Copy(bufferPtr.Ptr()+offset, sizeof(TMemSpyProcessData)); + aProcesses.AppendL(CMemSpyApiProcess::NewLC(data())); + } + CleanupStack::Pop(aProcesses.Count()); + CleanupStack::PopAndDestroy(buffer); + } + +EXPORT_C TProcessId RMemSpySession::GetProcessIdByNameL(const TDesC& aProcessName) + { + TPckgBuf<TProcessId> procId; + User::LeaveIfError(SendReceive(EMemSpyClienServerOpGetProcessIdByName, + TIpcArgs(&aProcessName, &procId))); + + return procId(); + } + +EXPORT_C TInt RMemSpySession::ProcessSystemPermanentOrCritical( TProcessId aId, TBool aValue ) + { + TPckgBuf<TProcessId> arg1( aId ); + TPckgBuf<TBool> arg2( aValue ); + TIpcArgs args( &arg1, &arg2 ); + + TInt error = SendReceive( EMemSpyClientServerOpProcessSystemPermanentOrCritical, args ); + + return error; + } + +EXPORT_C TInt RMemSpySession::EndProcess( TProcessId aId, TMemSpyEndType aType ) + { + TPckgBuf<TProcessId> arg1( aId ); + TPckgBuf<TMemSpyEndType> arg2( aType ); + TIpcArgs args( &arg1, &arg2 ); + + TInt error = SendReceive( EMemSpyClientServerOpEndProcess, args ); + + return error; + } + +EXPORT_C TInt RMemSpySession::SwitchToProcess( TProcessId aId, TBool aBrought ) + { + TPckgBuf<TProcessId> arg1( aId ); + TPckgBuf<TBool> arg2( aBrought ); + TIpcArgs args( &arg1, &arg2 ); + + TInt error = SendReceive( EMemSpyClientServerOpSwitchToProcess, args ); + + return error; + } + +EXPORT_C void RMemSpySession::GetThreadsL(TProcessId aProcessId, RArray<CMemSpyApiThread*> &aThreads, TSortType aSortType) + { + TPckgBuf<TInt> count; + TPckgBuf<TProcessId> pid(aProcessId); + User::LeaveIfError(SendReceive(EMemSpyClientServerOpGetThreadCount, TIpcArgs(&count, &pid))); + + TInt requestedCount = count(); + HBufC8* buffer = HBufC8::NewLC(requestedCount * sizeof(TMemSpyThreadData)); + TPtr8 bufferPtr(buffer->Des()); + + User::LeaveIfError(SendReceive(EMemSpyClientServerOpGetThreads, TIpcArgs(&count, &bufferPtr, &pid))); + aThreads.Reset(); + + TInt receivedCount = Min(count(), requestedCount); + for(TInt i=0, offset = 0; i<requestedCount; i++, offset+=sizeof(TMemSpyThreadData)) + { + TPckgBuf<TMemSpyThreadData> data; + data.Copy(bufferPtr.Ptr()+offset, sizeof(TMemSpyThreadData)); + aThreads.AppendL(CMemSpyApiThread::NewLC(data())); + } + CleanupStack::Pop(aThreads.Count()); + CleanupStack::PopAndDestroy(buffer); + } + +EXPORT_C void RMemSpySession::SetThreadPriorityL(TThreadId aId, TInt aPriority) + { + TPckgBuf<TThreadId> arg1( aId ); + TPckgBuf<TInt> arg2( aPriority ); + + User::LeaveIfError(SendReceive( EMemSpyClientServerOpSetThreadPriority, TIpcArgs(&arg1, &arg2))); + } + +EXPORT_C TInt RMemSpySession::ThreadSystemPermanentOrCritical( TThreadId aId, TBool aValue ) + { + TPckgBuf<TThreadId> arg1( aId ); + TPckgBuf<TBool> arg2( aValue ); + TIpcArgs args( &arg1, &arg2 ); + + TInt error = SendReceive( EMemSpyClientServerOpThreadSystemPermanentOrCritical, args ); + + return error; + } + +EXPORT_C TInt RMemSpySession::EndThread( TThreadId aId, TMemSpyEndType aType ) + { + TPckgBuf<TThreadId> arg1( aId ); + TPckgBuf<TMemSpyEndType> arg2( aType ); + TIpcArgs args( &arg1, &arg2 ); + + TInt error = SendReceive( EMemSpyClientServerOpEndThread, args ); + + return error; + } + +EXPORT_C TInt RMemSpySession::SwitchToThread( TThreadId aId, TBool aBrought ) + { + TPckgBuf<TThreadId> arg1( aId ); + TPckgBuf<TBool> arg2( aBrought ); + TIpcArgs args( &arg1, &arg2 ); + + TInt error = SendReceive( EMemSpyClientServerOpSwitchToThread, args ); + + return error; + } + +EXPORT_C TInt RMemSpySession::GetInfoItemType( TInt aIndex, TThreadId aId, TMemSpyThreadInfoItemType &aType ) + { + TPckgBuf<TInt> arg1( aIndex ); + TPckgBuf<TThreadId> arg2( aId ); + TPckgBuf<TMemSpyThreadInfoItemType> arg3; + TIpcArgs args( &arg1, &arg2, &arg3 ); + + TInt error = SendReceive( EMemSpyClientServerOpGetInfoItemType, args ); + + aType = arg3(); + + return error; + } + +EXPORT_C void RMemSpySession::GetThreadInfoItems( RArray<CMemSpyApiThreadInfoItem*> &aInfoItems, TThreadId aId, TMemSpyThreadInfoItemType aType ) + { + TPckgBuf<TThreadId> id( aId ); + TPckgBuf<TMemSpyThreadInfoItemType> type( aType ); + TPckgBuf<TInt> count; + + TInt error = SendReceive( EMemSpyClientServerOpGetThreadInfoItemsCount, TIpcArgs( &id, &type, &count ) ); + TInt itemCount = count(); + + if( error == KErrNone ) + { + if( itemCount == 0 ) + { + aInfoItems.Reset(); + } + else + { + HBufC8* buffer = HBufC8::NewLC( itemCount * sizeof(TMemSpyThreadInfoItemData) ); + TPtr8 bufferPtr(buffer->Des()); + + TPckgBuf<TInt> requestedCount( itemCount ); + + TIpcArgs args( &requestedCount, &id, &type, &bufferPtr ); + TInt error = SendReceive( EMemSpyClientServerOpGetThreadInfoItems, args ); + + for(TInt i=0, offset = 0; i < itemCount; i++, offset+=sizeof(TMemSpyThreadInfoItemData)) + { + TPckgBuf<TMemSpyThreadInfoItemData> data; + data.Copy(bufferPtr.Ptr()+offset, sizeof(TMemSpyThreadInfoItemData)); + aInfoItems.AppendL(CMemSpyApiThreadInfoItem::NewL(data())); + } + + CleanupStack::PopAndDestroy(buffer); + } + } + } + +//Kernel Objects specific operations +EXPORT_C TInt RMemSpySession::GetKernelObjects( RArray<CMemSpyApiKernelObject*> &aKernelObjects ) + { + TPckgBuf<TInt> count; + TInt error = SendReceive( EMemSpyClientServerOpGetKernelObjectCount, TIpcArgs(&count) ); + + if( error == KErrNone ) + { + TInt requestedCount = count(); + HBufC8* buffer = HBufC8::NewLC(requestedCount * sizeof(TMemSpyKernelObjectData)); + TPtr8 bufferPtr(buffer->Des()); + + TPckgBuf<TInt> count(requestedCount); + TIpcArgs args( &count, &bufferPtr ); + TInt error = SendReceive( EMemSpyClientServerOpGetKernelObjects, args ); + + for(TInt i=0, offset = 0; i<requestedCount; i++, offset+=sizeof(TMemSpyKernelObjectData)) + { + TPckgBuf<TMemSpyKernelObjectData> data; + data.Copy(bufferPtr.Ptr()+offset, sizeof(TMemSpyKernelObjectData)); + aKernelObjects.AppendL(CMemSpyApiKernelObject::NewL(data())); + } + + CleanupStack::PopAndDestroy(buffer); + } + return KErrNone; + } + +EXPORT_C TInt RMemSpySession::GetKernelObjectItems( RArray<CMemSpyApiKernelObjectItem*> &aKernelObjectItems, TMemSpyDriverContainerType aForContainer ) + { + TPckgBuf<TInt> count; + TPckgBuf<TMemSpyDriverContainerType> type(aForContainer); + TInt error = SendReceive( EMemSpyClientServerOpGetKernelObjectItemCount, TIpcArgs(&count, &type) ); + + if (error == KErrNone) + { + TInt requestedCount = count(); + HBufC8* buffer = HBufC8::NewLC(requestedCount * sizeof(TMemSpyDriverHandleInfoGeneric)); + TPtr8 bufferPtr(buffer->Des()); + + TPckgBuf<TInt> count(requestedCount); + TIpcArgs args( &count, &type, &bufferPtr ); + TInt error = SendReceive( EMemSpyClientServerOpGetKernelObjectItems, args ); + + for(TInt i=0, offset = 0; i<requestedCount; i++, offset+=sizeof(TMemSpyDriverHandleInfoGeneric)) + { + TPckgBuf<TMemSpyDriverHandleInfoGeneric> data; + data.Copy(bufferPtr.Ptr()+offset, sizeof(TMemSpyDriverHandleInfoGeneric)); + aKernelObjectItems.AppendL( CMemSpyApiKernelObjectItem::NewL( data() ) ); + } + + CleanupStack::PopAndDestroy(buffer); + } + return KErrNone; + } + +EXPORT_C void RMemSpySession::OutputAllContainerContents() + { + SendReceive( EMemSpyClientServerOpOutputAllContainerContents ); + } + + +//Heap specific operations +EXPORT_C CMemSpyApiHeap* RMemSpySession::GetHeap() + { + CMemSpyApiHeap* aHeap; + TInt error = KErrNone; + + HBufC8* buffer = HBufC8::NewLC( sizeof(TMemSpyHeapData) ); + TPtr8 bufferPtr(buffer->Des()); + TIpcArgs args( &bufferPtr ); + + error = SendReceive( EMemSpyClientServerOpGetHeap, args ); + + if( error == KErrNone ) + { + TPckgBuf<TMemSpyHeapData> data; + data.Copy(bufferPtr.Ptr(), sizeof(TMemSpyHeapData)); + aHeap = CMemSpyApiHeap::NewL( data() ); + } + CleanupStack::PopAndDestroy(buffer); + + return aHeap; + } + +EXPORT_C void RMemSpySession::DumpKernelHeap() + { + SendReceive( EMemSpyClientServerOpDumpKernelHeap ); + } + +EXPORT_C void RMemSpySession::OutputKernelHeapDataL(TMemSpyOutputType aOutputType) + { + SetOutputTypeL(aOutputType); + + User::LeaveIfError(SendReceive(EMemSpyClientServerOpHeapData | KMemSpyOpFlagsIncludesThreadId, + TIpcArgs(KMemSpyClientServerThreadIdKernel))); + + } +EXPORT_C void RMemSpySession::OutputThreadHeapDataL(TMemSpyOutputType aOutputType, TThreadId aThreadId) + { + SetOutputTypeL(aOutputType); + + User::LeaveIfError(SendReceive(EMemSpyClientServerOpHeapData | KMemSpyOpFlagsIncludesThreadId, + TIpcArgs(aThreadId))); + } +EXPORT_C void RMemSpySession::OutputThreadCellListL(TMemSpyOutputType aOutputType, TThreadId aThreadId) + { + SetOutputTypeL(aOutputType); + + User::LeaveIfError(SendReceive(EMemSpyClientServerOpHeapCellListing | KMemSpyOpFlagsIncludesThreadId, + TIpcArgs(aThreadId))); + } + +EXPORT_C void RMemSpySession::OutputKernelObjectsL(TMemSpyOutputType aOutputType) + { + SetOutputTypeL(aOutputType); + + User::LeaveIfError(SendReceive(EMemSpyClientServerOpEnumerateKernelContainerAll)); + } + +EXPORT_C void RMemSpySession::OutputCompactStackInfoL(TMemSpyOutputType aOutputType) + { + SetOutputTypeL(aOutputType); + + User::LeaveIfError(SendReceive(EMemSpyClientServerOpStackInfoCompact)); + } + +EXPORT_C void RMemSpySession::OutputCompactHeapInfoL(TMemSpyOutputType aOutputType) + { + SetOutputTypeL(aOutputType); + + User::LeaveIfError(SendReceive(EMemSpyClientServerOpHeapInfoCompact)); + } + +void RMemSpySession::SetOutputTypeL(TMemSpyOutputType aOutputType) + { + TInt operation = aOutputType == EOutputTypeFile ? + EMemSpyClientServerOpSwitchOutputSinkFile : + EMemSpyClientServerOpSwitchOutputSinkTrace; + + User::LeaveIfError(SendReceive(operation)); + } diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyServer/Include/MemSpyServerSession.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyServer/Include/MemSpyServerSession.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,62 @@ +/* +* 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: +* MemSpyServer headder file to declare MemSpyServer class +* +*/ + +#ifndef MEMSPYSERVERSESSION_H +#define MEMSPYSERVERSESSION_H + +// System includes +#include <e32base.h> +#include <BADESCA.H> + +// User includes +#include <memspyengineclientinterface.h> +#include <memspy/engine/memspyengineobjectthreadinfoobjects.h> + + // Classes referenced +class CMemSpyEngine; + + +NONSHARABLE_CLASS( CMemSpyServerSession ) : public CSession2 + { +public: + static CMemSpyServerSession* NewL( CMemSpyEngine& aEngine, const RMessage2& aMessage ); + ~CMemSpyServerSession(); + +private: + CMemSpyServerSession( CMemSpyEngine& aEngine ); + void ConstructL( const RMessage2& aMessage ); + +private: // From CSession2 + void ServiceL( const RMessage2& aMessage ); + +private: // Internal methods + void DoServiceL( const RMessage2& aMessage ); + void DoUiServiceL( const RMessage2& aMessage ); + void DoCmdServiceL( const RMessage2& aMessage ); + static TInt ValidateFunction( TInt aFunction, TBool aIncludesThreadId, TBool aIncludesThreadName ); + void HandleThreadSpecificOpL( TInt aFunction, const TThreadId& aThreadId ); + void HandleThreadSpecificOpL( TInt aFunction, const TDesC& aThreadName ); + void HandleThreadAgnosticOpL( TInt aFunction, const RMessage2& aMessage ); + +private: + CMemSpyEngine& iEngine; + HBufC* iClientThreadName; + TUint32 iClientThreadId; + }; + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyServer/Source/MemSpyServerMain.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyServer/Source/MemSpyServerMain.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,75 @@ +/* +* 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: +* MemSpyServer Main class +*/ + +// System includes +#include <e32std.h> +#include <e32base.h> +#include <f32file.h> + +// Engine includes +#include <memspy/engine/memspyengine.h> + +// User includes +//#include "MemSpyServer.h" + +static void RunServerL() + { + // Scheduler + CActiveScheduler* scheduler = new (ELeave) CActiveScheduler(); + CleanupStack::PushL( scheduler ); + CActiveScheduler::Install( scheduler ); + + // F32 + RFs fsSession; + User::LeaveIfError(fsSession.Connect()); + CleanupClosePushL(fsSession); + + // MemSpyEngine initialization + CMemSpyEngine* engine = CMemSpyEngine::NewL(fsSession); + CleanupStack::PushL(engine); + + // Play nicely with external processes + RProcess::Rendezvous( KErrNone ); + + // Start wait loop. + CActiveScheduler::Start(); + + // Tidy up + CleanupStack::PopAndDestroy( 3, scheduler ); + } + +TInt E32Main() + { + __UHEAP_MARK; + + CTrapCleanup* cleanupTrap = CTrapCleanup::New(); + + TInt r = KErrNoMemory; + if ( cleanupTrap ) + { + TRAPD(err, RunServerL()); + if ( err != KErrNone ) + { + RDebug::Print(_L("[MemSpyCmdLine] E32Main() - MemSpyServer - error: %d"), err); + } + delete cleanupTrap; + } + + __UHEAP_MARKEND; + + return r; + } diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyServer/Source/MemSpyServerSession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyServer/Source/MemSpyServerSession.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,953 @@ +/* +* 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: +* Implementation of the new MemSpyServer +*/ + +// System includes +#include <e32svr.h> +#include <e32cmn.h> +#include <e32base.h> +#include <w32std.h> +//#include <apgtask.h> +//#include <apgwgnam.h> + +//user includes +#include "MemSpyServerSession.h" + +// User includes +#include <memspy/engine/memspyengine.h> +#include <memspy/engine/memspyenginelogger.h> +#include <memspyengineclientinterface.h> +#include <memspy/engine/memspyengineobjectthread.h> +#include <memspy/engine/memspyengineobjectprocess.h> +#include <memspy/engine/memspyengineobjectcontainer.h> +#include <memspy/engine/memspyenginehelperchunk.h> +#include <memspy/engine/memspyenginehelpercodesegment.h> +#include <memspy/engine/memspyenginehelperheap.h> +#include <memspy/engine/memspyenginehelperstack.h> +#include <memspy/engine/memspyenginehelperthread.h> +#include <memspy/engine/memspyenginehelperprocess.h> +#include <memspy/engine/memspyenginehelperfilesystem.h> +#include <memspy/engine/memspyenginehelperram.h> +#include <memspy/engine/memspyenginehelpersysmemtracker.h> +#include <memspy/engine/memspyenginehelpersysmemtrackerconfig.h> +#include <memspy/engine/memspyenginehelperkernelcontainers.h> +#include <memspy/engine/memspyenginehelperserver.h> + +//cigasto +#include <memspysession.h> +//#include <memspy/driver/memspydriverclient.h> + +// --------------------------------------------------------- +// CMemSpyServerSession( CMemSpyEngine& aEngine ) +// --------------------------------------------------------- +// +CMemSpyServerSession::CMemSpyServerSession( CMemSpyEngine& aEngine ) +: iEngine( aEngine ) + { + } + +// --------------------------------------------------------- +// ~CMemSpyServerSession() +// --------------------------------------------------------- +// +CMemSpyServerSession::~CMemSpyServerSession() + { +#ifdef _DEBUG + TPtrC pThreadName( KNullDesC ); + if ( iClientThreadName ) + { + pThreadName.Set( *iClientThreadName ); + } + + RDebug::Print( _L("[MemSpy] CMemSpyServerSession::~CMemSpyServerSession() - DEAD SESSION - this: 0x%08x, id: %4d, name: %S"), this, iClientThreadId, iClientThreadName ); +#endif + + delete iClientThreadName; + } + +// --------------------------------------------------------- +// ConstructL( const RMessage2& aMessage ) +// --------------------------------------------------------- +// +void CMemSpyServerSession::ConstructL( const RMessage2& aMessage ) + { + RThread thread; + const TInt error = aMessage.Client( thread ); + CleanupClosePushL( thread ); + + TRACE( RDebug::Printf( "[MemSpy] CMemSpyServerSession::ConstructL() - this: 0x%08x - opening client thread - err: %d", this, error ) ); + + User::LeaveIfError( error ); + + const TFullName threadName( thread.FullName() ); + iClientThreadName = threadName.AllocL(); + iClientThreadId = thread.Id(); + + CleanupStack::PopAndDestroy( &thread ); + + TRACE( RDebug::Print( _L("[MemSpy] CMemSpyServerSession::ConstructL() - NEW SESSION - this: 0x%08x, id: %4d, client: %S"), this, iClientThreadId, iClientThreadName ) ); + } + +// --------------------------------------------------------- +// NewL( CMemSpyEngine& aEngine, const RMessage2& aMessage ) +// Two-phased constructor +// --------------------------------------------------------- +// +CMemSpyServerSession* CMemSpyServerSession::NewL( CMemSpyEngine& aEngine, const RMessage2& aMessage ) + { + CMemSpyServerSession* self = new(ELeave) CMemSpyServerSession( aEngine ); + CleanupStack::PushL( self ); + self->ConstructL( aMessage ); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------- +// ServiceL( const RMessage2& aMessage ) +// Method from which the clients request arrives +// --------------------------------------------------------- +// +void CMemSpyServerSession::ServiceL( const RMessage2& aMessage ) + { + TRACE( RDebug::Print( _L("[MemSpy] CMemSpyServerSession::ServiceL() - START - this: 0x%08x, fn: 0x%08x, id: %4d, client: %S"), this, aMessage.Function(), iClientThreadId, iClientThreadName ) ); + + TRAPD( error, DoServiceL( aMessage ) ); + if ( error != KErrNone ) + { + RDebug::Print( _L("[MemSpy] CMemSpyServerSession::ServiceL() - SERVICE ERROR - this: 0x%08x, fn: %d, err: %d, client: %S"), this, aMessage.Function(), error, iClientThreadName ); + } + aMessage.Complete( error ); + + TRACE( RDebug::Print( _L("[MemSpy] CMemSpyServerSession::ServiceL() - END - this: 0x%08x, fn: 0x%08x, id: %4d, client: %S"), this, aMessage.Function(), iClientThreadId, iClientThreadName ) ); + } + +// --------------------------------------------------------- +// DoCmdServiceL( const RMessage2& aMessage ) +// --------------------------------------------------------- +// +void CMemSpyServerSession::DoCmdServiceL( const RMessage2& aMessage ) + { + TInt error = KErrNone; + + // Check function attributes + const TInt function = aMessage.Function() & KMemSpyOpFlagsTypeMask; + const TInt argSpec = aMessage.Function() & KMemSpyOpFlagsInclusionMask; + const TBool byThreadId = ( argSpec == KMemSpyOpFlagsIncludesThreadId ); + const TBool byThreadName = ( argSpec == KMemSpyOpFlagsIncludesThreadName ); + + TRACE( RDebug::Printf( "[MemSpy] CMemSpyServerSession::DoServiceL() - START - unmodified function: 0x%08x, opCode: %d [TID: %d, TN: %d]", aMessage.Function(), function, byThreadId, byThreadName ) ); + + switch (function) + { + case EGetProcessCount: + { + aMessage.WriteL(0, TPckgBuf<TInt>(iEngine.Container().Count())); + break; + } + case EGetProcesses: + { + CMemSpyEngineObjectContainer& list = iEngine.Container(); + + TPckgBuf<TInt> a0; + aMessage.ReadL(0, a0); + TInt realCount = Min(a0(), list.Count()); + + for(TInt i=0, offset = 0; i<realCount; i++, offset += sizeof(TMemSpyProcessData)) + { + CMemSpyProcess& process = iEngine.Container().At(i); + TMemSpyProcessData data; + data.iId = process.Id(); + data.iName.Copy(process.Name()); + + TPckgBuf<TMemSpyProcessData> buffer(data); + aMessage.WriteL(1, buffer, offset); + } + + a0 = list.Count(); + aMessage.WriteL(0, a0); + + break; + } + case EProcessSystemPermanentOrCritical: + { + TBool ret = EFalse; + TPckgBuf<TProcessId> id; + aMessage.ReadL( 0, id ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess& process = container.ProcessByIdL( id() ); + + process.Open(); + + if ( process.IsSystemPermanent() || process.IsSystemCritical() ) + { + ret = ETrue; + } + TPckgBuf<TBool> retBuf( ret ); + aMessage.WriteL( 1, retBuf ); + + break; + } + case EEndProcess: + { + TPckgBuf<TProcessId> id; + aMessage.ReadL( 0, id ); + TPckgBuf<TEndType> type; + aMessage.ReadL( 1, type ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess& process = container.ProcessByIdL( id() ); + + switch ( type() ) + { + case ETerminate: + { + process.TerminateL(); + break; + } + case EPanic: + { + process.PanicL(); + break; + } + case EKill: + { + process.KillL(); + break; + } + } + break; + } + case ESwitchToProcess: + {/* + TInt wgCount; + RWsSession wsSession; + User::LeaveIfError( wsSession.Connect() ); + CleanupClosePushL( wsSession ); + User::LeaveIfError( wgCount = wsSession.NumWindowGroups() ); + RArray<RWsSession::TWindowGroupChainInfo> wgArray; + CleanupClosePushL( wgArray ); + User::LeaveIfError( wsSession.WindowGroupList( &wgArray ) ); + TApaTask task( wsSession ); + TBool brought( EFalse ); + TInt wgId( KErrNotFound ); + TThreadId threadId; + + TPckgBuf<TProcessId> id; + aMessage.ReadL( 0, id ); + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess& process = container.ProcessByIdL( id() ); + + // loop trough threads in a process + for ( TInt i = 0; i < process.MdcaCount(); i++ ) + { + TInt wgCountLocal = wgCount; + + // loop trough all window groups and see if a thread id matches + while( !brought && wgCountLocal-- ) + { + wgId = wgArray[wgCountLocal].iId; + User::LeaveIfError( wsSession.GetWindowGroupClientThreadId( wgId, threadId ) ); + if ( threadId == process.At( i ).Id() ) + { + CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC( wsSession, wgId ); + task.SetWgId( wgId ); + if ( !wgName->Hidden() && task.Exists() ) + { + task.BringToForeground(); + brought = ETrue; + } + CleanupStack::PopAndDestroy( wgName ); + } + } + } + + TPckgBuf<TBool> ret( brought ); + aMessage.WriteL( 1, ret ); + + break;*/ + } + case EGetThreadCount: + { + TPckgBuf<TProcessId> pid; + aMessage.ReadL(1, pid); + CMemSpyProcess& process = iEngine.Container().ProcessByIdL(pid()); + process.Open(); + aMessage.WriteL(0, TPckgBuf<TInt>(process.Count())); + process.Close(); + break; + } + case EGetThreads: + { + TPckgBuf<TProcessId> pid; + aMessage.ReadL(2, pid); + + CMemSpyProcess& list = iEngine.Container().ProcessByIdL(pid()); + list.Open(); + + TPckgBuf<TInt> a0; + aMessage.ReadL(0, a0); + TInt realCount = Min(a0(), list.Count()); + + for(TInt i=0, offset = 0; i<realCount; i++, offset += sizeof(TMemSpyThreadData)) + { + CMemSpyThread& thread = list.At(i); + thread.Open(); + + TMemSpyThreadData data; + data.iId = thread.Id(); + data.iName.Copy(thread.Name()); + data.iThreadPriority = thread.Priority(); + + TPckgBuf<TMemSpyThreadData> buffer(data); + aMessage.WriteL(1, buffer, offset); + + thread.Close(); + } + + a0 = list.Count(); + aMessage.WriteL(0, a0); + + list.Close(); + + break; + } + case ESetThreadPriority: + { + TPckgBuf<TThreadId> tid; + TPckgBuf<TInt> priority; + aMessage.ReadL(0, tid); + aMessage.ReadL(1, priority); + + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError(iEngine.Container().ProcessAndThreadByThreadId(tid(), process, thread)); + + if (thread) + { + thread->Open(); + thread->SetPriorityL(static_cast<TThreadPriority>(priority())); + thread->Close(); + } + break; + } + case EThreadSystemPermanentOrCritical: + { + TBool ret = EFalse; + TPckgBuf<TThreadId> id; + aMessage.ReadL( 0, id ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id(), process, thread ) ); + + if ( thread ) + { + thread->Open(); + + if ( thread->IsSystemPermanent() || thread->IsSystemCritical() ) + { + ret = ETrue; + } + thread->Close(); + } + TPckgBuf<TBool> retBuf( ret ); + aMessage.WriteL( 1, retBuf ); + + break; + } + case EEndThread: + { + TPckgBuf<TThreadId> id; + aMessage.ReadL( 0, id ); + TPckgBuf<TEndType> type; + aMessage.ReadL( 1, type ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id(), process, thread ) ); + + if( thread ) + { + switch ( type() ) + { + case ETerminate: + { + thread->TerminateL(); + break; + } + case EPanic: + { + thread->PanicL(); + break; + } + case EKill: + { + thread->KillL(); + break; + } + } + } + break; + } + // --- KernelObjects related functions --- + case EGetKernelObjectTypeCount: + { + TInt iCount = EMemSpyDriverContainerTypeLast - EMemSpyDriverContainerTypeFirst; + TPckgBuf<TInt> ret( iCount ); + aMessage.WriteL(0, ret); + break; + } + case EGetKernelObjects: + { + TPckgBuf<TInt> count; + aMessage.ReadL(0, count); + + CMemSpyEngineGenericKernelObjectContainer* model = iEngine.HelperKernelContainers().ObjectsAllL(); //contains all the objects + CleanupStack::PushL( model ); + + for( TInt i=0, offset = 0; i<count(); i++, offset += sizeof( TMemSpyKernelObjectData ) ) + { + TMemSpyKernelObjectData data; + + TPtrC name(model->At(i).Name().Mid(1)); + TInt tabPos = name.Locate('\t'); + if (tabPos != KErrNotFound) + name.Set(name.Left(tabPos)); + + data.iName.Copy(name); + data.iType = model->At(i).Type(); + data.iCount = model->At(i).Count(); + data.iSize = model->At(i).Count() * model->At(i).Count(); + + TPckgBuf<TMemSpyKernelObjectData> buffer(data); + aMessage.WriteL(1, buffer, offset); + } + aMessage.WriteL(0, count); + CleanupStack::PopAndDestroy( model ); + break; + } + case EGetKernelObjectItemsCount: + { + TPckgBuf<TMemSpyDriverContainerType> tempType; + aMessage.ReadL(1, tempType); //get type of kernel object + TMemSpyDriverContainerType type = tempType(); + + CMemSpyEngineHelperKernelContainers& kernelContainerManager = iEngine.HelperKernelContainers(); + CMemSpyEngineGenericKernelObjectList* iObjectList = kernelContainerManager.ObjectsForSpecificContainerL( type ); + CleanupStack::PushL( iObjectList ); + + TInt count = iObjectList->Count(); + TPckgBuf<TInt> ret( count ); + aMessage.WriteL( 0, ret ); + + CleanupStack::PopAndDestroy( iObjectList ); + break; + } + case EGetKernelObjectItems: + { + TPckgBuf<TInt> count; + TPckgBuf<TMemSpyDriverContainerType> tempType; + aMessage.ReadL( 0, count ); //get count of items + aMessage.ReadL(1, tempType); //get type of kernel object + TInt c = count(); + + CMemSpyEngineHelperKernelContainers& kernelContainerManager = iEngine.HelperKernelContainers(); + CMemSpyEngineGenericKernelObjectList* iObjectList = kernelContainerManager.ObjectsForSpecificContainerL( tempType() ); + CleanupStack::PushL( iObjectList ); + + for( TInt i=0, offset = 0; i<c; i++, offset += sizeof( TMemSpyDriverHandleInfoGeneric ) ) + { + TMemSpyDriverHandleInfoGeneric data; + + data = iObjectList->At( i ); + + TPckgBuf<TMemSpyDriverHandleInfoGeneric> buffer(data); + aMessage.WriteL(2, buffer, offset); + } + + CleanupStack::PopAndDestroy( iObjectList ); + break; + } + // --- Kernel Heap related functions --- + case EGetHeap: + { + TMemSpyHeapInfo heapInfo; + iEngine.HelperHeap().GetHeapInfoKernelL( heapInfo ); + TMemSpyHeapData data = iEngine.HelperHeap().NewHeapRawInfo( heapInfo ); + + TPckgBuf<TMemSpyHeapData> buffer(data); + aMessage.WriteL(0, buffer); + + break; + } + } +// else if( function == EProcessByIndex ) +// { +// TMemSpyProcess iProcess; +// TInt in; +// TPckgBuf<TInt> index( in ); +// aMessage.ReadL( 0, index ); +// CMemSpyProcess& process = iEngine.Container().At( index() ); +// //fill the data structure +// iProcess.iId = process.Id(); //process ID +// iProcess.iName.Append( process.Name() ); //raw process name +// iProcess.iThreadCount = process.Count(); //thread count +// iProcess.iPriority = process.Priority(); +// // +// TPckgBuf<TMemSpyProcess> buf( iProcess ); +// aMessage.WriteL( 1, buf ); +// aMessage.Complete( KErrNone ); +// } +// else if( function == EProcessIndexById ) +// { +// TProcessId iId; +// TPckgBuf<TProcessId> buf( iId ); +// aMessage.ReadL( 0, buf ); +// TInt index = iEngine.Container().ProcessIndexById( buf() ); +// TPckgBuf<TInt> out( index ); +// aMessage.WriteL( 1, out ); +// aMessage.Complete( KErrNone ); +// } +// else if( function == EOutputProcessInfo ) +// { +// TProcessId iId; +// TPckgBuf<TProcessId> buf( iId ); +// aMessage.ReadL( 0, buf ); +// CMemSpyProcess& process = iEngine.Container().ProcessByIdL( buf() ); +// iEngine.HelperProcess().OutputProcessInfoL( process ); +// } +// else if( function == EProcessIsDead ) +// { +// TProcessId iId; +// TPckgBuf<TProcessId> buf( iId ); +// aMessage.ReadL( 0, buf ); +// CMemSpyProcess& process = iEngine.Container().ProcessByIdL( buf() ); +// TBool dead = process.IsDead(); +// TPckgBuf<TBool> out( dead ); +// aMessage.WriteL( 1, out ); +// aMessage.Complete( KErrNone ); +// } +// else if( function == ESortProcessesBy ) +// { +// TSortType type; +// TPckgBuf<TSortType> buf(type); +// aMessage.ReadL( 0, buf ); +// if( buf() == ESortProcById ) +// { +// iEngine.Container().SortById(); +// } +// else if( buf() == ESortProcByName ) +// { +// iEngine.Container().SortByName(); +// } +// else if( buf() == ESortProcByThreadCount ) +// { +// iEngine.Container().SortByThreadCount(); +// } +// else if( buf() == ESortProcByCodeSegs ) +// { +// iEngine.Container().SortByCodeSegs(); +// } +// else if( buf() == ESortProcByHeapUsage ) +// { +// iEngine.Container().SortByHeapUsage(); +// } +// else if( buf() == ESortProcByStackUsage ) +// { +// iEngine.Container().SortByStackUsage(); +// } +// } +// else if( function == EOpenCloseCurrentProcess ) +// { +// TProcessId id; +// TBool open; +// TPckgBuf<TProcessId> buf(id); +// TPckgBuf<TBool> buf2(open); +// aMessage.ReadL( 0, buf ); +// aMessage.ReadL( 1, buf2 ); +// if( buf2() == 1 ) +// { +// iEngine.Container().ProcessByIdL( buf() ).Open(); +// } +// else +// { +// iEngine.Container().ProcessByIdL( buf() ).Close(); +// } +// } + +// // Check function is supported and argument combination is valid +// error = ValidateFunction( function, byThreadId, byThreadName ); +// TRACE( RDebug::Printf( "[MemSpy] CMemSpyServerSession::DoServiceL() - validation result: %d", error ) ); +// +// // Process function request +// if ( error == KErrNone ) +// { +// if ( byThreadId ) +// { +// TRACE( RDebug::Printf( "[MemSpy] CMemSpyServerSession::DoServiceL() - [TID] thread-specific..." ) ); +// +// const TThreadId threadId( aMessage.Int0() ); +// HandleThreadSpecificOpL( function, threadId ); +// } +// else if ( byThreadName ) +// { +// TRACE( RDebug::Printf( "[MemSpy] CMemSpyServerSession::DoServiceL() - [TN] thread-specific..." ) ); +// +// error = aMessage.GetDesLength( 0 /*slot 0*/ ); +// +// if ( error > 0 && error <= KMaxFullName ) +// { +// TFullName* threadName = new(ELeave) TFullName(); +// CleanupStack::PushL( threadName ); +// aMessage.ReadL( 0, *threadName ); +// HandleThreadSpecificOpL( function, *threadName ); +// CleanupStack::PopAndDestroy( threadName ); +// } +// else +// { +// error = KErrArgument; +// } +// } +// else +// { +// TRACE( RDebug::Printf( "[MemSpy] CMemSpyServerSession::DoServiceL() - thread-agnostic..." ) ); +// +// HandleThreadAgnosticOpL( function, aMessage ); +// } +// } + + User::LeaveIfError( error ); + + TRACE( RDebug::Printf( "[MemSpy] CMemSpyServerSession::DoServiceL() - HELLOOOOOO" ) ); + TRACE( RDebug::Printf( "[MemSpy] CMemSpyServerSession::DoServiceL() - END" ) ); + } + +// --------------------------------------------------------- +// ValidateFunction( TInt aFunction, TBool aIncludesThreadId, TBool aIncludesThreadName ) +// Validates the MemSpy operation types +// --------------------------------------------------------- +// +TInt CMemSpyServerSession::ValidateFunction( TInt aFunction, TBool aIncludesThreadId, TBool aIncludesThreadName ) + { + TInt err = KErrNotSupported; + + // Check the operation is within op-code range + if ( aFunction >= EMemSpyClientServerOpMarkerFirst && aFunction < EMemSpyClientServerOpMarkerLast ) + { + // Check the operation doesn't include unnecessary or not supported information + const TBool includesThreadIdentifier = ( aIncludesThreadId || aIncludesThreadName ); + if ( includesThreadIdentifier && aFunction >= EMemSpyClientServerOpMarkerThreadAgnosticFirst ) + { + // Passing a thread identifier to a thread agnostic operation + err = KErrArgument; + } + else + { + err = KErrNone; + } + } + // + if ( err != KErrNone ) + { + RDebug::Printf( "[MemSpy] CMemSpyServerSession::ValidateFunction() - function request did not validate - [withId: %d, withName: %d]", aIncludesThreadId, aIncludesThreadName ); + } + // + return err; + } + +// --------------------------------------------------------- +// HandleThreadSpecificOpL( TInt aFunction, const TThreadId& aThreadId ) +// --------------------------------------------------------- +// +void CMemSpyServerSession::HandleThreadSpecificOpL( TInt aFunction, const TThreadId& aThreadId ) + { +// TRACE( RDebug::Printf( "[MemSpy] CMemSpyServerSession::HandleThreadSpecificOpL() - START - aFunction: %d, aThreadId: %d", aFunction, (TUint) aThreadId ) ); +// +// ASSERT( (TUint) aThreadId != 0 ); +// TInt error = KErrNone; +// +// // Check if its a kernel thread identifier +// const TBool isKernel = ( static_cast<TUint32>( aThreadId ) == KMemSpyClientServerThreadIdKernel ); +// +// // Treat as thread specific operation +// CMemSpyProcess* process = NULL; +// CMemSpyThread* thread = NULL; +// if ( !isKernel ) +// { +// error = iEngine.Container().ProcessAndThreadByThreadId( aThreadId, process, thread ); +// TRACE( RDebug::Printf( "[MemSpy] CMemSpyServerSession::HandleThreadSpecificOpL() - search result: %d, proc: 0x%08x, thread: 0x%08x", error, process, thread ) ); +// } +// else +// { +// // Kernel is only supported for a couple of operations +// if ( aFunction == EMemSpyClientServerOpHeapInfo || aFunction == EMemSpyClientServerOpHeapData ) +// { +// } +// else +// { +// TRACE( RDebug::Printf( "[MemSpy] CMemSpyServerSession::HandleThreadSpecificOpL() - trying to call unsupported function for kernel thread!" ) ); +// error = KErrArgument; +// } +// } +// +// // Must be no error so far and we must have a valid thread & process when performing a non-kernel op +// // or then if we are performing a kernel op, we don't need the thread or process. +// if ( error == KErrNone && ( ( thread && process && !isKernel ) || ( isKernel ) ) ) +// { +//#ifdef _DEBUG +// if ( thread ) +// { +// HBufC* threadName = thread->FullName().AllocLC(); +// _LIT( KTrace2, "[MemSpy] CMemSpyServerSession::HandleThreadSpecificOpL() - thread: %S" ); +// RDebug::Print( KTrace2, threadName ); +// CleanupStack::PopAndDestroy( threadName ); +// } +// else if ( isKernel ) +// { +// _LIT( KTrace2, "[MemSpy] CMemSpyServerSession::HandleThreadSpecificOpL() - thread: Kernel" ); +// RDebug::Print( KTrace2 ); +// } +//#endif +// +// // Got a valid thread object - now work out which operation to perform... +// switch( aFunction ) +// { +// case EMemSpyClientServerOpSummaryInfo: +// iEngine.HelperProcess().OutputProcessInfoL( *process ); +// break; +// case EMemSpyClientServerOpSummaryInfoDetailed: +// iEngine.HelperProcess().OutputProcessInfoDetailedL( *process ); +// break; +// case EMemSpyClientServerOpHeapInfo: +// if ( isKernel ) +// { +// iEngine.HelperHeap().OutputHeapInfoKernelL(); +// } +// else +// { +// iEngine.HelperHeap().OutputHeapInfoUserL( *thread ); +// } +// break; +// case EMemSpyClientServerOpHeapCellListing: +// iEngine.HelperHeap().OutputCellListingUserL( *thread ); +// break; +// case EMemSpyClientServerOpHeapData: +// if ( isKernel ) +// { +// iEngine.HelperHeap().OutputHeapDataKernelL(); +// } +// else +// { +// iEngine.HelperHeap().OutputHeapDataUserL( *thread ); +// } +// break; +// case EMemSpyClientServerOpStackInfo: +// iEngine.HelperStack().OutputStackInfoL( *thread ); +// break; +// case EMemSpyClientServerOpStackDataUser: +// iEngine.HelperStack().OutputStackDataL( *thread, EMemSpyDriverDomainUser, EFalse ); +// break; +// case EMemSpyClientServerOpStackDataKernel: +// iEngine.HelperStack().OutputStackDataL( *thread, EMemSpyDriverDomainKernel, EFalse ); +// break; +// case EMemSpyClientServerOpOpenFiles: +// iEngine.HelperFileSystem().ListOpenFilesL( aThreadId ); +// break; +// +// default: +// error = KErrNotSupported; +// break; +// } +// } +// +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadSpecificOpL() - END - aFunction: %d, aThreadId: %d, error: %d", aFunction, (TUint) aThreadId, error ) ); +// User::LeaveIfError( error ); + } + +// --------------------------------------------------------- +// HandleThreadSpecificOpL( TInt aFunction, const TDesC& aThreadName ) +// Gets thread ID from aThreadName +// and calls HandleThreadSpecificOpL( , const TThreadId& aThreadId ) +// --------------------------------------------------------- +// +void CMemSpyServerSession::HandleThreadSpecificOpL( TInt aFunction, const TDesC& aThreadName ) + { +// TRACE( RDebug::Print( _L("[MemSpy] CMemSpyServerSession::HandleThreadSpecificOpL() - START - aFunction: %d, aThreadName: %S"), aFunction, &aThreadName ) ); +// // +// CMemSpyProcess* process = NULL; +// CMemSpyThread* thread = NULL; +// TInt error = iEngine.Container().ProcessAndThreadByPartialName( aThreadName, process, thread ); +// User::LeaveIfError( error ); +// // +// const TThreadId threadId( thread->Id() ); +// HandleThreadSpecificOpL( aFunction, threadId ); +// // +// TRACE( RDebug::Print( _L("[MemSpy] CMemSpyServerSession::HandleThreadSpecificOpL() - END - aFunction: %d, aThreadName: %S"), aFunction, &aThreadName ) ); + } + +// --------------------------------------------------------- +// HandleThreadAgnosticOpL( TInt aFunction, const RMessage2& aMessage ) +// --------------------------------------------------------- +// +void CMemSpyServerSession::HandleThreadAgnosticOpL( TInt aFunction, const RMessage2& aMessage ) + { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - START" ) ); +// // +// if ( aFunction == EMemSpyClientServerOpHeapInfoCompact ) +// { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpHeapInfoCompact") ); +// iEngine.HelperHeap().OutputHeapInfoForDeviceL(); +// } +// else if ( aFunction == EMemSpyClientServerOpStackInfoCompact ) +// { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpStackInfoCompact") ); +// iEngine.HelperStack().OutputStackInfoForDeviceL(); +// } +// else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingTimerStart ) +// { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSystemWideMemoryTrackingTimerStart") ); +// iEngine.HelperSysMemTracker().StartL(); +// } +// else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingTimerStop ) +// { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSystemWideMemoryTrackingTimerStop") ); +// iEngine.HelperSysMemTracker().StopL(); +// } +// else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingReset ) +// { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSystemWideMemoryTrackingReset") ); +// iEngine.HelperSysMemTracker().Reset(); +// } +// else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingForceUpdate ) +// { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSystemWideMemoryTrackingForceUpdate") ); +// iEngine.HelperSysMemTracker().CheckForChangesNowL(); +// } +// else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingTimerPeriodSet ) +// { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSystemWideMemoryTrackingTimerPeriodSet") ); +// +// // Get current config +// TMemSpyEngineHelperSysMemTrackerConfig config; +// iEngine.HelperSysMemTracker().GetConfig( config ); +// +// // Set new timer value +// config.iTimerPeriod = aMessage.Int0(); +// +// // And update config... which will leave if the config is invalid +// iEngine.HelperSysMemTracker().SetConfigL( config ); +// } +// else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingCategoriesSet ) +// { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSystemWideMemoryTrackingCategoriesSet") ); +// // Get current config +// TMemSpyEngineHelperSysMemTrackerConfig config; +// iEngine.HelperSysMemTracker().GetConfig( config ); +// +// // Set new categories +// config.iEnabledCategories = aMessage.Int0(); +// +// // And update config... which will leave if the config is invalid +// iEngine.HelperSysMemTracker().SetConfigL( config ); +// } +// else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingThreadNameFilterSet ) +// { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSystemWideMemoryTrackingThreadNameFilterSet") ); +// // Get current config +// TMemSpyEngineHelperSysMemTrackerConfig config; +// iEngine.HelperSysMemTracker().GetConfig( config ); +// +// // Set new filter +// RBuf buf; +// buf.CleanupClosePushL(); +// TInt len = aMessage.GetDesLength( 0 ); +// if ( len > 0 ) +// { +// buf.CreateL( len ); +// aMessage.ReadL( 0, buf, 0 ); +// config.iThreadNameFilter.Copy( buf ); +// } +// else +// { +// config.iThreadNameFilter.Zero(); +// } +// CleanupStack::PopAndDestroy( &buf ); +// +// // And update config... which will leave if the config is invalid +// iEngine.HelperSysMemTracker().SetConfigL( config ); +// } +// else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingHeapDumpSet ) +// { +// // Get current config +// TMemSpyEngineHelperSysMemTrackerConfig config; +// iEngine.HelperSysMemTracker().GetConfig( config ); +// +// // Set new Heap Dump value +// config.iDumpData = aMessage.Int0(); +// +// // And update config... which will leave if the config is invalid +// iEngine.HelperSysMemTracker().SetConfigL( config ); +// } +// else if ( aFunction == EMemSpyClientServerOpSwitchOutputSinkTrace ) +// { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSwitchOutputSinkTrace") ); +// iEngine.InstallSinkL( ESinkTypeDebug ); +// } +// else if ( aFunction == EMemSpyClientServerOpSwitchOutputSinkFile ) +// { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSwitchOutputSinkFile") ); +// iEngine.InstallSinkL( ESinkTypeFile ); +// } +// else if ( aFunction == EMemSpyClientServerOpEnumerateKernelContainer ) +// { +// const TMemSpyDriverContainerType type = CMemSpyEngineHelperKernelContainers::MapToType( static_cast< TObjectType >( aMessage.Int0() ) ); +// +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpEnumerateKernelContainer - type: %d", type ) ); +// +// CMemSpyEngineGenericKernelObjectList* model = iEngine.HelperKernelContainers().ObjectsForSpecificContainerL( type ); +// CleanupStack::PushL( model ); +// model->OutputL( iEngine.Sink() ); +// CleanupStack::PopAndDestroy( model ); +// } +// else if ( aFunction == EMemSpyClientServerOpEnumerateKernelContainerAll ) +// { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpEnumerateKernelContainerAll") ); +// CMemSpyEngineGenericKernelObjectContainer* model = iEngine.HelperKernelContainers().ObjectsAllL(); +// CleanupStack::PushL( model ); +// model->OutputL( iEngine.Sink() ); +// CleanupStack::PopAndDestroy( model ); +// } +// else if ( aFunction == EMemSpyClientServerOpOpenFiles ) +// { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpOpenFiles") ); +// iEngine.ListOpenFilesL(); +// } +// else if ( aFunction == EMemSpyClientServerOpDisableAknIconCache ) +// { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpDisableAknIconCache") ); +// iEngine.HelperRAM().SetAknIconCacheStatusL( EFalse ); +// } +// else +// { +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - [device-wide operation] => invoking UI") ); +// iEngine.NotifyClientServerOperationRequestL( aFunction ); +// } +// // +// TRACE( RDebug::Printf("[MemSpy] CMemSpyServerSession::HandleThreadAgnosticOpL() - END" ) ); + } diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/MemSpyServer/group/MemSpyServer.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/MemSpyServer/group/MemSpyServer.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,60 @@ +/* +* 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: +* +*/ + +#include <bldvariant.hrh> +#include <data_caging_paths.hrh> +#include <platform_paths.hrh> + +TARGETTYPE EXE +TARGET MemSpyServer.exe +UID 0 0x2002EA8D +SECUREID 0xE5883BC2 +VENDORID 0x101FB657 // Nokia + +EPOCSTACKSIZE 0x4000 +EPOCHEAPSIZE 0x100000 0x4000000 + + +SOURCEPATH ../Source +//SOURCE MemSpyServer.cpp +//SOURCE MemSpyServerSession.cpp +SOURCE MemSpyServerMain.cpp + +USERINCLUDE ../Include + +CAPABILITY ReadUserData WriteUserData ReadDeviceData WriteDeviceData + +OS_LAYER_SYSTEMINCLUDE + +APP_LAYER_SYSTEMINCLUDE + +LIBRARY MemSpyDriverClient.lib +LIBRARY MemSpyEngine.lib + +LIBRARY euser.lib +LIBRARY ecom.lib +LIBRARY efsrv.lib +LIBRARY estor.lib +LIBRARY bafl.lib +LIBRARY ws32.lib +LIBRARY cone.lib +LIBRARY eikcore.lib +LIBRARY fbscli.lib +LIBRARY PlatformEnv.lib +LIBRARY flogger.lib +LIBRARY apgrfx.lib + diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/memspy_plat/memspy_api/include/MemSpyEngineClientInterface.h --- a/memspy/memspy_plat/memspy_api/include/MemSpyEngineClientInterface.h Mon May 03 13:58:41 2010 +0300 +++ b/memspy/memspy_plat/memspy_api/include/MemSpyEngineClientInterface.h Thu May 13 23:59:27 2010 +0300 @@ -48,6 +48,7 @@ // Literal constants _LIT( KMemSpyServerName, "MemSpyServer" ); +_LIT( KMemSpyProcessName0, "MemSpyServer.exe" ); _LIT( KMemSpyProcessName1, "MemSpyUI.exe" ); _LIT( KMemSpyProcessName2, "MemSpyConsole.exe" ); @@ -258,12 +259,72 @@ EMemSpyClientServerOpSystemWideMemoryTrackingHeapDumpSet, /** + * [INTERNAL REQUEST] + */ + EMemSpyClientServerOpMarkerUiFirst, + + EMemSpyClientServerOpGetProcessCount = EMemSpyClientServerOpMarkerUiFirst, + + EMemSpyClientServerOpGetProcesses, + + EMemSpyClienServerOpGetProcessIdByName, + + EMemSpyClientServerOpGetThreadCount, + + EMemSpyClientServerOpGetThreads, + + EMemSpyClientServerOpSetThreadPriority, + + EMemSpyClientServerOpProcessSystemPermanentOrCritical, + + EMemSpyClientServerOpEndProcess, + + EMemSpyClientServerOpSwitchToProcess, + + //Threads operations + EMemSpyClientServerOpThreadSystemPermanentOrCritical, + + EMemSpyClientServerOpEndThread, + + EMemSpyClientServerOpSwitchToThread, + + EMemSpyClientServerOpGetInfoItemType, + + EMemSpyClientServerOpGetThreadInfoItemsCount, + + EMemSpyClientServerOpGetThreadInfoItems, + + + //Kernel Objects operations + EMemSpyClientServerOpGetKernelObjectCount, + + EMemSpyClientServerOpGetKernelObjects, + + EMemSpyClientServerOpGetKernelObjectItemCount, + + EMemSpyClientServerOpGetKernelObjectItems, + + EMemSpyClientServerOpGetHeap, + + EMemSpyClientServerOpMarkerUiLast, + + EMemSpyClientServerOpOutputAllContainerContents, + + EMemSpyClientServerOpDumpKernelHeap, + + /** * [INTERNAL REQUEST] */ EMemSpyClientServerOpMarkerLast, }; +enum TMemSpyEndType + { + ETerminate, + EKill, + EPanic + }; diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/memspy_plat/memspy_api/include/memspy/engine/MemSpyEngine.h --- a/memspy/memspy_plat/memspy_api/include/memspy/engine/MemSpyEngine.h Mon May 03 13:58:41 2010 +0300 +++ b/memspy/memspy_plat/memspy_api/include/memspy/engine/MemSpyEngine.h Thu May 13 23:59:27 2010 +0300 @@ -60,11 +60,12 @@ { public: IMPORT_C static CMemSpyEngine* NewL( RFs& aFsSession ); + IMPORT_C static CMemSpyEngine* NewL( RFs& aFsSession, TBool aStartServer ); IMPORT_C ~CMemSpyEngine(); private: CMemSpyEngine(); - void ConstructL( RFs& aFsSession ); + void ConstructL( RFs& aFsSession, TBool aStartServer ); public: // API IMPORT_C RFs& FsSession(); diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/memspy_plat/memspy_api/include/memspy/engine/MemSpyEngineImp.h --- a/memspy/memspy_plat/memspy_api/include/memspy/engine/MemSpyEngineImp.h Mon May 03 13:58:41 2010 +0300 +++ b/memspy/memspy_plat/memspy_api/include/memspy/engine/MemSpyEngineImp.h Thu May 13 23:59:27 2010 +0300 @@ -61,7 +61,7 @@ public: CMemSpyEngineImp( RFs& aFsSession, CMemSpyEngine& aEngine ); ~CMemSpyEngineImp(); - void ConstructL(); + void ConstructL( TBool aStartServer ); private: // Construction support void ConstructHelpersL(); diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/memspy_plat/memspy_api/include/memspy/engine/ThreadAndProcess/MemSpyEngineObjectProcess.h --- a/memspy/memspy_plat/memspy_api/include/memspy/engine/ThreadAndProcess/MemSpyEngineObjectProcess.h Mon May 03 13:58:41 2010 +0300 +++ b/memspy/memspy_plat/memspy_api/include/memspy/engine/ThreadAndProcess/MemSpyEngineObjectProcess.h Thu May 13 23:59:27 2010 +0300 @@ -65,7 +65,11 @@ IMPORT_C TBool IsDead() const; IMPORT_C TUint32 SID() const; IMPORT_C TUint32 VID() const; - + IMPORT_C TProcessPriority Priority() const; + IMPORT_C TExitCategoryName ExitCategory() const; + IMPORT_C TInt ExitReason() const; + IMPORT_C TExitType ExitType() const; + public: // API - misc IMPORT_C void KillL(); IMPORT_C void TerminateL(); diff -r ccab7f1f8266 -r a71a3e32a2ae memspy/memspy_plat/memspy_api/include/memspy/engine/ThreadAndProcess/MemSpyEngineObjectThreadInfoObjects.h --- a/memspy/memspy_plat/memspy_api/include/memspy/engine/ThreadAndProcess/MemSpyEngineObjectThreadInfoObjects.h Mon May 03 13:58:41 2010 +0300 +++ b/memspy/memspy_plat/memspy_api/include/memspy/engine/ThreadAndProcess/MemSpyEngineObjectThreadInfoObjects.h Thu May 13 23:59:27 2010 +0300 @@ -98,6 +98,8 @@ public: // From MDesCArray IMPORT_C TInt MdcaCount() const; IMPORT_C TPtrC MdcaPoint(TInt aIndex) const; + IMPORT_C TPtrC Caption(TInt aIndex ) const; + IMPORT_C TPtrC Value(TInt aIndex ) const; protected: class CItem : public CBase diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/group/ProfilerEngine.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/group/ProfilerEngine.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,54 @@ +/* +* 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: +* +*/ + + +#include <platform_paths.hrh> + + +TARGET PIProfilerEngine.exe +TARGETTYPE EXE +UID 0x100039CE 0x2001E5AD +VENDORID VID_DEFAULT +CAPABILITY ALL -TCB +SMPSAFE + +EPOCSTACKSIZE 0x10000 +EPOCHEAPSIZE 0x100000 0x2000000 // Min 1MB, Max 32MB + +OS_LAYER_SYSTEMINCLUDE +USERINCLUDE ../inc +SOURCEPATH ../src + +SOURCE ProfilerErrorChecker.cpp +SOURCE ProfilerEngine.cpp +SOURCE SamplerController.cpp +SOURCE SamplerPluginLoader.cpp +SOURCE WriterController.cpp +SOURCE WriterPluginLoader.cpp +SOURCE ProfilerTimer.cpp + +LIBRARY sysutil.lib +LIBRARY EFSRV.LIB +LIBRARY C32.LIB +LIBRARY EUSER.LIB +LIBRARY estor.lib +LIBRARY fbscli.lib +LIBRARY ws32.lib +LIBRARY bafl.lib +LIBRARY charconv.lib +LIBRARY ecom.lib +LIBRARY PlatformEnv.lib diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/group/ProfilerEshell.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/group/ProfilerEshell.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,41 @@ +/* +* 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: +* +*/ + + +#include <platform_paths.hrh> + + +TARGET PIProfiler.exe +TARGETTYPE EXE +UID 0x100039CE 0x2021E5AD // test UID, get an official +VENDORID VID_DEFAULT +CAPABILITY ALL -TCB +SMPSAFE + +EPOCSTACKSIZE 0x10000 + +OS_LAYER_SYSTEMINCLUDE +USERINCLUDE ../inc +SOURCEPATH ../src + + +SOURCE ProfilerEshell.cpp + +LIBRARY C32.LIB +LIBRARY EUSER.LIB +LIBRARY bafl.lib +LIBRARY efsrv.lib diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,22 @@ +/* +* Copyright (c) 2007 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: +* +*/ + + +PRJ_MMPFILES +ProfilerEngine.mmp +ProfilerEshell.mmp + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/inc/ProfilerEngine.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/inc/ProfilerEngine.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,258 @@ +/* +* 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: +* +*/ + + +#ifndef __PROFILERENGINE__ +#define __PROFILERENGINE__ + +#include <e32base.h> +#include <e32svr.h> +#include <e32property.h> + +#include <piprofiler/SamplerPluginInterface.h> +#include <piprofiler/WriterPluginInterface.h> +#include <piprofiler/ProfilerSession.h> +#include <piprofiler/ProfilerAttributes.h> // internal settings format presentations + +#include "SamplerController.h" +#include "WriterController.h" +#include "ProfilerErrorChecker.h" +#include "ProfilerTimer.h" + +// CONSTANTS +const TInt KProfilerPrefixMaxLength = 32; +const TInt KSettingsFileSize = 4096; + +/* + * This is an internal interface to the profiling engine which allows + * an additional control DLL to be loaded, replacing the profiler's + * default console UI + */ + +/** + * Implementation class providing access to the profiler engine + */ + +class MProfilerEngine +{ +public: + virtual TInt ControlL(TInt aCommand) =0; + virtual TInt ControlDataL(TInt aCommand, TAny* data1 = 0, TAny* data2 = 0) = 0; + + virtual TInt GetSamplerAttributesL(const RMessage2& aMessage) = 0; + virtual TInt GetSamplerAttributeCountL(const RMessage2& aMessage) = 0; + virtual TInt SetSamplerAttributesL(const RMessage2& aMessage) = 0; + virtual TInt GetGeneralAttributesL(const RMessage2& aMessage) = 0; + virtual TInt SetGeneralAttributesL(const RMessage2& aMessage) = 0; + virtual TInt RefreshStatus(const RMessage2& aMessage) = 0; + virtual RProfiler::TSamplerState State() const =0; +}; + +/** + * The interface that the extra controller must implement to access + * the profiler. + */ +class MProfilerController +{ + public: + /** Release the controller from the profiler. This is invoked when the profiler is unloading. */ + virtual void Release() = 0; + /** Ask the profiler to change state */ + inline TInt ControlL(TInt aCommand) const; + /** Ask the profiler to change state */ + inline TInt ControlDataL(TInt aCommand, TAny* data1 = 0, TAny* data2 = 0) const; + + inline TInt GetSamplerAttributesL(const RMessage2& aMessage) const; + inline TInt SetSamplerAttributesL(const RMessage2& aMessage) const; + inline TInt GetGeneralAttributesL(const RMessage2& aMessage) const; + inline TInt SetGeneralAttributesL(const RMessage2& aMessage) const; + inline TInt GetSamplerAttributeCountL(const RMessage2& aMessage) const; + inline TInt RefreshStatus(const RMessage2& aMessage) const; + /* Query the profiler state */ + inline RProfiler::TSamplerState GeTComand() const; + protected: + inline MProfilerController(MProfilerEngine& aEngine); + private: + MProfilerEngine& iEngine; +}; + +/** The signature of ordinal 1 in the controller DLL */ +typedef MProfilerController* (*TProfilerControllerFactoryL)(TInt aPriority, MProfilerEngine& aEngine); +/** The second UID required by the controller DLL */ +const TUid KUidProfilerKeys={0x1000945c}; + +inline MProfilerController::MProfilerController(MProfilerEngine& aEngine) + :iEngine(aEngine) +{ + +} + +inline TInt MProfilerController::ControlL(TInt aCommand) const +{ + return iEngine.ControlL(aCommand); +} + +inline TInt MProfilerController::ControlDataL(TInt aCommand,TAny* data1, TAny* data2) const +{ + return iEngine.ControlDataL(aCommand,data1,data2); +} + +inline TInt MProfilerController::GetSamplerAttributesL(const RMessage2& aMessage) const +{ + return iEngine.GetSamplerAttributesL(aMessage); +} + +inline TInt MProfilerController::SetSamplerAttributesL(const RMessage2& aMessage) const +{ + return iEngine.SetSamplerAttributesL(aMessage); +} + +inline TInt MProfilerController::GetGeneralAttributesL(const RMessage2& aMessage) const +{ + return iEngine.GetGeneralAttributesL(aMessage); +} + +inline TInt MProfilerController::GetSamplerAttributeCountL(const RMessage2& aMessage) const +{ + return iEngine.GetSamplerAttributeCountL(aMessage); +} + +inline TInt MProfilerController::SetGeneralAttributesL(const RMessage2& aMessage) const +{ + return iEngine.SetGeneralAttributesL(aMessage); +} + +inline TInt MProfilerController::RefreshStatus(const RMessage2& aMessage) const +{ + return iEngine.RefreshStatus(aMessage); +} + +inline RProfiler::TSamplerState MProfilerController::GeTComand() const +{ + return iEngine.State(); +} + +class CSamplerController; +class CWriterController; +class MSamplerControllerObserver; +class MProfilerErrorObserver; + +class CProfiler : public CBase, private MProfilerEngine, + MSamplerControllerObserver, + MProfilerErrorObserver, + MProfilerTimerObserver +{ + public: + + static CProfiler* NewLC(const TDesC& aSettingsFile); + + /** + * Method for control commands, i.e. start, stop and exit + * + * @param aCommand command to be parsed and executed + * @return TInt KErrNone if succeed, else error code + */ + TInt ControlL(TInt aCommand); + + /** + * Method for control data, e.g. settings + * + * @param aCommand command to be parsed and executed + * @param value1 can contain any value, integer or string, depends on use case + * @param value2 can contain any value, integer or string, depends on use case + * @return TInt KErrNone if succeed, else error code + */ + TInt ControlDataL(TInt aCommand, TAny* value1 = 0, TAny* value2 = 0); + + // setting attributes manipulation + TInt GetGeneralAttributesL(const RMessage2& aMessage); + TInt GetSamplerAttributesL(const RMessage2& aMessage); + TInt SetGeneralAttributesL(const RMessage2& aMessage); + TInt SetSamplerAttributesL(const RMessage2& aMessage); + TInt GetSamplerAttributeCountL(const RMessage2& aMessage); + TInt RefreshStatus(const RMessage2& /*aMessage*/); + + // from CProfilerErrorChecker + void HandleSamplerControllerReadyL(); + void NotifyRequesterForSettingsUpdate(); + void HandleProfilerErrorChangeL( TInt aError ); + + // from MProfilerTimerObserver + void HandleTimerExpiresL(TInt aError); + + void Finalise(); + CProfilerSampleStream* GetSamplerStream(); + void HandleError(TInt aErr); + static TBool CheckLocationSanity(RFs& fs, const TDesC8& aLocation); +private: + CProfiler(const TDesC& aSettingsFile); + ~CProfiler(); + void ConstructL(); + TInt LoadSettingsL(/*const TDesC& configFile*/); + void DoGetValueFromSettingsArray(CDesC8ArrayFlat* aLineArray, const TDesC8& aAttribute, TDes8& aValue); + void DoGetValueFromSettingsArray(CDesC8ArrayFlat* aLineArray, const TDesC8& aAttribute, TInt& aValue); + void UpdateSavedGeneralAttributes(CDesC8ArrayFlat* aSavedAttributes); + template<class T> CBufFlat* ExternalizeLC(const T& aElements); + + RProfiler::TSamplerState State() const; + + void DrainSampleStream(); + void InstallStreamForActiveTraces(CSamplerPluginInterface& aSampler, CWriterPluginInterface& aWriter, TDesC& totalPrefix); + void SaveSettingsL(); + + TInt HandleGeneralSettingsChange(); + TInt CheckOldProfilerRunning(); +public: + // trace file settings + TBuf8<KProfilerPrefixMaxLength> iFilePrefix; + TBuf8<KProfilerPrefixMaxLength> iDriveLetter; + TBuf8<KProfilerPrefixMaxLength*2> iTotalPrefix; + + TBuf<256> iSettingsFileLocation; + + MProfilerController* iServer; + RProfiler::TSamplerState iState; + + CProfilerSampleStream* iUserStream; + + // plug-in controllers + CWriterController* iWriterHandler; + CSamplerController* iSamplerHandler; + + // setting attribute containers + TGeneralAttributes iGeneralAttributes; + CArrayFixFlat<TSamplerAttributes>* iDefaultSamplerAttributesArray; + + // temporary settings file array container + CDesC8ArrayFlat* iSavedLineArray; + TInt iSavedLinesCount; + // saved settings, add extra 1 byte space to end buffer with a '\n' + TBuf8<KSettingsFileSize + 1> iSettingsBuffer; + + // P&S status properties + RProperty iEngineStatus; + RProperty iUpdateStatus; + TBuf<128> iFileNameStream; +private: + TBool iSettingsFileLoaded; + CProfilerErrorChecker* iErrorChecker; + CProfilerTimer* iTimer; +}; + +#include <piprofiler/ProfilerGenericClassesUsr.h> +#endif // __PROFILERENGINE__ + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/inc/ProfilerErrorChecker.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/inc/ProfilerErrorChecker.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,47 @@ +/* +* 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: +* +*/ + + +#ifndef PROFILERERRORCHECKER_H_ +#define PROFILERERRORCHECKER_H_ + +// CLASS DECLARATIONS +class MProfilerErrorObserver + { + public: // New + virtual void HandleProfilerErrorChangeL( TInt aError ) = 0; + }; + + +class CProfilerErrorChecker : public CActive + { +public: + static CProfilerErrorChecker* CProfilerErrorChecker::NewL(); + ~CProfilerErrorChecker(); + void SetObserver(MProfilerErrorObserver* aObserver); +private: + CProfilerErrorChecker(); + void ConstructL(); + void RunL(); + TInt RunError(TInt aError); + void DoCancel(); +private: + MProfilerErrorObserver* iObserver; + RProperty iErrorStatus; + }; + +#endif /* PROFILERERRORCHECKER_H_ */ diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/inc/ProfilerEshell.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/inc/ProfilerEshell.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,36 @@ +/* +* 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: +* +*/ +#ifndef PROFILERESHELL_H_ +#define PROFILERESHELL_H_ + +#include <e32base.h> +#include <e32std.h> +#include <bacline.h> // CCommandLineArguments + +class CProfilerEShell : public CBase + { +public: + static CProfilerEShell* NewL(); + ~CProfilerEShell(); + + void ConstructL(); +private: + CProfilerEShell(); + + }; + +#endif /* PROFILERESHELL_H_ */ diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/inc/ProfilerTimer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/inc/ProfilerTimer.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,57 @@ +/* +* 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: +* +*/ + +#ifndef PROFILERTIMER_H_ +#define PROFILERTIMER_H_ + +#include <e32std.h> +#include <e32base.h> + +class MProfilerTimerObserver + { +public: + virtual void HandleTimerExpiresL(TInt aError) = 0; + }; + +class CProfilerTimer : public CActive + { +public: + static CProfilerTimer* NewL(const TInt aPriority, MProfilerTimerObserver& aObserver); + ~CProfilerTimer(); + +public: + + void After(TUint aPeriodInSeconds); + +protected: + + // From CActive + void RunL(); + void DoCancel(); + +private: + + CProfilerTimer(const TInt aPriority, MProfilerTimerObserver& aObserver); + void ConstructL(void); + +private: + + RTimer iTimer; + MProfilerTimerObserver& iObserver; + }; + +#endif /* PROFILERTIMER_H_ */ diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/inc/SamplerController.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/inc/SamplerController.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,154 @@ +/* +* 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: +* +*/ + + +#ifndef __SAMPLERCONTROLLER_H__ +#define __SAMPLERCONTROLLER_H__ + +// system includes +#include <utf.h> +#include <e32cmn.h> + + +// The user-interface to the sampling device driver sued by the profiling engine +// user includes +#include <piprofiler/ProfilerConfig.h> +#include <piprofiler/ProfilerVersion.h> +#include <piprofiler/SamplerPluginInterface.h> + +#include "SamplerPluginLoader.h" + +/* + * Forward declarations + */ +class TBapBuf; +class CProfilerSampleStream; +class CSamplerPluginLoader; +class CSamplerPluginInterface; +class MSamplerControllerObserver; +/** + * The sampler controller for handling the actual sampler plugins. + */ + +class CSamplerController : public CBase, MSamplerPluginLoadObserver + { + +public: + static CSamplerController* NewL(CProfilerSampleStream& aStream); + void ConstructL(); + + CSamplerController(CProfilerSampleStream& aStream); + ~CSamplerController(); + + /** + * + * Methods for user mode sampling + * + **/ + + /** Initialise the user mode samplers **/ + void InitialiseSamplerListL(); + + /* Overrider of MSamplerPluginLoaderObserver class **/ + void HandlePluginLoaded( KSamplerPluginLoaderStatus aStatus ); + + /* returns the name matching plugin Uid */ + TUid GetPluginUID(TDesC8& name); + + /** Start enabled samplers **/ + void StartSamplerPluginsL(); + + /** Stop enabled samplers **/ + TInt StopSamplerPlugins(); + +public: + + CSamplerPluginInterface* GetPlugin(TUid aUid); + + TInt GetPluginList(TDes* aList); + + TInt SetSamplerSettingsL(TInt aUid, TSamplerAttributes aAttributes); + + void GetSamplerAttributesL(CArrayFixFlat<TSamplerAttributes>* aAttributes); + + TInt UpdateSavedSamplerAttributesL(CDesC8ArrayFlat* aSavedLineArray, CArrayFixFlat<TSamplerAttributes>* aAttributes); + + /* + * Compose all sampler (sampler or sub-sampler) attributes as text array for saving to settings file, + * called by CSamplerController (and Profiler Engine) + * + * @param aFile settings file where to write the settings + */ + void ComposeAttributesToSettingsFileFormat(RFile& aFile, CArrayFixFlat<TSamplerAttributes>* aAttributes); + + /* + * Compose all sampler (sampler or sub-sampler) attributes as text array for saving to settings file, + * called by CSamplerController (and Profiler Engine) + * + * @param aFile settings file where to write the settings + * @param aAttrArray is container for saving the text to + */ + void ComposeSettingsText(RFile& aFile, CArrayFixFlat<TSamplerAttributes>* aAttrArray); + + void SetObserver(MSamplerControllerObserver* aObserver); + + void Str2Bool(const TDesC8& aBuf, TBool& aValue); + + void Str2Int(const TDesC8& aBuf, TInt& aValue); + + void Str2Int(const TDesC8& aBuf, TUint32& aValue); + + TBuf8<16> Bool2Str(const TBool& aValue); + + TBuf8<16> Int2Str(const TInt& aValue); +public: + + CArrayPtrFlat<CSamplerPluginInterface>* iPluginArray; + + // Asynchronous loader for the sampler plug-ins. + CSamplerPluginLoader* iPluginLoader; + + // UID of the selected plugin in the container's lbx. + TUid iSelectedPluginUid; + + // shared sample stream for all plugin samplers + CProfilerSampleStream& iStream; + +private: + MSamplerControllerObserver* iObserver; +}; + +/** +* Interface for SamplerPluginLoader observer. MSamplerPluginLoadObserver gets +* notifications when plugins are loaded. +* +* @lib ProfilerEngine.exe/.lib +* @since Series60_30.1 +*/ + +class MSamplerControllerObserver + { + public: // New + + //CSamplerController calls this function when each plug-in is loaded or + //loading is finished.. + + virtual void HandleSamplerControllerReadyL() = 0; + virtual void HandleError(TInt aError) = 0; + }; + +#endif // __SAMPLERCONTROLLER_H__ diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/inc/SamplerPluginLoader.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/inc/SamplerPluginLoader.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,291 @@ +/* +* 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: +* +*/ + + +#ifndef SAMPLERPLUGINLOADER_H +#define SAMPLERPLUGINLOADER_H + +// INCLUDES +#include <e32base.h> +#include <ecom/implementationinformation.h> +#include <piprofiler/ProfilerConfig.h> +#include <piprofiler/SamplerPluginInterface.h> + +// CONSTANTS +// Value for a to b comparison result when logically a == b. +const TInt KSamplerComparisonEqual = 0; + +// Value for a to b comparison result when logically a < b. +const TInt KSamplerComparisonBefore = -1; + +// Value for a to b comparison result when logically a > b. +const TInt KSamplerComparisonAfter = 1; + +// CLASS DEFINITIONS +class CSamplerPluginInterface; +class MSamplerPluginLoadObserver; +class REComSession; + +/** +* CSamplerPluginLoader. Mechanism used to load plugins asynchronously. Uses +* MSamplerPluginLoadObserver as a callback. +* +* @lib ProfilerEngine.exe/.lib??????????? +* @since Series60_30.1 +*/ +class CSamplerPluginLoader : public CActive + { + public: // Constructor and destructor + + /** + * Two-phased constructor. + * + * @param aAppUi Pointer to application UI. Does not take ownership. + */ + static CSamplerPluginLoader* NewL(); + + /** + * Destructor + */ + ~CSamplerPluginLoader(); + + private: // Internal construction + + /** + * Default C++ contructor + */ + CSamplerPluginLoader(); + + /** + * Symbian OS default constructor + * @return void + */ + void ConstructL(); + + public: // API + + /** + * Starts loading GS plug-ins asynchronously. Will call + * MSamplerPluginLoadObserver::HandlePluginLoaded() each time a plug-in is + * loaded and when all plugins are loaded. + * + * CSamplerPluginLoader transfers the ownership of each loaded plugin view to + * CAknViewAppUi. It is client's responsibility to remove the views from + * CAknViewAppUi and delete the plugins if necessary. + * + * @param aInterfaceUid Uid ofthe interfaces to be loaded. + * @param aParentUid Uid of the parent. Only children of this parent + * will be loaded. + * @param aPluginArray An array for the loaded GS plug-ins. + * CSamplerPluginLoader does not take the ownership of this array. + */ + void LoadAsyncL( CArrayPtrFlat<CSamplerPluginInterface>* aPluginArray ); + + /** + * Load a specific plugin instance synchronously. + * + * @param aInterfaceUid Uid ofthe interfaces to be loaded. + * @param aImplementationUid Uid of the implementation to load + */ + void LoadSyncL( CArrayPtrFlat<CSamplerPluginInterface>* aPluginArray ); + + /** + * Sets observer for this loader. Only one observer per loader in one + * time is possible. + */ + void SetObserver(MSamplerPluginLoadObserver* aObserver); + + /** + * Aborts asynchronous loading of the GS plug-ins. + */ + void AbortAsyncLoad(); + + + /** + * Sorts the plugin array. + * + * Sorting criterias: + * + * 1. Order number if provider category is Internal. + * 2. Provider category. Precedence as follows: + * 1. KGSPluginProviderInternal + * 2. EGSPluginProviderOEM + * 3. EGSPluginProviderOperator + * 4. EGSPluginProvider3rdParty + * 3. Alphabetical + * + * @param aPlugins The array which will be sorted. + */ + void SortPluginsL( CArrayPtrFlat<CSamplerPluginInterface>* aPlugins ); + + private: // Internal methods + + /** + * Starts loading next plugin. + */ + void LoadNextPluginL(); + + /** + * Creates a plugin instance from given UID. Ownership is transferred. + */ + CSamplerPluginInterface& CreatePluginInstanceL( + const CImplementationInformation& aImpInfo ); + + /** + * Notifies MPluginLoadObserver. + */ + void NotifyProgress(); + + /** + * Notifies MPluginLoadObserver. + */ + void NotifyFinished(); + + /** + * Wait for the next round of CActive execution. + */ + void CompleteOwnRequest(); + + // Insertion function used by sorting: + + /** + * Inserts plugin in the correct position in the array using sorting + * criterias. Assumes aPlugins is ordered. + * + * @param aPlugin The plugin to be inserted. + * @param aPlugins Array in which the plugin is inserted into the + * corresponding location. + */ + void InsertPluginInOrderL( + CSamplerPluginInterface* aPlugin, + CArrayPtrFlat<CSamplerPluginInterface>* aPlugins ); + + // Comparison functions: + + /** + * Compares plugins according to comparison criterias. + * + * Note: GS internal comparison constants such as KGSComparisonEqual are + * different from the ones outputted by this function. This is because + * this function is also usable by RArray sort -functionality but BC + * cannot be broken in GS. + * + * @return Negative value: If aFirst before aSecond. + * 0: If equal. + * Positive value: If aSecond before aFirst. + */ + static TInt Compare( const CSamplerPluginInterface& aFirst, + const CSamplerPluginInterface& aSecond ); + + /** + * + * @return KGSComparisonEqual = equal indexes + * KGSComparisonBefore = aFirst is before aSecond + * KGSComparisonAfter = aFirst is after aSecond + */ + + static TInt CompareIndex( + const CSamplerPluginInterface& aFirst, + const CSamplerPluginInterface& aSecond ); + + private: // Utility methods + + /** + * Parses descriptor to UID. + */ + static TInt ParseToUid( const TDesC8& aSource, TUid& aTarget ); + + /** + * Parsers plugin's order number + */ + static TInt ParseOrderNumber( const TDesC8& aSource, TInt& aOrderNumber ); + + private: // From CActive + + /** + * See base class. + */ + void RunL(); + + /** + * See base class. + */ + TInt RunError( TInt aError ); + + /** + * See base class. + */ + void DoCancel(); + + private: // Data + // Pluginloader goes through this array and loads the plugins into + // iPluginArray if they fulfill the criterias. + RImplInfoPtrArray iImplInfoArray; + + // Used as an iterator to maintain location in iImplInfoArray. + TInt iImplInfoArrayIterator; + + // Array of loaded plugins.Plugins are owned by iAppUi. Only the array + // pointers are owned by this class and therefore only reset array. + CArrayPtrFlat<CSamplerPluginInterface>* iPluginArray; + + // Pointer to observer. Not owned. + MSamplerPluginLoadObserver* iObserver; + + // Number of RunL calls. + TInt iRunLDebugCount; + + }; + + +/** +* Interface for SamplerPluginLoader observer. MSamplerPluginLoadObserver gets +* notifications when plugins are loaded. +* +* @lib ProfilerEngine.exe/.lib??????????? +* @since Series60_30.1 +*/ + +class MSamplerPluginLoadObserver + { + public: // Enums + enum KSamplerPluginLoaderStatus + { + // One plugin loaded successfully, continue to next. + ESamplerSuccess, + // Loading one plugin failed, contiue to next. + ESamplerFail, + // Client called AbortAsyncLoad(), finished loading. + ESamplerAborted, + // All plugins loaded successfully, finished loading. + ESamplerFinished, + // Severe error with loader, finished loading. + ESamplerError + }; + + public: // New + + //CSamplerPluginLoader calls this function when each plug-in is loaded or + //loading is finished.. + + IMPORT_C virtual void HandlePluginLoaded( + KSamplerPluginLoaderStatus aStatus ) = 0; + }; + + +#endif // SAMPLERPLUGINLOADER_H +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/inc/WriterController.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/inc/WriterController.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,115 @@ +/* +* 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: +* +*/ + + +#ifndef __WRITERCONTROLLER_H__ +#define __WRITERCONTROLLER_H__ + +// system includes +#include <utf.h> +#include <e32cmn.h> + + +// The user-interface to the sampling device driver sued by the profiling engine +// user includes +#include <piprofiler/ProfilerConfig.h> +#include <piprofiler/ProfilerVersion.h> +#include <piprofiler/WriterPluginInterface.h> + +#include "WriterPluginLoader.h" + +/* + * Forward declarations + */ +class TBapBuf; +class CWriterPluginLoader; +class CWriterPluginInterface; + +/** + * The writer controller for handling the available Data writer plugins. + */ + +class CWriterController : public CBase, MWriterPluginLoadObserver + { + +public: + static CWriterController* NewL(CProfilerSampleStream& aStream); + void ConstructL(); + + CWriterController(CProfilerSampleStream& aStream); + ~CWriterController(); + + /** + * + * Methods for user mode sampling + * + **/ + + /** Initialise the user mode samplers **/ + void InitialiseWriterListL(); + + /* Overrider of MSamplerPluginLoaderObserver class **/ + void HandlePluginLoaded( KWriterPluginLoaderStatus /*aStatus*/ ); + + /* returns the matching plugin Uid */ + TUid GetPluginUID(TInt traceId); + + CWriterPluginInterface* GetActiveWriter(); + + /** Returns the sampler type (kernel/user) **/ + TUint32 GetWriterType(TUint32 samplerId); + + /** Set additional settings for a trace **/ + TInt AdditionalUserTraceSettings(TInt traceId, TInt settings); + + /** Set data stream for samplers **/ + //void SetSampleStream(RProfilerSampleStream* iStream); + + TInt StartSelectedPlugin(); + + void StopSelectedPlugin(); + + /** Set selected plugin active **/ + void SetPluginActive(TUid uid, const TWriterPluginValueKeys aKey); + + TInt SetPluginSettings(TUid aUid, TDes& aDes); + + /** Get settings for a specific plugin **/ + void GetPluginSettings(TUid uid, TDes& aVal); + + /** Request stream read **/ + //void FillThisStreamBuffer(TBapBuf* aBuffer, TRequestStatus& aStatus); + + CWriterPluginInterface* GetPlugin(TUid aUid); + + CArrayPtrFlat<CWriterPluginInterface>* GetPluginList(); + + void InitialisePluginStream(); +public: + CArrayPtrFlat<CWriterPluginInterface>* iPluginArray; + + // Asynchronous loader for the writer plug-ins. + CWriterPluginLoader* iPluginLoader; + + // UID of the selected plugin in the container's lbx. + TUid iSelectedPluginUid; + + CProfilerSampleStream& iStream; +}; + + +#endif // __WRITERCONTROLLER_H__ diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/inc/WriterPluginLoader.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/inc/WriterPluginLoader.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,302 @@ +/* +* 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: +* +*/ + + +#ifndef WRITERPLUGINLOADER_H +#define WRITERPLUGINLOADER_H + +// INCLUDES +#include <e32base.h> +#include <ecom/implementationinformation.h> +#include <piprofiler/ProfilerConfig.h> +#include <piprofiler/WriterPluginInterface.h> +#include <piprofiler/ProfilerTraces.h> + +// CONSTANTS + +// Value for a to b comparison result when logically a == b. +const TInt KWriterComparisonEqual = 0; + +// Value for a to b comparison result when logically a < b. +const TInt KWriterComparisonBefore = -1; + +// Value for a to b comparison result when logically a > b. +const TInt KWriterComparisonAfter = 1; + +// CLASS DEFINITIONS +class CWriterPluginInterface; +class MWriterPluginLoadObserver; +class REComSession; + +/** +* CWriterPluginLoader. Mechanism used to load plugins asynchronously. Uses +* MWriterPluginLoadObserver as a callback. +* +* @lib ProfilerEngine.exe/.lib??????????? +* @since Series60_30.1 +*/ +class CWriterPluginLoader : public CActive + { + public: // Constructor and destructor + + /** + * Two-phased constructor. + * + * @param aAppUi Pointer to application UI. Does not take ownership. + */ + static CWriterPluginLoader* NewL(); + + /** + * Destructor + */ + ~CWriterPluginLoader(); + + private: // Internal construction + + /** + * Default C++ contructor + */ + CWriterPluginLoader(); + + /** + * Symbian OS default constructor + * @return void + */ + void ConstructL(); + + public: // API + + /** + * Starts loading GS plug-ins asynchronously. Will call + * MWriterPluginLoadObserver::HandlePluginLoaded() each time a plug-in is + * loaded and when all plugins are loaded. + * + * CWriterPluginLoader transfers the ownership of each loaded plugin view to + * CAknViewAppUi. It is client's responsibility to remove the views from + * CAknViewAppUi and delete the plugins if necessary. + * + * @param aInterfaceUid Uid ofthe interfaces to be loaded. + * @param aParentUid Uid of the parent. Only children of this parent + * will be loaded. + * @param aPluginArray An array for the loaded GS plug-ins. + * CWriterPluginLoader does not take the ownership of this array. + */ + void LoadAsyncL( CArrayPtrFlat<CWriterPluginInterface>* aPluginArray ); + + /** + * Load a specific plugin instance synchronously. + * + * @param aInterfaceUid Uid ofthe interfaces to be loaded. + * @param aImplementationUid Uid of the implementation to load + */ + CWriterPluginInterface& LoadSyncL( TUid aImplementationUid ); + + /** + * Sets observer for this loader. Only one observer per loader in one + * time is possible. + */ + void SetObserver(MWriterPluginLoadObserver* aObserver); + + /** + * Aborts asynchronous loading of the GS plug-ins. + */ + void AbortAsyncLoad(); + + /** + * Sorts the plugin array. + * + * Sorting criterias: + * + * 1. Order number if provider category is Internal. + * 2. Provider category. Precedence as follows: + * 3. Alphabetical + * + * @param aPlugins The array which will be sorted. + */ + void SortPluginsL( CArrayPtrFlat<CWriterPluginInterface>* aPlugins ); + + private: // Internal methods + + /** + * Starts loading next plugin. + */ + void LoadNextPluginL(); + + /** + * Creates a plugin instance from given UID. Ownership is transferred. + */ + CWriterPluginInterface& CreatePluginInstanceL( + const CImplementationInformation& aImpInfo ); + + /** + * Notifies MGSPluginLoadObserver. + */ + void NotifyProgress(); + + /** + * Notifies MGSPluginLoadObserver. + */ + void NotifyFinished(); + + /** + * Wait for the next round of CActive execution. + */ + void CompleteOwnRequest(); + + // Insertion function used by sorting: + + /** + * Inserts plugin in the correct position in the array using sorting + * criterias. Assumes aPlugins is ordered. + * + * @param aPlugin The plugin to be inserted. + * @param aPlugins Array in which the plugin is inserted into the + * corresponding location. + */ + void InsertPluginInOrderL( + CWriterPluginInterface* aPlugin, + CArrayPtrFlat<CWriterPluginInterface>* aPlugins ); + + // Comparison functions: + + /** + * Compares plugins according to comparison criterias. + * + * Note: GS internal comparison constants such as KGSComparisonEqual are + * different from the ones outputted by this function. This is because + * this function is also usable by RArray sort -functionality but BC + * cannot be broken in GS. + * + * @return Negative value: If aFirst before aSecond. + * 0: If equal. + * Positive value: If aSecond before aFirst. + */ + static TInt Compare( const CWriterPluginInterface& aFirst, + const CWriterPluginInterface& aSecond ); + + /** + * + * @return KGSComparisonEqual = equal indexes + * KGSComparisonBefore = aFirst is before aSecond + * KGSComparisonAfter = aFirst is after aSecond + */ + + static TInt CompareIndex( + const CWriterPluginInterface& aFirst, + const CWriterPluginInterface& aSecond ); + + private: // Utility methods + + /** + * Parses descriptor to UID. + */ + static TInt ParseToUid( const TDesC8& aSource, TUid& aTarget ); + + /** + * Parsers plugin's order number + */ + static TInt ParseOrderNumber( const TDesC8& aSource, TInt& aOrderNumber ); + + /** + * Print debug information. + */ + static void PrintInfoDebug( const CImplementationInformation& aInfo, + TInt aIterator, + TInt aPluginCount ); + + /** + * Display loading error popup message. + */ + void DisplayErrorPopupL( TInt aError, + const CImplementationInformation* aInfo ); + + private: // From CActive + + /** + * See base class. + */ + void RunL(); + + /** + * See base class. + */ + TInt RunError( TInt aError ); + + /** + * See base class. + */ + void DoCancel(); + + private: // Data + + + // Pluginloader goes through this array and loads the plugins into + // iPluginArray if they fulfill the criterias. + RImplInfoPtrArray iImplInfoArray; + + // Used as an iterator to maintain location in iImplInfoArray. + TInt iImplInfoArrayIterator; + + // Array of loaded plugins.Plugins are owned by iAppUi. Only the array + // pointers are owned by this class and therefore only reset array. + CArrayPtrFlat<CWriterPluginInterface>* iPluginArray; + + // Pointer to observer. Not owned. + MWriterPluginLoadObserver* iObserver; + + // Number of RunL calls. + TInt iRunLDebugCount; + }; + + +/** +* Interface for WriterPluginLoader observer. MWriterPluginLoadObserver gets +* notifications when plugins are loaded. +* +* @lib ProfilerEngine.exe/.lib??????????? +* @since Series60_30.1 +*/ + +class MWriterPluginLoadObserver + { + public: // Enums + enum KWriterPluginLoaderStatus + { + // One plugin loaded successfully, continue to next. + EWriterSuccess, + // Loading one plugin failed, contiue to next. + EWriterFail, + // Client called AbortAsyncLoad(), finished loading. + EWriterAborted, + // All plugins loaded successfully, finished loading. + EWriterFinished, + // Severe error with loader, finished loading. + EWriterError + }; + + public: // New + + //CWriterPluginLoader calls this function when each plug-in is loaded or + //loading is finished.. + + IMPORT_C virtual void HandlePluginLoaded( + KWriterPluginLoaderStatus aStatus ) = 0; + }; + + +#endif // WRITERPLUGINLOADER_H +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/src/ProfilerEngine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/src/ProfilerEngine.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,1515 @@ +/* +* 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: +* +*/ + + +#include <e32cons.h> +#include <e32base.h> +#include <f32file.h> +#include <c32comm.h> +#include <s32file.h> +#include <pathinfo.h> +#include <s32mem.h> +#include <bautils.h> +#include <sysutil.h> +#include <piprofiler/ProfilerConfig.h> +#include "ProfilerEngine.h" +#include <piprofiler/ProfilerTraces.h> + +// properties +const TUid KEngineStatusPropertyCat={0x2001E5AD}; +enum TEnginePropertyKeys + { + EProfilerEngineStatus = 8, + EProfilerErrorStatus + }; + +static _LIT_SECURITY_POLICY_PASS( KAllowAllPolicy ); + +// CONSTANTS +const TInt KStreamBufferSize = 32768; +const TInt KSavedLineCount = 64; +const TInt KFileNameBufSize = 128; +// Use this UID if plugin belongs to DebOutWriterPlugin: +const TUid KDebOutWriterPluginUid = { 0x2001E5BA }; +// Use this UID if plugin belongs to MmcOutWriterPlugin: +const TUid KDiskWriterPluginUid = { 0x2001E5BB }; + +// LITERALS +_LIT8(KGenericTraceOutput, "output_type"); +_LIT8(KGenericTraceFilePrefix, "file_prefix"); +_LIT8(KGenericTraceFileSaveDrive, "save_file_location"); +_LIT8(KGenericTimedProfilingPeriod, "profiling_period"); +_LIT8(KEquals, "="); +_LIT8(KNewLineSeparator, "\n"); +_LIT8(KProfilerVersionTag, "version"); +_LIT8(KEndMark, "[end]"); +_LIT8(KOutputToDebugOutput, "debug_output"); + +/** + * + * The controller class used to provide the Profiler functions. + * This runs as a server in the engine thread + * + */ +class CPServer : public CServer2, public MProfilerController + { +public: + static MProfilerController* NewL(TInt aPriority, MProfilerEngine& aEngine); + +private: + CPServer(TInt aPriority, MProfilerEngine& aEngine); + void Release(); + CSession2* NewSessionL(const TVersion& aVersion,const RMessage2& aMessage) const; + +public: + static TInt iClientCount; + }; + +TInt CPServer::iClientCount = 0; + +// The session class used by the server controller +class CPSession : public CSession2 + { +private: + inline const CPServer& Server() const; + void ServiceL(const RMessage2& aMessage); + }; + +/* + * + * CProfiler class implementation + * + */ +// -------------------------------------------------------------------------------------------- +CProfiler* CProfiler::NewLC(const TDesC& aSettingsFile) + { + CProfiler* self = new(ELeave) CProfiler(aSettingsFile); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +// -------------------------------------------------------------------------------------------- +CProfiler::CProfiler(const TDesC& aSettingsFile) : + iSettingsFileLocation(aSettingsFile) + { + // define property for Profiler Engine status, UI may read it for control purposes + if ( RProperty::Define(KEngineStatusPropertyCat, + EProfilerEngineStatus, + RProperty::EInt, + KAllowAllPolicy, + KAllowAllPolicy, + 0) != KErrAlreadyExists ) + { + LOGTEXT(_L("CProfiler::CProfiler - status property already defined")); + } + + if ( RProperty::Define(KEngineStatusPropertyCat, + EProfilerErrorStatus, + RProperty::EInt, + KAllowAllPolicy, + KAllowAllPolicy, + 0) != KErrAlreadyExists ) + { + LOGTEXT(_L("CProfiler::CProfiler - status property already defined")); + } + + // attach to own property + iEngineStatus.Attach(KEngineStatusPropertyCat, EProfilerEngineStatus); + // set status idle + iEngineStatus.Set(KEngineStatusPropertyCat, EProfilerEngineStatus, RProfiler::EIdle); + + // attach to own property + iUpdateStatus.Attach(KEngineStatusPropertyCat, EProfilerErrorStatus); + // set status idle + iUpdateStatus.Set(KEngineStatusPropertyCat, EProfilerErrorStatus, EFalse); + } + +// -------------------------------------------------------------------------------------------- +CProfiler::~CProfiler() + { + LOGTEXT(_L("CProfiler::~CProfiler - Enter")); + + // delete error checker + if(iErrorChecker) + { + iErrorChecker->Cancel(); + delete iErrorChecker; + iErrorChecker = NULL; + } + + // delete settings array + if(iDefaultSamplerAttributesArray) + { + iDefaultSamplerAttributesArray->Reset(); + delete iDefaultSamplerAttributesArray; + iDefaultSamplerAttributesArray = NULL; + } + + // delete settings file raw line array + if(iSavedLineArray) + { + iSavedLineArray->Reset(); + delete iSavedLineArray; + iSavedLineArray = NULL; + } + + // delete sampler controller, cleans up the sampler plugin instances + if(iSamplerHandler) + { + delete iSamplerHandler; + iSamplerHandler = NULL; + } + // delete writer controller, cleans up the writer plugin instances + if(iWriterHandler) + { + delete iWriterHandler; + iWriterHandler = NULL; + } + + // delete user side sampler stream + if(iUserStream) + { + delete iUserStream; + iUserStream = NULL; + } + + // close engine status property + iEngineStatus.Close(); + if (RProperty::Delete(KEngineStatusPropertyCat, EProfilerEngineStatus) != KErrNotFound) + { + LOGTEXT(_L("CProfiler::~CProfiler - cannot close status property")); + } + // close engine update property + iUpdateStatus.Close(); + if (RProperty::Delete(KEngineStatusPropertyCat, EProfilerErrorStatus) != KErrNotFound) + { + LOGTEXT(_L("CProfiler::~CProfiler - cannot close update property")); + } + + // close server process + if (iServer) + { + LOGTEXT(_L("CProfiler::~CProfiler - Releasing server")); + iServer->Release(); + } + + if( iTimer ) + { + iTimer->Cancel(); + delete iTimer; + iTimer = 0; + } + + LOGTEXT(_L("CProfiler::~CProfiler - Finished")); + } + +// -------------------------------------------------------------------------------------------- +void CProfiler::ConstructL() + { + LOGTEXT(_L("CProfiler::ConstructL - Enter")); + TInt err(0); + TLex lex; + + if ( iSettingsFileLocation.CompareF(KNullDesC) != 0 ) + { + lex=(iSettingsFileLocation); + // parse the first command line argument, the command itself + lex.Mark(); + lex.SkipCharacters(); + if(lex.TokenLength() != 0) + { + // there is another item in the list + TPtrC filename = lex.MarkedToken(); + LOGSTRING2("filename %S", &filename); + lex.SkipSpace(); + lex.Mark(); + lex.SkipCharacters(); + if(lex.TokenLength() != 0) + { + TPtrC boot = lex.MarkedToken(); + LOGTEXT(_L("boot mode")); + } + } + } + + // create new sampler stream instance + iUserStream = CProfilerSampleStream::NewL(KStreamBufferSize); + if(!iUserStream) + { + LOGTEXT(_L("Profiler engine cannot reserve memory")); + User::Leave(KErrCancel); // operation cancelled + } + + // engine status checker + iErrorChecker = CProfilerErrorChecker::NewL(); + iErrorChecker->SetObserver(this); + + // create and initiate plug-in controller instances + iSamplerHandler = CSamplerController::NewL(*iUserStream); + iWriterHandler = CWriterController::NewL(*iUserStream); + + iWriterHandler->InitialiseWriterListL(); + + // set engine as an observer to sampler controller to get the notification of plugin load has ended + iSamplerHandler->SetObserver(this); + + // default settings from sampler plugins, maximum 20 sampler plugins + iDefaultSamplerAttributesArray = new(ELeave) CArrayFixFlat<TSamplerAttributes>(20); + + // set profiler status to initializing + iState = RProfiler::EInitializing; + iEngineStatus.Set(RProfiler::EInitializing); + + // set default general settings, will be overdriven if changed in settings file + iGeneralAttributes.iTraceOutput.Copy(KDefaultTraceOutput); + iGeneralAttributes.iTraceFilePrefix.Copy(KDefaultTraceFilePrefix); + iGeneralAttributes.iSaveFileDrive.Copy(KDefaultTraceFileSaveDrive); + iGeneralAttributes.iTimedSamplingPeriod = KDefaultTimedSamplingPeriod; + + RThread me; + + me.SetPriority(EPriorityRealTime); + + err = KErrGeneral; + TInt count = 0; + + while(err != KErrNone && count < 30) + { + err = User::RenameThread(KProfilerName); + if(err != KErrNone) + { + LOGSTRING2("CProfiler: error renaming the thread, err %d", err); + User::Leave(err); + } + else break; + } + + // set settings file loading preferences + iSettingsFileLoaded = EFalse; + + // change status property to idle since initialization successfull + iState = RProfiler::EIdle; + if( iEngineStatus.Set((TInt)RProfiler::EIdle) != KErrNone ) + { + LOGTEXT(_L("CProfiler::ConstructL - engine status property change failed")); + } + + if( iUpdateStatus.Set(EFalse) != KErrNone ) + { + LOGTEXT(_L("CProfiler::ConstructL - engine status property change failed")); + } + + // create a server instance for clients to communicate with + iServer = CPServer::NewL(10,*this); + + // close the handle + me.Close(); + + iTimer = CProfilerTimer::NewL(CActive::EPriorityStandard, *this); + + LOGTEXT(_L("CProfiler::ConstructL - Exit")); + + } + +CProfilerSampleStream* CProfiler::GetSamplerStream() + { + return iUserStream; + } + +void CProfiler::HandleSamplerControllerReadyL() + { + // load settings + // check if settings file already loaded + if(!iSettingsFileLoaded) + { + // load default settings file + LoadSettingsL(); + + iSettingsFileLoaded = ETrue; + } + + // notify engine's launcher(UI or PIProfilerLauncher) to continue launch + RProcess::Rendezvous(KErrNone); + } + +void CProfiler::NotifyRequesterForSettingsUpdate() + { + // set update status P&S property true => update needed on UI side + iUpdateStatus.Set(ETrue); + } + +void CProfiler::HandleProfilerErrorChangeL(TInt aError) + { + LOGSTRING2("CProfiler::HandleProfilerErrorChangeL() - error received, %d", aError); + + // check if profiler running + if(iState == RProfiler::ERunning) + { + // stop profiler if error occurred during the trace + iEngineStatus.Set(aError); + + // stop samplers, NOTE! Writer plugins not stopped since + iSamplerHandler->StopSamplerPlugins(); + + // stop debug output plugin and write the rest of the trace data to output + if(iGeneralAttributes.iTraceOutput.CompareF(KOutputToDebugOutput) == 0) + { + // write the rest of trace data only if debug output selected + iWriterHandler->StopSelectedPlugin(); + } + LOGSTRING2("CProfiler::HandleProfilerErrorChangeL - sampling stopped, going to state %d", RProfiler::EIdle); + } + } + +// ---------------------------------------------------------------------------- +// Gets a value from settings file for certain attribute. +// ---------------------------------------------------------------------------- +void CProfiler::DoGetValueFromSettingsArray(CDesC8ArrayFlat* aLineArray, const TDesC8& aAttribute, TDes8& aValue) + { + LOGTEXT(_L("CProfiler::DoGetValueFromSettingsFile()")); + _LIT8(KSettingItemSeparator, "="); + + // read a line of given array + for (TInt i=0; i<aLineArray->MdcaCount(); i++) + { + // check if this line has a separator + TInt sepPos = aLineArray->MdcaPoint(i).Find(KSettingItemSeparator); + if (sepPos > 0) + { + // check that the element matches + if (aLineArray->MdcaPoint(i).Left(sepPos).CompareF(aAttribute) == 0) + { + // get the value + aValue.Copy(aLineArray->MdcaPoint(i).Right(aLineArray->MdcaPoint(i).Length()-sepPos-1)); + break; + } + } + } + } + +void CProfiler::DoGetValueFromSettingsArray(CDesC8ArrayFlat* aLineArray, const TDesC8& aAttribute, TInt& aValue) + { + LOGTEXT(_L("CProfiler::DoGetValueFromSettingsFile()")); + _LIT8(KSettingItemSeparator, "="); + + // read a line of given array + for (TInt i=0; i<aLineArray->MdcaCount(); i++) + { + // check if this line has a separator + TInt sepPos = aLineArray->MdcaPoint(i).Find(KSettingItemSeparator); + if (sepPos > 0) + { + // check that the element matches + if (aLineArray->MdcaPoint(i).Left(sepPos).CompareF(aAttribute) == 0) + { + // get the value + TLex8 parser(aLineArray->MdcaPoint(i).Right(aLineArray->MdcaPoint(i).Length()-sepPos-1)); + parser.Val(aValue); + break; + } + } + } + } + +// -------------------------------------------------------------------------------------------- +TInt CProfiler::GetSamplerAttributesL(const RMessage2& aMessage) + { + TInt err(KErrNone); + TInt pos(0); + + // get sampler count + TInt count(iDefaultSamplerAttributesArray->Count()); + + // write each of the default sampler plugin setting attributes over client-server session + for (TInt i(0); i<count; ++i) + { + TSamplerAttributes attr = iDefaultSamplerAttributesArray->At(i); + TPckgC<TSamplerAttributes> attrPckg(attr); + + // write a TSamplerAttributes container at a time + aMessage.WriteL(0, attrPckg, pos); + pos += attrPckg.Length(); + } + + aMessage.Complete(err); + return err; + } + +// -------------------------------------------------------------------------------------------- +TInt CProfiler::SetSamplerAttributesL(const RMessage2& aMessage) + { + TSamplerAttributes attr; + TPckg<TSamplerAttributes> inAttr(attr); + + TInt err = aMessage.Read(0, inAttr, 0); + + // apply the changes directly to a plugin + iSamplerHandler->SetSamplerSettingsL(attr.iUid, attr); + + aMessage.Complete(err); + return err; + } + +// -------------------------------------------------------------------------------------------- +TInt CProfiler::GetGeneralAttributesL(const RMessage2& aMessage) + { + TPckgBuf<TGeneralAttributes> generalSettings( iGeneralAttributes ); + + // write general attributes over client-server session + TInt err = aMessage.Write(0, generalSettings); + + aMessage.Complete(err); + return err; + } + +// -------------------------------------------------------------------------------------------- +TInt CProfiler::SetGeneralAttributesL(const RMessage2& aMessage) + { + // read the general settings from message + TGeneralAttributes attr; + TPckg<TGeneralAttributes> inPckg(attr); + TInt err = aMessage.Read(0, inPckg, 0); + + // copy to the general attributes + iGeneralAttributes.iSaveFileDrive.Copy(attr.iSaveFileDrive); + iGeneralAttributes.iTraceFilePrefix.Copy(attr.iTraceFilePrefix); + iGeneralAttributes.iTraceOutput.Copy(attr.iTraceOutput); + iGeneralAttributes.iTimedSamplingPeriod = attr.iTimedSamplingPeriod; + + aMessage.Complete(err); + return err; + } + +TInt CProfiler::GetSamplerAttributeCountL(const RMessage2& aMessage) + { + // get the plugin array count and wrap it to TPckgBuf<> + TPckgBuf<TInt> attributeCount(iDefaultSamplerAttributesArray->Count()); + + // write general attributes over client-server session + TInt err = aMessage.Write(0, attributeCount); + + aMessage.Complete(err); + return err; + } + +TInt CProfiler::RefreshStatus(const RMessage2& aMessage) + { + TInt err(KErrNone); + + // update profiler status for requester + iEngineStatus.Set(iState); + + aMessage.Complete(err); + return err; + } + +// -------------------------------------------------------------------------------------------- +TInt CProfiler::LoadSettingsL(/*const TDesC& configFile*/) + { + RFs fileServer; + RFile file; + TInt err(KErrNone); + + // connect to file server + err = fileServer.Connect(); + + // check if file server can be connected + if (err != KErrNone) + { + // file server couldn't be connected + return KErrGeneral; + } + + // check if settings file location length reasonable + if ( iSettingsFileLocation.CompareF(KNullDesC) == 0 ) + { + // open the file with the default path and name + TBuf<256> pathAndName; + pathAndName.Append(PathInfo::PhoneMemoryRootPath()); + pathAndName.Append(KProfilerSettingsFileName); + iSettingsFileLocation.Copy(pathAndName); + LOGTEXT(_L("CProfiler::LoadSettings - Opening settings file with name (with the default path)")); + LOGTEXT(pathAndName); + } + + // open the file with the given path and name + err = file.Open(fileServer,iSettingsFileLocation,EFileRead); + + + // check if RFile::Open() returned error + if (err != KErrNone) + { + // file couldn't be opened + LOGTEXT(_L("CProfiler::LoadSettings - Failed to open settings, using default")); + + // check if settings already loaded + if(iDefaultSamplerAttributesArray->Count() > 0) + { + // reset default settings array + iDefaultSamplerAttributesArray->Reset(); + } + + // load default settings, instead of settings file ones + iSamplerHandler->GetSamplerAttributesL(iDefaultSamplerAttributesArray); + + fileServer.Close(); + return KErrNone; + } + + // initialize iSavedLineArray, initial settings file lines 64 + if(iSavedLineArray) + { + iSavedLineArray->Reset(); + } + else + { + iSavedLineArray = new (ELeave) CDesC8ArrayFlat(KSavedLineCount); + } + + iSavedLinesCount = KSavedLineCount; + + // get size of the file + TInt fileSize(0); + err = file.Size(fileSize); + // check if an error occurred reading the file size + if(err != KErrNone) + { + return KErrGeneral; // could not find the size + } + + // sanity check for the file size + if (fileSize < 3 || fileSize > 20000) + { + fileSize = KSettingsFileSize; + return KErrNotSupported; + } + + // read the contents of the file to buffer. + iSettingsBuffer.Zero(); + file.Read(iSettingsBuffer, fileSize); + file.Close(); + fileServer.Close(); + LOGSTRING2("CProfiler::LoadSettings: read %d bytes",iSettingsBuffer.Length()); + + // append end mark "[end]" + iSettingsBuffer.Append(KEndMark); + // force an ending newline + iSettingsBuffer.Append('\n'); + + // next fill the saved settings array (CDesC8ArrayFlat) for further comparison with changes and default values + TBuf8<384> tmpBuf; + TInt lineCount(0); + TBool commentFound(EFalse); + for (TInt i(0); i<iSettingsBuffer.Length(); i++) // loop all chars + { + // if new line char found, create a new text line + if (iSettingsBuffer[i]=='\r' || iSettingsBuffer[i]=='\n') + { + // check if collected string has reasonable length + if (tmpBuf.Length() > 0) + { + // remove extra spaces + tmpBuf.TrimAll(); + // check if the size of the array too small + if(lineCount >= iSavedLinesCount) + { + iSavedLineArray->ExpandL(20); // expand by 20 lines + iSavedLinesCount += 20; + } + iSavedLineArray->AppendL(tmpBuf); + tmpBuf.Copy(KNullDesC8); + lineCount++; + } + commentFound = EFalse; + } + // check if comment mark ';' is found on the line, skip the rest of the line + else if(iSettingsBuffer[i]==';') + { + commentFound = ETrue; + } + // otherwise append a char to the temp line buffer if it is a wanted ASCII char + else if (iSettingsBuffer[i]>=32 && iSettingsBuffer[i]<=127 && !commentFound) + { + tmpBuf.Append(iSettingsBuffer[i]); + } + } + + // empty tmpBuf + tmpBuf.Copy(KNullDesC8); + // check settings file version + DoGetValueFromSettingsArray(iSavedLineArray, KProfilerVersionTag, tmpBuf); + + TBuf8<32> version; + version.Copy(PROFILER_VERSION_SHORT); + + // check if settings file version is + if(tmpBuf.CompareF(version) >= 0) + { + // update general attributes + UpdateSavedGeneralAttributes(iSavedLineArray); + + // update settings to sampler plugins and save the attributes to default array + iSamplerHandler->UpdateSavedSamplerAttributesL(iSavedLineArray, iDefaultSamplerAttributesArray); + } + else + { + // check if settings already loaded + if(iDefaultSamplerAttributesArray) + { + // reset default settings array + iDefaultSamplerAttributesArray->Reset(); + + // get the default settings if settings file version too old + iSamplerHandler->GetSamplerAttributesL(iDefaultSamplerAttributesArray); + } + } + + return err; + } + +// -------------------------------------------------------------------------------------------- +void CProfiler::UpdateSavedGeneralAttributes(CDesC8ArrayFlat* aSavedAttributes) + { + // get saved general settings + DoGetValueFromSettingsArray(aSavedAttributes, KGenericTraceOutput, iGeneralAttributes.iTraceOutput); + DoGetValueFromSettingsArray(aSavedAttributes, KGenericTraceFilePrefix, iGeneralAttributes.iTraceFilePrefix); + DoGetValueFromSettingsArray(aSavedAttributes, KGenericTraceFileSaveDrive, iGeneralAttributes.iSaveFileDrive); + DoGetValueFromSettingsArray(aSavedAttributes, KGenericTimedProfilingPeriod, iGeneralAttributes.iTimedSamplingPeriod); + } + +TBool CProfiler::CheckLocationSanity(RFs& fs, const TDesC8& aLocation) + { + TBool ret(EFalse); + TBool noDiskSpace(EFalse); + TBuf<32> drive; + + CnvUtfConverter::ConvertToUnicodeFromUtf8(drive, aLocation); + TDriveUnit driveUnit = TDriveUnit(drive); + + // check that the root folder is correct + if (drive.Length() > 2 && BaflUtils::CheckFolder(fs, drive.Left(3)) == KErrNone) + { + // test available disk space + TRAP_IGNORE((noDiskSpace = SysUtil::DiskSpaceBelowCriticalLevelL(&fs, 0, driveUnit))); + if(!noDiskSpace) + ret = ETrue; + } + + return ret; + } + +TInt CProfiler::HandleGeneralSettingsChange() + { + // local literals + _LIT8(KBackSlash, "\\"); + _LIT8(KTraceFileExtension, ".dat"); + + TBuf8<KFileNameBufSize> fileNameBuf; + TBuf8<10> number; + TInt result(0); + TInt index(1); + TInt hashLocation(0); + TParse parse; + + // check if plugin writer changed + if(iGeneralAttributes.iTraceOutput.CompareF(KOutputToDebugOutput) == 0) + { + iWriterHandler->SetPluginActive( KDebOutWriterPluginUid, EWriterPluginEnabled ); + } + else + { + RFs fileServer; + RFile file; + + // connect to the file server + result = fileServer.Connect(); + if(result == KErrNone) + { + // disk writer plugin will be activated + iWriterHandler->SetPluginActive( KDiskWriterPluginUid, EWriterPluginEnabled ); + + // fix the trace data file location as well + iTotalPrefix.Zero(); + iTotalPrefix.Append(iGeneralAttributes.iSaveFileDrive); + + // check that trace file location sane + if(!CProfiler::CheckLocationSanity(fileServer, iTotalPrefix)) + { + fileServer.Close(); + return KErrPathNotFound; + } + + // remove extra spaces + iTotalPrefix.TrimAll(); + + // check the directory contains a trailing backlash + if(iTotalPrefix.Right(1) != _L8("\\") && + iTotalPrefix.Right(1) != _L8("/")) + { + // append backslash to end + iTotalPrefix.Append(KBackSlash); + } + + // append trace file name prefix e.g. PIProfiler_# + iTotalPrefix.Append(iGeneralAttributes.iTraceFilePrefix); + + // locate '#' mark for finding the next free trace file name, e.g. E:\data\PIProfiler_4.dat + hashLocation = iTotalPrefix.Locate('#'); + if( hashLocation == KErrNotFound ) + { + // append simply at the end of the trace file prefix, no need to inform user + iTotalPrefix.Append('#'); + // get new hash mark location + hashLocation = iTotalPrefix.Locate('#'); + } + + // add the file extension + iTotalPrefix.Append(KTraceFileExtension); + + // search for files with different indices + // until a free filename is found + while(result != KErrNotFound) + { + fileNameBuf.Zero(); + // start with the original prefix + fileNameBuf.Append(iTotalPrefix); + // convert the number to a descriptor + number.Num(index); + // replace the hashmark with the real number + fileNameBuf.Replace(hashLocation,1,number); + + // make a copy to the iFileNameStream descriptor + iFileNameStream.Zero(); + CnvUtfConverter::ConvertToUnicodeFromUtf8(iFileNameStream, fileNameBuf); + + LOGSTRING2("CProfiler::HandleGeneralSettingsChange() - trying to open files %S ",&iFileNameStream); + + if((result = parse.Set(iFileNameStream, NULL, NULL)) != KErrNone) + { + // break loop if fails, problems in file name => change to log into debug output + break; + } + + // create directory for trace files if not exists + result = fileServer.MkDirAll(parse.FullName()); + + // check that file server responded with KErrNone or KErrAlreadyExists + if( result != KErrNone && result != KErrAlreadyExists) + { + // if some other result, e.g. memory full => break + break; + } + + // attempt opening the file + result = file.Open(fileServer,parse.FullName(),EFileShareReadersOnly); + if(result != KErrNotFound) + { + if( result != KErrNotReady && + result != KErrServerBusy ) + { + // close the file if it could be opened + LOGSTRING2("Found STREAM file with index %d",index); + index++; + } + else + { + // in boot measurements the file system might not be ready yet. + LOGSTRING2("Problem in opening STREAM file %d",index); + } + file.Close(); + } + } // while + } + else + { + // return error code + return result; + } + + TUint32 id(iWriterHandler->GetActiveWriter()->GetWriterType()); + + // check if a file name is one that does not exist and selected plugin is disk writer + if(result == KErrNotFound && id == KDiskWriterPluginUid.iUid) + { + // write right trace data file name to disk writer plugin + iWriterHandler->SetPluginSettings( KDiskWriterPluginUid, iFileNameStream ); + } + else + { + // return error if could not create trace log file + return result; + } + // close file server + fileServer.Close(); + } // if output == KOutputToDebugOutput + return KErrNone; + } + +// -------------------------------------------------------------------------------------------- +void CProfiler::HandleTimerExpiresL(TInt aError) + { + LOGSTRING2("CProfiler::HandleTimerExpiresL - Error: %d", aError); + this->ControlL(RProfiler::EStopSampling); + if( CPServer::iClientCount <= 0 ) + { + LOGSTRING("CProfiler::HandleTimerExpiresL - No clients attached, shutting down server..."); + this->ControlL(RProfiler::EExitProfiler); + } + } + +// -------------------------------------------------------------------------------------------- +void CProfiler::SaveSettingsL() + { + LOGTEXT(_L("CProfiler::SaveSettings()")); + + // local literal + _LIT(KGeneralHeader, "[general]"); + _LIT(KVersionHeader, "version"); + _LIT8(KPIProfilerSettingsHeader, "; PI Profiler Settings File"); + _LIT8(KGeneralSettingsHeader, "; general settings"); + _LIT8(KOutputFileDescription,"; \"output_type=file_system\" writes *.dat file to external memory"); + _LIT8(KOutputDebugDescription,"; \"output_type=debug_output\" writes *.dat file to debug port"); + _LIT8(KOutputFilePrefixDescription,"; if writing to file, prefix of the *.dat file\r\n; first '#' in the prefix is replaced with an integer"); + _LIT8(KOutputSaveDriveDescription,"; if writing to file, the location to store the *.dat file"); + _LIT8(KTimedProfilingPeriod,"; period (in seconds) used when using timed profiling"); + + RFs fs; + RFile settingsFile; + TInt err(KErrNone); + TBuf8<384> line; + + // connect to file server + err = fs.Connect(); + if( err != KErrNone ) + { + // failed to write settings to settings file + return; + } + + // create and set the private path + fs.CreatePrivatePath(EDriveC); + fs.SetSessionToPrivate(EDriveC); + + // create the new settings file + err = settingsFile.Replace(fs, iSettingsFileLocation, EFileWrite); + if(err != KErrNone) + return; + + CleanupClosePushL(settingsFile); + + // write the header + line.Copy(KPIProfilerSettingsHeader); + line.Append(KNewLineSeparator); + line.Append(KNewLineSeparator); + settingsFile.Write(line); + + // write the header + line.Copy(KGeneralSettingsHeader); + line.Append(KNewLineSeparator); + settingsFile.Write(line); + + // write all generic settings + line.Copy(KGeneralHeader); + line.Append(KNewLineSeparator); + settingsFile.Write(line); + + // write version info + line.Copy(KVersionHeader); + line.Append(KEquals); + line.Append(PROFILER_VERSION_SHORT); + line.Append(KNewLineSeparator); + settingsFile.Write(line); + + // output explanation + line.Copy(KOutputFileDescription); + line.Append(KNewLineSeparator); + line.Append(KOutputDebugDescription); + line.Append(KNewLineSeparator); + settingsFile.Write(line); + + // write trace output + line.Copy(KGenericTraceOutput); + line.Append(KEquals); + line.Append(iGeneralAttributes.iTraceOutput); + line.Append(KNewLineSeparator); + settingsFile.Write(line); + + // file prefix explanation + line.Copy(KOutputFilePrefixDescription); + line.Append(KNewLineSeparator); + settingsFile.Write(line); + + // write trace file prefix + line.Copy(KGenericTraceFilePrefix); + line.Append(KEquals); + line.Append(iGeneralAttributes.iTraceFilePrefix); + line.Append(KNewLineSeparator); + settingsFile.Write(line); + + // file prefix explanation + line.Copy(KOutputSaveDriveDescription); + line.Append(KNewLineSeparator); + settingsFile.Write(line); + + // write trace file location + line.Copy(KGenericTraceFileSaveDrive); + line.Append(KEquals); + line.Append(iGeneralAttributes.iSaveFileDrive); + line.Append(KNewLineSeparator); + settingsFile.Write(line); + + // timed profiling period explanation + line.Copy(KTimedProfilingPeriod); + line.Append(KNewLineSeparator); + settingsFile.Write(line); + + // Write timed profiling period value + line.Copy(KGenericTimedProfilingPeriod); + line.Append(KEquals); + TBuf<16> tmpNum; + tmpNum.AppendNum(iGeneralAttributes.iTimedSamplingPeriod); + line.Append(tmpNum); + line.Append(KNewLineSeparator); + settingsFile.Write(line); + + // reset the default attributes array + iDefaultSamplerAttributesArray->Reset(); + + // update the latest changes from plugins + iSamplerHandler->GetSamplerAttributesL(iDefaultSamplerAttributesArray); + + // call CSamplerController to write all sampler settings + iSamplerHandler->ComposeAttributesToSettingsFileFormat(settingsFile, iDefaultSamplerAttributesArray); + + CleanupStack::PopAndDestroy(); //settingsFile + // close file + fs.Close(); + } + +TInt CProfiler::CheckOldProfilerRunning() + { + TFindProcess procName; + procName.Find(_L("BappeaProf.exe*")); + TFullName aResult; + TInt err(KErrNone); + RProcess proc; + + // now check if old Profiler is still running on + err = procName.Next(aResult); + // check if old profiler process found + if(err == KErrNone) + { + // other process found, i.e. right process to communicate with, in case started from eshell + err = proc.Open(procName); + if(err == KErrNone) + { + if(proc.ExitCategory().Length() > 0) + { + proc.Close(); + // process already exited => create a new one + return KErrNotFound; + } + proc.Close(); + } + // return error for error handling + return KErrAlreadyExists; + } + return err; + } + +// -------------------------------------------------------------------------------------------- +void CProfiler::HandleError(TInt aErr) + { + // write error to status property to inform requester + TInt err(iEngineStatus.Set(KEngineStatusPropertyCat, EProfilerEngineStatus, aErr)); + if(err != KErrNone) + RDebug::Print(_L("CProfiler::HandleError() - error setting status: %d"), err); + } + +// -------------------------------------------------------------------------------------------- +TInt CProfiler::ControlDataL(TInt aCommand,TAny* value1,TAny* /*value2*/) + { + LOGSTRING3("CProfiler::ControlData %d, 0x%x",aCommand,value1); + + _LIT(KDebugOutput, "debug_output"); + _LIT(KFileOutput, "file_system"); + _LIT8(KOutputToDebugOutput, "debug_output"); + + TDes* desc; + TPtrC ptrDesc; + + switch(aCommand) + { + // new controls + case RProfiler::EGetFileName: + { + LOGTEXT(_L("Profiler::EGetFileName - start")); + LOGSTRING2("Profiler::EGetFileName - total file name is: %S",(TDes*)value1); + desc = (TDes*)value1; + desc->Zero(); + desc->Append(iFileNameStream); + LOGSTRING2("Profiler::EGetFileName - now total file name is: %S",(TDes*)value1); + return KErrNone; + } + case RProfiler::EGetActiveWriter: + { + LOGTEXT(_L("Profiler::EGetActiveWriter - start")); + desc = (TDes*)value1; + desc->Zero(); + if(iGeneralAttributes.iTraceOutput.CompareF(KOutputToDebugOutput) == 0) + { + desc->Append(KDebugOutput); + } + else + { + desc->Append(KFileOutput); + } + return KErrNone; + } + } + + return KErrNone; + } + +// -------------------------------------------------------------------------------------------- +TInt CProfiler::ControlL(TInt aCommand) + { + LOGSTRING2("CProfiler::Control - Controlling ProfilerEngine %d",aCommand); + TInt err(KErrNone); + + switch (aCommand) + { + case RProfiler::EStartSampling: + case RProfiler::EStartTimedSampling: + { + // check first if old Profiler already running + err = CheckOldProfilerRunning(); + if(err == KErrAlreadyExists) + { + // if exists do not start a profiling process since corrupts the collected trace data + HandleError(err); + err = KErrNone; + return err; + } + + // save settings before launching the profiler + // reason: the profiling may have set to the background => need for get right settings + SaveSettingsL(); + + // set the general settings to writer plugins to reflect the latest changes + err = HandleGeneralSettingsChange(); + if(err == KErrNone) + { + // reset the buffers before new profiling + iUserStream->ResetBuffers(); + + // give the CProfilerSampleStream a handle to current writer + iUserStream->SetWriter(*iWriterHandler->GetActiveWriter()); + + // set initially debug output writer active + err = iWriterHandler->StartSelectedPlugin(); + + // check that writer plugin started + if(err != KErrNone) + { + // if not started handle error + HandleError(err); + } + else + { + // start activated sampler plug-in, NOTE: plugins check if errors occur in startup for some reason + iSamplerHandler->StartSamplerPluginsL(); + + // set engine state P&S property to running, e.g. for PIProfiler UI to read + iState = RProfiler::ERunning; + + // set the engine into running mode + iEngineStatus.Set(iState); + } + } + else + { + // handle error and notify requester + HandleError(err); + } + + if( aCommand == RProfiler::EStartTimedSampling ) + { + iTimer->After(iGeneralAttributes.iTimedSamplingPeriod); + LOGTEXT(_L("CProfiler::Control - Finished processing EStartTimedSampling!")); + } + else + { + LOGTEXT(_L("CProfiler::Control - Finished processing EStartSampling!")); + } + + return err; + } + case RProfiler::EStopSampling: + LOGTEXT(_L("CProfiler::Control - Starting to stop sampling...")); + // stop sampler plugins + if(iState == RProfiler::ERunning) + { + iState = RProfiler::EStopping; + iEngineStatus.Set(RProfiler::EStopping); + + iSamplerHandler->StopSamplerPlugins(); + + // finalize the filled buffer writing + iUserStream->Finalise(); + + // stop output plugin and write the rest of the trace data to output + LOGTEXT(_L("CProfiler::Control - stopping writer")); + iWriterHandler->StopSelectedPlugin(); + + // set engine state P&S property idle + iState = RProfiler::EIdle; + iEngineStatus.Set(RProfiler::EIdle); + + LOGSTRING2("CProfiler::Control - sampling stopped, going to state %d", RProfiler::EIdle); + } + return KErrNone; + + case RProfiler::EExitProfiler: + { + // save settings into settings file when exiting + SaveSettingsL(); + + if(iUserStream) + { + delete iUserStream; + iUserStream = NULL; + } + + // set engine state P&S property idle + iState = RProfiler::EIdle; + iEngineStatus.Set(RProfiler::EIdle); + + LOGTEXT(_L("Stopping Activer Scheduler")); + CActiveScheduler::Stop(); + LOGTEXT(_L("Stopped Activer Scheduler")); + + return KErrNone; + } + + case RProfiler::EAttachClient: + { + // Increase client reference count + ++CPServer::iClientCount; + LOGSTRING2("Increased client reference count to: %d", CPServer::iClientCount); + return KErrNone; + } + case RProfiler::ERemoveClient: + { + // Decrease client reference count + --CPServer::iClientCount; + LOGSTRING2("Decreasing client reference count to: %d", CPServer::iClientCount); + return KErrNone; + } + } + + LOGTEXT(_L("CProfiler::Control - returning")); + + return err; + } + +// -------------------------------------------------------------------------------------------- +void CProfiler::Finalise() + { + LOGTEXT(_L("CProfiler::Finalise - Finished processing EStopSampling!")); + } + +// -------------------------------------------------------------------------------------------- +RProfiler::TSamplerState CProfiler::State() const + { + return iState; + } + +/* + * + * Class CPServer definition + * + */ +// -------------------------------------------------------------------------------------------- +inline const CPServer& CPSession::Server() const + { + return *static_cast<const CPServer*>(CSession2::Server()); + } + +// -------------------------------------------------------------------------------------------- +void CPSession::ServiceL(const RMessage2& aMessage) + { + LOGTEXT(_L("CPSession::ServiceL - Starting to process message")); + TInt err(KErrNone); + + if(aMessage.Function() == RProfiler::EGetGeneralAttributes) + { + Server().GetGeneralAttributesL(aMessage); + } + else if(aMessage.Function() == RProfiler::ESetGeneralAttributes) + { + Server().SetGeneralAttributesL(aMessage); + } + else if(aMessage.Function() == RProfiler::EGetSamplerAttributes) + { + Server().GetSamplerAttributesL(aMessage); + } + else if(aMessage.Function() == RProfiler::EGetSamplerAttributeCount) + { + Server().GetSamplerAttributeCountL(aMessage); + } + else if(aMessage.Function() == RProfiler::ESetSamplerAttributes) + { + Server().SetSamplerAttributesL(aMessage); + } + else if(aMessage.Function() == RProfiler::ERefreshProfilerStatus) + { + Server().RefreshStatus(aMessage); + } + else if(aMessage.Ptr0() == 0 && aMessage.Ptr1() == 0 && aMessage.Ptr2() == 0) + { + LOGTEXT(_L("Ptr0 && Ptr1 == 0 && Ptr2 == 0")); + aMessage.Complete(Server().ControlL(RProfiler::TCommand(aMessage.Function()))); + LOGTEXT(_L("CPSession::ServiceL - Message completed")); + } + else if(aMessage.Ptr0() != 0 && aMessage.Ptr1() != 0 && aMessage.Ptr2() != 0) + { + LOGTEXT(_L("Error with message, all pointers contain data!")); + } + + else if (aMessage.Ptr0() != 0) + { + if(aMessage.Ptr1() == 0) + { + LOGTEXT(_L("ServiceL: Ptr0 != 0 && Ptr1 == 0")); + // provided value is a descriptor + TBuf<64>* dst = new TBuf<64>; + aMessage.ReadL(0,*dst,0); + + err = Server().ControlDataL(aMessage.Function(),(TAny*)dst); + delete dst; + aMessage.Complete(err); + LOGTEXT(_L("CPSession::ServiceL - Message completed")); + } + else + { + LOGTEXT(_L("ServiceL: Ptr0 != 0 && Ptr1 != 0")); + // provided value is a descriptor + TBuf<64>* dst = new TBuf<64>; + aMessage.ReadL(0,*dst,0); + + TUint32 num1 = (TUint32)aMessage.Ptr1(); + + err = Server().ControlDataL(aMessage.Function(),(TAny*)dst, (TAny*)num1); + delete dst; + aMessage.Complete(err); + LOGTEXT(_L("CPSession::ServiceL - Message completed")); + } + } + else if (aMessage.Ptr1() != 0) + { + LOGTEXT(_L("ServiceL: Ptr1 != 0")); + // provided value is a TUint32 + if( ((TUint32)aMessage.Ptr3()) == 0xffffffff) + { + TUint32 num = (TUint32)aMessage.Ptr1(); + err = Server().ControlDataL(aMessage.Function(),(TAny*)num); + aMessage.Complete(err); + LOGTEXT(_L("CPSession::ServiceL - Message completed")); + } + else + { + LOGTEXT(_L("ServiceL: Ptr3 != 0xffffffff")); + TUint32 num1 = (TUint32)aMessage.Ptr1(); + TUint32 num2 = (TUint32)aMessage.Ptr3(); + err = Server().ControlDataL(aMessage.Function(),(TAny*)num1,(TAny*)num2); + aMessage.Complete(err); + LOGTEXT(_L("CPSession::ServiceL - Message completed")); + } + } + else if (aMessage.Ptr2() != 0) + { + // command requests for data, provided + // value should be a descriptor + if( ((TUint32)aMessage.Ptr3()) == 0xffffffff) + { + LOGTEXT(_L("ServiceL: Ptr2 != 0 && Ptr3 == 0xffffffff")); + + TBuf<256>* src = new TBuf<256>; + src->Zero(); + err = Server().ControlDataL(aMessage.Function(),(TAny*)src); + + LOGSTRING2("Got sampler data %S",src); + + aMessage.WriteL(2, *src, 0); + + delete src; + aMessage.Complete(err); + LOGTEXT(_L("CPSession::ServiceL - Message completed")); + } + else + { + LOGTEXT(_L("ServiceL: Ptr2 != 0 && Ptr3 != 0xffffffff")); + + TUint32 num1 = (TUint32)aMessage.Ptr2(); // containing id + TBuf<256>* buffer = new TBuf<256>; // Text data, e.g. plug-in name or description + + LOGSTRING3("Getting data for sampler: 0x%X, buffer max len %d",num1, aMessage.GetDesMaxLength(3)); + + err = Server().ControlDataL(aMessage.Function(), (TAny*)num1, (TAny*)buffer); + + LOGSTRING2("Got sampler data %S",&buffer); + + // write back to same parameter + aMessage.WriteL(3, *buffer, 0); + + delete buffer; + aMessage.Complete(err); + LOGTEXT(_L("CPSession::ServiceL - Message completed")); + } + } + LOGTEXT(_L("CPSession::ServiceL - Message processed")); + } + +// -------------------------------------------------------------------------------------------- +MProfilerController* CPServer::NewL(TInt aPriority, MProfilerEngine& aEngine) + { + LOGTEXT(_L("CPServer::NewL - Enter")); + CPServer* self = new(ELeave) CPServer(aPriority, aEngine); + CleanupStack::PushL(self); + self->StartL(KProfilerName); + CleanupStack::Pop(); + LOGTEXT(_L("CPSession::NewL - Exit")); + return self; + } + +// -------------------------------------------------------------------------------------------- +CPServer::CPServer(TInt aPriority, MProfilerEngine& aEngine) + : CServer2(aPriority), MProfilerController(aEngine) + { + + } + +// -------------------------------------------------------------------------------------------- +void CPServer::Release() + { + delete this; + } + +// -------------------------------------------------------------------------------------------- +CSession2* CPServer::NewSessionL(const TVersion&,const RMessage2&) const + { + return new(ELeave) CPSession(); + } + +/* + * + * Static methods for controlling the profiler + * through command line + * + */ +// -------------------------------------------------------------------------------------------- +static void RunEngineServerL(const TDesC& aSettingsFile) + { + RDebug::Print(_L("Profiler: RunEngineServerL() - Install active scheduler")); + CActiveScheduler* pS = new CActiveScheduler; + CActiveScheduler::Install(pS); + CProfiler* p = CProfiler::NewLC(aSettingsFile); + CActiveScheduler::Start(); + p->Finalise(); + CleanupStack::PopAndDestroy(p); + delete pS; + } + +// -------------------------------------------------------------------------------------------- +static TInt TestSettingsFile(const TDesC& configFile) + { + RFs fs; + LOGSTRING2("TestSettingsFile: entry %S", &configFile); + // check if file server can be connected + if (fs.Connect() != KErrNone) + { + LOGTEXT(_L("TestSettingsFile: could not connect file server")); + // file server couldn't be connected, return false + return KErrNotFound; + } + + // check if config file name length is > 0 + if (configFile.Length() > 0) + { + LOGTEXT(_L("TestSettingsFile: checking location sanity")); + // check sanity of settings file location + if(BaflUtils::CheckFolder(fs, configFile) != KErrNone) + { + LOGTEXT(_L("TestSettingsFile: location sanity check failed")); + fs.Close(); + return KErrGeneral; + } + } + else + { + // configFile length 0, return false + LOGTEXT(_L("TestSettingsFile: config file string null length")); + fs.Close(); + return KErrNotFound; + } + // return true if tests passed + LOGTEXT(_L("TestSettingsFile: exiting...")); + fs.Close(); + return KErrNone; + } + +// -------------------------------------------------------------------------------------------- +GLDEF_C TInt E32Main() + { + // parse command line arguments + TBuf<256> c; + TInt err(KErrNone); + + // copy the full command line with arguments into a buffer + User::CommandLine(c); + + TBuf<256> fileName; + fileName.Append(c); // only one settings param should be + LOGSTRING3("Filename is %S, response %d 1", &fileName, err); + err = TestSettingsFile(fileName); + if(err != KErrNone) + { + LOGSTRING3("Filename is %S, response %d 2", &fileName, err); + // settings file does not exist, copy null desc to file name + fileName.Copy(KNullDesC); + } + + LOGSTRING3("Filename is %S, response %d 3", &fileName, err); + + // if no command line arguments found just start the profiler process + __UHEAP_MARK; + CTrapCleanup* cleanup = CTrapCleanup::New(); + TInt ret(KErrNoMemory); + if( cleanup ) + { + TRAPD( ret, RunEngineServerL(fileName) ); + RDebug::Print(_L("Profiler: E32Main() - ret %d"), ret); + delete cleanup; + } + __UHEAP_MARKEND; + + return ret; + } + + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/src/ProfilerErrorChecker.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/src/ProfilerErrorChecker.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,115 @@ +/* +* 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: +* +*/ + + +#include <e32std.h> +#include <e32base.h> +#include <e32property.h> + +#include <piprofiler/ProfilerTraces.h> + +#include "ProfilerErrorChecker.h" + +// properties +const TUid KEngineStatusPropertyCat={0x2001E5AD}; +enum TEnginePropertyKeys + { + EProfilerEngineStatus = 8, + EProfilerErrorStatus + }; + +/* + * + * CProfilerErrorChecker class implementation + * + */ +CProfilerErrorChecker* CProfilerErrorChecker::NewL() + { + CProfilerErrorChecker* self = new(ELeave) CProfilerErrorChecker; + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +// -------------------------------------------------------------------------------------------- +CProfilerErrorChecker::CProfilerErrorChecker() : + CActive(EPriorityStandard) + { + } + +CProfilerErrorChecker::~CProfilerErrorChecker() + { + Cancel(); + iErrorStatus.Close(); + } + +// -------------------------------------------------------------------------------------------- +void CProfilerErrorChecker::ConstructL() + { + + LOGTEXT(_L("Trying to attach to profiler engine error status property")); + User::LeaveIfError(iErrorStatus.Attach(KEngineStatusPropertyCat, EProfilerErrorStatus)); + CActiveScheduler::Add(this); + + // subscribe to P&S status property + iErrorStatus.Subscribe(iStatus); + SetActive(); + } + +// -------------------------------------------------------------------------------------------- +void CProfilerErrorChecker::SetObserver(MProfilerErrorObserver* aObserver) + { + iObserver = aObserver; + } + +// -------------------------------------------------------------------------------------------- +TInt CProfilerErrorChecker::RunError(TInt aError) + { + iErrorStatus.Close(); + return aError; + } +// -------------------------------------------------------------------------------------------- +void CProfilerErrorChecker::RunL() + { + // resubscribe before processing new value to prevent missing updates + iErrorStatus.Subscribe(iStatus); + SetActive(); + + TInt stat(0); + if(iErrorStatus.Get(stat) != KErrNone) + { + // check if error status != KErrNone + if(stat != 0) + { + iObserver->HandleProfilerErrorChangeL(stat); + } + + // reset error code + iErrorStatus.Set(KErrNone); + } + } + +// -------------------------------------------------------------------------------------------- + +void CProfilerErrorChecker::DoCancel() + { + iErrorStatus.Cancel(); + } + +// end of file + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/src/ProfilerEshell.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/src/ProfilerEshell.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,440 @@ +/* +* 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: +* +*/ + +#include <f32file.h> +#include <e32cons.h> + +#include "ProfilerEshell.h" +#include <piprofiler/ProfilerSession.h> + + + +_LIT(KProfilerEngineExe, "PIProfilerEngine.exe"); + +/* + * + * Static methods for controlling the profiler + * through command line + * + */ +// -------------------------------------------------------------------------------------------- +static void PrintUsageInfo(const TDesC& aAdditionalInfo) + { + _LIT(KConsoleName, "Console"); + _LIT(KLegalNote, "PIProfiler Version 2.2.0.2 Copyright @ 2009 Nokia\n"); + _LIT(KUsageNote, "Usage: PIProfiler [start/end/timed] settingsfile [time to run]\n"); + _LIT(KExample, "Example: PIProfiler timed C:\\data\\piprofilersettings.txt 60\n"); + + TRAP_IGNORE(CConsoleBase* console = Console::NewL(KConsoleName,TSize(KConsFullScreen,KConsFullScreen)); + console->Printf(KLegalNote); + console->Printf(KUsageNote); + console->Printf(KExample); + console->Write(aAdditionalInfo); + + console->Printf(_L("\n[Press any key]")); + console->Getch(); + delete console;); + } + +// -------------------------------------------------------------------------------------------- +static TInt FindProcess() + { + TFindProcess procName; + procName.Find(_L("PIProfilerEngine.exe*")); + TFullName aResult; + + // find the first appearance, i.e. "myself"... + TInt err(procName.Next(aResult)); // the first appearance + if(err == KErrNotFound) + { + // now check if old Profiler is still running on + procName.Find(_L("BappeaProf.exe*")); + err = procName.Next(aResult); + // check if old profiler process found + if(err == KErrNone) + { + // return error for error handling + return KErrAlreadyExists; + } + // return KErrNotFound and a new profiler engine process can be started + return KErrNotFound; + } + return err; + } + +/** + * Function for starting profiler engine in the background, + * call profiler to load settings + * and start sampling process + * + * @param configFile name and location of settings file + * @param aRunTimeInSeconds run time in seconds + * @param aBootTime run boot time sampling or not. + */ +// -------------------------------------------------------------------------------------------- +static TInt StartProfilerProcess(const TDesC& configFile, TInt aRunTimeInSeconds, TBool aBootTime) + { + TInt err(KErrNone); + RProcess proc; + TRequestStatus status = KRequestPending; + TBuf<256> conf; + conf.Zero(); + conf.Append(configFile); + if(aBootTime) + { + RDebug::Printf("boot time measurement"); + conf.Append(_L(" ")); + conf.Append(_L("boot")); + } + RDebug::RawPrint(conf); + // check if process exists + err = FindProcess(); + LOGSTRING2("PIProfiler: tried to find process, response %d", err); + + // check if already exists and don't start a new eshell profiling + if( err == KErrNotFound ) + { + // try create new process + err = proc.Create(KProfilerEngineExe, conf); + + LOGSTRING2("PIProfiler: created process, response %d", err); + + // check if RProcess::Create() succeeded + if( err == KErrNone ) + { + // Trigger rendezvous on the supplied TRequestStatus object + proc.Rendezvous(status); + + // kick off the engine process + proc.Resume(); + + // wait for the constructor to complete + User::WaitForRequest(status); + + // just lose the handle + proc.Close(); + + // start sampling, using settings found in settings file or if not found the default settings + err = RProfiler::StartSampling(); + // check if command succesful + if( err != KErrNone ) + { + LOGSTRING2("PI Profiler start: err %d", err); + _LIT(KNoteProfilerCannotStart, "PI Profiler: cannot start PI Profiler, check settings!"); + PrintUsageInfo(KNoteProfilerCannotStart); + + // check if process still alive + if(err != KErrNotFound) + { + // exit the profiler process since process was started + RProfiler::ExitProfiler(); + } + return err; + } + + if(aRunTimeInSeconds > 0) + { + RDebug::Print(_L("Profiler running for %d s... "), aRunTimeInSeconds); + User::After(aRunTimeInSeconds*1000000); + RDebug::Print(_L("************* Profiler process closing *********")); + + // stop sampling process + err = RProfiler::StopSampling(); + // check if command succesfull + if( err != KErrNone ) + { + LOGTEXT(_L("Profiler: could not connect engine, stop failed")); + return err; + } + + // exit the profiler process + err = RProfiler::ExitProfiler(); + // check if command succesfull + if( err != KErrNone ) + { + LOGTEXT(_L("Profiler: could not connect engine, exit failed")); + return err; + } + } + } + else + { + _LIT(KNoteCannotFindProfiler, "PI Profiler: could not find PIProfilerEngine.exe"); + PrintUsageInfo(KNoteCannotFindProfiler); + } + } + // check if old Profiler is already running + else if( err == KErrAlreadyExists ) + { + _LIT(KNoteAlreadyRunning, "PI Profiler: old Profiler process already running, close it down before launching the new!"); + PrintUsageInfo(KNoteAlreadyRunning); + } + // otherwise show error note + else + { + _LIT(KNoteAlreadyRunning, "PI Profiler: already running, not able to launch new one. NOTE: check if UI running!"); + PrintUsageInfo(KNoteAlreadyRunning); + } + return KErrNone; + } + +// -------------------------------------------------------------------------------------------- +static TInt EndProfilerProcess() + { + LOGTEXT(_L("EndProfilerProcess() ...")); + + // call profiler to stop sampling + TInt err = RProfiler::StopSampling(); + + // check if command succesfull + if( err != KErrNone ) + { + LOGTEXT(_L("Profiler: could not connect engine, stop failed")); + return err; + } + + // exit the profiler process + err = RProfiler::ExitProfiler(); + // check if command succesfull + if( err != KErrNone ) + { + LOGTEXT(_L("Profiler: could not connect engine, exit failed")); + return err; + } + + return KErrNone; + } + +// -------------------------------------------------------------------------------------------- +static TInt TestSettingsFile(const TDesC& configFile) + { + RFs fs; + RFile file; + TInt err(KErrNone); + + // check if file server can be connected + if (fs.Connect() != KErrNone) + { + // file server couldn't be connected, return false + return KErrNotFound; + } + + // check if config file name length is > 0 + if (configFile.Length() > 0) + { + // open the file with the given path and name + err = file.Open(fs,configFile,EFileRead); + // check if file open was succesfull + if(err != KErrNone) + { + // return false if failed + fs.Close(); + return err; + } + + } + else + { + // configFile length 0, return false + fs.Close(); + return KErrNotFound; + } + // return true if tests passed + file.Close(); + fs.Close(); + return KErrNone; + } + +// -------------------------------------------------------------------------------------------- +static TInt ParseCommandAndExecute() + { + // commands literals for finding the right keyword + _LIT(KAutomatedTestStart,"start*"); + _LIT(KAutomatedTestEnd,"end*"); + _LIT(KAutomatedTestTimed,"timed*"); + _LIT(KBootMeasurement,"boot*"); + TBuf<256> c; + TInt match(KErrNotFound); + TInt bootmatch(KErrNotFound); + TBool myBoot=false; + // copy the full command line with arguments into a buffer + User::CommandLine(c); + LOGSTRING2("command: %S", &c); + + // try to match with each of the literals defined above + // (commands in atf format) + + // check if command is "start" + match = c.Match(KAutomatedTestStart); + if (match != KErrNotFound) + { + LOGTEXT(_L("Found keyword start")); + + TBuf<256> fileName; + fileName.Append(c.Right(c.Length()-6)); + LOGSTRING2("Filename is %S", &fileName); + if(TestSettingsFile(fileName) != KErrNone) + { + _LIT(KSettingsFileFailed, "False settings file"); + PrintUsageInfo(KSettingsFileFailed); + return -2; + } + // execute Profile process + if( StartProfilerProcess(fileName, 0, myBoot) == KErrNone ) + { + return -10; + } + return -2; + } + + // check if command is "end" + match = c.Match(KAutomatedTestEnd); + if (match != KErrNotFound) + { + LOGTEXT(_L("Found keyword end")); + + // stop the profiling process + EndProfilerProcess(); + return -10; + } + + // check if command is "timed" + match = c.Match(KAutomatedTestTimed); + // check if command is "boot" + bootmatch = c.Match(KBootMeasurement); + if ((match!= KErrNotFound) || (bootmatch != KErrNotFound)) + { + // command "timed" or " boot" found, need for finding settings file and run time next + if(bootmatch != KErrNotFound) + { + LOGTEXT(_L("Found keyword boot")); + myBoot = TRUE; + } + if(match != KErrNotFound) + { + LOGTEXT(_L("Found keyword timed")); + } + + TBuf<256> temp; + temp.Append(c); + TLex lex(temp); + + TBuf<256> fileName; + TInt seconds; + + // parse the first command line argument, the command itself + lex.Mark(); + lex.SkipCharacters(); + if(lex.TokenLength() != 0) + { + #ifdef PIPROFILER_PRINTS + TPtrC token = lex.MarkedToken(); + LOGSTRING2("Token 1 %S",&token); + #endif + } + else + { + LOGTEXT(_L("Problem 1 in parsing command line")); + _LIT(KSettingsFileFailed, "Failure: False argument"); + PrintUsageInfo(KSettingsFileFailed); + return -2; + } + + // parse the second command line argument, the settings file name + lex.SkipSpace(); + lex.Mark(); + lex.SkipCharacters(); + if(lex.TokenLength() != 0) + { + TPtrC token2 = lex.MarkedToken(); + LOGSTRING2("Token 2 %S",&token2); + fileName.Append(token2); + LOGSTRING2("Value of fileName is %S",&fileName); +// if(TestSettingsFile(fileName) != KErrNone) +// { +// _LIT(KSettingsFileFailed, "Failure: False settings file"); +// PrintUsageInfo(KSettingsFileFailed); +// return -2; +// } + } + else + { + LOGTEXT(_L("Problem 2 in parsing command line")); + _LIT(KSettingsFileFailed, "Failure: No settings file specified"); + PrintUsageInfo(KSettingsFileFailed); + return -2; + } + + // parse the third command line argument, the run time in seconds + lex.SkipSpace(); + lex.Mark(); + lex.SkipCharacters(); + if(lex.TokenLength() != 0) + { + // third token ok, try to convert into TInt value + TPtrC token3 = lex.MarkedToken(); + LOGSTRING2("Token 3 %S",&token3); + TLex num(token3); + TInt err = num.Val(seconds); + // check if given time value acceptable + if (err != KErrNone) + { + // value parsing failed, show info note to user + _LIT(KSecondsFailed, "Failure: False time value"); + PrintUsageInfo(KSecondsFailed); + return -2; + } + } + else + { + LOGTEXT(_L("Problem 3 in parsing command line")); + _LIT(KSecondsFailed, "Failure: False time value"); + PrintUsageInfo(KSecondsFailed); + return -2; + } + + LOGSTRING3("Filename is %S, seconds is %d", &fileName, seconds); + // execute Profile process + if( StartProfilerProcess(fileName, seconds, myBoot) == KErrNone ) + { + return -10; + } + return -2; + } + + // check if space character in the middle of command line string + if( c.LocateReverse(' ') != KErrNotFound) + { + _LIT(KWrongParameters, "Failure: Check command line parameters"); + PrintUsageInfo(KWrongParameters); + return -2; + } + + // return -1 if no command found + LOGTEXT(_L("No keyword found")); + return -1; + } + +// -------------------------------------------------------------------------------------------- +GLDEF_C TInt E32Main() + { + // parse command line arguments + ParseCommandAndExecute(); + + return KErrNone; + + } diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/src/ProfilerTimer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/src/ProfilerTimer.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,76 @@ +/* +* 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: +* +*/ + +#include "ProfilerTimer.h" + +/* + * + * CProfilerTimer class implementation + * + */ +// -------------------------------------------------------------------------------------------- +CProfilerTimer::CProfilerTimer(const TInt aPriority, MProfilerTimerObserver& aObserver) +: +CActive(aPriority), +iObserver(aObserver) + { + } + +// -------------------------------------------------------------------------------------------- +CProfilerTimer::~CProfilerTimer() + { + Cancel(); + iTimer.Close(); + } + +// -------------------------------------------------------------------------------------------- +CProfilerTimer* CProfilerTimer::NewL(const TInt aPriority, MProfilerTimerObserver& aObserver) + { + CProfilerTimer* self = new (ELeave) CProfilerTimer(aPriority, aObserver); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +// -------------------------------------------------------------------------------------------- +void CProfilerTimer::ConstructL(void) + { + CActiveScheduler::Add(this); + iTimer.CreateLocal(); + } + +// -------------------------------------------------------------------------------------------- +void CProfilerTimer::After(TUint aPeriodInSeconds) + { + Cancel(); + TTimeIntervalMicroSeconds32 period = aPeriodInSeconds * 1000000; + iTimer.After(iStatus, period); + SetActive(); + } + +// -------------------------------------------------------------------------------------------- +void CProfilerTimer::DoCancel() + { + iTimer.Cancel(); + } + +// -------------------------------------------------------------------------------------------- +void CProfilerTimer::RunL() + { + iObserver.HandleTimerExpiresL(iStatus.Int()); + } diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/src/SamplerController.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/src/SamplerController.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,500 @@ +/* +* 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: +* +*/ + + +#include "SamplerController.h" +//#include <piprofiler/EngineUIDs.h> + +// CONSTANTS +const TInt KMaxSamplerPluginCount = 20; +const TInt KMaxExtraSettingsItemCount = 6; + +// LITERALS +_LIT8(KSamplingPeriod, "sampling_period_ms"); +_LIT8(KNewLine8, "\n"); +_LIT8(KEquals8, "="); +_LIT8(KSettingsText, " settings"); +_LIT(KNewLine, "\n"); +_LIT(KEquals, "="); +_LIT(KCommentSeparator, " ; "); + +CSamplerController* CSamplerController::NewL(CProfilerSampleStream& aStream) + { + CSamplerController* self = new( ELeave ) CSamplerController(aStream); + CleanupStack::PushL( self ); + self->ConstructL( ); + CleanupStack::Pop( self ); + return self; + } + +void CSamplerController::ConstructL() + { + // initiate sampler plugin list + InitialiseSamplerListL(); + } + + +CSamplerController::CSamplerController(CProfilerSampleStream& aStream) : + iStream(aStream) + { + } + +void CSamplerController::InitialiseSamplerListL() + { + // create new sampler plugin array + iPluginArray = new (ELeave) CArrayPtrFlat<CSamplerPluginInterface>( KMaxSamplerPluginCount ); + + // create plugin loader instance + iPluginLoader = CSamplerPluginLoader::NewL(); + + // register sampler controller to get notifications of succesfull plugin load + iPluginLoader->SetObserver( this ); + + // load sampler plugins asynchronously + iPluginLoader->LoadAsyncL( iPluginArray ); + + LOGTEXT(_L(" RSamplerController::InitialiseUserSideSamplerList - exit")); + } + +CSamplerController::~CSamplerController() + { + LOGTEXT(_L("CSamplerController::~CSamplerController - entry" )); + + if ( iPluginArray ) + { + // destroy the plugin instances + // empty loaded plugins from array + for(TInt i(0);i<iPluginArray->Count();i++) + { + if(iPluginArray->At(i)) + { + delete iPluginArray->At(i); + iPluginArray->At(i) = NULL; + } + } + iPluginArray->Reset(); + delete iPluginArray; + iPluginArray = NULL; + } + + if ( iPluginLoader ) + { + iPluginLoader->AbortAsyncLoad(); + delete iPluginLoader; + iPluginLoader = NULL; + } + + LOGTEXT(_L("CSamplerController::~CSamplerController - exit" )); + } + +void CSamplerController::SetObserver(MSamplerControllerObserver* aObserver) + { + iObserver = aObserver; + } + +TInt CSamplerController::UpdateSavedSamplerAttributesL(CDesC8ArrayFlat* aSavedLineArray, CArrayFixFlat<TSamplerAttributes>* aAttributes) + { + TInt err(KErrNone); + TInt count(iPluginArray->Count()); + // all plugins get their own settings among whole lump of setting strings + CSamplerPluginInterface* plugin = NULL; + + // loop through the plugin array + for(TInt i(0);i<count;i++) + { + // get each plugin at a time + plugin = iPluginArray->At(i); + + // call each plugin to sort out its own settings + err = plugin->ConvertRawSettingsToAttributes(aSavedLineArray); + + // get plugin specific attributes, array may contain attributes of several sub samplers + plugin->GetAttributesL(aAttributes); + } + + return err; + } + +TInt CSamplerController::SetSamplerSettingsL(TInt aUid, TSamplerAttributes aAttributes) + { + // parse right plugin based on UID + CSamplerPluginInterface* plugin = GetPlugin(TUid::Uid(aUid)); + + // set the sampler attributes of a sampler plugin + plugin->SetAttributesL(aAttributes); + + return KErrNone; + } + +void CSamplerController::GetSamplerAttributesL(CArrayFixFlat<TSamplerAttributes>* aAttributes) + { + CSamplerPluginInterface* plugin = NULL; + + TInt count(iPluginArray->Count()); + + // get first all the attributes from all the sampler plugins listed in iPluginArray + for(TInt i(0);i<count;i++) + { + // get the plugin first + plugin = iPluginArray->At(i); + + // get plugin specific attributes, array may contain attributes of several sub samplers + plugin->GetAttributesL(aAttributes); + } + } + +void CSamplerController::ComposeAttributesToSettingsFileFormat(RFile& aFile, CArrayFixFlat<TSamplerAttributes>* aAttributes) + { + // write immediately to settings file + ComposeSettingsText(aFile, aAttributes); + } + +void CSamplerController::ComposeSettingsText(RFile& aFile, CArrayFixFlat<TSamplerAttributes>* aAttrArray) + { + // temporary buffer for a setting line + TBuf<384> settingLine; + TBuf8<384> settingLine8; + TInt itemCount(0); + TBuf<266> tBuf; + + TSamplerAttributes attr; + + for(TInt i(0);i<aAttrArray->Count();i++) + { + // get the attribute container + attr = aAttrArray->At(i); + + // add the name and description of the sampler in brackets first + settingLine8.Copy(KBracketOpen); + settingLine8.Append(attr.iShortName); + settingLine8.Append(KBracketClose); + settingLine8.Append(KCommentSeparator()); + settingLine8.Append(attr.iName); + settingLine8.Append(KSettingsText); + settingLine8.Append(KNewLine8); + aFile.Write(settingLine8); + + // enabled + settingLine8.Copy(KEnabled); + settingLine8.Append(KEquals8); + settingLine8.Append(Bool2Str(attr.iEnabled)); + settingLine8.Append(KNewLine8); + aFile.Write(settingLine8); + + // sampling rate (if set) + if( attr.iSampleRate != -1 ) + { + settingLine8.Copy(KSamplingPeriod); + settingLine8.Append(KEquals8); + settingLine8.Append(Int2Str(attr.iSampleRate)); + settingLine8.Append(KNewLine8); + aFile.Write(settingLine8); + } + + itemCount = attr.iItemCount; + + // check if item count set is sane, max extra settings item count 6 + if(itemCount > KMaxExtraSettingsItemCount) + { + // probably forgot to set the item count value in plugin => safe to set it 0 + itemCount = 0; + } + + // setting items + for (TInt j(0);j<itemCount;j++) + { + switch(j) + { + case 0: // settingItem1 + { + settingLine.Copy(attr.iSettingItem1.iSettingText); + settingLine.Append(KEquals()); + settingLine.Append(attr.iSettingItem1.iValue); + settingLine.Append(KCommentSeparator()); + settingLine.Append(attr.iSettingItem1.iUIText); + settingLine.Append(KNewLine()); + CnvUtfConverter::ConvertFromUnicodeToUtf8(settingLine8, settingLine); + aFile.Write(settingLine8); + break; + } + case 1: // settingItem2 + { + settingLine.Copy(attr.iSettingItem2.iSettingText); + settingLine.Append(KEquals()); + settingLine.Append(attr.iSettingItem2.iValue); + settingLine.Append(KCommentSeparator()); + settingLine.Append(attr.iSettingItem2.iUIText); + settingLine.Append(KNewLine()); + CnvUtfConverter::ConvertFromUnicodeToUtf8(settingLine8, settingLine); + aFile.Write(settingLine8); + break; + } + case 2: // settingItem3 + { + settingLine.Copy(attr.iSettingItem3.iSettingText); + settingLine.Append(KEquals()); + settingLine.Append(attr.iSettingItem3.iValue); + settingLine.Append(KCommentSeparator()); + settingLine.Append(attr.iSettingItem3.iUIText); + settingLine.Append(KNewLine()); + CnvUtfConverter::ConvertFromUnicodeToUtf8(settingLine8, settingLine); + aFile.Write(settingLine8); + break; + } + case 3: // settingItem4 + { + settingLine.Copy(attr.iSettingItem4.iSettingText); + settingLine.Append(KEquals()); + settingLine.Append(attr.iSettingItem4.iValue); + settingLine.Append(KCommentSeparator()); + settingLine.Append(attr.iSettingItem4.iUIText); + settingLine.Append(KNewLine()); + CnvUtfConverter::ConvertFromUnicodeToUtf8(settingLine8, settingLine); + aFile.Write(settingLine8); + break; + } + case 4: // settingItem5 + { + settingLine.Copy(attr.iSettingItem5.iSettingText); + settingLine.Append(KEquals()); + settingLine.Append(attr.iSettingItem5.iValue); + settingLine.Append(KCommentSeparator()); + settingLine.Append(attr.iSettingItem5.iUIText); + settingLine.Append(KNewLine()); + CnvUtfConverter::ConvertFromUnicodeToUtf8(settingLine8, settingLine); + aFile.Write(settingLine8); + break; + } + case 5: // settingItem6 + { + settingLine.Copy(attr.iSettingItem6.iSettingText); + settingLine.Append(KEquals()); + settingLine.Append(attr.iSettingItem6.iValue); + settingLine.Append(KCommentSeparator()); + settingLine.Append(attr.iSettingItem6.iUIText); + settingLine.Append(KNewLine()); + CnvUtfConverter::ConvertFromUnicodeToUtf8(settingLine8, settingLine); + aFile.Write(settingLine8); + break; + } + } + } + } + } + +// ---------------------------------------------------------------------------- +// Converts given descriptor into TBool value. +// ---------------------------------------------------------------------------- +// +inline void CSamplerController::Str2Bool(const TDesC8& aBuf, TBool& aValue) + { + if (aBuf.CompareF(KFalse) == 0) + aValue = EFalse; + else + aValue = ETrue; + } + +// ---------------------------------------------------------------------------- +// Converts given descriptor into TInt value. +// ---------------------------------------------------------------------------- +// +inline void CSamplerController::Str2Int(const TDesC8& aBuf, TInt& aValue) + { + TLex8 conv; + conv.Assign(aBuf); + + if (conv.Val(aValue) != KErrNone) + aValue = 0; + } + +// ---------------------------------------------------------------------------- +// Converts given descriptor into TInt value. +// ---------------------------------------------------------------------------- +// +inline void CSamplerController::Str2Int(const TDesC8& aBuf, TUint32& aValue) + { + TInt temp(0); + + TLex8 conv; + conv.Assign(aBuf); + + if (conv.Val(temp) != KErrNone) + aValue = 0; + else + aValue = (TUint32)temp; + } + +// ---------------------------------------------------------------------------- +// Converts given boolean into a descriptor. +// ---------------------------------------------------------------------------- +// +inline TBuf8<16> CSamplerController::Bool2Str(const TBool& aValue) + { + TBuf8<16> buf; + + if (aValue) + buf.Copy(KTrue); + else + buf.Copy(KFalse); + + return buf; + } + +// ---------------------------------------------------------------------------- +// Converts given integer into a descriptor. +// ---------------------------------------------------------------------------- +// +inline TBuf8<16> CSamplerController::Int2Str(const TInt& aValue) + { + TBuf8<16> buf; + buf.AppendNum(aValue); + + return buf; + } + + +void CSamplerController::HandlePluginLoaded( KSamplerPluginLoaderStatus aStatus ) + { + + // process status value + switch(aStatus) + { + case 0: + LOGSTRING2("RSamplerController - one plugin loaded, status: %d", aStatus); + break; + case 1: + LOGSTRING2("RSamplerController - a plugin load failed: %d", aStatus); + break; + case 2: + LOGSTRING2("RSamplerController - plugin loading aborted: %d", aStatus); + break; + case 3: + LOGSTRING2("RSamplerController - all plugins loaded: %d", aStatus); + TRAPD(err, iPluginLoader->SortPluginsL(iPluginArray)); + if(err != KErrNone) + { + LOGTEXT(_L("Sampler controller unable to sort plugins")); + } + + // call engine to finalize the startup + TRAPD(result, iObserver->HandleSamplerControllerReadyL();); + if(result != KErrNone) + { + LOGTEXT(_L("Failed to notify engine")); + } + break; + case 4: + LOGSTRING2("RSamplerController - error in loading plugins: %d", aStatus); + break; + default: + break; + } + } + + +CSamplerPluginInterface* CSamplerController::GetPlugin(TUid aUid) + { + LOGTEXT(_L("RSamplerController::GetPlugin - entry")); + // check that plugin array contains samplers + if( iPluginArray && iPluginArray->Count() > 0 ) + { + for(TInt i=0;i<iPluginArray->Count();i++) + { + CSamplerPluginInterface* plugin = iPluginArray->At(i); + TUid uid = plugin->Id(-1); // get parent uid first + if(uid == aUid) + { + LOGTEXT(_L("CSamplerController::GetPlugin() - main plug-in found!")); + return plugin; + } + + if(plugin->SubId(aUid) != KErrNotFound) + { + LOGTEXT(_L("CSamplerController::GetPlugin() - subsampler found!")); + return plugin; + } + } + } + LOGTEXT(_L("CSamplerController::GetPlugin() - No plug-in found for UID")); + + return (CSamplerPluginInterface*)0; + } + +// start user mode samplers +void CSamplerController::StartSamplerPluginsL() + { + CSamplerPluginInterface* plugin = NULL; + + if( iPluginArray ) + { + TInt count(iPluginArray->Count()); + + for(TInt i(0);i<count;i++) + { + plugin = iPluginArray->At(i); + // check if some error received when starting profiling + TRAPD(err, plugin->ResetAndActivateL(iStream)); + LOGSTRING2(" RSamplerController::StartSamplerPlugin - plugin activated (0x%X)", plugin->Id(-1)); + if( err != KErrNone) + { + LOGSTRING2(" RSamplerController::StartSamplerPlugin - error %d", i); + // handle received error, need to update UI! + iObserver->HandleError(err); + } + } + } + } + +// stop user mode samplers +TInt CSamplerController::StopSamplerPlugins() + { + TInt count(0); + + if( iPluginArray && iPluginArray->Count() > 0 ) + { + TInt i(0); + CSamplerPluginInterface* plugin = NULL; + // stop kernel mode samplers + for(;i<iPluginArray->Count();i++) + { + plugin = iPluginArray->At(i); + TUint32 id = plugin->Id(-1).iUid; + LOGSTRING2(" CSamplerController::StopSamplerPlugins - traceId = %d", + id); + // stop only started samplers + if(plugin->Enabled()) + { + // stop selected plugin + plugin->StopSampling(); + // check if user mode sampler, special flush needed to direct data to stream + if(plugin->GetSamplerType() == PROFILER_USER_MODE_SAMPLER) + { + LOGTEXT(_L(" CSamplerController::StopSamplerPlugins - flushing user mode sampler stream")); + plugin->Flush(); + } + } + count++; + } + } + return count; + } + +// end of file + + + + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/src/SamplerPluginLoader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/src/SamplerPluginLoader.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,539 @@ +/* +* 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: +* +*/ + + +// INCLUDE FILES +#include "SamplerPluginLoader.h" +//#include <piprofiler/EngineUIDs.h> +#include <utf.h> // CnvUtfConverter +#include <basched.h> + +// CONSTANTS + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::NewL +// +// EPOC two-phased constructor +// ---------------------------------------------------------------------------- +// +CSamplerPluginLoader* CSamplerPluginLoader::NewL() + { + CSamplerPluginLoader* self = new( ELeave ) CSamplerPluginLoader; + CleanupStack::PushL( self ); + self->ConstructL( ); + CleanupStack::Pop( self ); + return self; + } + + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::CSamplerPluginLoader +// +// C++ default constructor can NOT contain any code, that +// might leave. +// ---------------------------------------------------------------------------- +// +CSamplerPluginLoader::CSamplerPluginLoader() : CActive( EPriorityStandard ) + { + LOGSTRING( "CSamplerPluginLoader()::CSamplerPluginLoader()" ); + } + + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::ConstructL +// +// EPOC default constructor can leave. +// ---------------------------------------------------------------------------- +// +void CSamplerPluginLoader::ConstructL( ) + { + LOGSTRING( "CSamplerPluginLoader()::ConstructL()" ); + + // get list of implementations + CSamplerPluginInterface::ListAllImplementationsL( iImplInfoArray ); + + CActiveScheduler::Add( this ); + } + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::~CSamplerPluginLoader +// +// Destructor +// ---------------------------------------------------------------------------- +// +CSamplerPluginLoader::~CSamplerPluginLoader() + { + LOGSTRING( "CSamplerPluginLoader()::~CSamplerPluginLoader()" ); + + AbortAsyncLoad(); + + Cancel(); + + // reset ECOM implementation info array + iImplInfoArray.ResetAndDestroy(); // This is needed + iImplInfoArray.Close(); + } + + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::LoadAsync +// ---------------------------------------------------------------------------- +// +void CSamplerPluginLoader::LoadAsyncL(CArrayPtrFlat<CSamplerPluginInterface>* aPluginArray ) + { + iPluginArray = aPluginArray; + + // Reset iterator + iImplInfoArrayIterator = 0; + + LOGSTRING2( "CSamplerPluginLoader()::Implementation info count: %d", + iImplInfoArray.Count() ); + + NotifyProgress(); + + //Begin CActive asynchronous loop. + CompleteOwnRequest(); + } + + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::LoadSyncL +// ---------------------------------------------------------------------------- +// +void CSamplerPluginLoader::LoadSyncL(CArrayPtrFlat<CSamplerPluginInterface>* aPluginArray) + { + // cancel first active object from loading samplers dynamically + Cancel(); + CSamplerPluginInterface* plugin = NULL; + + iPluginArray = aPluginArray; + + // Get a list of all implementations, even though we only want one specific + // one. There appears to be no way to otherwise extract a specific implementation + // info object :( + // Search for the implementation that matches aImplementationUid + const TInt impCount = iImplInfoArray.Count(); + for( TInt i=0; i<impCount; i++ ) + { + const CImplementationInformation* info = iImplInfoArray[ i ]; + { + TRAPD(ret, plugin = &CreatePluginInstanceL( *info ); ); + if( ret == KErrNone ) + { + // Plugin ownership is transfered to iPluginArray + InsertPluginInOrderL( plugin, iPluginArray ); + } + else + { + // Error note is displayed even if plugin is not loaded + LOGSTRING2("CSamplerPluginLoader::LoadSyncL() - plugin load failed, error %d", ret); + } + break; + } + } + + if ( plugin == NULL ) + { + User::Leave( KErrNotFound ); + } + } + + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::AbortAsyncLoad +// ---------------------------------------------------------------------------- +// +void CSamplerPluginLoader::AbortAsyncLoad() + { + LOGSTRING( "CSamplerPluginLoader()::AbortAsyncLoad()" ); + Cancel(); + } + + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::RunL +// ---------------------------------------------------------------------------- +// +void CSamplerPluginLoader::RunL() + { + iRunLDebugCount++; + LoadNextPluginL(); + + // Check if there are still more plugins to be loaded: + if ( iImplInfoArrayIterator < iImplInfoArray.Count() ) + { + NotifyProgress(); + // Continue CActive asynchronous loop. + CompleteOwnRequest(); + } + else + { + // All plugins loaded: + LOGSTRING( "CSamplerPluginLoader()::Loading plugins finished." ); + NotifyFinished(); + } + } + + +// --------------------------------------------------------------------------- +// CScGenreItemConstructionConductor::CompleteOwnRequest +// +// Issue request complete notification. +// --------------------------------------------------------------------------- +void CSamplerPluginLoader::CompleteOwnRequest() + { + TRequestStatus* status = &iStatus; + User::RequestComplete( status, KErrNone ); + SetActive(); + } + + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::RunError +// ---------------------------------------------------------------------------- +// +TInt CSamplerPluginLoader::RunError( TInt aError ) + { + // This method is called when a plugin loading fails. + // Always "fake" the return value so that ActiveSchedule + // keeps running and later plugins are continued to be loaded. + // Check if still plugins to be loaded: + LOGTEXT(_L("CSamplerPluginLoader::RunError() - error in loading plugin")); + if( iImplInfoArrayIterator < iImplInfoArray.Count() ) + { + NotifyProgress(); + + //Continue CActive asynchronous loop. + CompleteOwnRequest(); + } + else // All plugins loaded: + { + NotifyFinished(); + } + + if ( aError == KLeaveExit ) + { + return KLeaveExit; + } + + return KErrNone; + } + + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::DoCancel +// ---------------------------------------------------------------------------- +// +void CSamplerPluginLoader::DoCancel() + { + + } + + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::NotifyProgress +// ---------------------------------------------------------------------------- +// +void CSamplerPluginLoader::NotifyProgress() + { + if( iObserver ) + { + iObserver->HandlePluginLoaded( MSamplerPluginLoadObserver::ESamplerSuccess); + } + } + + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::NotifyFinished +// ---------------------------------------------------------------------------- +// +void CSamplerPluginLoader::NotifyFinished() + { + if( iObserver ) + { + iObserver->HandlePluginLoaded( MSamplerPluginLoadObserver::ESamplerFinished ); + } + } + + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::SetObserver +// ---------------------------------------------------------------------------- +// +void CSamplerPluginLoader::SetObserver(MSamplerPluginLoadObserver* aObserver) + { + LOGSTRING2("CSamplerPluginLoader()::Observer set:0x%X", aObserver); + iObserver = aObserver; + } + + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::ParseToUid +// Parses a UID from descriptor of form '0xNNNNNNNN' where N is hexadecimal. +// +// ---------------------------------------------------------------------------- +// +TInt CSamplerPluginLoader::ParseToUid( const TDesC8& aSource, TUid& aTarget ) + { + // Remove "0x" from the descriptor if it exists + _LIT8(KHexPrefix, "0x"); + + TPtrC8 pSource( aSource ); + const TInt prefixPosition = pSource.Find( KHexPrefix ); + if ( prefixPosition != KErrNotFound ) + { + pSource.Set( aSource.Mid( prefixPosition + KHexPrefix().Length() ) ); + } + + // Parse to integer + TLex8 lex( pSource ); + TUint integer = 0; + + // Parse using TRadix::EHex as radix: + const TInt err = lex.Val( integer, EHex ); + aTarget.iUid = integer; + + if( err != KErrNone ) + { + // If parsing parent UID failed, do not load plugin: + LOGSTRING2( + "CSamplerPluginLoader()::Parsing parent UID failed. Error code:%d", + err ); + } + return err; + } + + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::ParseOrderNumber +// +// +// ---------------------------------------------------------------------------- +// +TInt CSamplerPluginLoader::ParseOrderNumber( const TDesC8& aSource, TInt& aOrderNumber ) + { + // Parse plugin's order number from opaque_data: + TLex8 lex( aSource ); + const TInt orderErr = lex.Val( aOrderNumber ); + return orderErr; + } + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::LoadNextPluginL +// Iterate through iImplInfoArray. Load the plugin if it is eligible for +// loading. Loaded plugin is added to iPluginArray. Each time a plugin is +// loaded, iObserver is notified. +// +// ---------------------------------------------------------------------------- +// +void CSamplerPluginLoader::LoadNextPluginL() + { + // Iterate through iImplInfoArray. This loop continues between function + // calls. Therefore member variable iImplInfoArrayIterator is used as a + // counter. Loop will break when match is found and continues on next RunL. + for( ; iImplInfoArrayIterator < iImplInfoArray.Count(); ) + { + const CImplementationInformation* info = + iImplInfoArray[ iImplInfoArrayIterator ]; + + iImplInfoArrayIterator++; + +// PrintInfoDebug( *info, iImplInfoArrayIterator, iImplInfoArray.Count() ); + LOGSTRING3("CSamplerPluginLoader() - iImplInfoArrayIterator %d, iImplInfoArray.Count() %d", + iImplInfoArrayIterator, + iImplInfoArray.Count() ); + + // If this plugin is OK -> load it: + LOGSTRING2( "CSamplerPluginLoader() %S eligible for parent", + &info->DisplayName()); + CSamplerPluginInterface* plugin = NULL; + TInt error(KErrNone); + // Create plugin. Trap leave for debugging purposes. + TRAP( error, plugin = &CreatePluginInstanceL( *info ); ); + + if( error == KErrNone ) + { + // Plugin ownership is transfered to iPluginArray + InsertPluginInOrderL( plugin, iPluginArray ); + } + else + { + // Error note is displayed even if plugin is not loaded + LOGSTRING2("CSamplerPluginLoader::LoadNextPluginL() - plugin load failed, error %d", error); + } + // Wait for next round + break; + } + } + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::CreatePluginInstanceL +// +// +// ---------------------------------------------------------------------------- +// + +CSamplerPluginInterface& CSamplerPluginLoader::CreatePluginInstanceL( + const CImplementationInformation& aImpInfo ) + { + // Now we can load the plugin + const TUid implUid = aImpInfo.ImplementationUid(); + + CSamplerPluginInterface* plugin = CSamplerPluginInterface::NewL( implUid , (TAny*)&aImpInfo.DisplayName() ); + CleanupStack::PushL ( plugin ); + + // Parse plugin's order number from opaque_data: + TInt orderNumber(0); + const TInt orderErr = ParseOrderNumber( aImpInfo.OpaqueData(), orderNumber ); + + if ( orderErr == KErrNone && orderNumber >= 0 ) + { + plugin->iOrder = orderNumber; + } + CleanupStack::Pop( plugin ); // CSamplerController is now responsible for this memory. + + return *plugin; + } + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::SortPluginsL +// +// ---------------------------------------------------------------------------- +// +void CSamplerPluginLoader::SortPluginsL( + CArrayPtrFlat<CSamplerPluginInterface>* aPlugins ) + { + RPointerArray<CSamplerPluginInterface> plugins; + TLinearOrder<CSamplerPluginInterface> order( CSamplerPluginLoader::Compare ); + + // Insertion will also order + for( TInt i = 0; i < aPlugins->Count(); i++ ) + { + plugins.InsertInOrderL( (*aPlugins)[i], order ); + } + + // Replace original array content with sorted items + aPlugins->Reset(); + for( TInt i = 0; i < plugins.Count(); i++ ) + { + aPlugins->AppendL( plugins[i] ); + } + } + + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::Compare +// +// Compare two plugins. +// Precedence: +// [1. plugin provider category] +// 2. plugin order number +// 3. plugin caption +// Plugin provider gategory is currently disabled (not supported yet). +// ---------------------------------------------------------------------------- +// +TInt CSamplerPluginLoader::Compare( const CSamplerPluginInterface& aFirst, + const CSamplerPluginInterface& aSecond ) + { + // compare indexes and sort + return CompareIndex( aFirst, aSecond ); + } + + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::InsertPluginInOrderL +// +// ---------------------------------------------------------------------------- +// +void CSamplerPluginLoader::InsertPluginInOrderL( + CSamplerPluginInterface* aPlugin, + CArrayPtrFlat<CSamplerPluginInterface>* aPlugins ) + { + CSamplerPluginInterface* comparedPlugin; + TInt comparison = 0; + TBool inserted = EFalse; + + for( TInt i = 0; i < aPlugins->Count(); i++ ) + { + comparedPlugin = (*aPlugins)[i]; + // Optimization: do not call time consuming Compare() multiple times! + comparison = Compare( *aPlugin, *comparedPlugin ); + if( comparison < 0 ) + { + aPlugins->InsertL( i, aPlugin ); + inserted = ETrue; + break; + } + else if( comparison == 0 ) + { + aPlugins->InsertL( i+1, aPlugin ); + inserted = ETrue; + break; + } + } + // Plugin was not before any other plugin - make sure it's appended + if( !inserted ) + { + aPlugins->AppendL( aPlugin ); + } + + #ifdef _GS_PLUGINLOADER_SORTING_TRACES + PrintOrderTraces( aPlugins ); + #endif // _GS_PLUGINLOADER_SORTING_TRACES + + } + +// ---------------------------------------------------------------------------- +// CSamplerPluginLoader::CompareIndex +// ---------------------------------------------------------------------------- +// +TInt CSamplerPluginLoader::CompareIndex( const CSamplerPluginInterface& aFirst, + const CSamplerPluginInterface& aSecond ) + { + TInt comparison = KSamplerComparisonEqual; + // The plugin having index is before the one not having one + + if( aFirst.iOrder == KSamplerPluginNotIndexed && + aSecond.iOrder == KSamplerPluginNotIndexed ) + { + // Neither have index -> equal + comparison = KSamplerComparisonEqual; + } + else if( aFirst.iOrder == KSamplerPluginNotIndexed ) + { + // The plugin having index is before the one not having one + comparison = KSamplerComparisonAfter; + } + else if( aSecond.iOrder == KSamplerPluginNotIndexed ) + { + // The plugin having index is before the one not having one + comparison = KSamplerComparisonBefore; + } + else if( aFirst.iOrder < aSecond.iOrder ) + { + // Compare actual index values + comparison = KSamplerComparisonBefore; + } + else if( aFirst.iOrder > aSecond.iOrder ) + { + // Compare actual index values + comparison = KSamplerComparisonAfter; + } + return comparison; + } + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/src/WriterController.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/src/WriterController.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,283 @@ +/* +* 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: +* +*/ + + +#include <piprofiler/EngineUIDs.h> +#include <piprofiler/ProfilerTraces.h> + +#include "WriterController.h" + +const TInt KMaxWriterPluginCount = 10; + + +CWriterController* CWriterController::NewL(CProfilerSampleStream& aStream) + { + CWriterController* self = new( ELeave ) CWriterController(aStream); + CleanupStack::PushL( self ); + self->ConstructL( ); + CleanupStack::Pop( self ); + return self; + } + +CWriterController::CWriterController(CProfilerSampleStream& aStream) : + iStream(aStream) + { + } + +void CWriterController::ConstructL() + { + // initiate writer plugin list + + } + + +void CWriterController::InitialiseWriterListL() + { + // create new writer plugin array + iPluginArray = new(ELeave) CArrayPtrFlat<CWriterPluginInterface>( KMaxWriterPluginCount ); + + // create new writer plugin loader + iPluginLoader = CWriterPluginLoader::NewL(); + iPluginLoader->SetObserver( this ); + iPluginLoader->LoadAsyncL( iPluginArray ); + + LOGTEXT(_L(" RWriterController::InitialiseWriterList - exit")); + } + +CWriterController::~CWriterController() + { + LOGTEXT(_L("RWriterController::~RWriterController" )); + if ( iPluginArray ) + { + // destroy the plugin instances + // empty loaded plugins from array + for(TInt i(0);i<iPluginArray->Count();i++) + { + if(iPluginArray->At(i)) + { + delete iPluginArray->At(i); + iPluginArray->At(i) = NULL; + } + } + iPluginArray->Reset(); + delete iPluginArray; + iPluginArray = NULL; + } + + if ( iPluginLoader ) + { + iPluginLoader->AbortAsyncLoad(); + delete iPluginLoader; + iPluginLoader = NULL; + } + + } + + +void CWriterController::InitialisePluginStream() + { + LOGTEXT(_L("RWriterController::InitialisePluginStream - entry")); + if( iPluginArray ) + { + TInt pluginCount(iPluginArray->Count()); + + LOGSTRING2("RWriterController::InitialisePluginStream - plugin count %d, searching through", pluginCount); + for(TInt i=0;i<pluginCount;i++) + { + LOGSTRING2("RWriterController::InitialisePluginStream - getting plugin n:o: %d...", i); + CWriterPluginInterface* plugin = iPluginArray->At(i); + LOGSTRING2("RWriterController::InitialisePluginStream - writer found, 0x%x, initializing stream...", plugin->Id()); + plugin->SetStream(iStream); + LOGTEXT(_L("RSamplerController::InitialisePluginStream - succeeded!")); + } + } + LOGTEXT(_L("RSamplerController::InitialisePluginStream - exit")); + + } + +CArrayPtrFlat<CWriterPluginInterface>* CWriterController::GetPluginList() + { + return iPluginArray; + } + +void CWriterController::HandlePluginLoaded( KWriterPluginLoaderStatus aStatus ) + { + + switch(aStatus) + { + case 0: + LOGSTRING2("RWriterController - one plugin loaded, status: %d", aStatus); + break; + case 1: + LOGSTRING2("RWriterController - a plugin load failed: %d", aStatus); + break; + case 2: + LOGSTRING2("RWriterController - plugin loading aborted: %d", aStatus); + break; + case 3: + LOGSTRING2("RWriterController - all plugins loaded: %d", aStatus); + // set stream after all loaded writer plugins + InitialisePluginStream(); + break; + case 4: + LOGSTRING2("RWriterController - error in loading plugins: %d", aStatus); + break; + default: + break; + } + } + + + +TUid CWriterController::GetPluginUID(TInt traceId) + { + LOGSTRING2(" RWriterController::GetPluginUID - checking UID for traceId = %d",traceId); + // this part has to be changed for each new writer + + if( iPluginArray && iPluginArray->Count() > 0 ) + { + for(TInt i=0;i<iPluginArray->Count();i++) + { + CWriterPluginInterface* plugin = iPluginArray->At(i); + if(plugin->Id().iUid == traceId) + { + LOGSTRING2(" RWriterController::GetPluginUID - got: 0x%X",plugin->Id()); + return plugin->Id(); + } + } + } + return KWriterNoneSelected; + + } + +CWriterPluginInterface* CWriterController::GetActiveWriter() + { + CWriterPluginInterface* plugin = NULL; + + if( iPluginArray ) + { + TInt count(iPluginArray->Count()); + + for(TInt i=0;i<count;i++) + { + plugin = iPluginArray->At(i); + if(plugin->GetEnabled()) + { + return plugin; + } + } + } + + return (CWriterPluginInterface*)0; + } + +TUint32 CWriterController::GetWriterType(TUint32 writerId) + { + TUid id; + + id = this->GetPluginUID(writerId); + + if(id != KWriterNoneSelected) + return GetPlugin(id)->GetWriterType(); + else + return 0; + } + +CWriterPluginInterface* CWriterController::GetPlugin(TUid aUid) + { + if( iPluginArray && iPluginArray->Count() > 0 ) + { + for(TInt i=0;i<iPluginArray->Count();i++) + { + CWriterPluginInterface* plugin = iPluginArray->At(i); + // check if searched uid found + if(plugin->Id().iUid == aUid.iUid) + { + // return pointer to found plugin + return plugin; + } + } + } + // return null plugin + return (CWriterPluginInterface*)0; + } + +TInt CWriterController::StartSelectedPlugin() + { + LOGTEXT(_L("RWriterController::StartSelectedPlugin - entry")); + + CWriterPluginInterface* plugin = GetActiveWriter(); + + if(plugin) + { + return plugin->Start(); + } + + LOGTEXT(_L("RWriterController::StartSelectedPlugin - exit")); + return KErrNotFound; + } + +void CWriterController::StopSelectedPlugin() + { + LOGTEXT(_L("RWriterController::StopSelectedPlugin - entry")); + + CWriterPluginInterface* plugin = GetActiveWriter(); + + if(plugin) + { + plugin->Stop(); + } + LOGTEXT(_L("RWriterController::StopSelectedPlugin - exit")); + } + +/** Set selected plugin active **/ +void CWriterController::SetPluginActive(TUid uid, const TWriterPluginValueKeys aKey) + { + CWriterPluginInterface* plugin = NULL; + _LIT(KDummy, ""); + TBuf<1> buf; + buf.Append(KDummy); + + for(TInt i(0);i<iPluginArray->Count();i++) + { + plugin = iPluginArray->At(i); + if(plugin->Id().iUid == uid.iUid) + { + plugin->SetValue(aKey, buf); + } + else + { + plugin->SetValue(EWriterPluginDisabled, buf); + } + } + } + +TInt CWriterController::SetPluginSettings(TUid aUid, TDes& aDes) + { + LOGSTRING2(" CWriterController::SetPluginSettings, traceId = 0x%X", aUid.iUid); + GetPlugin(aUid)->SetValue(EWriterPluginSettings, aDes); + return KErrNone; + } + +/** Get settings for a specific plugin **/ +void CWriterController::GetPluginSettings(TUid uid, TDes& aVal) + { + GetPlugin(uid)->GetValue(EWriterPluginSettings, aVal); + } + + +// end of file diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/engine/src/WriterPluginLoader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/src/WriterPluginLoader.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,565 @@ +/* +* 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: +* +*/ + + +// INCLUDE FILES +#include "WriterPluginLoader.h" +//#include <piprofiler/EngineUIDs.h> +#include <utf.h> // CnvUtfConverter +#include <basched.h> + +// constants + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::NewL +// +// EPOC two-phased constructor +// ---------------------------------------------------------------------------- +// +CWriterPluginLoader* CWriterPluginLoader::NewL() + { + CWriterPluginLoader* self = new( ELeave ) CWriterPluginLoader; + CleanupStack::PushL( self ); + self->ConstructL( ); + CleanupStack::Pop( self ); + return self; + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::CWriterPluginLoader +// +// C++ default constructor can NOT contain any code, that +// might leave. +// ---------------------------------------------------------------------------- +// +CWriterPluginLoader::CWriterPluginLoader() : CActive( EPriorityStandard ) + { + LOGTEXT(_L("CWriterPluginLoader()::CWriterPluginLoader()" )); + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::ConstructL +// +// EPOC default constructor can leave. +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::ConstructL( ) + { + LOGTEXT(_L("CWriterPluginLoader()::ConstructL()" )); + + // get list of implementations + CWriterPluginInterface::ListAllImplementationsL( iImplInfoArray ); + + CActiveScheduler::Add( this ); + } + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::~CWriterPluginLoader +// +// Destructor +// ---------------------------------------------------------------------------- +// +CWriterPluginLoader::~CWriterPluginLoader() + { + LOGTEXT(_L("CWriterPluginLoader()::~CWriterPluginLoader()") ); + + AbortAsyncLoad(); + + Cancel(); + + // reset ECOM implementation info array + iImplInfoArray.ResetAndDestroy(); // This is needed + iImplInfoArray.Close(); + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::LoadAsync +// +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::LoadAsyncL( CArrayPtrFlat<CWriterPluginInterface>* aPluginArray ) + { + iPluginArray = aPluginArray; + + // Reset iterator: + iImplInfoArrayIterator = 0; + + LOGSTRING2( "CWriterPluginLoader()::Implementation info count: %d", + iImplInfoArray.Count() ); + + NotifyProgress(); + + //Begin CActive asynchronous loop. + CompleteOwnRequest(); + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::LoadSyncL +// +// +// ---------------------------------------------------------------------------- +// +CWriterPluginInterface& CWriterPluginLoader::LoadSyncL( TUid aImplementationUid ) + { + Cancel(); + CWriterPluginInterface* plugin = NULL; + + // Get a list of all implementations, even though we only want one specific + // one. There appears to be no way to otherwise extract a specific implementation + // info object :( + // Search for the implementation that matches aImplementationUid + const TInt impCount = iImplInfoArray.Count(); + for( TInt i=0; i<impCount; i++ ) + { + const CImplementationInformation* info = iImplInfoArray[ i ]; + if ( info->ImplementationUid() == aImplementationUid ) + { + TRAPD(ret, plugin = &CreatePluginInstanceL( *info ); ); + if( ret == KErrNone ) + { + // Plugin ownership is transfered to iPluginArray + InsertPluginInOrderL( plugin, iPluginArray ); + } + else + { + // Error note is displayed even if plugin is not loaded + LOGSTRING2("CWriterPluginLoader::LoadSyncL() - plugin load failed, error %d", ret); + } + break; + } + } + + if ( plugin == NULL ) + { + User::Leave( KErrNotFound ); + } + return *plugin; + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::AbortAsyncLoad +// +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::AbortAsyncLoad() + { + LOGTEXT(_L("CWriterPluginLoader()::AbortAsyncLoad()" )); + Cancel(); + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::RunL +// +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::RunL() + { + iRunLDebugCount++; + LoadNextPluginL(); + + // Check if there are still more plugins to be loaded: + if ( iImplInfoArrayIterator < iImplInfoArray.Count() ) + { + NotifyProgress(); + // Continue CActive asynchronous loop. + CompleteOwnRequest(); + } + else + { + // All plugins loaded: + LOGTEXT(_L("CWriterPluginLoader()::Loading plugins finished." )); + NotifyFinished(); + } + } + + +// --------------------------------------------------------------------------- +// CScGenreItemConstructionConductor::CompleteOwnRequest +// +// Issue request complete notification. +// --------------------------------------------------------------------------- +void CWriterPluginLoader::CompleteOwnRequest() + { + TRequestStatus* status = &iStatus; + User::RequestComplete( status, KErrNone ); + SetActive(); + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::RunError +// +// +// ---------------------------------------------------------------------------- +// +TInt CWriterPluginLoader::RunError( TInt aError ) + { + // This method is called when a plugin loading fails. + // Always "fake" the return value so that ActiveSchedule + // keeps running and later plugins are continued to be loaded. + // Check if still plugins to be loaded: + if( iImplInfoArrayIterator < iImplInfoArray.Count() ) + { + NotifyProgress(); + + //Continue CActive asynchronous loop. + CompleteOwnRequest(); + } + else // All plugins loaded: + { + NotifyFinished(); + } + + if ( aError == KLeaveExit ) + { + return KLeaveExit; + } + + return KErrNone; + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::DoCancel +// +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::DoCancel() + { + + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::NotifyProgress +// +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::NotifyProgress() + { + if( iObserver ) + { + iObserver->HandlePluginLoaded( MWriterPluginLoadObserver::EWriterSuccess); + } + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::NotifyFinished +// +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::NotifyFinished() + { + if( iObserver ) + { + iObserver->HandlePluginLoaded( MWriterPluginLoadObserver::EWriterFinished ); + } + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::SetObserver +// +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::SetObserver(MWriterPluginLoadObserver* aObserver) + { + LOGSTRING2("CWriterPluginLoader()::Observer set:0x%X", aObserver); + iObserver = aObserver; + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::ParseToUid +// Parses a UID from descriptor of form '0xNNNNNNNN' where N is hexadecimal. +// +// ---------------------------------------------------------------------------- +// +TInt CWriterPluginLoader::ParseToUid( const TDesC8& aSource, TUid& aTarget ) + { + // Remove "0x" from the descriptor if it exists + _LIT8(KHexPrefix, "0x"); + + TPtrC8 pSource( aSource ); + const TInt prefixPosition = pSource.Find( KHexPrefix ); + if ( prefixPosition != KErrNotFound ) + { + pSource.Set( aSource.Mid( prefixPosition + KHexPrefix().Length() ) ); + } + + // Parse to integer + TLex8 lex( pSource ); + TUint integer = 0; + + // Parse using TRadix::EHex as radix: + const TInt err = lex.Val( integer, EHex ); + aTarget.iUid = integer; + + if( err != KErrNone ) + { + // If parsing parent UID failed, do not load plugin: + LOGSTRING2( + "CWriterPluginLoader()::Parsing parent UID failed. Error code:%d", + err ); + } + return err; + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::ParseOrderNumber +// +// +// ---------------------------------------------------------------------------- +// +TInt CWriterPluginLoader::ParseOrderNumber( const TDesC8& aSource, TInt& aOrderNumber ) + { + // Parse plugin's order number from opaque_data: + TLex8 lex( aSource ); + const TInt orderErr = lex.Val( aOrderNumber ); + return orderErr; + } + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::LoadNextPluginL +// Iterate through iImplInfoArray. Load the plugin if it is eligible for +// loading. Loaded plugin is added to iPluginArray. Each time a plugin is +// loaded, iObserver is notified. +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::LoadNextPluginL() + { + // Iterate through iImplInfoArray. This loop continues between function + // calls. Therefore member variable iImplInfoArrayIterator is used as a + // counter. Loop will break when match is found and continues on next RunL. + for( ; iImplInfoArrayIterator < iImplInfoArray.Count(); ) + { + const CImplementationInformation* info = + iImplInfoArray[ iImplInfoArrayIterator ]; + + iImplInfoArrayIterator++; + + // If this plugin is OK -> load it: + LOGSTRING2( "CWriterPluginLoader() %S eligible for parent", + &info->DisplayName() ); + CWriterPluginInterface* plugin = NULL; + TInt error(KErrNone); + // Create plugin. Trap leave for debugging purposes. + TRAP( error, plugin = &CreatePluginInstanceL( *info ); ); + if( error == KErrNone ) + { + // Plugin ownership is transfered to iPluginArray + InsertPluginInOrderL( plugin, iPluginArray ); + } + else + { + LOGSTRING2("CWriterPluginLoader::LoadNextPluginL() - plugin load failed, error %d", error); + } + // Wait for next round + break; + } + } + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::CreatePluginInstanceL +// +// +// ---------------------------------------------------------------------------- +// + +CWriterPluginInterface& CWriterPluginLoader::CreatePluginInstanceL( + const CImplementationInformation& aImpInfo ) + { + // Now we can load the plugin + const TUid implUid = aImpInfo.ImplementationUid(); + + CWriterPluginInterface* plugin = CWriterPluginInterface::NewL( implUid , (TAny*)&aImpInfo.DisplayName() ); + CleanupStack::PushL ( plugin ); + + TInt orderNumber(0); + const TInt orderErr = ParseOrderNumber( aImpInfo.OpaqueData(), orderNumber ); + + if ( orderErr == KErrNone && orderNumber >= 0 ) + { + plugin->iOrder = orderNumber; + } + + CleanupStack::Pop( plugin ); // CWriterController is now responsible for this memory. + + return *plugin; + } + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::SortPluginsL +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::SortPluginsL( + CArrayPtrFlat<CWriterPluginInterface>* aPlugins ) + { + RPointerArray<CWriterPluginInterface> plugins; + TLinearOrder<CWriterPluginInterface> order( CWriterPluginLoader::Compare ); + + // Insertion will also order + for( TInt i = 0; i < aPlugins->Count(); i++ ) + { + plugins.InsertInOrderL( (*aPlugins)[i], order ); + } + + // Replace original array content with sorted items + aPlugins->Reset(); + for( TInt i = 0; i < plugins.Count(); i++ ) + { + aPlugins->AppendL( plugins[i] ); + } + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::Compare +// +// Compare two plugins. +// Precedence: +// [1. plugin provider category] +// 2. plugin order number +// 3. plugin caption +// Plugin provider gategory is currently disabled (not supported yet). +// ---------------------------------------------------------------------------- +// +TInt CWriterPluginLoader::Compare( const CWriterPluginInterface& aFirst, + const CWriterPluginInterface& aSecond ) + { + return CompareIndex( aFirst, aSecond ); + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::InsertPluginInOrderL +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::InsertPluginInOrderL( + CWriterPluginInterface* aPlugin, + CArrayPtrFlat<CWriterPluginInterface>* aPlugins ) + { + CWriterPluginInterface* comparedPlugin; + TInt comparison = 0; + TBool inserted = EFalse; + + for( TInt i = 0; i < aPlugins->Count(); i++ ) + { + comparedPlugin = (*aPlugins)[i]; + // Optimization: do not call time consuming Compare() multiple times! + comparison = Compare( *aPlugin, *comparedPlugin ); + if( comparison < 0 ) + { + aPlugins->InsertL( i, aPlugin ); + inserted = ETrue; + break; + } + else if( comparison == 0 ) + { + aPlugins->InsertL( i+1, aPlugin ); + inserted = ETrue; + break; + } + } + // Plugin was not before any other plugin - make sure it's appended + if( !inserted ) + { + aPlugins->AppendL( aPlugin ); + } + + #ifdef _GS_PLUGINLOADER_SORTING_TRACES + PrintOrderTraces( aPlugins ); + #endif // _GS_PLUGINLOADER_SORTING_TRACES + + } + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::CompareIndex +// +// +// ---------------------------------------------------------------------------- +// + +TInt CWriterPluginLoader::CompareIndex( const CWriterPluginInterface& aFirst, + const CWriterPluginInterface& aSecond ) + { + TInt comparison = KWriterComparisonEqual; + // The plugin having index is before the one not having one + + if( aFirst.iOrder == KWriterPluginNotIndexed && + aSecond.iOrder == KWriterPluginNotIndexed ) + { + // Neither have index -> equal + comparison = KWriterComparisonEqual; + } + else if( aFirst.iOrder == KWriterPluginNotIndexed ) + { + // The plugin having index is before the one not having one + comparison = KWriterComparisonAfter; + } + else if( aSecond.iOrder == KWriterPluginNotIndexed ) + { + // The plugin having index is before the one not having one + comparison = KWriterComparisonBefore; + } + else if( aFirst.iOrder < aSecond.iOrder ) + { + // Compare actual index values + comparison = KWriterComparisonBefore; + } + else if( aFirst.iOrder > aSecond.iOrder ) + { + // Compare actual index values + comparison = KWriterComparisonAfter; + } + return comparison; + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::GetDocument +// +// +// ---------------------------------------------------------------------------- +// +/* +CWriterBaseDocument* CWriterPluginLoader::GetDocument() + { + CWriterBaseDocument* document = static_cast<CWriterBaseDocument*>( iAppUi->Document() ); + return document; + } +*/ + +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/group/ReleaseNotes_PIProfiler.txt Binary file piprofiler/group/ReleaseNotes_PIProfiler.txt has changed diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,33 @@ +/* +* 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: +* +*/ +//PRJ_PLATFORMS +//DEFAULT ARMV5SMP + +#include <platform_paths.hrh> + +#include "../piprofiler_plat/group/bld.inf" +#include "../engine/group/bld.inf" +#include "../plugins/GeneralsPlugin/group/bld.inf" +#include "../plugins/BUPplugin/group/bld.inf" +#include "../plugins/DebugOutputWriterPlugin/group/bld.inf" +#include "../plugins/DiskWriterPlugin/group/bld.inf" + + +PRJ_EXPORTS +../rom/piprofiler.iby CORE_IBY_EXPORT_PATH(tools,piprofiler.iby) +../rom/piprofiler_ldd.iby CORE_IBY_EXPORT_PATH(tools/rom,piprofiler_ldd.iby) + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,44 @@ +/* +* 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: File that exports the files belonging to +: PIProfilerAPI +* +*/ + + +#include <platform_paths.hrh> + + +PRJ_EXPORTS +../inc/ProfilerTraces.h OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/ProfilerTraces.h) +../inc/ProfilerVersion.h OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/ProfilerVersion.h) +../inc/ProfilerConfig.h OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/ProfilerConfig.h) +../inc/ProfilerAttributes.h OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/ProfilerAttributes.h) +../inc/ProfilerGenericClassesUsr.h OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/ProfilerGenericClassesUsr.h) +../inc/ProfilerGenericClassesUsr.inl OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/ProfilerGenericClassesUsr.inl) +../inc/ProfilerGenericClassesKrn.h OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/ProfilerGenericClassesKrn.h) +../inc/ProfilerGenericClassesKrn.inl OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/ProfilerGenericClassesKrn.inl) +../inc/ProfilerGenericClassesCommon.h OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/ProfilerGenericClassesCommon.h) +../inc/ProfilerEngineAPI.h OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/ProfilerEngineAPI.h) +../inc/EngineUIDs.h OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/EngineUIDs.h) +../inc/PluginDriver.h OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/PluginDriver.h) +../inc/PluginDriver.inl OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/PluginDriver.inl) +../inc/PluginSampler.h OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/PluginSampler.h) +../inc/ProfilerSession.h OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/ProfilerSession.h) +../inc/SamplerPluginInterface.h OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/SamplerPluginInterface.h) +../inc/SamplerPluginInterface.inl OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/SamplerPluginInterface.inl) +../inc/WriterPluginInterface.h OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/WriterPluginInterface.h) +../inc/WriterPluginInterface.inl OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/WriterPluginInterface.inl) +../inc/ProfilerEngineStatusChecker.h OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/ProfilerEngineStatusChecker.h) +../inc/ProfilerEngineStatusChecker.inl OS_LAYER_PLATFORM_EXPORT_PATH(piprofiler/ProfilerEngineStatusChecker.inl) diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/EngineUIDs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/EngineUIDs.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,29 @@ +/* +* 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: +* +*/ + + +#ifndef ENGINEUIDS_H +#define ENGINEUIDS_H + +#include <e32cmn.h> + +// No item is selected in the container's listbox +const TUid KSamplerNoneSelected = { 0x00000001 }; +const TUid KWriterNoneSelected = { 0x00000002 }; + +#endif // ENGINEUIDS_H +// End of File diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/PluginDriver.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/PluginDriver.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,85 @@ +/* +* 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: +* +*/ + + +#include <piprofiler/ProfilerGenericClassesKrn.h> + +const TInt KMinRate = 10; +const TInt KMaxRate = 1000; + +enum TState{ERunning, EStopping, EStopped}; + +const TUid KGppPropertyCat={0x20201F70}; +enum TGppPropertyKeys + { + EGppPropertySyncSampleNumber + }; + + +/* + * + * + * Class DPluginDriver definition, inherited by sampler implementations except GPP + * + * + */ + +class DPluginDriver : public DLogicalChannel +{ + +public: + DPluginDriver(); + ~DPluginDriver(); + +public: + TInt ProcessStreamReadCancel(); + + TInt StopSampling(); + +private: + TInt ProcessPrintStreamRequest(TDesC8* aDes/*,TRequestStatus* aStatus*/); + + void FastPrintf(TDesC8* aDes); + +public: + DThread* iClient; + + // property and value; + // GPP sampler start time, needed to set other samplers in sync + RPropertyRef iSampleStartTimeProp; + TInt iSampleStartTime; + TUint32 iSyncOffset; // offset from the start + + + TUint32 sampleRunning; + const TUint* iInterruptStack; + TState iState; + TInt doingDfc; + + // request status objects for requests + TRequestStatus* iEndRequestStatus; + TRequestStatus* iStreamReadCancelStatus; + + // sample stream object used in stream mode + DProfilerSampleStream iSampleStream; + + // just for testing + TUint32* stackTop; + +}; + +#include <piprofiler/PluginDriver.inl> diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/PluginDriver.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/PluginDriver.inl Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,77 @@ +/* +* 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: +* +*/ + + +// +// LDD for thread time profiling +// + +#include <piprofiler/ProfilerConfig.h> +#include <piprofiler/ProfilerVersion.h> + + +#include <kern_priv.h> +#include <sproperty.h> + +#include <piprofiler/PluginSampler.h> + + +/* + * + * + * Class DPluginDriver implementation + * + * + */ +inline DPluginDriver::DPluginDriver() //: iSubsRequest(&HandleSubsComplete, this) + { + //iClientProcess = &Kern::CurrentProcess(); + } +inline DPluginDriver::~DPluginDriver() + { + + } + +/* + * Methods for controlling stream read option + */ + +inline TInt DPluginDriver::ProcessStreamReadCancel() +{ + return KErrNone; +} + +/* + * Mark traces active or inactive, this can be done + * only if sampling is not running + */ + +inline TInt DPluginDriver::StopSampling() +{ + if(this->iState == ERunning) + { + this->iState = EStopping; + return KErrNone; + } + else + { + return KErrGeneral; + } +} + + + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/PluginSampler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/PluginSampler.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,247 @@ +/* +* 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: +* +*/ + + +#ifndef __PLUGINSAMPLER_H__ +#define __PLUGINSAMPLER_H__ + +/* + * The user-interface to the sampling device driver sued by the profiling engine + */ +// #include <piprofiler/ProfilerConfig.h> +// #include <piprofiler/ProfilerVersion.h> // versions removed from ProfilerConfig.h + +#ifndef __KERNEL_MODE__ +#include <utf.h> +#endif + +/* + * Forward declarations + */ +class TBapBuf; + +/** + * A minimal capabilities class for the Sampling device. + * It just returns the version number. + */ +class TCapsSamplerV01 + { +public: + TVersion iVersion; + }; + + +const TInt KMinDelay = 1; +const TInt KMaxDelay = 10000; + +/** + * The user device driver class for controlling the plugin sampler. + */ + +class RPluginSampler : public RBusLogicalChannel +{ + friend class DPluginDriver; + public: + enum TControl + { + EOutputSettingsForTrace, + EMarkTraceActive, + EMarkTraceInactive, + ESample, + EStartSampling, + EGetSampleTime, + EGetSamplerVersion, + EStopAndWaitForEnd, + ESetSamplingPeriod, + EAdditionalTraceSettings, + EAdditionalTraceSettings2, + EAdditionalTraceSettings3, + EAdditionalTraceSettings4, + //EPrintTraces, + ECancelStreamRead, + ERequestFillThisStreamBuffer, + ERequestPrintStreamBuffer, + ETest + }; + + public: + #ifndef __KERNEL_MODE__ + + inline ~RPluginSampler(); + + /** + * + * Methods for controlling the sampler device + * + **/ + /** Open a channel to the sampling device **/ + virtual TInt Open() = 0; + + /** Set sampling period for sampler */ + inline void SetSamplingPeriod(TInt samplerId, TInt settings); + + /** Set additional trace settings **/ + inline void AdditionalSettingsForTrace(TInt samplerId,TInt settings); + inline void AdditionalSettingsForTrace2(TInt samplerId,TInt settings); + inline void AdditionalSettingsForTrace3(TInt samplerId,TInt settings); + inline void AdditionalSettingsForTrace4(TInt samplerId,TInt settings); + + /** Mark trace active **/ + inline void MarkTraceActive(TUint32 id); + + /** Mark trace inactive **/ + inline void MarkTraceInactive(TUint32 id); + + /** Sample command to kernel LDD**/ + inline void Sample(); + + /** Start tracing **/ + inline void StartSampling(); + + /** Stop tracing **/ + inline void StopSampling(); + + /** Get current sampling time **/ + inline TUint32 GetSampleTime(); + + /** Get sampler version as descriptor **/ + virtual void GetSamplerVersion(TDes*); + + /** Get next filled buffer in stream mode **/ + void GetNextbuffer( ); + + /** Request stream read **/ + void FillThisStreamBuffer(TBapBuf* aBuffer, TRequestStatus& aStatus); + + /** Request print buffer**/ + void PrintStreamBuffer(TDesC16* aBuffer); + + /** Run test case **/ + inline void Test(TUint32 testCase); + + #endif // !__KERNEL_MODE__ +}; + + +#ifndef __KERNEL_MODE__ +inline RPluginSampler::~RPluginSampler() +{ +} + +inline void RPluginSampler::AdditionalSettingsForTrace(TInt samplerId,TInt settings) + { + DoControl(EAdditionalTraceSettings, + reinterpret_cast<TAny*>(samplerId), + reinterpret_cast<TAny*>(settings)); + } + +inline void RPluginSampler::AdditionalSettingsForTrace2(TInt samplerId,TInt settings) + { + DoControl(EAdditionalTraceSettings2, + reinterpret_cast<TAny*>(samplerId), + reinterpret_cast<TAny*>(settings)); + } + +inline void RPluginSampler::AdditionalSettingsForTrace3(TInt samplerId,TInt settings) + { + DoControl(EAdditionalTraceSettings3, + reinterpret_cast<TAny*>(samplerId), + reinterpret_cast<TAny*>(settings)); + } + +inline void RPluginSampler::AdditionalSettingsForTrace4(TInt samplerId,TInt settings) + { + DoControl(EAdditionalTraceSettings4, + reinterpret_cast<TAny*>(samplerId), + reinterpret_cast<TAny*>(settings)); + } + +inline void RPluginSampler::SetSamplingPeriod(TInt samplerId, TInt settings) + { + DoControl(ESetSamplingPeriod, + reinterpret_cast<TAny*>(samplerId), + reinterpret_cast<TAny*>(settings)); + } + + +inline void RPluginSampler::MarkTraceActive(TUint32 id) +{ + DoControl(EMarkTraceActive, reinterpret_cast<TAny*>(id)); +} + +inline void RPluginSampler::MarkTraceInactive(TUint32 id) +{ + DoControl(EMarkTraceInactive, reinterpret_cast<TAny*>(id)); +} + +inline void RPluginSampler::Sample() + { + DoControl(ESample); + } + +inline void RPluginSampler::StartSampling() +{ + // at first, start the kernel side samplers + DoControl(EStartSampling); +} + +inline void RPluginSampler::StopSampling() +{ + // stop the device driver and the kernel mode samplers + TRequestStatus status; + status = KRequestPending; + DoRequest(EStopAndWaitForEnd,status); + User::WaitForRequest(status); +} + +inline TUint32 RPluginSampler::GetSampleTime() +{ + TUint32* sampleTime = new TUint32; + + DoControl(EGetSampleTime,reinterpret_cast<TAny*>(sampleTime)); + TUint32 value = *sampleTime; + delete sampleTime; + + return value; +} + +inline void RPluginSampler::GetSamplerVersion(TDes* aDes) +{ + TBuf8<16> buf; + DoControl(EGetSamplerVersion,(TAny*)&buf); + CnvUtfConverter::ConvertToUnicodeFromUtf8(*aDes,buf); +} + +inline void RPluginSampler::PrintStreamBuffer(TDesC16* aDes) +{ + DoControl(ERequestPrintStreamBuffer,reinterpret_cast<TAny*>(aDes)); +} + +inline void RPluginSampler::FillThisStreamBuffer(TBapBuf* aBuffer, TRequestStatus& aStatus) +{ + aStatus = KRequestPending; + DoRequest(ERequestFillThisStreamBuffer,aStatus,(TAny*)aBuffer); + +} + +inline void RPluginSampler::Test(TUint32 testCase) +{ + DoControl(ETest,reinterpret_cast<TAny*>(testCase)); +} + +#endif +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/ProfilerAttributes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/ProfilerAttributes.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,151 @@ +/* +* 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: +* +*/ + + +#ifndef PROFILER_ATTRIBUTES_H +#define PROFILER_ATTRIBUTES_H + +// INCLUDES +#include <e32std.h> +#include <e32base.h> +#include <s32mem.h> + +// LITERALS +_LIT8(KDefaultTraceFilePrefix, "PIProfiler_#"); +_LIT8(KDefaultTraceOutput, "file_system"); +_LIT8(KDefaultTraceFileSaveDrive, "C:\\data\\"); + +_LIT8(KEnabled, "enabled"); +_LIT8(KBracketOpen, "["); +_LIT8(KBracketClose, "]"); +_LIT8(KSettingItemSeparator, "="); + +// CONSTANTS +const TUint KPrefixMaxLength = 64; +const TUint KShortNameMaxLength = 3; +const TUint KNameMaxLength = 63; +const TUint KDescriptionMaxLength = 255; +const TInt KDefaultTimedSamplingPeriod = 60; // Sampling time in seconds +/* + * + * TGeneralAttributes class definition, internal settings format + * + */ +class TGeneralAttributes + { +public: + TBuf8<KPrefixMaxLength> iTraceOutput; + TBuf8<KPrefixMaxLength> iTraceFilePrefix; + TBuf8<KPrefixMaxLength> iSaveFileDrive; + TInt iTimedSamplingPeriod; + }; + + + +/* + * + * TSettingItem class definition, internal settings format + * + */ +class TSettingItem + { +public: + enum + { + ESettingItemTypeInt = 0, + ESettingItemTypeBool, + ESettingItemTypeHex, + ESettingItemTypeText + }; + +public: + TBuf<64> iSettingText; + TUint32 iType; + TBuf<128> iValue; + TBuf<256> iSettingDescription; + TBuf<64> iUIText; + }; +/* + * + * TSamplerAttributes class definition, internal settings format + * + */ +class TSamplerAttributes + { +public: + // default constructor + TSamplerAttributes(); + // constructor + TSamplerAttributes(TInt32 aUid, + const TDesC8& aShortName, + const TDesC8& aName, + const TDesC8& aDescription, + TInt aSampleRate, + TBool aEnabled, + TBool aHidden, + TInt aItemCount); +public: + TInt32 iUid; + TBuf8<8> iShortName; // name of the plugin, short name + TBuf8<64> iName; // name of the plugin, long name + TBuf8<256> iDescription; // sampler description, info about HW/SW dependencies etc. + TInt iSampleRate; // sample rate of the plugin + TBool iEnabled; // enabled for profiling + TBool iIsHidden; // hidden, i.e. no start/stop controls + TInt iItemCount; // plugin specific setting item count + + // plugin specific settings, plugin implementation dependent + TSettingItem iSettingItem1; + TSettingItem iSettingItem2; + TSettingItem iSettingItem3; + TSettingItem iSettingItem4; + TSettingItem iSettingItem5; + TSettingItem iSettingItem6; + }; + +inline TSamplerAttributes::TSamplerAttributes() + {} + +inline TSamplerAttributes::TSamplerAttributes(TInt32 aUid, + const TDesC8& aShortName, + const TDesC8& aName, + const TDesC8& aDescription, + TInt aSampleRate, + TBool aEnabled, + TBool aHidden, + TInt aItemCount) + { + iUid = aUid; + // check if given short name too long + aShortName.Length() > KShortNameMaxLength ? + iShortName.Copy(aShortName.Left(KShortNameMaxLength)) : + iShortName.Copy(aShortName); + // check if given name too long + aName.Length() > KNameMaxLength ? + iName.Copy(aName.Left(KNameMaxLength)) : + iName.Copy(aName); + // check if description too long + aDescription.Length() > KDescriptionMaxLength ? + iDescription.Copy(aDescription.Left(KDescriptionMaxLength)) : + iDescription.Copy(aDescription); + iSampleRate = aSampleRate; + iEnabled = aEnabled; + iIsHidden = aHidden; + iItemCount = aItemCount; + } + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/ProfilerConfig.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/ProfilerConfig.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,108 @@ +/* +* 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: +* +*/ + + +#ifndef PI_PROFILER_CONFIG_H +#define PI_PROFILER_CONFIG_H + +// NCP release process will move the PIProfiler flags as Carbon feature flags +// where the product responsibles can choose the right settings for PI Profiler +// compilation. + + /*** NOTE!!! + * Uncomment the following definition if compiling the Profiler by your own + ***/ + #define PROFILER_SISX + + /* + * + * Filename and path for the settings file + * this file is written on application exit and + * it contains the settings of the profiler application + * + */ + +// #define PROFILER_SETTINGS_DRIVE _L("C:\\") +// #define PROFILER_SETTINGS_MAXLENGTH 32 +// #define PROFILER_SETTINGS_FILENAME _L("ProfilerSettings.txt") + const TInt KProfilerSettingsMaxLength = 32; + _LIT(KProfilerSettingsFileName, "PIProfilerSettings.txt"); + + // a fix for going through the different drives for settings file + #define PROFILER_SETTINGS_DRIVE_COUNT 3 + #define PROFILER_SETTINGS_DRIVE_ARRAY TBuf<4> settingsDrives[PROFILER_SETTINGS_DRIVE_COUNT]; + #define PROFILER_DEFINE_SETTINGS_DRIVE(name,number) settingsDrives[number].Append(_L(name)); + + // change these to reflect the drive names and numbers + // the last number must be PROFILER_SETTINGS_DRIVE_COUNT-1 + #define PROFILER_SETTINGS_DRIVES PROFILER_DEFINE_SETTINGS_DRIVE("C:\\",0) \ + PROFILER_DEFINE_SETTINGS_DRIVE("E:\\",1) \ + PROFILER_DEFINE_SETTINGS_DRIVE("Z:\\",2) + + /* + * + * Locations of PI Profiler binaries + * + */ + + #define PROFILERENGINE_EXE_PATH_PRIMARY _L("C:\\sys\\bin\\PIProfilerEngine.exe") + #define PROFILERENGINE_EXE_PATH_SECONDARY _L("Z:\\sys\\bin\\PIProfilerEngine.exe") + + /* + * + * PI Profiler tool composition definitions + * + */ + + // sampler codes and names + #define PROFILER_USER_MODE_SAMPLER 123 + #define PROFILER_KERNEL_MODE_SAMPLER 321 + #define PROFILER_DUMMY_SAMPLER 213 + + // old definitions + #define PROFILER_GENERALS_SAMPLER_ID 100 + #define PROFILER_INTERNALS_SAMPLER_ID 101 + #define PROFILER_GPP_SAMPLER_ID 1 + #define PROFILER_GFC_SAMPLER_ID 2 + #define PROFILER_ITT_SAMPLER_ID 3 + #define PROFILER_MEM_SAMPLER_ID 4 + #define PROFILER_PRI_SAMPLER_ID 5 + #define PROFILER_IRQ_SAMPLER_ID 6 + #define PROFILER_BUP_SAMPLER_ID 7 + #define PROFILER_SWI_SAMPLER_ID 8 + #define PROFILER_TIP_SAMPLER_ID 9 + #define PROFILER_PEC_SAMPLER_ID 10 + #define PROFILER_PWR_SAMPLER_ID 11 + #define PROFILER_IPC_SAMPLER_ID 12 + #define PROFILER_ISA_SAMPLER_ID 13 + #define PROFILER_GPU_SAMPLER_ID 14 + + // sampler IDs for external, e.g. 3rd party sampler plug-ins + #define PROFILER_EXT1_SAMPLER_ID 15 + #define PROFILER_EXT2_SAMPLER_ID 16 + #define PROFILER_EXT3_SAMPLER_ID 17 + #define PROFILER_EXT4_SAMPLER_ID 18 + #define PROFILER_EXT5_SAMPLER_ID 19 + + #define PROFILER_GPP_SAMPLER_NAME _L("GPP") + #define PROFILER_GFC_SAMPLER_NAME _L("GFC") + #define PROFILER_ITT_SAMPLER_NAME _L("ITT") + #define PROFILER_MEM_SAMPLER_NAME _L("MEM") + #define PROFILER_PRI_SAMPLER_NAME _L("PRI") + #define PROFILER_GPU_SAMPLER_NAME _L("GPU") + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/ProfilerEngineAPI.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/ProfilerEngineAPI.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,88 @@ +/* +* 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: +* +*/ + + +#ifndef PROFILERCONTROLLER_H +#define PROFILERCONTROLLER_H + +#include <e32std.h> +#include <s32stor.h> + +class CProfilerSettings; + +class CProfilerEngineAPI : public CBase +{ +public: + enum TProfilerEngineTraceMode + { + EProfilerEngineDebugOutputMode, + EProfilerEngineFileSystemMode + }; + + ~CProfilerEngineAPI(); + + IMPORT_C static CProfilerEngineAPI* NewL(); + void ConstructL(); + + IMPORT_C void SaveSettings(); + IMPORT_C void LoadSettings(); + + // controlling all sampler plugins + IMPORT_C TInt StartProfiling(); + IMPORT_C TBool StopProfiling(); + IMPORT_C TInt LaunchProfiler(); + + // controlling separate plugins + IMPORT_C TInt StartSampler(TUint32 aUid); + IMPORT_C TInt StopSampler(TUint32 aUid); + IMPORT_C TInt EnableSampler(TUint32 aUid); + IMPORT_C TInt DisableSampler(TUint32 aUid); + IMPORT_C TInt EnableWriter(TUint32 aUid); + IMPORT_C TInt DisableWriter(TUint32 aUid); + + // for meeting the HTI requirements + IMPORT_C TInt SetSettings(TUint aSamplerId, TDes& aSettings); + IMPORT_C TInt SetTraceMode(TProfilerEngineTraceMode aMode, TDes& aTraceDataStruct); + IMPORT_C TInt GetSamplerInfo(TUint aSamplerId, TDes& aCompleteSamplerInfo); + + // old implementations + IMPORT_C TBool GetSamplerVersion(TDes& version); + + IMPORT_C void LeaveProfilerBG(TBool aVal); + + +public: + TBool DriveIsValidL(const TDesC& drive); + IMPORT_C CProfilerSettings* Settings() const; + +private: + + CProfilerEngineAPI(); + + TInt FindProcessL(); +private: + CProfilerSettings* iSettings; + + RProcess* iProfilerProcess; + + TBool iProfilerLaunched; + + TBool iLeaveProfilerBG; + + }; + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/ProfilerEngineStatusChecker.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/ProfilerEngineStatusChecker.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,74 @@ +/* +* 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: +* +*/ + +#ifndef PROFILER_STATUS_CHECKER_H +#define PROFILER_STATUS_CHECKER_H + +#include <e32std.h> +#include <e32base.h> +#include <e32property.h> // RProperty + +// CONSTANTS +const TUid KEngineStatusPropertyCat = { 0x2001E5AD }; +enum TEnginePropertyKeys + { + EProfilerEngineStatus = 8 + }; + +// CLASS DECLARATIONS +class MProfilerStatusObserver + { + public: // Enums + enum KProfilerStatus + { + EIdle = 0, + EInitializing, + ERunning, + EStopping, + ERestarting + }; + + public: // New + virtual void HandleProfilerStatusChange( + KProfilerStatus aStatus ) = 0; + virtual void HandleProfilerErrorL( + TInt aError ) = 0; + }; + + +class CProfilerEngineStatusChecker : public CActive + { +public: + inline static CProfilerEngineStatusChecker* CProfilerEngineStatusChecker::NewL(); + inline ~CProfilerEngineStatusChecker(); + inline void SetObserver(MProfilerStatusObserver* aObserver); + inline TInt GetInitialState(); +private: + inline CProfilerEngineStatusChecker(); + inline void ConstructL(); + inline void RunL(); + inline void DoCancel(); +private: + TInt iPrevStat; + MProfilerStatusObserver* iObserver; + RProperty iEngineStatus; + }; + +#include <piprofiler/ProfilerEngineStatusChecker.inl> + + +#endif // PROFILER_STATUS_CHECKER_H diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/ProfilerEngineStatusChecker.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/ProfilerEngineStatusChecker.inl Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,128 @@ +/* +* 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: +* +*/ + +// ------------------------------------------------------------------------------ +// +// class CProfilerEngineStatusChecker +// +// ------------------------------------------------------------------------------ +// +inline CProfilerEngineStatusChecker* CProfilerEngineStatusChecker::NewL() + { + CProfilerEngineStatusChecker* self = new(ELeave) CProfilerEngineStatusChecker(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +// -------------------------------------------------------------------------------------------- +inline CProfilerEngineStatusChecker::CProfilerEngineStatusChecker() : + CActive(EPriorityStandard) + { + } + +inline CProfilerEngineStatusChecker::~CProfilerEngineStatusChecker() + { + Cancel(); + iEngineStatus.Close(); + } + +// -------------------------------------------------------------------------------------------- +inline void CProfilerEngineStatusChecker::ConstructL() + { + User::LeaveIfError(iEngineStatus.Attach(KEngineStatusPropertyCat, EProfilerEngineStatus)); + CActiveScheduler::Add(this); + + // check engine status, if not available set to idle + if(iEngineStatus.Get(iPrevStat) != KErrNone) + { + iPrevStat = MProfilerStatusObserver::EIdle; + } + + // subscribe to P&S status property + iEngineStatus.Subscribe(iStatus); + SetActive(); + } + +inline TInt CProfilerEngineStatusChecker::GetInitialState() + { + // check engine status, if not available set to idle + TInt err(iEngineStatus.Get(KEngineStatusPropertyCat, EProfilerEngineStatus, iPrevStat)); + if(err != KErrNone) + { + iPrevStat = MProfilerStatusObserver::EIdle; + } + return iPrevStat; + } + +// -------------------------------------------------------------------------------------------- +inline void CProfilerEngineStatusChecker::RunL() + { + // resubscribe before processing new value to prevent missing updates + iEngineStatus.Subscribe(iStatus); + SetActive(); + + TInt stat(0); + if(iEngineStatus.Get(KEngineStatusPropertyCat, EProfilerEngineStatus, stat) == KErrNone) + { + // check if status one of error codes (< 0) + if(stat < KErrNone) + { + // some error occurred on engine side => set UI idle and show an error note + iObserver->HandleProfilerErrorL(stat); + } + else + { + if(iPrevStat != stat) + { + switch(stat) + { + case 0: + iObserver->HandleProfilerStatusChange(MProfilerStatusObserver::EIdle); + break; + case 1: + iObserver->HandleProfilerStatusChange(MProfilerStatusObserver::EInitializing); + break; + case 2: + iObserver->HandleProfilerStatusChange(MProfilerStatusObserver::ERunning); + break; + case 3: + iObserver->HandleProfilerStatusChange(MProfilerStatusObserver::EStopping); + break; + default: + iObserver->HandleProfilerErrorL(stat); + break; + } + iPrevStat = stat; + } + } + } + } + +// -------------------------------------------------------------------------------------------- + +inline void CProfilerEngineStatusChecker::DoCancel() + { + iEngineStatus.Cancel(); + } + +// -------------------------------------------------------------------------------------------- +inline void CProfilerEngineStatusChecker::SetObserver(MProfilerStatusObserver* aObserver) + { + iObserver = aObserver; + } diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/ProfilerGenericClassesCommon.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/ProfilerGenericClassesCommon.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,55 @@ +/* +* 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: +* +*/ + + +#ifndef PROFILERGENERICCLASSESCOMMON_H +#define PROFILERGENERICCLASSESCOMMON_H + + #include <e32cmn.h> + +/* + * + * Class TProfilerSampleBufStruct definition + * + */ + + +class TProfilerSampleBufStruct +{ +public: + TUint32 iSampleRemainder; + TUint8 iDataStart; +}; + +/* + * + * Class TBapBuf definition + * + */ + +class TBapBuf +{ +public: + TPtr8* iDes; + TPtr8* iBufDes; + TInt iBufferSize; + TInt iDataSize; + TUint8* iBuffer; + TBapBuf* iNext; +}; + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/ProfilerGenericClassesKrn.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/ProfilerGenericClassesKrn.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,422 @@ +/* +* 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: +* +*/ + + +#ifndef PROFILERGENERICCLASSESKRN_H +#define PROFILERGENERICCLASSESKRN_H + + #include <piprofiler/ProfilerGenericClassesCommon.h> + #include <piprofiler/ProfilerTraces.h> + + #include <e32cmn.h> + + #define PROFILER_KERNEL_MODE + +#ifdef PROFILER_KERNEL_MODE +class DProfilerSampleBuffer; + +class DProfilerSampleStream + { +public: + DProfilerSampleStream(); + ~DProfilerSampleStream(); + + void InsertCurrentClient(DThread* aClient); + void AddSampleBuffer(TBapBuf* aBuffer,TRequestStatus* aStatus); + void ReleaseIfPending(); + + void AddSamples(DProfilerSampleBuffer& aBuffer, TInt aSamplerId); + TInt EndSampling(DProfilerSampleBuffer& aBuffer,TInt aSamplerId); + + void PerformCopy(TUint8 aSamplerId,TUint8* aSrc,TPtr8* dst,TInt aOffset,TInt aAmount); + +private: + TBapBuf* iCurrentBuffer; + TRequestStatus* iPendingRequest; + DThread* iClient; + TInt iAddingSamples; + }; + +class DProfilerSampleBuffer : public DBase + { + friend class DProfilerSampleStream; +public: + + enum ProfilerBufferStatus + { + BufferOk, + BufferCopyAsap, + BufferBeingCopied, + BufferFull, + BufferDataEnd + }; + + DProfilerSampleBuffer(TUint8* aBuffer, TUint8* aDblBuffer, TUint32 aSize); + ~DProfilerSampleBuffer(); + TInt AddSample(TUint8* aSample, TUint32 aLength); + TUint32 GetBufferStatus(); + void ClearBuffer(); + void EndSampling(); + void DataCopied(); + + TUint32 iBufferStatus; +private: + TUint32 iBytesWritten; + TUint32 iDblBytesWritten; + TUint32 iDblBytesRead; + + TUint32 iBufferDataSize; + TUint32 iBufferRealSize; + + TProfilerSampleBufStruct* iDblBufStruct; + TProfilerSampleBufStruct* iBufStruct; + }; + +#endif + + + +/* + * + * Abstract class CProfilerSamplerBase definition + * + */ + +#ifdef PROFILER_KERNEL_MODE +class DProfilerSamplerBase : public DBase + { +public: + DProfilerSamplerBase(); + virtual ~DProfilerSamplerBase(); + + virtual TInt Initialise() = 0; + virtual void Sample() = 0; + virtual TBool PostSampleNeeded() = 0; + virtual TInt PostSample() = 0; + virtual TInt EndSampling() = 0; + + virtual TInt Reset(DProfilerSampleStream* aStream = 0, TUint32 aSyncOffset = 0) = 0; + + virtual void SetEnabledFlag(TBool aFlag) = 0; + virtual TBool GetEnabledFlag() = 0; + virtual void SetOutputCombination(TInt aSettings) = 0; + virtual void SetSamplingPeriod(TInt aSettings) = 0; + virtual void SetAdditionalSettings(TInt aSettings) = 0; + virtual void SetAdditionalSettings2(TInt aSettings) = 0; + virtual void SetAdditionalSettings3(TInt aSettings) = 0; + virtual void SetAdditionalSettings4(TInt aSettings) = 0; + + TInt iSamplerId; + TInt iOutputCombination; + TBool iEnabled; + }; + +/* + * + * Template abstract class CProfilerGenericSampler definition + * + */ + +// size parameter given defines the explicit buffer size in bytes for this sampler +template <int BufferSize> +class DProfilerGenericSampler : public DProfilerSamplerBase + { +public: + DProfilerGenericSampler(TInt aSamplerId); + virtual ~DProfilerGenericSampler(); + + TInt Initialise(); + virtual void Sample() = 0; + TBool PostSampleNeeded(); + TInt PostSample(); + TInt EndSampling(); + virtual TInt Reset(DProfilerSampleStream* aStream = 0, TUint32 aSyncOffset = 0); + + + void SetEnabledFlag(TBool aFlag); + TBool GetEnabledFlag(); + void SetOutputCombination(TInt aComb); + void SetSamplingPeriod(TInt aSettings); + void SetAdditionalSettings(TInt aSettings); + void SetAdditionalSettings2(TInt aSettings); + void SetAdditionalSettings3(TInt aSettings); + void SetAdditionalSettings4(TInt aSettings); + + DProfilerSampleBuffer* iSampleBuffer; + DProfilerSampleStream* iStream; + + // for right alignment + TUint8 iBuffer[BufferSize+4]; + TUint8 iDblBuffer[BufferSize+4]; + + TInt iSamplingPeriod; + TInt iAdditionalSettings; + TInt iAdditionalSettings2; + TInt iAdditionalSettings3; + TInt iAdditionalSettings4; + }; + +/* + * + * Template abstract class CProfilerGenericSampler implementation + * + */ + +template <int BufferSize> +DProfilerGenericSampler<BufferSize>::DProfilerGenericSampler(TInt aSamplerId) + { + iSamplerId = aSamplerId; + iEnabled = false; + iSampleBuffer = 0; + iAdditionalSettings = 0; + iAdditionalSettings2 = 0; + iAdditionalSettings3 = 0; + iAdditionalSettings4 = 0; + iStream = 0; + Initialise(); + } + +template <int BufferSize> +DProfilerGenericSampler<BufferSize>::~DProfilerGenericSampler() + { + LOGSTRING2("CProfilerGenericSampler<%d>::CProfilerGenericSampler",BufferSize); + + if(iSampleBuffer != 0) + delete iSampleBuffer; + + } + +template <int BufferSize> +TInt DProfilerGenericSampler<BufferSize>::Initialise() + { + LOGSTRING2("CProfilerGenericSampler<%d>::Initialise - chunk option",BufferSize); + + // stream is not used in chunk mode + iStream = 0; + + // create the sample buffer object with the buffers + if(iSampleBuffer == 0) + { + iSampleBuffer = new DProfilerSampleBuffer(iBuffer,iDblBuffer,BufferSize); + } + else + { + LOGSTRING2("CProfilerGenericSampler<%d>::Initialise - ERROR 1",BufferSize); + } + + return KErrNone; + } + + + +template <int BufferSize> +TInt DProfilerGenericSampler<BufferSize>::Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset) + { + LOGSTRING4("CProfilerGenericSampler<%d>::Reset %d, sync offset %d",BufferSize,aStream,aSyncOffset); + // reset the sample buffer and resolve the chunk again + + // CURRENT VERSION SUPPORTS ONLY STREAM MODE! + LOGSTRING2("CProfilerGenericSampler<%d>::Reset - stream option",BufferSize); + + // initialise the sampler with the stream option + iStream = aStream; + + // clear the sample buffer + if(iSampleBuffer != 0) + { + iSampleBuffer->ClearBuffer(); + } + else + { + LOGSTRING2("CProfilerGenericSampler<%d>::Initialise - ERROR no buffer",BufferSize); + } + + return KErrNone; + + } + +template <int BufferSize> +TBool DProfilerGenericSampler<BufferSize>::PostSampleNeeded() + { + LOGSTRING4("CProfilerGenericSampler<%d>::PostSampleNeeded - ID %d, state %d",iSamplerId,BufferSize,iSampleBuffer->GetBufferStatus()); + + TUint32 status = iSampleBuffer->iBufferStatus; + + if(status == DProfilerSampleBuffer::BufferCopyAsap || status == DProfilerSampleBuffer::BufferFull) + { + return true; + } + + return false; + } + + +template <int BufferSize> +TInt DProfilerGenericSampler<BufferSize>::PostSample() + { + LOGSTRING4("CProfilerGenericSampler<%d>::PostSample - ID %d, state %d",iSamplerId,BufferSize,iSampleBuffer->GetBufferStatus()); + + TUint32 status = iSampleBuffer->iBufferStatus; + + if(status == DProfilerSampleBuffer::BufferCopyAsap || status == DProfilerSampleBuffer::BufferFull) + { + // write data to the stream + iStream->AddSamples(*iSampleBuffer,iSamplerId); + } + + return KErrNone; + } + +template <int BufferSize> +TInt DProfilerGenericSampler<BufferSize>::EndSampling() + { + LOGSTRING3("CProfilerGenericSampler<%d>::EndSampling, ID %d",BufferSize,iSamplerId); + + // only if write to stream option is selected + if(iStream->EndSampling(*iSampleBuffer,iSamplerId) == 0) + { + return KErrNone; + } + else + { + // there is still data to copy + return KErrNotReady; + } + } + +template <int BufferSize> +void DProfilerGenericSampler<BufferSize>::SetEnabledFlag(TBool aFlag) + { + LOGSTRING2("CProfilerGenericSampler<%d>::SetEnabledFlag",BufferSize); + iEnabled = aFlag; + } + +template <int BufferSize> +TBool DProfilerGenericSampler<BufferSize>::GetEnabledFlag() + { + LOGSTRING2("CProfilerGenericSampler<%d>::GetEnabledFlag",BufferSize); + return iEnabled; + } + +template <int BufferSize> +void DProfilerGenericSampler<BufferSize>::SetOutputCombination(TInt aComb) + { + LOGSTRING2("CProfilerGenericSampler<%d>::SetOutputCombination",BufferSize); + iOutputCombination = aComb; + } + +template <int BufferSize> +void DProfilerGenericSampler<BufferSize>::SetAdditionalSettings(TInt aSettings) + { + LOGSTRING3("CProfilerGenericSampler<%d>::SetAdditionalSettings to 0x%x",BufferSize,aSettings); + iAdditionalSettings = aSettings; + } + +template <int BufferSize> +void DProfilerGenericSampler<BufferSize>::SetAdditionalSettings2(TInt aSettings) + { + LOGSTRING3("CProfilerGenericSampler<%d>::SetAdditionalSettings2 to 0x%x",BufferSize,aSettings); + iAdditionalSettings2 = aSettings; + } + +template <int BufferSize> +void DProfilerGenericSampler<BufferSize>::SetAdditionalSettings3(TInt aSettings) + { + LOGSTRING3("CProfilerGenericSampler<%d>::SetAdditionalSettings3 to 0x%x",BufferSize,aSettings); + iAdditionalSettings3 = aSettings; + } + +template <int BufferSize> +void DProfilerGenericSampler<BufferSize>::SetAdditionalSettings4(TInt aSettings) + { + LOGSTRING3("CProfilerGenericSampler<%d>::SetAdditionalSettings4 to 0x%x",BufferSize,aSettings); + iAdditionalSettings4 = aSettings; + } + +template <int BufferSize> +void DProfilerGenericSampler<BufferSize>::SetSamplingPeriod(TInt aSettings) + { + LOGSTRING3("CProfilerGenericSampler<%d>::SetSamplingPeriod to 0x%x",BufferSize,aSettings); + iSamplingPeriod = aSettings; + } + +/* + * + * Just a test class that is derived from CProfilerGenericSampler + * + */ + +template <int BufferSize> +class DProfilerExampleSampler : public DProfilerGenericSampler<BufferSize> + { +public: + TUint32 iSampleNumber; + + DProfilerExampleSampler(TInt aSamplerId); + ~DProfilerExampleSampler(); + + void Sample(); + void Sample(TInt aCount, TInt aLastPc); + }; + + +/* + * + * Just a test class that is derived from CProfilerGenericSampler + * + */ + +template <int BufferSize> +DProfilerExampleSampler<BufferSize>::DProfilerExampleSampler(TInt aSamplerId) : + DProfilerGenericSampler<BufferSize>(aSamplerId) + { + iSampleNumber = 0; + LOGSTRING2("CProfilerExampleSampler<%d>::CProfilerExampleSampler",BufferSize); + } + +template <int BufferSize> +void DProfilerExampleSampler<BufferSize>::Sample() + { + LOGSTRING2("CProfilerExampleSampler<%d>::Sample",BufferSize); + TBuf8<20>* testiBuf = new TBuf8<20>; + + testiBuf->AppendNum((TInt)iSampleNumber); + iSampleNumber++; + + this->iSampleBuffer->AddSample((TUint8*)testiBuf->Ptr(),testiBuf->Length()); + delete testiBuf; + return; + } + +template <int BufferSize> +void DProfilerExampleSampler<BufferSize>::Sample(TInt aCount, TInt aLastPc) + { + return; + } + +template <int BufferSize> +DProfilerExampleSampler<BufferSize>::~DProfilerExampleSampler() + { + LOGSTRING2("CProfilerExampleSampler<%d>::~CProfilerExampleSampler",BufferSize); + } + +#include <piprofiler/ProfilerGenericClassesKrn.inl> + +#endif + + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/ProfilerGenericClassesKrn.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/ProfilerGenericClassesKrn.inl Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,530 @@ +/* +* 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: +* +*/ + + +#include <kern_priv.h> + +#include <piprofiler/ProfilerGenericClassesKrn.h> + + +/* + * + * Class CProfilerSamplerBase implementation + * + */ + +inline DProfilerSamplerBase::DProfilerSamplerBase() + { + + } + +inline DProfilerSamplerBase::~DProfilerSamplerBase() + { + + } + +/* + * + * Class CProfilerSampleBuffer implementation + * + */ + +inline DProfilerSampleBuffer::DProfilerSampleBuffer(TUint8* aBuffer, + TUint8* aDblBuffer, + TUint32 aBufferSize ) + { + LOGSTRING3("CProfilerSampleBuffer::CProfilerSampleBuffer AtFirst: b:0x%x db:0x%x",aBuffer,aDblBuffer); + + // make sure the alignment is right + if((((TUint32)aBuffer) %4) != 0) + aBuffer += (4-(((TUint32)aBuffer)%4)); + if((((TUint32)aDblBuffer) %4) != 0) + aDblBuffer += (4-(((TUint32)aDblBuffer)%4)); + + LOGSTRING3("CProfilerSampleBuffer::CProfilerSampleBuffer b:0x%x db:0x%x",aBuffer,aDblBuffer); + + iBufStruct = (TProfilerSampleBufStruct*)aBuffer; + iDblBufStruct = (TProfilerSampleBufStruct*)aDblBuffer; + + LOGSTRING3("CProfilerSampleBuffer::CProfilerSampleBuffer bufStruct rem:0x%x dbuStruct rem:0x%x", + &iBufStruct->iSampleRemainder,&iDblBufStruct->iSampleRemainder); + + iBufferDataSize = aBufferSize-4; + iBufferRealSize = aBufferSize; + + ClearBuffer(); + } + +inline DProfilerSampleBuffer::~DProfilerSampleBuffer() + { + + } + +inline TInt DProfilerSampleBuffer::AddSample(TUint8* aSample, TUint32 aLength) + { + TUint32 bytesTotal; + + // check whether the buffer status is + switch (iBufferStatus) + { + case DProfilerSampleBuffer::BufferOk: + // add the data normally to the buffer + bytesTotal = iBytesWritten+aLength; + + if(bytesTotal < iBufferDataSize) + { + memcpy((&(iBufStruct->iDataStart))+iBytesWritten,aSample,aLength); + iBytesWritten+=aLength; + return 0; + } + else + { + + // the sample does not fit to the buffer + // first copy as much data as we can fit to the first buffer + TUint32 fitsToBuffer = iBufferDataSize-iBytesWritten; + TUint32 remaining = aLength-fitsToBuffer; + + memcpy((&(iBufStruct->iDataStart))+iBytesWritten,aSample,fitsToBuffer); + iBytesWritten = iBufferDataSize; + + // ->switch to the double buffer + iBufferStatus = DProfilerSampleBuffer::BufferCopyAsap; + + TProfilerSampleBufStruct* tmpPtr = iBufStruct; + iBufStruct = iDblBufStruct; + iDblBufStruct = tmpPtr; + + iDblBytesWritten = iBytesWritten; + + // and this is the remainder of a sample + // that will be copied to the new buffer + // just in a while + iBufStruct->iSampleRemainder = remaining; + + // now that the buffers have been switched + // add the rest of the sample to the buffer + aSample+=fitsToBuffer; + + // there should be room - in case the single sample + // is smaller than the whole buffer! so we don't + // bother to check + + memcpy((&(iBufStruct->iDataStart)),aSample,remaining); + iBytesWritten = remaining; + return 0; + } + + case DProfilerSampleBuffer::BufferCopyAsap: + + // no difference to the BufferOk case + // unless the double buffer gets filled + // before the data has been copied + // add the data normally to the buffer + bytesTotal = iBytesWritten+aLength; + + if(bytesTotal < iBufferDataSize) + { + memcpy((&(iBufStruct->iDataStart))+iBytesWritten,aSample,aLength); + iBytesWritten+=aLength; + return 0; + } + else + { + // the double buffer is now also full - there is no + // place to put the data -> we have to waste it! + // this is an indication of a too small buffer size + iBufferStatus = DProfilerSampleBuffer::BufferFull; + LOGSTRING("DProfilerSampleBuffer::AddSample - double buffer full1!!"); + return -1; + } + + case DProfilerSampleBuffer::BufferBeingCopied: + + // no difference to the BufferCopyAsap case + bytesTotal = iBytesWritten+aLength; + + if(bytesTotal < iBufferDataSize) + { + memcpy((&(iBufStruct->iDataStart))+iBytesWritten,aSample,aLength); + iBytesWritten+=aLength; + return 0; + } + else + { + // the double buffer is now also full - there is no + // place to put the data -> we have to waste it! + // this is an indication of a too small buffer size + LOGSTRING("DProfilerSampleBuffer::AddSample - double buffer full2!!"); + + // don't change the state to CProfilerSampleBuffer::BufferFull, since it is + // already being copied + return -1; + } + + case DProfilerSampleBuffer::BufferFull: + // the buffer is still full, there is noting we can do + // about it -> return + LOGSTRING("DProfilerSampleBuffer::AddSample - double buffer full3!!"); + return -1; + + default: + LOGSTRING("DProfilerSampleBuffer::AddSample - wrong switch!!"); + return -1; + } + } + +inline void DProfilerSampleBuffer::EndSampling() + { + LOGSTRING("DProfilerSampleBuffer::EndSampling"); + // this will switch to the dbl buffer even though + // the buffer is not full, so that data can be copied + + // during this operation, no other buffer + // operations are allowed + + // ensure that the normal buffer is in use and that the + // buffer is in normal state ( this procedure is performed only once ) + if(iBufferStatus == DProfilerSampleBuffer::BufferOk) + { + // ->switch to the double buffer + LOGSTRING("DProfilerSampleBuffer::EndSampling - switching to double buffer"); + iBufferStatus = DProfilerSampleBuffer::BufferCopyAsap; + + TProfilerSampleBufStruct* tmpPtr = iBufStruct; + iBufStruct = iDblBufStruct; + iDblBufStruct = tmpPtr; + + iDblBytesWritten = iBytesWritten; + + // there is no new sample so the remainder is + // zero, (this shouldn't be used anyway) + iBufStruct->iSampleRemainder = 0; + } + } + +inline TUint32 DProfilerSampleBuffer::GetBufferStatus() + { + return iBufferStatus; + } + +inline void DProfilerSampleBuffer::ClearBuffer() + { + LOGSTRING2("CProfilerSampleBuffer::ClearBuffer - %d",iBufferDataSize); + + // the buffers are of same size + TUint8* ptr1 = (TUint8*)&(iBufStruct->iDataStart); + TUint8* ptr2 = (TUint8*)&(iDblBufStruct->iDataStart); + + for(TUint32 i=0;i<iBufferDataSize;i++) + { + ptr1[i] = 0; + ptr2[i] = 0; + } + + + iBufStruct->iSampleRemainder = 0; + iDblBufStruct->iSampleRemainder = 0; + + // written the dblBufStruct + iBytesWritten = 0; + iDblBytesWritten = 0; + iDblBytesRead = 0; + + iBufferStatus = DProfilerSampleBuffer::BufferOk; + } + +inline void DProfilerSampleBuffer::DataCopied() + { + iDblBytesRead = 0; + iDblBytesWritten = 0; + iBufferStatus = DProfilerSampleBuffer::BufferOk; + } + +/* + * + * Class DProfilerSampleStream implementation + * + */ + +inline DProfilerSampleStream::DProfilerSampleStream() + { + LOGSTRING("DProfilerSampleStream::DProfilerSampleStream"); + + iCurrentBuffer = 0; + iPendingRequest = 0; + iAddingSamples = 0; + iClient = 0; + } + +inline DProfilerSampleStream::~DProfilerSampleStream() + { + LOGSTRING("DProfilerSampleStream::~DProfilerSampleStream"); + } + +inline void DProfilerSampleStream::InsertCurrentClient(DThread* aClient) + { + iClient = aClient; + LOGSTRING2("DProfilerSampleStream::InsertCurrentClient - iClient is 0x%x",iClient); + } + + +inline void DProfilerSampleStream::AddSampleBuffer(TBapBuf* aBuffer,TRequestStatus* aStatus) + { + if(iCurrentBuffer != 0 || iPendingRequest != 0) + { + LOGSTRING("DProfilerSampleStream::AddSampleBuffer - ERROR 1"); + return; + } + + LOGSTRING3("DProfilerSampleStream::AddSampleBuffer - OK 0x%x,0x%x",aBuffer,aStatus); + iCurrentBuffer = aBuffer; + iPendingRequest = aStatus; + + LOGSTRING2("DProfilerSampleStream::AddSampleBuffer - Current Client is 0x%x",iClient); + } + + +inline void DProfilerSampleStream::ReleaseIfPending() + { + LOGSTRING("DProfilerSampleStream::ReleaseIfPending - entry"); + + if(iCurrentBuffer != 0 && iPendingRequest != 0 && iClient != 0) + { + LOGSTRING("DProfilerSampleStream::ReleaseIfPending - release buffer"); + + LOGSTRING2("DProfilerSampleStream::AddSamples - completing request 0x%x",iPendingRequest); + Kern::RequestComplete(iClient,iPendingRequest,KErrNone); + + iPendingRequest = 0; + iCurrentBuffer = 0; + } + + LOGSTRING("DProfilerSampleStream::ReleaseIfPending - exit"); + } + +inline void DProfilerSampleStream::AddSamples(DProfilerSampleBuffer& aBuffer, TInt aSamplerId) + { + LOGSTRING3("DProfilerSampleStream::AddSamples - entry ID: %d, currentbuffer: 0x%x", aSamplerId,iCurrentBuffer); + if(iCurrentBuffer != 0) + { + // the following will perform simple mutual exclusion + iAddingSamples++; + if(iAddingSamples > 1) + { + // there is someone else adding samples to the buffer + LOGSTRING("DProfilerSampleStream::AddSamples - mutex in use"); + iAddingSamples--; + return; + } + + LOGSTRING("DProfilerSampleStream::AddSamples - reading TBapBuf"); + + // use a copy of the client TBapBuf structure during processing + TBapBuf realBuf; + TPtr8 ptr((TUint8*)&realBuf,(TInt)sizeof(TBapBuf)); + + Kern::ThreadRawRead(iClient,(TAny*)(iCurrentBuffer),(TAny*)&realBuf,sizeof(TBapBuf)); + + ptr.SetLength(sizeof(TBapBuf)); + + LOGSTRING4("DProfilerSampleStream::AddSamples - read %d bytes from 0x%x of thread 0x%x",ptr.Size(),iCurrentBuffer,iClient); + + LOGSTRING5("DProfilerSampleStream::AddSamples - current buffer 0x%x -> b:0x%x s:%d d:%d", + &realBuf, + realBuf.iBuffer, + realBuf.iBufferSize, + realBuf.iDataSize); + + // get the address of the source buffer data + TUint8* src = (TUint8*)&(aBuffer.iDblBufStruct->iDataStart); + src += aBuffer.iDblBytesRead; + + // the amount of data to copy is the 4 header bytes + + // the remaining data in the buffer + TInt amount = aBuffer.iDblBytesWritten-aBuffer.iDblBytesRead; + + TUint8* dst = realBuf.iBuffer; + + LOGSTRING4("DProfilerSampleStream::AddSamples - s:0x%x d:0x%x a:%d",src,dst,amount); + + if(realBuf.iDataSize == 0) + { + LOGSTRING("DProfilerSampleStream::AddSamples - case 1"); + + // the buffer is empty + if(realBuf.iBufferSize >= (amount+4)) + { + LOGSTRING("DProfilerSampleStream::AddSamples - case 1.1"); + + // the source buffer is smaller or of equal size than the amount of output data + PerformCopy((TUint8)aSamplerId,src,realBuf.iBufDes,0,amount); + realBuf.iDataSize += amount+4; + // the rest of the source buffer was copied at once, so signal the buffer + aBuffer.DataCopied(); + } + else + { + LOGSTRING("DProfilerSampleStream::AddSamples - case 1.2"); + + // only a part of the source buffer will fit to the client side buffer + amount = realBuf.iBufferSize-4; + PerformCopy((TUint8)aSamplerId,src,realBuf.iBufDes,0,amount); + realBuf.iDataSize += amount+4; + // add the amount of bytes read to the source buffer + aBuffer.iDblBytesRead+=amount; + } + } + else + { + LOGSTRING("DProfilerSampleStream::AddSamples - case 2"); + + // there is data in the client buffer + dst += realBuf.iDataSize; + TInt remainingSpace = realBuf.iBufferSize-realBuf.iDataSize; + + if( remainingSpace >= (amount+4) ) + { + LOGSTRING("DProfilerSampleStream::AddSamples - case 2.1"); + + // the source buffer is smaller or of equal size than the amount of output data + PerformCopy((TUint8)aSamplerId,src,realBuf.iBufDes,realBuf.iDataSize,amount); + realBuf.iDataSize += (amount+4); + // the rest of the source buffer was copied at once, so signal the buffer + aBuffer.DataCopied(); + } + else + { + LOGSTRING("DProfilerSampleStream::AddSamples - case 2.2"); + + // only a part of the source buffer will fit to the client side buffer + if(remainingSpace >= 12) + { + LOGSTRING("DProfilerSampleStream::AddSamples - case 2.3"); + + amount = remainingSpace-4; + // there are at least 8 bytes left for data, write it + PerformCopy((TUint8)aSamplerId,src,realBuf.iBufDes,realBuf.iDataSize,amount); + realBuf.iDataSize += (amount+4); + // add the amount of bytes read to the source buffer + aBuffer.iDblBytesRead+=amount; + } + } + } + + // copy the data in the modified TBapBuf structure back to the client + LOGSTRING("DProfilerSampleStream::AddSamples - writing TBapBuf"); + + Kern::ThreadDesWrite(iClient,(TAny*)(realBuf.iDes),ptr,0,KChunkShiftBy0,iClient); + + // if the client side buffer is full or nearly full, signal the client + LOGSTRING("DProfilerSampleStream::AddSamples - data copied"); + + if(realBuf.iBufferSize-realBuf.iDataSize < 12) + { + LOGSTRING("DProfilerSampleStream::AddSamples - release buffer"); + + LOGSTRING2("DProfilerSampleStream::AddSamples - completing request 0x%x",iPendingRequest); + + Kern::RequestComplete(iClient,iPendingRequest,KErrNone); + + iPendingRequest = 0; + iCurrentBuffer = 0; + //iClient = 0; + } + + // free the lock + iAddingSamples--; + } + LOGSTRING("DProfilerSampleStream::AddSamples - exit"); + } + + + +inline TInt DProfilerSampleStream::EndSampling(DProfilerSampleBuffer& aBuffer,TInt aSamplerId) + { + LOGSTRING2("DProfilerSampleStream::EndSampling, sampler ID: %d",aSamplerId); + + // switch the buffer to double buffer + // even though it would not be full yet + // the switch is done only once / end sampling procedure + // (Only with BufferOk status) + aBuffer.EndSampling(); + + LOGSTRING2("DProfilerSampleStream::EndSampling, iClient: 0x%x",iClient); + + if(aBuffer.iBufferStatus != DProfilerSampleBuffer::BufferDataEnd) + { + // add these final samples to the client buffer + AddSamples(aBuffer,aSamplerId); + + // if all data was copied to the buffer, the buffer status is now BufferOk + + if(aBuffer.iBufferStatus != DProfilerSampleBuffer::BufferOk) + { + LOGSTRING("DProfilerSampleStream::EndSampling - more data to copy"); + // there is still more data to copy, the pending request should have been + // completed in AddSamples(), because the client buffer got filled + return 1; + } + else + { + // buffer status was changed to BufferOk in AddSamples() - + // this means all data from it could be copied + // now we have to change the status of the buffer to BufferDataEnd, so + // we know that the particular buffer has no more data to copy + LOGSTRING("DProfilerSampleStream::EndSampling - switch to BufferDataEnd"); + aBuffer.iBufferStatus = DProfilerSampleBuffer::BufferDataEnd; + } + } + + // the buffer was completely emptied to the client buffer, or there was no + // data to copy to the client side + LOGSTRING("DProfilerSampleStream::EndSampling - no more data to copy"); + + return 0; + } + +inline void DProfilerSampleStream::PerformCopy(TUint8 aSamplerId,TUint8* aSrc,TPtr8* aDst,TInt aOffset,TInt aAmount) + { + LOGSTRING2("DProfilerSampleStream::PerformCopy for sampler ID: %d",aSamplerId); + LOGSTRING5("DProfilerSampleStream::PerformCopy - 0x%x -> 0x%x - %d - offset: %d",aSrc, aDst, aAmount, aOffset); + TUint32 header; + header = aAmount & 0x00ffffff; + header += (aSamplerId << 24); + TPtr8 ptr((TUint8*)&header,4); + ptr.SetLength(4); + + LOGSTRING2("DProfilerSampleStream::PerformCopy - start header copy HDR = 0x%x",header); + + // write the header + Kern::ThreadDesWrite(iClient,(TAny*)aDst,ptr,aOffset,KChunkShiftBy0); + + LOGSTRING2("DProfilerSampleStream::PerformCopy - copied header %d bytes",ptr.Size()); + aOffset+=4; + + LOGSTRING("DProfilerSampleStream::PerformCopy - start copy"); + // write the data + ptr.Set(aSrc,aAmount,aAmount); + ptr.SetLength(aAmount); + + Kern::ThreadDesWrite(iClient,(TAny*)aDst,ptr,aOffset,KChunkShiftBy0); + + + LOGSTRING2("DProfilerSampleStream::PerformCopy - copied data %d bytes",ptr.Size()); + + } diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/ProfilerGenericClassesUsr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/ProfilerGenericClassesUsr.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,121 @@ +/* +* 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: +* +*/ + + +#ifndef PROFILERGENERICCLASSESUSR_H +#define PROFILERGENERICCLASSESUSR_H + +#include <piprofiler/ProfilerConfig.h> +#include <piprofiler/ProfilerVersion.h> +#include <piprofiler/ProfilerGenericClassesCommon.h> +#include <piprofiler/PluginSampler.h> +#include <piprofiler/WriterPluginInterface.h> + +#include <e32cmn.h> +#include <e32std.h> +#include <f32file.h> + + +/* + * + * Class MProfilerBufferHandlerObserver definition + * + */ +class MProfilerBufferHandlerObserver + { +public: + virtual TBapBuf* GetNextFreeBuffer() = 0; + virtual void AddToFilledBuffers(TBapBuf* aFilledBuffer) = 0; + }; + +/* + * + * Class CProfilerBufferHandler definition + * + */ +// forward declarations +class CProfilerSampleStream; + +class CProfilerBufferHandler : public CActive + { +public: + static CProfilerBufferHandler* CProfilerBufferHandler::NewL(CProfilerSampleStream& aStream, RPluginSampler& aSampler); + CProfilerBufferHandler(CProfilerSampleStream& aStream, RPluginSampler& aSampler); + ~CProfilerBufferHandler(); + + void ConstructL(); + + // for plugins to start receiving trace data + void StartReceivingData(); +private: + void RunL(); + TInt RunError(TInt aError); + void DoCancel(); + void HandleEndOfStream(); +public: + TInt iFinished; +private: + RPluginSampler& iSampler; + TBapBuf* iBufferInProcess; + TBool iEndOfStreamDetected; + + CProfilerSampleStream& iObserver; + }; + +/* + * + * Class CProfilerSampleStream definition + * + */ +class CWriterPluginInterface; + +class CProfilerSampleStream : public CBase, MProfilerBufferHandlerObserver +{ +public: + static CProfilerSampleStream* CProfilerSampleStream::NewL(TInt aBufSize); + ~CProfilerSampleStream(); + + void ConstructL(); + + void Finalise(); + void EmptyBuffers(); + inline void AddToFreeBuffers(TBapBuf* freeBuffer); + void SetWriter(CWriterPluginInterface& aWriter); + + // from MProfilerBufferHandlerObserver + TBapBuf* GetNextFreeBuffer(); + void AddToFilledBuffers(TBapBuf* aFilledBuffer); + inline TBapBuf* GetNextFilledBuffer(); + void ResetBuffers(); + void InitialiseBuffers(); + inline void NotifyWriter(); +private: + CProfilerSampleStream(TInt aBufSize); + + +public: + TInt iFinished; + CWriterPluginInterface* iWriter; +private: + TInt iBufferSize; + TBapBuf* iFreeBuffers; + TBapBuf* iFilledBuffers; +}; + +#include <piprofiler/ProfilerGenericClassesUsr.inl> + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/ProfilerGenericClassesUsr.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/ProfilerGenericClassesUsr.inl Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,498 @@ +/* +* 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: +* +*/ + + +#include <f32file.h> +#include <e32svr.h> + +#include <piprofiler/ProfilerTraces.h> + +// constants +const TInt KInitialFreeBufferAmount = 4; + +/* + * + * Class CProfilerBufferHandler implementation + * + */ +inline CProfilerBufferHandler* CProfilerBufferHandler::NewL(CProfilerSampleStream& aStream, RPluginSampler& aSampler) + { + LOGTEXT(_L("CProfilerBufferHandler::NewL - entry")); + CProfilerBufferHandler* self = new(ELeave) CProfilerBufferHandler(aStream, aSampler); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +inline CProfilerBufferHandler::CProfilerBufferHandler(CProfilerSampleStream& aStream, RPluginSampler& aSampler) + : CActive(EPriorityStandard), + iSampler(aSampler), + iObserver(aStream) + { + } + +inline CProfilerBufferHandler::~CProfilerBufferHandler() + { + LOGTEXT(_L("CProfilerBufferHandler::~CProfilerBufferHandler() - entry")); + } + +inline void CProfilerBufferHandler::ConstructL() + { + LOGTEXT(_L("CProfilerBufferHandler::ConstructL - entry")); + iBufferInProcess = 0; + iEndOfStreamDetected = false; + + iFinished = 0; + // add the buffer handler to the active scheduler + CActiveScheduler::Add(this); + } + +inline void CProfilerBufferHandler::StartReceivingData() + { + LOGTEXT(_L("CProfilerBufferHandler::StartReceivingData - entry")); + + iEndOfStreamDetected = false; + // this method initiates receiving data from the sampler + iBufferInProcess = iObserver.GetNextFreeBuffer(); + + LOGSTRING5("CProfilerBufferHandler::StartReceivingData - 0x%x -> b:0x%x s:%d d:%d", + iBufferInProcess, + iBufferInProcess->iBuffer, + iBufferInProcess->iBufferSize, + iBufferInProcess->iDataSize); + + iSampler.FillThisStreamBuffer(iBufferInProcess,iStatus); + + LOGTEXT(_L("CProfilerBufferHandler::StartReceivingData - SetActive")); + SetActive(); + + LOGTEXT(_L("CProfilerBufferHandler::StartReceivingData - exit")); + } + +inline TInt CProfilerBufferHandler::RunError(TInt aError) + { + // handle the error case by stopping the trace + HandleEndOfStream(); + return aError; + } + +inline void CProfilerBufferHandler::HandleEndOfStream() + { + LOGTEXT(_L("CProfilerBufferHandler::RunError - entry")); + // Cancel has been called, the stream should be about to end now, + // we will wait for the rest of the buffers to be filled synchronously + // the end of the stream will be indicated through an empty buffer + // at first, complete the ongoing request + if(iStatus == KRequestPending && iBufferInProcess != 0) + { + LOGTEXT(_L("CProfilerBufferHandler::DoCancel - case 1")); + + // wait for the buffer to be filled synchronously + User::WaitForRequest(iStatus); + + // add the received buffer to the list of filled buffers + iObserver.AddToFilledBuffers(iBufferInProcess); + // continue writing to output + iObserver.NotifyWriter(); + + if(iBufferInProcess->iDataSize == 0) + { + // a buffer with size 0 was received + LOGTEXT(_L("CProfilerBufferHandler::DoCancel - case 1.1")); + iEndOfStreamDetected = true; + } + + // there will be no more asynchronous requests + iBufferInProcess = 0; + } + else if (iBufferInProcess != 0) + { + LOGTEXT(_L("CProfilerBufferHandler::DoCancel - case 2")); + + // add the buffer into filled, i.e. ready-to-write buffers + iObserver.AddToFilledBuffers(iBufferInProcess); + iObserver.NotifyWriter(); + + if(iBufferInProcess->iDataSize == 0) + { + // a buffer with size 0 was received + LOGTEXT(_L("CProfilerBufferHandler::DoCancel - case 2.1")); + iEndOfStreamDetected = true; + } + // there will be no more asynchronous requests + iBufferInProcess = 0; + } + + // then, continue until end of stream has been reached + while(iEndOfStreamDetected == false) + { + // the end of stream has not yet been detected, so get more + // buffers from the sampler, until we get an empty one + + if(iStatus == KRequestPending) + { + LOGTEXT(_L("CProfilerBufferHandler::DoCancel - ERROR 1")); + } + + LOGTEXT(_L("CProfilerBufferHandler::DoCancel - case 3")); + + TBapBuf* nextFree = iObserver.GetNextFreeBuffer(); + iSampler.FillThisStreamBuffer(nextFree,iStatus); + // wait for the buffer to be filled synchronously + User::WaitForRequest(iStatus); + + // call the writer plugin to write data to output + iObserver.AddToFilledBuffers(nextFree); + iObserver.NotifyWriter(); + + // check if end-of-data message (i.e. data size is 0 sized) received + if(nextFree->iDataSize == 0) + { + LOGTEXT(_L("CProfilerBufferHandler::DoCancel - case 3.1")); + // a buffer with size 0 was received + iEndOfStreamDetected = true; + nextFree = 0; + } + } + } + +inline void CProfilerBufferHandler::RunL() + { + LOGTEXT(_L("CProfilerBufferHandler::RunL - entry")); + + // is called by the active scheduler + // when a buffer has been received + + // buffer with dataSize 0 is returned when the sampling ends + if(iBufferInProcess->iDataSize != 0) + { + LOGTEXT(_L("CProfilerBufferHandler::RunL - buffer received")); + + TBapBuf* nextFree = iObserver.GetNextFreeBuffer(); + + LOGSTRING5("CProfilerBufferHandler::RunL - 0x%x -> b:0x%x s:%d d:%d", + nextFree, + nextFree->iBuffer, + nextFree->iBufferSize, + nextFree->iDataSize); + + iSampler.FillThisStreamBuffer(nextFree,iStatus); + + LOGTEXT(_L("CProfilerBufferHandler::RunL - issued new sample command")); + + // add the received buffer to the list of filled buffers + iObserver.AddToFilledBuffers(iBufferInProcess); + iObserver.NotifyWriter(); + + // the empty buffer is now the one being processed + iBufferInProcess = nextFree; + + LOGTEXT(_L("CProfilerBufferHandler::RunL - SetActive")); + SetActive(); + } + else + { + LOGTEXT(_L("CProfilerBufferHandler::RunL - end of stream detected")); + iEndOfStreamDetected = true; + + // add the empty buffer to the writer so that it will also get the information + // about the finished stream + iObserver.AddToFilledBuffers(iBufferInProcess); + iObserver.NotifyWriter(); + + iBufferInProcess = 0; + Cancel(); + + } + LOGTEXT(_L("CProfilerBufferHandler::RunL - exit")); + } + +inline void CProfilerBufferHandler::DoCancel() + { + LOGTEXT(_L("CProfilerBufferHandler::DoCancel - entry")); + HandleEndOfStream(); + LOGTEXT(_L("CProfilerBufferHandler::DoCancel - exit")); + } + + +/* + * + * Class CProfilerSampleStream implementation + * + * - used by Plugin + **/ + +inline CProfilerSampleStream* CProfilerSampleStream::NewL(TInt aBufSize) + { + LOGTEXT(_L("CProfilerSampleStream::NewL - entry")); + CProfilerSampleStream* self = new(ELeave) CProfilerSampleStream(aBufSize); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +inline CProfilerSampleStream::CProfilerSampleStream(TInt aBufSize) : + iBufferSize(aBufSize) + { + LOGTEXT(_L("CProfilerSampleStream::CProfilerSampleStream - entry")); + + iFilledBuffers = 0; + iFreeBuffers = 0; + iFinished = 0; + + LOGTEXT(_L("CProfilerSampleStream::CProfilerSampleStream - exit")); + } + +inline CProfilerSampleStream::~CProfilerSampleStream() + { + LOGTEXT(_L("CProfilerSampleStream::~CProfilerSampleStream - entry")); + + // empty all buffers + EmptyBuffers(); + + LOGTEXT(_L("CProfilerSampleStream::~CProfilerSampleStream - exit")); + } + +inline void CProfilerSampleStream::ConstructL() + { + + } + +inline void CProfilerSampleStream::SetWriter(CWriterPluginInterface& aWriter) + { + // set writer plugin + iWriter = &aWriter; + } + +inline void CProfilerSampleStream::Finalise() + { + LOGTEXT(_L("CProfilerSampleStream::Finalise - entry")); + } + +inline void CProfilerSampleStream::ResetBuffers() + { + + // empty buffers + EmptyBuffers(); + + // re-initialise buffers + InitialiseBuffers(); + } + +inline void CProfilerSampleStream::InitialiseBuffers() + { + // re-initialize member variables + iFilledBuffers = 0; + iFreeBuffers = 0; + iFinished = 0; + + // create three(orig. two) new TBapBuf objects and add them to the + // list of free buffers + for(TInt i(0);i<KInitialFreeBufferAmount;i++) + { + // alloc new buffer + TBapBuf* newBuf = (TBapBuf*)User::Alloc(sizeof(TBapBuf)); + newBuf->iBuffer = (TUint8*)User::Alloc(iBufferSize); + + // initialize the new buffer + newBuf->iBufferSize = iBufferSize; + newBuf->iDataSize = 0; + newBuf->iNext = 0; + newBuf->iDes = new TPtr8((TUint8*)newBuf,sizeof(TBapBuf)); + newBuf->iDes->SetLength(sizeof(TBapBuf)); + newBuf->iBufDes = new TPtr8((TUint8*)newBuf->iBuffer,iBufferSize); + newBuf->iBufDes->SetLength(iBufferSize); + AddToFreeBuffers(newBuf); + } + } + +inline void CProfilerSampleStream::EmptyBuffers() + { + LOGTEXT(_L("CProfilerSampleStream::EmptyBuffers - entry")); + + // delete all free buffers + while(iFreeBuffers != 0) + { + LOGSTRING2("CProfilerSampleStream::EmptyBuffers - deleting 0x%x",iFreeBuffers); + + // store the next buffer in the list + TBapBuf* nextFree = iFreeBuffers->iNext; + // delete the first one in the list + delete iFreeBuffers->iBufDes; + delete iFreeBuffers->iDes; + delete iFreeBuffers->iBuffer; + delete iFreeBuffers; + // set the list start to the next buffer + iFreeBuffers = nextFree; + } + iFreeBuffers = 0; + LOGTEXT(_L("CProfilerSampleStream::EmptyBuffers - exit")); + } + +inline TBapBuf* CProfilerSampleStream::GetNextFreeBuffer() + { + LOGTEXT(_L("CProfilerSampleStream::GetNextFreeBuffer - entry")); + + // get a new buffer from the free buffers list + TBapBuf* nextFree = iFreeBuffers; + + // check if we got a buffer or not + if(nextFree == 0) + { + // if there are no free buffers, + // create a new one + LOGTEXT(_L("CProfilerSampleStream::GetNextFreeBuffer - creating new buffer")); + TBapBuf* newBuf = (TBapBuf*)User::Alloc(sizeof(TBapBuf)); + if(newBuf != 0) + { + newBuf->iBuffer = (TUint8*)User::Alloc(iBufferSize); + if(newBuf->iBuffer != 0) + { + newBuf->iBufferSize = iBufferSize; + newBuf->iDataSize = 0; + newBuf->iNext = 0; + newBuf->iDes = new TPtr8((TUint8*)newBuf,sizeof(TBapBuf)); + newBuf->iDes->SetLength(sizeof(TBapBuf)); + newBuf->iBufDes = new TPtr8((TUint8*)newBuf->iBuffer,iBufferSize); + newBuf->iBufDes->SetLength(iBufferSize); + nextFree = newBuf; + } + else + { + LOGTEXT(_L("CProfilerSampleStream::GetNextFreeBuffer - Out of memory (1)!!")); + return 0; + } + } + else + { + LOGTEXT(_L("CProfilerSampleStream::GetNextFreeBuffer - Out of memory (2)!!")); + delete newBuf; + return 0; + } + } + else + { + // set the list to point to next free buffer + iFreeBuffers = nextFree->iNext; + } + + LOGTEXT(_L("CProfilerSampleStream::GetNextFreeBuffer - exit")); + return nextFree; + } + +inline void CProfilerSampleStream::AddToFilledBuffers(TBapBuf* aFilledBuffer) + { + LOGSTRING2("CProfilerSampleStream::AddToFilledBuffers - entry, size %d", aFilledBuffer->iDataSize); + + // add this buffer to the list of filled buffers + if(iFilledBuffers == 0) + { + // the list is empty, so add the the beginning of the list + // there is no next buffer in the list at the moment + aFilledBuffer->iNext = 0; + iFilledBuffers = aFilledBuffer; + } + else + { + // there are buffers in the list, add this buffer to the beginning of the list + aFilledBuffer->iNext = iFilledBuffers; + iFilledBuffers = aFilledBuffer; + } + LOGTEXT(_L("CProfilerSampleStream::AddToFilledBuffers - exit")); + } + +TBapBuf* CProfilerSampleStream::GetNextFilledBuffer() + { + LOGTEXT(_L("CProfilerSampleStream::GetNextFilledBuffer - entry")); + + if(iFilledBuffers == 0) + { + // there are no filled buffers in the list + LOGTEXT(_L("CProfilerSampleStream::GetNextFilledBuffer - no filled bufs")); + return 0; + } + else + { + // get a buffer from the end of the list + TBapBuf* buf = iFilledBuffers; + TBapBuf* prev = 0; + + if(buf->iNext == 0) + { + // this was the last (and only) buffer + iFilledBuffers = 0; + LOGTEXT(_L("CProfilerSampleStream::GetNextFilledBuffer - last filled")); + return buf; + } + else + { + LOGTEXT(_L("CProfilerSampleStream::GetNextFilledBuffer - searching last filled")); + while(buf->iNext != 0) + { + // there are two or more buffers in the list + // proceed until the end of the list is found + prev = buf; + buf = buf->iNext; + } + // now buf->next is 0, return buf and set the next + // element of prev to NULL + prev->iNext = 0; + LOGTEXT(_L("CProfilerSampleStream::GetNextFilledBuffer - found last")); + return buf; + } + } + } + +inline void CProfilerSampleStream::AddToFreeBuffers(TBapBuf* aFreeBuffer) + { + LOGTEXT(_L("CProfilerSampleStream::AddToFreeBuffers - entry")); + + // set data size of the buffer to 0 + aFreeBuffer->iDataSize = 0; + + // add this buffer to the list of free buffers + if(iFreeBuffers == 0) + { + // this is the first buffer, so set the next to point to NULL + aFreeBuffer->iNext = 0; + } + else + { + // otherwise set to point to the beginning of the list + aFreeBuffer->iNext = iFreeBuffers; + } + + // set this buffer to be the first one in the list + iFreeBuffers = aFreeBuffer; + + LOGTEXT(_L("CProfilerSampleStream::AddToFreeBuffers - exit")); + } + +void CProfilerSampleStream::NotifyWriter() + { + // notify writer plugin to write data from filled buffer list + LOGTEXT(_L("CProfilerSampleStream::NotifyWriter() - entry")); + iWriter->WriteData(); + LOGTEXT(_L("CProfilerSampleStream::NotifyWriter() - exit")); + } + +// end of file + + + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/ProfilerSession.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/ProfilerSession.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,417 @@ +/* +* 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: +* +*/ + + +#ifndef __PROFILER_SESSION_H__ +#define __PROFILER_SESSION_H__ + +#include <e32base.h> +#include <e32svr.h> +#include <piprofiler/ProfilerConfig.h> +#include <piprofiler/ProfilerVersion.h> +#include <piprofiler/ProfilerTraces.h> +#include <piprofiler/ProfilerAttributes.h> + +_LIT(KProfilerName,"PIProfilerEngine"); + +/** + * The RProfiler class provides a functional interface to the sampling profiler. + * + * The engine must already be running for this interface to work, this can be + * achieved by executing PIProfilerEngine.exe. The control methods are all static, and + * require no other context. + */ +NONSHARABLE_CLASS( RProfiler ) : public RSessionBase + { +public: + enum TCommand { + // profiler controls + EStartSampling = 1, + EStartTimedSampling, + EStopSampling, +// ELoadSettings, + EExitProfiler, + EFinalise, + EAttachClient, + ERemoveClient, + + // general attributes + EGetGeneralAttributes, + EGetSamplerAttributes, + EGetSamplerAttributeCount, + ESetGeneralAttributes, + ESetSamplerAttributes, + + // generic settings + ESetTraceFilePrefix, + ESetTraceFileDrive, + EGetSamplerVersion, + EGetFileName, + EGetActiveWriter, + ERefreshProfilerStatus + }; + + enum TSamplerState { + EIdle = 0, + EInitializing, + ERunning, + EStopping, + EStopped + }; + + enum TProfilingMode + { + EProfilingModeNormal = 0, + EProfilingModeTimed + }; +public: + + + /* + * + * Methods for commanding Profiler Engine + * + */ + + // get general settings + static inline TInt GetGeneralAttributes(TGeneralAttributes& aAttributes); + + // get samplers; names, settings, states, descriptions etc. in one array containing all sampler attributes + static inline TInt GetSamplerAttributes(CArrayFixFlat<TSamplerAttributes>& aAttributeArray); + + // save settings back to engine and plugins + static inline TInt SetGeneralAttributes(TGeneralAttributes aAttributes); + + // save settings back to engine and plugins + static inline TInt SetSamplerAttributes(TSamplerAttributes aAttributes); + + // refresh profiler engine status + static inline TInt RefreshProfilerStatus(); + + /** Start sampling */ + static inline TInt StartSampling(TProfilingMode aProfilingMode = EProfilingModeNormal); + /** Stop sampling */ + static inline TInt StopSampling(); + /** Load settings */ +// static inline TInt LoadSettings(TDesC& aSettingsFile); + /** Exit profiler */ + static inline TInt ExitProfiler(); + + /** Get file name */ + static inline TInt GetFileName(TDes&); + /** Get active writer */ + static inline TInt GetActiveWriter(TDes&); + /** Perform a test case */ + static inline TInt Test(TUint32 testCase); + /** Issue a control request to the engine without data*/ + static inline TInt ControlState(TCommand aRequest); + /** Issue a control request to the engine with descriptor data to write there*/ + static inline TInt ControlWrite(TCommand aRequest,TDesC& data); + /** Issue a control request to the engine with numeric and descriptor data to write there*/ + static inline TInt ControlWrite(TCommand aRequest,TInt numData, TDesC& data); + /** Issue a control request to read descriptor data from the engine*/ + static inline TInt ControlRead(TCommand aRequest,TDes& data); + /** Actually sends the message to profiler engine*/ + static inline TInt PerformControl( TCommand aRequest, + TDesC* fromDescriptor = NULL, + TUint32 numData1 = 0, + TDes* toDescriptor = NULL, + TUint32 numData2 = 0xffffffff); + + static inline TInt AttachClient(); + static inline TInt RemoveClient(); + +private: + inline RProfiler(); + }; + +inline RProfiler::RProfiler() + {} + +// +// Connect to the profiler engine, and issue the control request if successful +// +inline TInt RProfiler::ControlState(TCommand aRequest) + { return PerformControl(aRequest); } + +// +// Connect to the profiler engine, and issue the control request if successful +// +inline TInt RProfiler::ControlWrite(TCommand aRequest,TDesC& data) + { return PerformControl(aRequest,&data,0); } + +// +// Connect to the profiler engine, and issue the control request if successful +// +inline TInt RProfiler::ControlWrite(TCommand aRequest,TInt numData, TDesC& data) + { return PerformControl(aRequest,&data,numData); } + +// +// Connect to the profiler engine, and issue the control request if successful +// +inline TInt RProfiler::ControlRead(TCommand aRequest,TDes& data) + { return PerformControl(aRequest,0,0,&data); } + +inline TInt RProfiler::PerformControl(TCommand aRequest,TDesC* fromDescriptor,TUint32 numData1,TDes* toDescriptor,TUint32 numData2) + { + LOGTEXT(_L("Creating a session to profiler")); + RProfiler p; + TUint count(0); + TInt r(KErrNone); + + // in boot measurement mode, count until 30s + #ifdef PROFILER_BOOT_MEASUREMENT + while(count < 60) + #else + while(count < 6) + #endif + { + r = p.CreateSession(KProfilerName, TVersion(), 0); + if (r == KErrNone) + { + LOGSTRING2("Succeeded, sending a message %d", aRequest); + LOGSTRING5(" - parameters 0x%x 0x%x 0x%x 0x%x",fromDescriptor,numData1,toDescriptor,numData2); + TInt err = KErrNone; + + TIpcArgs a; + a.Set(0,fromDescriptor); + a.Set(1,numData1); + a.Set(2,toDescriptor); + a.Set(3,numData2); + err = p.SendReceive(aRequest,a); + + p.RSessionBase::Close(); + + if(err != KErrNone) + { + LOGSTRING2("Profiler responded with an error - code %d !!",err); + return err; + } + else + { + LOGTEXT(_L("OK, message sent, closing")); + return KErrNone; + } + } + + LOGSTRING2("Error in opening session to profiler - code %d !!",r); + //#ifdef PROFILER_BOOT_MEASUREMENT + // there was an error contacting the Profiler + // indicates that the server is most probably not up + // however, since it should be(unless some resource is not yet ready) + // we can just wait + User::After(500000); // wait 1/2 s + count++; + //#else + // exit immediately on error + //return r; + //#endif + } + return r; + } + +// the new UI access methods +inline TInt RProfiler::GetGeneralAttributes(TGeneralAttributes& aAttributes) + { +#ifdef _TEST_ + _LIT(KDefaultTraceOutput,"debug_output"); + _LIT(KDefaultTraceFilePrefix,"PIProfiler_#"); + _LIT(KDefaultTraceFileSaveDrive,"E:\\"); + aAttributes.iTraceOutput.Copy(KDefaultTraceOutput); + aAttributes.iTraceFilePrefix.Copy(KDefaultTraceFilePrefix); + aAttributes.iSaveFileDrive.Copy(KDefaultTraceFileSaveDrive); +#else + LOGTEXT(_L("Creating a session to profiler")); + RProfiler p; + TInt r(KErrNone); + r = p.CreateSession(KProfilerName, TVersion(), 0); + if (r == KErrNone) + { + LOGSTRING2("Succeeded, sending a message %d", EGetGeneralAttributes); + + TPckg<TGeneralAttributes> attrPckg(aAttributes); + TIpcArgs a(&attrPckg); + r = p.SendReceive(RProfiler::EGetGeneralAttributes,a); + + p.RSessionBase::Close(); + + if(r != KErrNone) + { + LOGSTRING2("Profiler responded with an error - code %d !!",r); + return r; + } + else + { + LOGTEXT(_L("OK, message sent, closing")); + return KErrNone; + } + } +#endif + return r; // return error code + } +inline TInt RProfiler::GetSamplerAttributes(CArrayFixFlat<TSamplerAttributes>& aAttributes) + { +#ifdef _TEST_ + _LIT(KDefaultTraceOutput,"debug_output"); + _LIT(KDefaultTraceFilePrefix,"PIProfiler_#"); + _LIT(KDefaultTraceFileSaveDrive,"E:\\"); + aAttributes.iTraceOutput.Copy(KDefaultTraceOutput); + aAttributes.iTraceFilePrefix.Copy(KDefaultTraceFilePrefix); + aAttributes.iSaveFileDrive.Copy(KDefaultTraceFileSaveDrive); +#else + // do receive stream of TSamplerAttributes + LOGTEXT(_L("Creating a session to profiler")); + RProfiler p; + TInt r(KErrNone); + r = p.CreateSession(KProfilerName, TVersion(), 0); + if (r == KErrNone) + { + TInt attrCount(0); + TPckg<TInt> pckg(attrCount); + TIpcArgs args(&pckg); + + r = p.SendReceive(RProfiler::EGetSamplerAttributeCount, args); + + HBufC8* buffer = HBufC8::NewL(attrCount*sizeof(TSamplerAttributes)); + TPtr8 ptr(buffer->Des()); + TIpcArgs args2(&ptr); + r = p.SendReceive(RProfiler::EGetSamplerAttributes, args2); + + TInt len(ptr.Length()); + TInt pos(0); + while (pos != len) + { + TPckgBuf<TSamplerAttributes> attrPckg; + attrPckg.Copy(ptr.Mid(pos, attrPckg.Length())); + pos += attrPckg.Length(); + + aAttributes.AppendL(attrPckg()); + } + + p.RSessionBase::Close(); + + if(r != KErrNone) + { + LOGSTRING2("Profiler responded with an error - code %d !!",r); + return r; + } + else + { + LOGTEXT(_L("OK, message sent, closing")); + return KErrNone; + } + } +#endif + return KErrNone; + } + +inline TInt RProfiler::SetGeneralAttributes(TGeneralAttributes aAttributes) + { + // do receive stream of TSamplerAttributes + LOGTEXT(_L("Creating a session to profiler")); + RProfiler p; + TInt r(KErrNone); + r = p.CreateSession(KProfilerName, TVersion(), 0); + if (r == KErrNone) + { + + TPckg<TGeneralAttributes> attrPckg(aAttributes); + TIpcArgs a(&attrPckg); + r = p.SendReceive(RProfiler::ESetGeneralAttributes,a); + + p.RSessionBase::Close(); + + if(r != KErrNone) + { + LOGSTRING2("Profiler responded with an error - code %d !!",r); + return r; + } + else + { + LOGTEXT(_L("OK, message sent, closing")); + return KErrNone; + } + } + return r; + } + +// save settings back to engine and plugins +inline TInt RProfiler::SetSamplerAttributes(TSamplerAttributes aAttributes) + { + // do receive stream of TSamplerAttributes + LOGTEXT(_L("Creating a session to profiler")); + RProfiler p; + TInt r(KErrNone); + r = p.CreateSession(KProfilerName, TVersion(), 0); + if (r == KErrNone) + { + + TPckg<TSamplerAttributes> attrPckg(aAttributes); + + TIpcArgs a; + a.Set(0,&attrPckg); + + r = p.SendReceive(RProfiler::ESetSamplerAttributes,a); + + p.RSessionBase::Close(); + + if(r != KErrNone) + { + LOGSTRING2("Profiler responded with an error - code %d !!",r); + return r; + } + else + { + LOGTEXT(_L("OK, message sent, closing")); + return KErrNone; + } + } + return r; + } + +inline TInt RProfiler::RefreshProfilerStatus() + {return ControlState(RProfiler::ERefreshProfilerStatus); } + +inline TInt RProfiler::StartSampling(RProfiler::TProfilingMode aProfilingMode) + { + RProfiler::TCommand command = RProfiler::EStartSampling; + if( aProfilingMode == RProfiler::EProfilingModeTimed ) + { + command = RProfiler::EStartTimedSampling; + } + return ControlState(command); + } + +inline TInt RProfiler::StopSampling() + {return ControlState(RProfiler::EStopSampling);} + +inline TInt RProfiler::ExitProfiler() + {return ControlState(RProfiler::EExitProfiler);} + +inline TInt RProfiler::AttachClient() + {return ControlState(RProfiler::EAttachClient);} + +inline TInt RProfiler::RemoveClient() + {return ControlState(RProfiler::ERemoveClient);} + +inline TInt RProfiler::GetFileName(TDes& fileName) + {return ControlRead(EGetFileName,fileName);} + +inline TInt RProfiler::GetActiveWriter(TDes& writerDes) + {return ControlRead(EGetActiveWriter,writerDes);} + +#endif // __PROFILER_SESSION_H__ diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/ProfilerTraces.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/ProfilerTraces.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,146 @@ +/* +* 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: +* +*/ + + +#ifndef __PROFILER_TRACES_H__ +#define __PROFILER_TRACES_H__ + +#include <e32def.h> + + +// --------------------------------------------------------------------------- +// You change these logging method values below! Recompile the application to take changes effect. + + // logging methods + // 0 = No logging + // 1 = Flogger + // 2 = RDebug + // 3 = Flogger and RDebug + +#undef _DEBUG + + #ifndef _DEBUG + + // Logging method for UREL builds: + #define PROFILER_LOGGING_METHOD 0 + + #else + + // Logging method for UDEB builds: + #define PROFILER_LOGGING_METHOD 2 + + #endif + + #ifndef _KERNEL_DEBUG + + // Logging method for UREL builds: + #define KERNEL_LOGGING_METHOD 0 + + #else + + // Logging method for UDEB builds: + #define KERNEL_LOGGING_METHOD 1 + + #endif + + + +#ifndef __KERNEL_MODE__ + +// --------------------------------------------------------------------------- +// Do not make any changes to lines below... + + #if PROFILER_LOGGING_METHOD == 1 || PROFILER_LOGGING_METHOD == 3 + + #include <flogger.h> + _LIT(KLogFolder,"PIProfiler"); + _LIT(KLogFile,"PIProfiler_Trace.txt"); + + #endif + + #if PROFILER_LOGGING_METHOD == 2 || PROFILER_LOGGING_METHOD == 3 + + #include <e32debug.h> + + #endif + + + #if PROFILER_LOGGING_METHOD == 0 + + #define LOGTEXT(AAA) + #define LOGSTRING(AAA) + #define LOGSTRING2(AAA,BBB) + #define LOGSTRING3(AAA,BBB,CCC) + #define LOGSTRING4(AAA,BBB,CCC,DDD) + #define LOGSTRING5(AAA,BBB,CCC,DDD,EEE) + + + #elif PROFILER_LOGGING_METHOD == 1 + + #define LOGTEXT(AAA) RFileLogger::Write(KLogFolder(),KLogFile(),EFileLoggingModeAppend, AAA) + #define LOGSTRING(AAA) do { _LIT(tempLogDes,AAA); RFileLogger::Write(KLogFolder(),KLogFile(),EFileLoggingModeAppend,tempLogDes()); } while (0) + #define LOGSTRING2(AAA,BBB) do { _LIT(tempLogDes,AAA); RFileLogger::WriteFormat(KLogFolder(),KLogFile(),EFileLoggingModeAppend,TRefByValue<const TDesC>(tempLogDes()),BBB); } while (0) + #define LOGSTRING3(AAA,BBB,CCC) do { _LIT(tempLogDes,AAA); RFileLogger::WriteFormat(KLogFolder(),KLogFile(),EFileLoggingModeAppend,TRefByValue<const TDesC>(tempLogDes()),BBB,CCC); } while (0) + #define LOGSTRING4(AAA,BBB,CCC,DDD) do { _LIT(tempLogDes,AAA); RFileLogger::WriteFormat(KLogFolder(),KLogFile(),EFileLoggingModeAppend,TRefByValue<const TDesC>(tempLogDes()),BBB,CCC,DDD); } while (0) + #define LOGSTRING5(AAA,BBB,CCC,DDD,EEE) do { _LIT(tempLogDes,AAA); RFileLogger::WriteFormat(KLogFolder(),KLogFile(),EFileLoggingModeAppend,TRefByValue<const TDesC>(tempLogDes()),BBB,CCC,DDD,EEE); } while (0) + + #elif PROFILER_LOGGING_METHOD == 2 + + #define LOGTEXT(AAA) RDebug::Print(AAA); + #define LOGSTRING(AAA) do { _LIT(tempLogDes,AAA); RDebug::Print(tempLogDes); } while (0) + #define LOGSTRING2(AAA,BBB) do { _LIT(tempLogDes,AAA); RDebug::Print(tempLogDes, BBB); } while (0) + #define LOGSTRING3(AAA,BBB,CCC) do { _LIT(tempLogDes,AAA); RDebug::Print(tempLogDes, BBB, CCC); } while (0) + #define LOGSTRING4(AAA,BBB,CCC,DDD) do { _LIT(tempLogDes,AAA); RDebug::Print(tempLogDes, BBB, CCC, DDD); } while (0) + #define LOGSTRING5(AAA,BBB,CCC,DDD,EEE) do { _LIT(tempLogDes,AAA); RDebug::Print(tempLogDes, BBB, CCC, DDD, EEE); } while (0) + + #elif PROFILER_LOGGING_METHOD == 3 + + #define LOGTEXT(AAA) RDebug::Print(AAA); RFileLogger::Write(KLogFolder(),KLogFile(),EFileLoggingModeAppend, AAA) + #define LOGSTRING(AAA) do { _LIT(tempLogDes,AAA); RDebug::Print(tempLogDes); RFileLogger::Write(KLogFolder(),KLogFile(),EFileLoggingModeAppend,tempLogDes()); } while (0) + #define LOGSTRING2(AAA,BBB) do { _LIT(tempLogDes,AAA); RDebug::Print(tempLogDes, BBB); RFileLogger::WriteFormat(KLogFolder(),KLogFile(),EFileLoggingModeAppend,TRefByValue<const TDesC>(tempLogDes()),BBB); } while (0) + #define LOGSTRING3(AAA,BBB,CCC) do { _LIT(tempLogDes,AAA); RDebug::Print(tempLogDes, BBB, CCC); RFileLogger::WriteFormat(KLogFolder(),KLogFile(),EFileLoggingModeAppend,TRefByValue<const TDesC>(tempLogDes()),BBB,CCC); } while (0) + #define LOGSTRING4(AAA,BBB,CCC,DDD) do { _LIT(tempLogDes,AAA); RDebug::Print(tempLogDes, BBB, CCC, DDD); RFileLogger::WriteFormat(KLogFolder(),KLogFile(),EFileLoggingModeAppend,TRefByValue<const TDesC>(tempLogDes()),BBB,CCC,DDD); } while (0) + #define LOGSTRING5(AAA,BBB,CCC,DDD,EEE) do { _LIT(tempLogDes,AAA); RDebug::Print(tempLogDes, BBB, CCC, DDD, EEE); RFileLogger::WriteFormat(KLogFolder(),KLogFile(),EFileLoggingModeAppend,TRefByValue<const TDesC>(tempLogDes()),BBB,CCC,DDD,EEE); } while (0) + + #endif + +#else __KERNEL_MODE__ + + #if KERNEL_LOGGING_METHOD == 0 + + #define LOGTEXT(AAA) + #define LOGSTRING(AAA) + #define LOGSTRING2(AAA,BBB) + #define LOGSTRING3(AAA,BBB,CCC) + #define LOGSTRING4(AAA,BBB,CCC,DDD) + #define LOGSTRING5(AAA,BBB,CCC,DDD,EEE) + + #else + + #define LOGTEXT(AAA) Kern::Printf(AAA) + #define LOGSTRING(AAA) Kern::Printf(AAA); + #define LOGSTRING2(AAA,BBB) Kern::Printf(AAA, BBB); + #define LOGSTRING3(AAA,BBB,CCC) Kern::Printf(AAA, BBB, CCC); + #define LOGSTRING4(AAA,BBB,CCC,DDD) Kern::Printf(AAA, BBB, CCC, DDD); + #define LOGSTRING5(AAA,BBB,CCC,DDD,EEE) Kern::Printf(AAA, BBB, CCC, DDD, EEE); + + #endif +#endif +// --------------------------------------------------------------------------- + +#endif // __PROFILER_TRACES_H__ + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/ProfilerVersion.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/ProfilerVersion.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,47 @@ +/* +* 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: +* +*/ + + +#ifndef PROFILER_TOOL_VERSION_H +#define PROFILER_TOOL_VERSION_H + + /* + * + * PI Profiler tool composition definitions + * + */ + + #define PROFILER_VERSION "PI Profiler v2.1.0" + #define PROFILER_VERSION_SHORT _L("2.00.0") + #define PROFILER_SAMPLER_VERSION _L("2.00.0") + #define PROFILER_RELEASE_DATE _L("23rd February 2009. ") + + #define PROFILER_GPP_SAMPLER_VERSION _L("2.00") // SMPfied v2.00 + #define PROFILER_GFC_SAMPLER_VERSION _L8("1.10") + #define PROFILER_ITT_SAMPLER_VERSION _L8("1.22") + #define PROFILER_MEM_SAMPLER_VERSION _L8("2.02") + #define PROFILER_PRI_SAMPLER_VERSION _L8("1.56") + #define PROFILER_BUP_SAMPLER_VERSION _L8("1.20") + #define PROFILER_IRQ_SAMPLER_VERSION _L8("1.20") + #define PROFILER_TIP_SAMPLER_VERSION _L8("1.10") + #define PROFILER_PEC_SAMPLER_VERSION _L8("1.24") + #define PROFILER_PWR_SAMPLER_VERSION _L8("1.57") + #define PROFILER_SCR_SAMPLER_VERSION _L8("1.57") + #define PROFILER_IPC_SAMPLER_VERSION _L8("1.59") + #define PROFILER_GPU_SAMPLER_VERSION _L8("1.00") + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/SamplerPluginInterface.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/SamplerPluginInterface.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,257 @@ +/* +* 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: +* +*/ + + +#ifndef __SAMPLER_PLUGIN_INTERFACE__ +#define __SAMPLER_PLUGIN_INTERFACE__ + +#include <e32base.h> +#include <ecom/ecom.h> +#include <badesca.h> +#include <piprofiler/ProfilerAttributes.h> // internal settings format presentations + + +// Constant for indexing (iOrder): +const TInt KSamplerPluginNotIndexed = -1; + +/** + * Constant: KSamplerPluginInterfaceUid + * + * Description: UID of this ECOM interface. It should be unique in the system. + * It is used to identify this specific custom interface. + * Implementations of this interface will use this ID, when they + * publish the implementation. Clients use this UID to search for + * implementations for this interface (the + * EcomInterfaceDefinition.inl does this). + */ +const TUid KSamplerPluginInterfaceUid = {0x2001E5BC}; + +/** + * + * Description: UID of this ECOM interface. It should be unique in the system. + * + */ +enum TGenericSettingTypes +{ + EEnablePlugin, + EOutputSettings, + ESaveDrive, + EFilePrefix, + ETracingMode +}; + + +enum TSamplerCaptionTypes + { + ECaptionLengthShort, + ECaptionLengthMedium, + ECaptionLengthLong, + ESettingsCaption + }; + + +/** +* Used by GetValue(). These are the keys for retrieving a specific +* value. This enum can be extended to provide other values as well as +* long as the original keys are not changed. +*/ +enum TSamplerPluginValueKeys + { + + ESamplerPluginKeySettingsItemValueString = 1, + ESamplerPluginSettings, + ESamplerPluginEnabled, + ESamplerPluginDisabled, + ESamplerPluginType, + ESamplerPluginVersion + }; + + +/** + * Class: CSamplerInterfaceDefinition + * + * Description: Custom ECOM interface definition. This interface is used by + * clients to find specific instance and do corresponding + * calculation operation for given too numbers. Plugin + * implementations implement the Calculate function. + */ +class TBapBuf; +class CProfilerSampleStream; + +class CSamplerPluginInterface : public CBase +{ + + // CSamplerPluginLoader accesses iOrder which should not be accessed outside. + friend class CSamplerPluginLoader; + +public: + // Wrapper functions to handle ECOM "connectivity". + // These are implemented in EComInterfaceDefinition.inl. + // These functions are used only by the client. + + /** + * Function: NewL + * + * Description: Wraps ECom object instantitation. Will search for + * interface implementation, which matches to given + * aOperationName. + * + * Param: aOperationName name of requested implementation. + * Implementations advertise their "name" as specified + * in their resource file field + * IMPLEMENTATION_INFO::default_data. + * For details, see EcomInterfaceDefinition.inl comments. + * In this example, the allowed values are "sum" and + * "multiply". + * + * Note: This is not a "normal" NewL method, since normally NewL + * methods are only defined for concrete classes. + * Note that also implementations of this interface provide + * NewL methods. They are the familiar NewL's, which create + * instance of classes. + */ + static CSamplerPluginInterface* NewL(const TUid aImplementationUid, TAny* aInitParams); + + /** + * Function: ~CSamplerPluginInterface + * + * Description: Wraps ECom object destruction. Notifies the ECOM + * framework that specific instance is being destroyed. + * See EcomInterfaceDefinition.inl for details. + */ + virtual ~CSamplerPluginInterface(); +protected: // New + + /** + * C++ constructor. + */ + CSamplerPluginInterface(); + +public: + // Public pure virtual functions, which are implemented by + // interface implementations (See ..\plugin) + + /** + * Method for initializing and starting of profiling in single plugin implementation + * @param aStream is a data stream to store the gathered data, provided by engine + * @return TInt if no error KErrNone, else any of system-wide errors + */ + virtual TInt ResetAndActivateL(CProfilerSampleStream& aStream) = 0; + + /** + * Method for stopping of profiling in single plugin implementation + * @return TInt if no error KErrNone, else any of system-wide errors + */ + virtual TInt StopSampling() = 0; + + /** + * Method for checking if plugin is enabled + * @return TBool if enabled return ETrue else EFalse + */ + virtual TBool Enabled() = 0; + + /** + * Method for getting an array of sampler attributes, size of an array: 1...n + * @return array of settings of one or several sampler plugins + */ + virtual void GetAttributesL(CArrayFixFlat<TSamplerAttributes>* aAttributeArray) = 0; + + /** + * Method for setting configurations of single sampler attributes + * @param aAttributes contains settings of a single sampler plugin + */ + virtual TInt SetAttributesL(TSamplerAttributes aAttributes) = 0; + + /** + * Method for parsing text formatted settings block and converting + * it to TSamplerAttributes data structure + * @param aSingleSettingArray containing setting lines of a single sampler + * @return status of conversion, if success KErrNone, else KErrGeneral + */ + virtual TInt ConvertRawSettingsToAttributes(CDesC8ArrayFlat* aSingleSettingArray) = 0; + + /** + * Method for getting UID of this plugin. + * @param aSubId the implementation id of sub sampler + * @returns uid of sampler or sub sampler, if aSubId -1 uid of sampler, else uid of sub sampler + */ + virtual TUid Id(TInt aSubId) const = 0; + + /** + * Method for getting locally defined sub ID value inside a specific plug-in. + * @param aUid of a specific sampler + * @returns local ID of sampler or sub sampler + */ + virtual TInt SubId(TUid aUid) const = 0; + + /** + * Method for getting sampler type. + * @returns PROFILER_USER_MODE_SAMPLER, PROFILER_KERNEL_MODE_SAMPLER or PROFILER_DUMMY_MODE_SAMPLER + */ + virtual TInt GetSamplerType() = 0; + + + // some internal inline methods, used by engine + inline TInt Flush(); + inline TInt AddSample(TUint8* sample, TUint32 length, TInt limitSize); + inline void SetOrder( TInt aOrder ); + inline static void ListAllImplementationsL(RImplInfoPtrArray& aImplInfoArray); + + /** + * Static methods for getting setting value out of descriptor + * + * @param aBuf buffer where to convert the value + * @param aValue parameter where to store the requested type of value + */ + inline static void Str2Bool(const TDesC8& aBuf, TBool& aValue); + inline static void Str2Int(const TDesC8& aBuf, TInt& aValue); + inline static void Str2Int(const TDesC8& aBuf, TUint32& aValue); + + /** iDtor_ID_Key Instance identifier key. When instance of an + * implementation is created by ECOM framework, the + * framework will assign UID for it. The UID is used in + * destructor to notify framework that this instance is + * being destroyed and resources can be released. + */ + TUid iDtor_ID_Key; + + /** + * Index of the plugin in listbox. Used for CSamplerPluginLoader. Default + * value is KSamplerPluginNotIndexed which means not ordered. This value is + * read, if defined, from the opaque_data field of the plugin's resource + * definition. Index starts from 0. + */ + TInt iOrder; + +public: + TInt iSamplerType; + + // this variable must be defined by the extending classes!! + TInt iSamplerId; + + CProfilerSampleStream* iStream; + TBool iEnabled; + +private: + TBapBuf* iBuffer; +}; + +#include <piprofiler/ProfilerGenericClassesUsr.h> +#include <piprofiler/SamplerPluginInterface.inl> + + +#endif // __SAMPLER_PLUGIN_INTERFACE__ diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/SamplerPluginInterface.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/SamplerPluginInterface.inl Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,215 @@ +/* +* 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: +* +*/ + + +// LITERALS +_LIT8(KTrue, "true"); +_LIT8(KFalse, "false"); + +inline CSamplerPluginInterface::CSamplerPluginInterface() + : iOrder( KSamplerPluginNotIndexed ) + { + iBuffer = 0; + iStream = 0; + } + +// ----------------------------------------------------------------------------- +// CSamplerPluginInterface::~CSamplerPluginInterface() +// Destructor. +// ----------------------------------------------------------------------------- +// +inline CSamplerPluginInterface::~CSamplerPluginInterface() + { + iBuffer = 0; + REComSession::DestroyedImplementation(iDtor_ID_Key); + } + + +inline CSamplerPluginInterface* CSamplerPluginInterface::NewL(const TUid aImplementationUid, TAny* aInitParams) + { + // Define options, how the default resolver will find appropriate + // implementation. + return REINTERPRET_CAST(CSamplerPluginInterface*, + REComSession::CreateImplementationL(aImplementationUid, + _FOFF( CSamplerPluginInterface, iDtor_ID_Key ), + aInitParams)); + } + +inline void CSamplerPluginInterface::ListAllImplementationsL(RImplInfoPtrArray& aImplInfoArray) + { + REComSession::ListImplementationsL(KSamplerPluginInterfaceUid, aImplInfoArray); + } + +inline void CSamplerPluginInterface::SetOrder( TInt aOrder ) + { + iOrder = aOrder; + } + +inline TInt CSamplerPluginInterface::Flush() + { + // complete the header + TUint32 header; + header = (iBuffer->iDataSize & 0x00ffffff) - 4; + header += (iSamplerId << 24); + + // flush the header info + iBuffer->iBuffer[0] = header; + iBuffer->iBuffer[1] = header >> 8; + iBuffer->iBuffer[2] = header >> 16; + iBuffer->iBuffer[3] = header >> 24; + + // write data to filled buffers + iStream->AddToFilledBuffers(iBuffer); + // notify selected writer plugin to write data to output + iStream->NotifyWriter(); + + iBuffer = 0; + + return KErrNone; +} + + +inline TInt CSamplerPluginInterface::AddSample(TUint8* aSample, TUint32 aLength, TInt aLimitSize) + { + LOGTEXT(_L("CSamplerPluginInterface::AddSample - entry")); + if(iBuffer == 0) + { + // get next free buffer where to write data + iBuffer = iStream->GetNextFreeBuffer(); + iBuffer->iBufDes->Zero(); + + // get space for the header + TUint32 header = 0; + iBuffer->iBufDes->Append((TUint8*)&header, 4); + iBuffer->iDataSize += 4; + } + + // add data to the buffer... + // if all data fit to the current buffer + if(iBuffer->iBufferSize - iBuffer->iDataSize >= (TInt)aLength) + { + iBuffer->iBufDes->Append(aSample, (TInt)aLength); + iBuffer->iDataSize += (TInt)aLength; + } + else + { + // fill in the buffer + TUint32 rest = iBuffer->iBufferSize - iBuffer->iDataSize; + iBuffer->iBufDes->Append(aSample, rest); + iBuffer->iDataSize += (TInt)rest; + + // The buffer is full now, complete the header + TUint32 header; + header = (iBuffer->iDataSize & 0x00ffffff) - 4; + header += (iSamplerId << 24); + iBuffer->iBuffer[0] = header; + iBuffer->iBuffer[1] = header >> 8; + iBuffer->iBuffer[2] = header >> 16; + iBuffer->iBuffer[3] = header >> 24; + + // write data to filled buffers + iStream->AddToFilledBuffers(iBuffer); + // notify selected writer plugin to write data to output + iStream->NotifyWriter(); + + // Fetch an empty buffer and reserve space for the header + iBuffer = iStream->GetNextFreeBuffer(); + iBuffer->iBufDes->Zero(); + header = 0; + iBuffer->iBufDes->Append((TUint8*)&header, 4); + iBuffer->iDataSize += 4; + + // copy the rest of data to the new buffer + iBuffer->iBufDes->Append(aSample+rest, aLength-rest); + iBuffer->iDataSize += (TInt)aLength-rest; + } + + // Once iBuffer->dataSize reaches the limitSize, data from iBuffer is flushed to file/debug port. + // If limitSize is set to zero, buffer is not changed until iBuffer gets full. + if(aLimitSize != 0) + { + if(iBuffer->iDataSize >= aLimitSize) + { + // The buffer is full now, complete the header + TUint32 header; + header = (iBuffer->iDataSize & 0x00ffffff) - 4; + header += (iSamplerId << 24); + iBuffer->iBuffer[0] = header; + iBuffer->iBuffer[1] = header >> 8; + iBuffer->iBuffer[2] = header >> 16; + iBuffer->iBuffer[3] = header >> 24; + + + // write data to filled buffers + iStream->AddToFilledBuffers(iBuffer); + // notify selected writer plugin to write data to output + iStream->NotifyWriter(); + + // Fetch an empty buffer and reserve space for the header + iBuffer = iStream->GetNextFreeBuffer(); + iBuffer->iBufDes->Zero(); + header = 0; + iBuffer->iBufDes->Append((TUint8*)&header, 4); + iBuffer->iDataSize += 4; + } + } + return KErrNone; + } + +// ---------------------------------------------------------------------------- +// Converts given descriptor into TBool value. +// ---------------------------------------------------------------------------- +// +inline void CSamplerPluginInterface::Str2Bool(const TDesC8& aBuf, TBool& aValue) + { + if (aBuf.CompareF(KFalse) == 0) + aValue = EFalse; + else + aValue = ETrue; + } + +// ---------------------------------------------------------------------------- +// Converts given descriptor into TInt value. +// ---------------------------------------------------------------------------- +// +inline void CSamplerPluginInterface::Str2Int(const TDesC8& aBuf, TInt& aValue) + { + TLex8 conv; + conv.Assign(aBuf); + + if (conv.Val(aValue) != KErrNone) + aValue = 0; + } + +// ---------------------------------------------------------------------------- +// Converts given descriptor into TInt value. +// ---------------------------------------------------------------------------- +// +inline void CSamplerPluginInterface::Str2Int(const TDesC8& aBuf, TUint32& aValue) + { + TInt temp(0); + + TLex8 conv; + conv.Assign(aBuf); + + if (conv.Val(temp) != KErrNone) + aValue = 0; + else + aValue = (TUint32)temp; + } + +// End of file diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/WriterPluginInterface.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/WriterPluginInterface.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,174 @@ +/* +* 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: +* +*/ + + +#ifndef __WRITERPLUGIN_INTERFACE__ +#define __WRITERPLUGIN_INTERFACE__ + +#include <e32base.h> +#include <ecom/ecom.h> +#include <badesca.h> + + +// Constant for indexing (iOrder): +const TInt KWriterPluginNotIndexed = -1; + +/** + * Constant: KWriterPluginInterfaceUid + * + * Description: UID of this ECOM interface. It should be unique in the system. + * It is used to identify this specific custom interface. + * Implementations of this interface will use this ID, when they + * publish the implementation. Clients use this UID to search for + * implementations for this interface (the + * EcomInterfaceDefinition.inl does this). + */ +const TUid KWriterPluginInterfaceUid = {0x2001E5BD}; + +/** +* Used by GetValue(). These are the keys for retrieving a specific +* value. This enum can be extended to provide other values as well as +* long as the original keys are not changed. +*/ +enum TWriterPluginValueKeys + { + EWriterPluginKeySettingsItemValueString = 1, + EWriterPluginSettings, + EWriterPluginEnabled, + EWriterPluginDisabled, + EWriterPluginType, + EWriterPluginVersion + }; +/** + * + * Description: UID of this ECOM interface. It should be unique in the system. + * + */ + +/** + * Class: CWriterInterfaceDefinition + * + * Description: Custom ECOM interface definition. This interface is used by + * clients to find specific instance and do corresponding + * calculation operation for given too numbers. Plugin + * implementations implement the Calculate function. + */ + +class CProfilerSampleStream; + +class CWriterPluginInterface : public CBase + { + + // CSamplerPluginLoader accesses iOrder which should not be accessed outside. + friend class CWriterPluginLoader; + +public: // Wrapper functions to handle ECOM "connectivity". + // These are implemented in EComInterfaceDefinition.inl. + // These functions are used only by the client. + /** + * Function: NewL + * + * Description: Wraps ECom object instantitation. Will search for + * interface implementation, which matches to given + * aOperationName. + * + * Param: aOperationName name of requested implementation. + * Implementations advertise their "name" as specified + * in their resource file field + * IMPLEMENTATION_INFO::default_data. + * For details, see EcomInterfaceDefinition.inl comments. + * In this example, the allowed values are "sum" and + * "multiply". + * + * Note: This is not a "normal" NewL method, since normally NewL + * methods are only defined for concrete classes. + * Note that also implementations of this interface provide + * NewL methods. They are the familiar NewL's, which create + * instance of classes. + */ + static CWriterPluginInterface* NewL(const TUid aImplementationUid, TAny* aInitParams); + + /** + * Function: ~CWriterPluginInterface + * + * Description: Wraps ECom object destruction. Notifies the ECOM + * framework that specific instance is being destroyed. + * See EcomInterfaceDefinition.inl for details. + */ + virtual ~CWriterPluginInterface(); +protected: // New + + /** + * C++ constructor. + */ + CWriterPluginInterface(); + +public: + /** + * Method for getting caption of this plugin. This should be the + * localized name of the settings view to be shown in parent view. + * + * @param aCaption pointer to Caption variable + */ + virtual TInt Start() = 0; + + virtual void Stop() = 0; + + virtual TUid Id() const = 0; + + virtual void GetValue( const TWriterPluginValueKeys aKey, TDes& aValue ) = 0; + + virtual void SetValue( const TWriterPluginValueKeys aKey, TDes& aValue ) = 0; + + virtual void GetWriterVersion(TDes* aDes) = 0; + + virtual TUint32 GetWriterType() = 0; + + virtual TBool GetEnabled() = 0; + + virtual void WriteData() = 0; + virtual void SetStream( CProfilerSampleStream& aStream ) = 0; + + // internal inline functions + inline static void ListAllImplementationsL( RImplInfoPtrArray& aImplInfoArray ); + inline void SetOrder( TInt aOrder ); + +private: + + /** iDtor_ID_Key Instance identifier key. When instance of an + * implementation is created by ECOM framework, the + * framework will assign UID for it. The UID is used in + * destructor to notify framework that this instance is + * being destroyed and resources can be released. + */ + TUid iDtor_ID_Key; + + /** + * Index of the plugin in listbox. Used for CSamplerPluginLoader. Default + * value is KSamplerPluginNotIndexed which means not ordered. This value is + * read, if defined, from the opaque_data field of the plugin's resource + * definition. Index starts from 0. + */ + TInt iOrder; +public: + TInt iAdditionalSettings; + TBool isEnabled; + }; + +#include <piprofiler/WriterPluginInterface.inl> + +#endif // __WRITERPLUGIN_INTERFACE__ diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/inc/WriterPluginInterface.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/inc/WriterPluginInterface.inl Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,69 @@ +/* +* 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: +* +*/ + + +inline CWriterPluginInterface::CWriterPluginInterface() + : iOrder( KWriterPluginNotIndexed ) + { + + } + +// ----------------------------------------------------------------------------- +// CWriterPluginInterface::~CWriterPluginInterface() +// Destructor. +// ----------------------------------------------------------------------------- +// +inline CWriterPluginInterface::~CWriterPluginInterface() + { + // We don't unload the plugin object here. The loader + // has to do this for us. Without this kind of destruction idiom, + // the view framework can potentially unload an ECOM plugin dll whilst + // there are still child views (Created by the plugin) that are registered + // with the view framework. If this occurs, the plugin code segment isn't + // loaded anymore and so there is no way to run the subsequent destructor + // code => exception. + + // If in the NewL some memory is reserved for member data, it must be + // released here. This interface does not have any instance variables so + // no need to delete anything. + + // Inform the ECOM framework that this specific instance of the + // interface has been destroyed. + REComSession::DestroyedImplementation(iDtor_ID_Key); + } + +inline CWriterPluginInterface* CWriterPluginInterface::NewL(const TUid aImplementationUid, TAny* aInitParams) + { + // Define options, how the default resolver will find appropriate + // implementation. + return REINTERPRET_CAST(CWriterPluginInterface*, + REComSession::CreateImplementationL(aImplementationUid, + _FOFF( CWriterPluginInterface, iDtor_ID_Key ), + aInitParams)); + } + +inline void CWriterPluginInterface::ListAllImplementationsL(RImplInfoPtrArray& aImplInfoArray) + { + REComSession::ListImplementationsL(KWriterPluginInterfaceUid, aImplInfoArray); + } + +inline void CWriterPluginInterface::SetOrder( TInt aOrder ) + { + iOrder = aOrder; + } + +// end of file diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/piprofiler_plat/piprofiler_api.metaxml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/piprofiler_plat/piprofiler_api.metaxml Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<api id="59f5d0509cc9c1556b04d7b6ff036bd0" dataversion="2.0"> + <name>PIProfiler API</name> + <description>Defines the PIProfiler API, which is used for different PI Profiler sub projects.</description> + <type>c++</type> + <collection>piprofiler</collection> + <libs> + <lib name="piprofilerapi.lib"/> + </libs> + <release category="platform" sinceversion=""/> + <attributes> + <!-- This indicates wether the api provedes separate html documentation --> + <!-- or is the additional documentation generated from headers. --> + <!-- If you are unsuere then the value is "no" --> + <htmldocprovided>no</htmldocprovided> + <adaptation>no</adaptation> + </attributes> +</api> diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/BUPplugin/data/2001E5B6.rss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/BUPplugin/data/2001E5B6.rss Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,51 @@ +/* +* 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: +* +*/ + + +#include <ecom/registryinfo.rh> + +// Declares info for two implementations +RESOURCE REGISTRY_INFO theInfo + { + // UID for the DLL. See mmp files + //__SERIES60_3X__ can't be used in resource files + dll_uid = 0x2001E5B6; + + // Declare array of interface info. This dll contains implementations for + // only one interface (CSamplerInterfaceDefinition). + interfaces = + { + INTERFACE_INFO + { + // UID of interface that is implemented + interface_uid = 0x2001E5BC; + + implementations = + { + IMPLEMENTATION_INFO + { + implementation_uid = 0x2001E5B6; + + version_no = 1; + display_name = "BUP Sampler"; + default_data = "bup"; + opaque_data = "6"; + } + }; + } + }; + } diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/BUPplugin/group/BUPPlugin.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/BUPplugin/group/BUPPlugin.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,51 @@ +/* +* 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: +* +*/ + + +#include <platform_paths.hrh> + + +TARGET PIProfilerBUP.dll +TARGETTYPE PLUGIN +UID 0x10009D8D 0x2001E5B6 +VENDORID VID_DEFAULT +CAPABILITY ALL -TCB +SMPSAFE + +OS_LAYER_SYSTEMINCLUDE +USERINCLUDE ../inc +SOURCEPATH ../src + +START RESOURCE ../data/2001E5B6.rss +TARGET PIProfilerBUP.rsc +END + +SOURCE BupPluginImplementationTable.cpp +SOURCE BupPlugin.cpp +SOURCE TouchEventClientDll.cpp + +LIBRARY euser.lib +LIBRARY bafl.lib +LIBRARY ECom.lib +LIBRARY apparc.lib +LIBRARY cone.lib +LIBRARY gdi.lib +LIBRARY ws32.lib +LIBRARY EFSRV.LIB +LIBRARY charconv.lib +LIBRARY commonengine.lib +LIBRARY flogger.lib diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/BUPplugin/group/TouchAnimDll.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/BUPplugin/group/TouchAnimDll.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,36 @@ +/* +* 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: +* +*/ + + +#include <platform_paths.hrh> + + +TARGET PIProfilerTouchEventAnim.DLL +UID 0x10003B22 0x2001E5B7 +TARGETTYPE ANI +EPOCSTACKSIZE 0x5000 +VENDORID VID_DEFAULT +CAPABILITY ALL -TCB // -AllFiles -NetworkControl -DiskAdmin -MultimediaDD -TCB -DRM +SMPSAFE + +OS_LAYER_SYSTEMINCLUDE +USERINCLUDE ../inc +SOURCEPATH ../src + +SOURCE TouchEventAnimDll.cpp + +LIBRARY euser.lib diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/BUPplugin/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/BUPplugin/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,21 @@ +/* +* 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: +* +*/ + + +PRJ_MMPFILES +TouchAnimDll.mmp +BUPPlugin.mmp diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/BUPplugin/inc/BupPlugin.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/BUPplugin/inc/BupPlugin.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,211 @@ +/* +* 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: +* +*/ + + +#ifndef PIPROFILER_BUPECOM_SAMPLER_H +#define PIPROFILER_BUPECOM_SAMPLER_H + +#include <w32std.h> +#include <w32std.h> // RWsSession +#include <w32adll.h> // RAnim DLL +#include <e32std.h> +#include <e32property.h> // RProperty + +#include <piprofiler/ProfilerTraces.h> +#include <piprofiler/ProfilerConfig.h> +#include <piprofiler/ProfilerVersion.h> +#include <piprofiler/SamplerPluginInterface.h> +#include <piprofiler/ProfilerGenericClassesUsr.h> + +#include <data_caging_path_literals.hrh> // for KDC_SHARED_LIB_DIR + +// Button press&touch event Anim DLL interface +#include "TouchEventClientDll.h" + +// caption definitions +_LIT8(KBUPShortName, "bup"); +_LIT8(KBUPLongName, "Button and touch event capture"); +_LIT8(KBUPDescription, "Button and touch event sampler\nTracing button and touch screen events\nHW dep: N/A\nSW dep: S60 3.0\n"); + +const TUid KProfilerKeyEventPropertyCat={0x2001E5AD}; +enum TProfilerKeyEventPropertyKeys + { + EProfilerKeyEventPropertySample = 7 + }; + +const TUid KGppPropertyCat={0x20201F70}; +enum TGppPropertyKeys + { + EGppPropertySyncSampleNumber + }; + + +static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy); +static _LIT_SECURITY_POLICY_C1(KCapabilityNone, ECapability_None); + +_LIT(KDllName, "PIProfilerTouchEventAnim.DLL"); // animation server dll on user disk + +/* + * + * BUP sampler definition + * + */ +class CProfilerButtonListener; +class CSamplerPluginInterface; + +class CBupPlugin : public CSamplerPluginInterface +{ +public: + static CBupPlugin* NewL(const TUid aImplementationUid, TAny* aInitParams); + ~CBupPlugin(); + + TInt ResetAndActivateL(CProfilerSampleStream& aStream); + TInt StopSampling(); + TBool Enabled() { return iEnabled; } + + TInt CreateFirstSample(); + + // no sub samplers, from CSamplerPluginInterface + TInt SubId(TUid /*aId*/) const {return KErrNotFound;} + TInt GetSamplerType(); + + void GetAttributesL(CArrayFixFlat<TSamplerAttributes>* aAttributes); + TInt SetAttributesL(TSamplerAttributes aAttributes); + void InitiateSamplerAttributesL(); + + TInt ConvertRawSettingsToAttributes(CDesC8ArrayFlat* aSingleSettingArray); + + TInt DoSetSamplerSettings(CDesC8ArrayFlat* aAllSettings, TDesC8& aSamplerName, TInt aIndex); + void SaveSettingToAttributes(const TDesC8& aSetting, TInt aIndex); + + TUid Id(TInt aSubId) const; + + void FillThisStreamBuffer(TBapBuf* nextFree,TRequestStatus& aStatus); + +private: + CBupPlugin(); + void ConstructL(); + +private: + TUint8 iVersion[20]; + TPtr8 iVersionDescriptor; + + TInt iSamplerType; + + CProfilerButtonListener* iButtonListener; + CArrayFixFlat<TSamplerAttributes>* iSamplerAttributes; +public: + TUint32* iSampleTime; +}; + + +/* +* +* Base class for all windows +* +*/ +class CWsClient : public CActive + { + protected: + //construct + CWsClient(); + CWsScreenDevice* iScreen; + RWsSession iWs; + public: + void ConstructL(); + // destruct + ~CWsClient(); + // main window + virtual void ConstructMainWindowL(); + // terminate cleanly + void Exit(); + // active object protocol + void IssueRequest(); // request an event + void DoCancel(); // cancel the request + virtual TInt RunError(TInt aError) = 0; + virtual void RunL() = 0; // handle completed request + virtual void HandleKeyEventL (TKeyEvent& aKeyEvent) = 0; + + RWindowGroup Group() {return iGroup;}; + + private: + RWindowGroup iGroup; + CWindowGc* iGc; + friend class CWindow; // needs to get at session + RProperty iProperty; + + }; + + + +class CWindow; + +class CProfilerButtonListener : public CWsClient +{ +public: + static CProfilerButtonListener* NewL(CBupPlugin* aSamplerm); + ~CProfilerButtonListener(); +private: + CProfilerButtonListener(CBupPlugin* aSampler); + + +public: + void ConstructMainWindowL(); + void HandleKeyEventL (TKeyEvent& aKeyEvent); + void RunL(); + TInt RunError(TInt aError); + TInt StartL(); + TInt Stop(); + +private: + TUint8 iSample[8]; + + CBupPlugin* iSampler; + RProfilerTouchEventAnim* iAnim; + RAnimDll* iAnimDll; + CWindow* iMainWindow; // main window + + TInt iSampleStartTime; +}; + + + +/* +* +* CWindow declaration +* +*/ +class CWindow : public CBase + { + protected: + RWindow iWindow; // window server window + TRect iRect; // rectangle re owning window + public: + CWindow(CWsClient* aClient); + void ConstructL (const TRect& aRect, CWindow* aParent=0); + ~CWindow(); + // access + RWindow& Window(); // our own window + CWindowGc* SystemGc(); // system graphics context + + CWsClient* Client() {return iClient;}; + private: + CWsClient* iClient; // client including session and group + }; + + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/BUPplugin/inc/TouchEventAnimDll.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/BUPplugin/inc/TouchEventAnimDll.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,83 @@ +/* +* 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: +* +*/ + + +#ifndef _PROFILER_TOUCH_EVENT_ANIM_DLL_ +#define _PROFILER_TOUCH_EVENT_ANIM_DLL_ + +/* +* +* TouchEventAnimDll.h +* +*/ + +// system includes +#include <w32adll.h> +#include <e32def.h> + + + +/* +* +* Class definition of CProfilerTouchEventAnim +* +*/ +class CProfilerTouchEventAnim : public CWindowAnim +{ +public: + CProfilerTouchEventAnim(); + virtual ~CProfilerTouchEventAnim(); + + // from CWindowAnim + void ConstructL(TAny* aAny, TBool aHasFocus); + void Redraw(); + void FocusChanged(TBool aState); + // from MEventHandler + TBool OfferRawEvent(const TRawEvent& aRawEvent); + // from CAnim + void Animate(TDateTime* aDateTime); + void Command(TInt aOpcode, TAny* aArgs); + TInt CommandReplyL(TInt aOpcode, TAny* aArgs); + +private: + TBool HandlePointerDown(TPoint aPoint); + TBool HandlePointerUp(TPoint aPoint); + TBool HandleKeyDown(TInt aScanCode); + TBool HandleKeyUp(TInt aScanCode); +private: + TInt iState; +}; + + +/* +* +* Class definition of CProfilerTouchEventAnimDll +* +*/ + +class CProfilerTouchEventAnimDll : public CAnimDll +{ +public: + CProfilerTouchEventAnimDll(); + +public: + IMPORT_C CAnim* CreateInstanceL(TInt aType); + +}; + + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/BUPplugin/inc/TouchEventClientDll.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/BUPplugin/inc/TouchEventClientDll.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,50 @@ +/* +* 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: +* +*/ + + +#ifndef _PROFILER_TOUCH_EVENT_CLIENT_DLL__ +#define _PROFILER_TOUCH_EVENT_CLIENT_DLL__ + +#include <w32adll.h> + +class CProfilerTouchEventControl; + +class RProfilerTouchEventAnim : public RAnim +{ + public: + RProfilerTouchEventAnim( RAnimDll& aAnimDll ); + void ConstructL( const RWindow& aParent ); + + void Activate(); + void Deactivate(); + + + enum KAnimCommands + { + KActivate = 70002, + KDeactivate = 70003 + }; + /** + * Closes the animation object + */ + void Close(); + + private: + CProfilerTouchEventControl* iTouchEventControl; +}; + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/BUPplugin/sis/BupPlugin_S60-30.pkg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/BUPplugin/sis/BupPlugin_S60-30.pkg Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,44 @@ +; +; 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: +; +; ShapeImplementation_30_gcce.pkg +; + +;Language - standard language definitions +&EN + +; standard sis file header +#{"Shape plugin"},(0xE01F614F),2,0,0 + + +; +;Localised Vendor name +; +%{"Forum Nokia"} + +; +;Unique Vendor name +; +:"Forum Nokia" + +; +;Supports Series 60 v 3.0 +; +[0x101F7961], 0, 0, 0, {"Series60ProductID"} + + +;Files to include. Check the source paths they match your SDK setup. +"\Symbian\9.1\S60_3rd_MR\Epoc32\release\gcce\urel\shapeimplementation.dll" - "!:\sys\bin\shapeimplementation.dll" +"\Symbian\9.1\S60_3rd_MR\epoc32\data\Z\Resource\plugins\shapeimplementation.rsc" - "!:\Resource\Plugins\shapeimplementation.RSC" diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/BUPplugin/src/BupPlugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/BUPplugin/src/BupPlugin.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,582 @@ +/* +* 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: +* +*/ + + +#include "BupPlugin.h" +//#include <piprofiler/EngineUIDs.h> + +#include <w32std.h> // for listening key events + + +// LITERALS +// CONSTANTS +const TUid KSamplerBupPluginUid = { 0x2001E5B6 }; + +/* + * + * class CBupPlugin implementation + * + */ + +CBupPlugin* CBupPlugin::NewL(const TUid /*aImplementationUid*/, TAny* /*aInitParams*/) + { + LOGTEXT(_L("CBupPlugin::NewL() - entry")); + CBupPlugin* self = new (ELeave) CBupPlugin(); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + LOGTEXT(_L("CBupPlugin::NewL() - exit")); + return self; + } + +CBupPlugin::CBupPlugin() : + iVersionDescriptor(&(this->iVersion[1]),0,19), + iSamplerType(PROFILER_USER_MODE_SAMPLER) + { + iSamplerId = PROFILER_BUP_SAMPLER_ID; + iEnabled = EFalse; + LOGTEXT(_L("CBupPlugin::CBupPlugin() - konstruktori")); + } + +void CBupPlugin::ConstructL() + { + LOGTEXT(_L("CBupPlugin::ConstructL() - entry")); + + // initiate sampler attributes array + iSamplerAttributes = new(ELeave) CArrayFixFlat<TSamplerAttributes>(1); // only one sampler + + // insert default attributes to array + InitiateSamplerAttributesL(); + + LOGTEXT(_L("CBupPlugin::ConstructL() - exit")); + } + + +CBupPlugin::~CBupPlugin() + { + LOGTEXT(_L("CBupPlugin::~CBupPlugin() - entry")); + if(iButtonListener) + { + // check if button listener still running + if(Enabled()) + { + // stop profiling + iButtonListener->Stop(); + } + delete iButtonListener; + } + + if(iSamplerAttributes) + { + iSamplerAttributes->Reset(); + } + delete iSamplerAttributes; + + LOGTEXT(_L("CBupPlugin::~CBupPlugin() - exit")); + } + +TUid CBupPlugin::Id(TInt /*aUid*/) const + { + LOGSTRING2("CBupPlugin::Id():0x%X", KSamplerBupPluginUid.iUid ); + return KSamplerBupPluginUid; + } + +void CBupPlugin::InitiateSamplerAttributesL() + { + // create sampler attribute container + TSamplerAttributes attr(KSamplerBupPluginUid.iUid, + KBUPShortName(), + KBUPLongName(), + KBUPDescription(), + -1, + ETrue, + EFalse, + 0); // default item count + this->iSamplerAttributes->AppendL(attr); + } + +// returns setting array +void CBupPlugin::GetAttributesL(CArrayFixFlat<TSamplerAttributes>* aAttributes) + { + // append my own attributes to complete array, requested by profiler engine + aAttributes->AppendL(iSamplerAttributes->At(0)); + } + +TInt CBupPlugin::SetAttributesL(TSamplerAttributes aAttributes) + { + TSamplerAttributes attr; + + attr = iSamplerAttributes->At(0); + // if UIDs match replace the old + if(attr.iUid == aAttributes.iUid) + { + // replace the old attribute container + iSamplerAttributes->Delete(0); + iSamplerAttributes->InsertL(0, aAttributes); + return KErrNone; + } + return KErrNotFound; + } + +/* + * Method for parsing and transforming text array settings into TSamplerAttributes (per each sub sampler), + * called by CSamplerController class + * + * @param array of raw text setting lines, e.g. [gpp]\nenabled=true\nsampling_period_ms=1\n + */ +TInt CBupPlugin::ConvertRawSettingsToAttributes(CDesC8ArrayFlat* aAllSettingsArray) + { + // local literals + _LIT8(KBUPShort, "bup"); + + TInt err(KErrNone); + TBuf8<16> samplerSearchName; + samplerSearchName.Copy(KBUPShort); + + // get sampler specific settings + err = DoSetSamplerSettings(aAllSettingsArray, samplerSearchName, 0); + + // returns KErrNone if settings found, otherwise KErrNotFound + return err; + } + +TInt CBupPlugin::DoSetSamplerSettings(CDesC8ArrayFlat* aAllSettings, TDesC8& aSamplerName, TInt aIndex) + { + // + TBuf8<16> samplerSearch; + samplerSearch.Copy(KBracketOpen); + samplerSearch.Append(aSamplerName); + samplerSearch.Append(KBracketClose); + + // read a line + for (TInt i(0); i<aAllSettings->MdcaCount(); i++) + { + // check if this line has a setting block start, i.e. contains [xxx] in it + if (aAllSettings->MdcaPoint(i).CompareF(samplerSearch) == 0) + { + // right settings block found, now loop until the next block is found + for(TInt j(i+1);j<aAllSettings->MdcaCount();j++) + { + // check if the next settings block was found + if(aAllSettings->MdcaPoint(j).Left(1).CompareF(KBracketOpen) != 0) + { + // save found setting value directly to its owners attributes + SaveSettingToAttributes(aAllSettings->MdcaPoint(j), aIndex); + } + else + { + // next block found, return KErrNone + return KErrNone; + } + } + } + } + + return KErrNotFound; + } + +/** + * Method for setting a specific descriptor (from settings file) to attribute structure + * + * @param aSetting + * @param aName + */ +void CBupPlugin::SaveSettingToAttributes(const TDesC8& aSetting, TInt aIndex) + { + // find the equal mark from the setting line + TInt sepPos = aSetting.Find(KSettingItemSeparator); + // check that '=' is found + if (sepPos > 0) + { + // check that the element matches + if (aSetting.Left(sepPos).CompareF(KEnabled) == 0) + { + TBool en; + CSamplerPluginInterface::Str2Bool(aSetting.Right(aSetting.Length()-sepPos-1), en); + if(iSamplerAttributes->At(aIndex).iEnabled != en) + { + iSamplerAttributes->At(aIndex).iEnabled = en; + } + } + } + } + +TInt CBupPlugin::GetSamplerType() + { + return iSamplerType; + } + +TInt CBupPlugin::ResetAndActivateL(CProfilerSampleStream& aStream) + { + LOGTEXT(_L("CBupPlugin::ResetAndActivate() - entry")); + TInt ret(KErrNone); + + // check if sampler enabled + if(iSamplerAttributes->At(0).iEnabled) + { + // create first the listener instance + iButtonListener = CProfilerButtonListener::NewL(this); + + LOGTEXT(_L("CBupPlugin::ResetAndActivate() - listener created")); + + iStream = &aStream; + TInt length = this->CreateFirstSample(); + iVersion[0] = (TUint8)length; + LOGSTRING2("CBupPlugin::ResetAndActivate() - AddSample, length %d",length); + ret = AddSample(iVersion, length+1, 0); + if(ret != KErrNone) + return ret; + + // activate button listener + ret = iButtonListener->StartL(); + + iEnabled = ETrue; + + LOGTEXT(_L("CBupPlugin::ResetAndActivate() - exit")); + } + return ret; + + } + +TInt CBupPlugin::CreateFirstSample() + { + LOGTEXT(_L("CBupPlugin::CreateFirstSample - entry")); + this->iVersionDescriptor.Zero(); + this->iVersionDescriptor.Append(_L8("Bappea_BUP_V")); + this->iVersionDescriptor.Append(PROFILER_BUP_SAMPLER_VERSION); + LOGTEXT(_L("CBupPlugin::CreateFirstSample - exit")); + return (TInt)(this->iVersionDescriptor.Length()); + } + +TInt CBupPlugin::StopSampling() + { + if(iButtonListener) + { + iButtonListener->Stop(); + delete iButtonListener; // delete listener after every trace + iButtonListener = NULL; + } + + // set disabled + iEnabled = EFalse; + + return KErrNone; + } + +void CBupPlugin::FillThisStreamBuffer(TBapBuf* /*aBapBuf*/, TRequestStatus& /*aStatus*/) + { + } + +/* + * + * Implementation of class CProfilerButtonListener + * + */ +CProfilerButtonListener::CProfilerButtonListener(CBupPlugin* aSampler) + { + LOGTEXT(_L("CProfilerButtonListener::CProfilerButtonListener() - konstuktori")); + this->iSampler = aSampler; + iSampleStartTime = 0; + LOGTEXT(_L("CProfilerButtonListener::CProfilerButtonListener() - konstuktori exit")); + } + +CProfilerButtonListener* CProfilerButtonListener::NewL(CBupPlugin* aSampler) + { + LOGTEXT(_L("CProfilerButtonListener::NewL() - entry")); + CProfilerButtonListener* self = new (ELeave) CProfilerButtonListener(aSampler); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + LOGTEXT(_L("CProfilerButtonListener::NewL() - exit")); + return self; + } + +CProfilerButtonListener::~CProfilerButtonListener() + { + LOGTEXT(_L("CProfilerButtonListener::~CProfilerButtonListener() - entry af")); + + if(iMainWindow) + { + LOGTEXT(_L("CProfilerButtonListener::~CProfilerButtonListener(): flushing iWs")); + iWs.Flush(); + LOGTEXT(_L("CProfilerButtonListener::~CProfilerButtonListener(): finishing")); + } + delete iMainWindow; + LOGTEXT(_L("CProfilerButtonListener::~CProfilerButtonListener() - exit")); + } + +void CProfilerButtonListener::ConstructMainWindowL() + { + LOGTEXT(_L("CProfilerButtonListener::ConstructMainWindowL() - Entry")); + + CWindow* window = new (ELeave) CWindow(this); + CleanupStack::PushL( window ); + window->ConstructL(TRect(TPoint(0,0), TSize(0,0))); + delete iMainWindow; + iMainWindow = window; + CleanupStack::Pop( window ); + + LOGTEXT(_L("CProfilerButtonListener::ConstructMainWindowL() - Exit")); + } + +void CProfilerButtonListener::HandleKeyEventL (TKeyEvent& /*aKeyEvent*/) + { + LOGTEXT(_L("CProfilerButtonListener::HandleKeyEventL() - Start")); + LOGTEXT(_L("CProfilerButtonListener::HandleKeyEventL() - End")); + } + + +TInt CProfilerButtonListener::RunError(TInt aError) + { + // get rid of everything we allocated + // deactivate the anim dll before killing window, otherwise anim dll dies too early + iAnim->Deactivate(); + iAnim->Close(); + + iAnimDll->Close(); + + return aError; + } + +void CProfilerButtonListener::RunL() + { + // resubscribe before processing new value to prevent missing updates + IssueRequest(); + + TInt c = 0; + if(RProperty::Get(KProfilerKeyEventPropertyCat, EProfilerKeyEventPropertySample, c) == KErrNone) + { + // do something with event + LOGSTRING2("CProfilerButtonListener::RunL() - event [%d] received",c); + + iSample[0] = c; + iSample[1] = c >> 8; + iSample[2] = c >> 16; + iSample[3] = c >> 24; + + // Space for GPP sample time + TUint32 sampleTime = User::NTickCount() - iSampleStartTime; + LOGSTRING2("CProfilerButtonListener::RunL() - sample time is %d",sampleTime); + + iSample[4] = sampleTime; + iSample[5] = sampleTime >> 8; + iSample[6] = sampleTime >> 16; + iSample[7] = sampleTime >> 24; + + iSampler->AddSample(iSample, 8, 0xb0); + } + } + +TInt CProfilerButtonListener::StartL() + { + LOGTEXT(_L("CProfilerButtonListener::StartL() - Activate touch server dll")); + TInt err(KErrNone); + + // get the property value + TInt r = RProperty::Get(KGppPropertyCat, EGppPropertySyncSampleNumber, iSampleStartTime); + if(r != KErrNone) + { + LOGSTRING2("CProfilerButtonListener::StartL() - getting iSyncOffset failed, error %d", r); + } + + iAnimDll = new (ELeave) RAnimDll(iWs); + LOGTEXT(_L("CProfilerButtonListener::StartL() - #1")); + + TParse* fp = new (ELeave) TParse(); + CleanupStack::PushL(fp); + fp->Set( KDllName, &KDC_SHARED_LIB_DIR , NULL ); + LOGSTRING2("CProfilerButtonListener::StartL() - touch event server: %S" , &(fp->FullName())); + + err = iAnimDll->Load(fp->FullName()); + // check if anim dll load failed + if(err != KErrNone) + { + CleanupStack::PopAndDestroy(fp); + // stop plugin if failed + iAnimDll->Close(); + return KErrGeneral; + } + CleanupStack::PopAndDestroy(fp); + LOGTEXT(_L("CProfilerButtonListener::StartL() - #2")); + + iAnim = new (ELeave) RProfilerTouchEventAnim(*iAnimDll); + LOGTEXT(_L("CProfilerButtonListener::StartL() - #3")); + iAnim->ConstructL(iMainWindow->Window()); + + // activate the animation dll for collecting touch and key events + iAnim->Activate(); + + // wait for a new sample + IssueRequest(); + + // hide this window group from the app switcher + iMainWindow->Client()->Group().SetOrdinalPosition(-1); + iMainWindow->Client()->Group().EnableReceiptOfFocus(EFalse); + return KErrNone; + } + +TInt CProfilerButtonListener::Stop() + { + LOGTEXT(_L("CProfilerButtonListener::Stop() - enter")); + // deactivate the anim dll before killing window, otherwise anim dll dies too early + iAnim->Deactivate(); + iAnim->Close(); + + iAnimDll->Close(); + + Cancel(); + LOGTEXT(_L("CProfilerButtonListener::Stop() - exit")); + return KErrNone; + } + + +/////////////////////////////////////////////////////////////////////////////// +////////////////////////// CWindow implementation ///////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +CWindow::CWindow(CWsClient* aClient) +: iClient(aClient) + { + LOGTEXT(_L("CWindow::CWindow()")); + } + +void CWindow::ConstructL (const TRect& aRect, CWindow* aParent) + { + LOGTEXT(_L("CWindow::ConstructL(): Start")); + + // If a parent window was specified, use it; if not, use the window group + // (aParent defaults to 0). + RWindowTreeNode* parent= aParent ? (RWindowTreeNode*) &(aParent->Window()) : &(iClient->iGroup); + iWindow=RWindow(iClient->iWs); // use app's session to window server + User::LeaveIfError(iWindow.Construct(*parent,(TUint32)this)); + LOGSTRING2("CWindow::ConstructL(): Start - window handle is: 0x%08x", this); + iRect = aRect; + iWindow.SetExtent(iRect.iTl, iRect.Size()); // set extent relative to group coords + iWindow.Activate(); // window is now active + LOGTEXT(_L("CWindow::ConstructL(): End")); + } + + +CWindow::~CWindow() + { + LOGTEXT(_L("CWindow::~CWindow(): Start")); + iWindow.Close(); // close our window + LOGTEXT(_L("CWindow::~CWindow(): End")); + } + +RWindow& CWindow::Window() + { + LOGTEXT(_L("CWindow::Window()")); + return iWindow; + } + +CWindowGc* CWindow::SystemGc() + { + LOGTEXT(_L("CWindow::SystemGc()")); + return iClient->iGc; + } + +///////////////////////////////////////////////////////////////////////////////////// +/////////////////////////// CWsClient implementation //////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +CWsClient::CWsClient() +: CActive(CActive::EPriorityStandard) + { + LOGTEXT(_L("CWsClient::CWsClient()")); + } + +void CWsClient::ConstructL() + { + LOGTEXT(_L("CWsClient::ConstructL() - Start")); + TInt r = RProperty::Define(EProfilerKeyEventPropertySample, RProperty::EInt, KAllowAllPolicy, KCapabilityNone); + if (r!=KErrAlreadyExists) + { + User::LeaveIfError(r); + } + + CActiveScheduler::Add(this); + + // attach to + User::LeaveIfError(iProperty.Attach(KProfilerKeyEventPropertyCat,EProfilerKeyEventPropertySample)); + + // get a session going + User::LeaveIfError(iWs.Connect()); + + // construct screen device and graphics context + iScreen=new (ELeave) CWsScreenDevice(iWs); // make device for this session + User::LeaveIfError(iScreen->Construct( 0 )); // and complete its construction + User::LeaveIfError(iScreen->CreateContext(iGc)); // create graphics context + + // construct our one and only window group + iGroup=RWindowGroup(iWs); + User::LeaveIfError(iGroup.Construct((TInt)this, EFalse)); // meaningless handle; enable focus + + // construct main window + ConstructMainWindowL(); + + LOGTEXT(_L("CWsClient::CWsClient() - End")); + } + +CWsClient::~CWsClient() + { + LOGTEXT(_L("CWsClient::~CWsClient() - Start")); + + // get rid of everything we allocated + delete iGc; + delete iScreen; + + iGroup.Close(); + // finish with window server + iWs.Close(); + + LOGTEXT(_L("CWsClient::~CWsClient() - Exit")); + } + +void CWsClient::Exit() + { + LOGTEXT(_L("CWsClient::Exit() - Start")); + + // destroy window group + iGroup.Close(); + // finish with window server + iProperty.Close(); + iWs.Close(); + LOGTEXT(_L("CWsClient::Exit() - Exit")); + } + +void CWsClient::IssueRequest() + { + LOGTEXT(_L("CWsClient::IssueRequest() - Start")); + iProperty.Subscribe( iStatus ); + SetActive(); // so we're now active + LOGTEXT(_L("CWsClient::IssueRequest() - Exit")); + } + +void CWsClient::DoCancel() + { + LOGTEXT(_L("CWsClient::DoCancel() - Start")); + // clean up the sample property + iProperty.Cancel(); + iProperty.Close(); + LOGTEXT(_L("CWsClient::DoCancel() - Exit")); + } + +void CWsClient::ConstructMainWindowL() + { + LOGTEXT(_L("CWsClient::ConstructMainWindowL()")); + } + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/BUPplugin/src/BupPluginImplementationTable.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/BUPplugin/src/BupPluginImplementationTable.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,39 @@ +/* +* 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: +* +*/ + + +// INCLUDE FILES +#include <e32std.h> +#include <ecom/implementationproxy.h> + +#include "BupPlugin.h" + + +// Provides a key value pair table, this is used to identify +// the correct construction function for the requested interface. +const TImplementationProxy ImplementationTable[] = +{ + IMPLEMENTATION_PROXY_ENTRY(0x2001E5B6, CBupPlugin::NewL) +}; + +// Function used to return an instance of the proxy table. +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) +{ + aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); + return ImplementationTable; +} + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/BUPplugin/src/TouchEventAnimDll.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/BUPplugin/src/TouchEventAnimDll.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,205 @@ +/* +* 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: +* +*/ + + + +#include <e32base.h> +#include <e32cons.h> +#include <w32std.h> +#include <in_sock.h> +#include <txtfrmat.h> +#include <e32property.h> +#include <piprofiler/ProfilerTraces.h> + +// user includes +#include "TouchEventAnimDll.h" + +// control commands +static const TInt KActivate = 70002; +static const TInt KDeactivate = 70003; + +// touch events +static const TInt KTouchEventDown = 69999; +static const TInt KTouchEventUp = 70000; + +static const TInt KUpEventOffset = 70000; + +_LIT( KTouchEventServer, "PIProfilerTouchEvent server" ); +enum TAnimationPanics + { + EProfilerTouchEventServerPanic = 100 + }; + +const TUid KProfilerKeyEventPropertyCat={0x2001E5AD}; +enum TProfilerKeyEventPropertyKeys + { + EProfilerKeyEventPropertySample = 7 + }; + +/* +* +* Implementation of CProfilerTouchEventAnim +* +*/ +CProfilerTouchEventAnim::CProfilerTouchEventAnim() : iState(EFalse) + { + LOGTEXT(_L("CProfilerTouchEventAnim::CProfilerTouchEventAnim - entry")); + } + +CProfilerTouchEventAnim::~CProfilerTouchEventAnim() + { + LOGTEXT(_L("CProfilerTouchEventAnim::~CProfilerTouchEventAnim - entry")); + //iFunctions->GetRawEvents( EFalse ); // disable capture + LOGTEXT(_L("CProfilerTouchEventAnim::~CProfilerTouchEventAnim - exit")); + } + +void CProfilerTouchEventAnim::ConstructL(TAny* /*aArgs*/, TBool /*aHasFocus*/) + { + LOGTEXT(_L("CProfilerTouchEventAnim::ConstructL - entry")); + iFunctions->GetRawEvents( ETrue ); + LOGTEXT(_L("CProfilerTouchEventAnim::ConstructL - exit")); + } + +void CProfilerTouchEventAnim::Command(TInt /*aOpcode*/, TAny* /*aArgs*/) + { + + } + +TInt CProfilerTouchEventAnim::CommandReplyL(TInt aOpcode, TAny* /*aArgs*/) + { + LOGSTRING2("CProfilerTouchEventAnim::CommandReplyL - entry, aOpcode: %d", aOpcode); + switch(aOpcode) + { + case KActivate: // activate + iState = ETrue; + LOGTEXT(_L("CProfilerTouchEventAnim::CommandReplyL - activate")); + break; + case KDeactivate: // deactivate + iState = EFalse; + iFunctions->GetRawEvents( EFalse ); // disable capture + LOGTEXT(_L("CProfilerTouchEventAnim::CommandReplyL - deactivate")); + break; + default: + User::Panic( KTouchEventServer, EProfilerTouchEventServerPanic ); + LOGSTRING2("CProfilerTouchEventAnim::CommandReplyL - panic, code %d", EProfilerTouchEventServerPanic); + return EProfilerTouchEventServerPanic; + + } + return KErrNone; + } + + +TBool CProfilerTouchEventAnim::OfferRawEvent(const TRawEvent& aRawEvent) + { + LOGTEXT(_L("CProfilerTouchEventAnim::OfferRawEvent - entry")); + if(iState == EFalse) + return EFalse; // if not activated yet just pass through + + + switch(aRawEvent.Type()) + { + // handle the pointer events here + case TRawEvent::EButton1Down: + { + LOGTEXT(_L("CProfilerTouchEventAnim::OfferRawEvent - pointer down")); + return HandlePointerDown(aRawEvent.Pos()); + } + case TRawEvent::EButton1Up: + { + LOGTEXT(_L("CProfilerTouchEventAnim::OfferRawEvent - pointer up")); + return HandlePointerUp(aRawEvent.Pos()); + } + + // handle the key events here, replacing the BUP trace functionality + case TRawEvent::EKeyDown: + { + TInt scan = aRawEvent.ScanCode() & 0xFFFF; + return HandleKeyDown(scan); + } + case TRawEvent::EKeyUp: + { + TInt scan = (aRawEvent.ScanCode() & 0xFFFF)+KUpEventOffset; // + return HandleKeyUp(scan); + } + default: + return EFalse; // no action + } + } + +TBool CProfilerTouchEventAnim::HandlePointerDown( TPoint /*aPoint*/ ) + { + RProperty::Set(KProfilerKeyEventPropertyCat,EProfilerKeyEventPropertySample, KTouchEventDown); + return EFalse; + } + +TBool CProfilerTouchEventAnim::HandlePointerUp( TPoint /*aPoint*/ ) + { + RProperty::Set(KProfilerKeyEventPropertyCat,EProfilerKeyEventPropertySample, KTouchEventUp); + return EFalse; + } + +TBool CProfilerTouchEventAnim::HandleKeyDown( TInt aScanCode ) + { + LOGSTRING2("CProfilerTouchEventAnim::HandleKeyDown - scancode = %d", aScanCode); + RProperty::Set(KProfilerKeyEventPropertyCat,EProfilerKeyEventPropertySample, aScanCode); + return EFalse; + } + +TBool CProfilerTouchEventAnim::HandleKeyUp( TInt aScanCode ) + { + LOGSTRING2("CProfilerTouchEventAnim::HandleKeyUp - scancode = %d", aScanCode); + RProperty::Set(KProfilerKeyEventPropertyCat,EProfilerKeyEventPropertySample, aScanCode); + return EFalse; + } + + +void CProfilerTouchEventAnim::Animate(TDateTime* /*aDateTime*/) + { + } + +void CProfilerTouchEventAnim::Redraw() + { + } + +void CProfilerTouchEventAnim::FocusChanged(TBool /*aState*/) + { + } + + +/* +* +* Implementation of CProfilerTouchEventAnimDll +* +*/ +CProfilerTouchEventAnimDll::CProfilerTouchEventAnimDll() : CAnimDll() + { + } + +CAnim* CProfilerTouchEventAnimDll::CreateInstanceL(TInt /*aType*/) + { + LOGTEXT(_L("CProfilerTouchEventAnimDll::CreateInstanceL - entry")); + return (new (ELeave) CProfilerTouchEventAnim()); + } + + +// DLL entry +EXPORT_C CAnimDll* CreateCAnimDllL() + { + return (new (ELeave) CProfilerTouchEventAnimDll); + } + + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/BUPplugin/src/TouchEventClientDll.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/BUPplugin/src/TouchEventClientDll.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,60 @@ +/* +* 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: +* +*/ + + +#include "TouchEventClientDll.h" +#include <piprofiler/ProfilerTraces.h> + +/* + * + * class RProfilerTouchEventAnim implementation + * + */ +void RProfilerTouchEventAnim::ConstructL( const RWindow& aParent) +{ + LOGTEXT(_L("RProfilerTouchEventAnim::ConstructL - entry")); + LOGTEXT(_L("RProfilerTouchEventAnim::ConstructL - calling RAnim::Construct...")); + RAnim::Construct(aParent, 0, TPtrC8()); +} + + +RProfilerTouchEventAnim::RProfilerTouchEventAnim( RAnimDll &aAnimDll ) : + RAnim( aAnimDll ) +{ +} + +void RProfilerTouchEventAnim::Activate() +{ + LOGTEXT(_L("RProfilerTouchEventAnim::Activate - entry")); + TInt err = RAnim::CommandReply(KActivate); + LOGSTRING2("RProfilerTouchEventAnim::Activate - error: %d", err); +} + +void RProfilerTouchEventAnim::Deactivate() +{ + LOGTEXT(_L("RProfilerTouchEventAnim::Deactivate - entry")); + TInt err = RAnim::CommandReply(KDeactivate); + LOGSTRING2("RProfilerTouchEventAnim::Deactivate - error: %d", err); +} + +void RProfilerTouchEventAnim::Close() + { + RAnim::Close(); + } + + + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/DebugOutputWriterPlugin/data/2001E5BA.rss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/DebugOutputWriterPlugin/data/2001E5BA.rss Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,51 @@ +/* +* 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: +* +*/ + + +#include <ecom/registryinfo.rh> + +// Declares info for two implementations +RESOURCE REGISTRY_INFO theInfo + { + // UID for the DLL. See mmp files + //__SERIES60_3X__ can't be used in resource files + dll_uid = 0x2001E5BA; + + // Declare array of interface info. This dll contains implementations for + // only one interface (CSamplerInterfaceDefinition). + interfaces = + { + INTERFACE_INFO + { + // UID of interface that is implemented + interface_uid = 0x2001E5BD; + + implementations = + { + IMPLEMENTATION_INFO + { + implementation_uid = 0x2001E5BA; + + version_no = 1; + display_name = "Debug output writer implementation"; + default_data = "dow"; + opaque_data = "1"; + } + }; + } + }; + } diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/DebugOutputWriterPlugin/group/DebOutWriterPlugin.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/DebugOutputWriterPlugin/group/DebOutWriterPlugin.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,51 @@ +/* +* 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: +* +*/ + + +#include <platform_paths.hrh> + + +TARGET PIProfilerDebugWriter.dll +TARGETTYPE PLUGIN +UID 0x10009D8D 0x2001E5BA +#ifdef WINSCW +VENDORID 0 +#else +VENDORID VID_DEFAULT +#endif +CAPABILITY ALL -TCB // AllFiles ReadDeviceData ReadUserData UserEnvironment WriteDeviceData WriteUserData +SMPSAFE + +OS_LAYER_SYSTEMINCLUDE +USERINCLUDE ../inc ../traces +#ifdef OST_TRACE_COMPILER_IN_USE +USERINCLUDE ../traces +#endif +SOURCEPATH ../src + +START RESOURCE ../data/2001E5BA.rss +TARGET piprofilerdebugwriter.rsc +END + +SOURCE DebOutWriterPlugin.cpp +SOURCE DebOutWriterPluginImplementationTable.cpp + +LIBRARY euser.lib +LIBRARY ECom.lib +LIBRARY EFSRV.LIB +LIBRARY commonengine.lib +LIBRARY flogger.lib diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/DebugOutputWriterPlugin/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/DebugOutputWriterPlugin/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,20 @@ +/* +* 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: +* +*/ + + +PRJ_MMPFILES +DebOutWriterPlugin.mmp diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/DebugOutputWriterPlugin/inc/DebOutWriterPlugin.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/DebugOutputWriterPlugin/inc/DebOutWriterPlugin.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,137 @@ +/* +* 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: +* +*/ + + +// This file defines the API for DebOutWriterPlugin.dll + +#ifndef __DEBOUTWRITERPLUGIN_H__ +#define __DEBOUTWRITERPLUGIN_H__ + +// Include Files +#include <w32std.h> +#include <piprofiler/WriterPluginInterface.h> +#include <piprofiler/ProfilerGenericClassesUsr.h> +#include <e32base.h> // CBase +#include <e32std.h> // TBuf +#include <e32property.h> + +#ifdef OST_TRACE_COMPILER_IN_USE +// trace core ldd activation/deactivation interface +#include <TcDriverIf.h> + +// trace core ldd global definitions +_LIT( KTcLdd, "tcldd.ldd" ); +GLDEF_D RTcDriver tcldd; + +#endif + +_LIT(KDebOutShortName, "dow"); + +// forward declarations +class CDebOutWriterHandler; + +// Class Definitions + +class CDebOutWriterPlugin : public CWriterPluginInterface + { +public: + // new function + static CDebOutWriterPlugin* NewL(const TUid aImplementationUid, TAny* /*aInitParams*/); + ~CDebOutWriterPlugin(); + + void DoCancel(); + static void PrintDescriptorAsBase64(TDesC8& aDes, TRequestStatus* aStatus, TUint32 sampleTime, TBool aEmptying); + +public: // new functions + + TInt Start(); + + void Stop(); + + void GetValue( const TWriterPluginValueKeys aKey, TDes& aValue ); + + void SetValue( const TWriterPluginValueKeys aKey, TDes& aValue ); + + TUid Id() const; + + void GetWriterVersion(TDes* aDes); + + TUint32 GetWriterType(); + + void SetStream(CProfilerSampleStream& aStream) { iStream = &aStream; } + + void HandleError(TInt aError); + + void WriteData(); +private: // new functions + CDebOutWriterPlugin(const TUid aImplementationUid); + void ConstructL(); + + void GetValueL( const TWriterPluginValueKeys aKey, TDes& aValue ); + void SetValueL( const TWriterPluginValueKeys aKey, TDes& aValue ); + TBool GetEnabled(); +public: + CProfilerSampleStream* iStream; +private: // data + TBapBuf* iBufferBeingWritten; + + TInt iWriterType; + TInt iWriterId; + CDebOutWriterHandler* iWriterHandler; + RProperty iErrorStatus; + + }; + +/* + * + * Definition of class CDebOutWriterHandler + * + */ +class CDebOutWriterHandler : public CActive + { +public: + + + static CDebOutWriterHandler* NewL(CDebOutWriterPlugin* aWriter); + ~CDebOutWriterHandler(); + void DoCancel(); + void StartL(); + + void Stop(); + + void Reset(); +private: + CDebOutWriterHandler(CDebOutWriterPlugin* aWriter); + + void ConstructL(); + void RunL(); + + void WriteBufferToOutput(TBapBuf* aBuf); + void PrintBufferToOutput(TBapBuf* aBuffer, TRequestStatus& aStatus); + void HandleFullBuffers(); +private: + CDebOutWriterPlugin* iWriter; + RFile iFile; + RFs iFs; + TBuf<256> iFileName; +// CPeriodic* iTimer; + TBapBuf* iBufferBeingWritten; + TBool iStopping; + }; + +#endif // __DEBOUTWRITERPLUGIN_H__ + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/DebugOutputWriterPlugin/sis/DebOutWriterPlugin_EKA2.pkg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/DebugOutputWriterPlugin/sis/DebOutWriterPlugin_EKA2.pkg Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,36 @@ +; +; 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: +; +; Installation file for DebOutWriterPlugin dll +; +; This is an auto-generated PKG file by Carbide. +; This file uses variables specific to Carbide builds that will not work +; on command-line builds. If you want to use this generated PKG file from the +; command-line tools you will need to modify the variables with the appropriate +; values: $(EPOCROOT), $(PLATFORM), $(TARGET) + +; +; UID is the dll's UID +; +#{"DebOutWriterPlugin DLL"},(0x00DA58C7),1,0,0 + + +;Localised Vendor name +%{"Vendor-EN"} + +;Unique Vendor name +:"Vendor" + +"$(EPOCROOT)Epoc32\release\$(PLATFORM)\$(TARGET)\DebOutWriterPlugin.dll" -"!:\sys\bin\DebOutWriterPlugin.dll" diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/DebugOutputWriterPlugin/src/DebOutWriterPlugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/DebugOutputWriterPlugin/src/DebOutWriterPlugin.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,542 @@ +/* +* 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: +* +*/ + + +// Include Files + +#include "DebOutWriterPlugin.h" +#include <e32base.h> +//#include <piprofiler/EngineUIDs.h> +#include <piprofiler/ProfilerTraces.h> +#ifdef OST_TRACE_COMPILER_IN_USE +#include <OpenSystemTrace.h> +#include "DebOutWriterPluginTraces.h" +#endif + +// engine properties +const TUid KEngineStatusPropertyCat={0x2001E5AD}; +enum TEnginePropertyKeys + { + EProfilerEngineStatus = 8, + EProfilerErrorStatus + }; + +// CONSTANTS +// own UID +const TUid KDebOutWriterPluginUid = { 0x2001E5BA }; + +// Member Functions +/* + * + * Class CDebOutWriterPlugin implementation + * + */ + +CDebOutWriterPlugin* CDebOutWriterPlugin::NewL(const TUid /*aImplementationUid*/, TAny* /*aInitParams*/) +{ + LOGTEXT(_L("CDebOutWriterPlugin::NewL() - entry")); + CDebOutWriterPlugin* self = new (ELeave) CDebOutWriterPlugin(KDebOutWriterPluginUid); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + LOGTEXT(_L("CDebOutWriterPlugin::NewL() - exit")); + return self; +} + +CDebOutWriterPlugin::CDebOutWriterPlugin(const TUid aImplementationUid) : + iWriterType(aImplementationUid.iUid) + { + LOGTEXT(_L("CDebOutWriterPlugin::CDebOutWriterPlugin - entry")); + isEnabled = EFalse; + iWriterId = Id().iUid; + LOGTEXT(_L("CDebOutWriterPlugin::CDebOutWriterPlugin - exit")); + } + +CDebOutWriterPlugin::~CDebOutWriterPlugin() + { + LOGTEXT(_L("CDebOutWriterPlugin::~CDebOutWriterPlugin - entry")); + + iErrorStatus.Close(); + + if(iWriterHandler) + { + iWriterHandler->Cancel(); + delete iWriterHandler; + } + LOGTEXT(_L("CDebOutWriterPlugin::~CDebOutWriterPlugin - exit")); + } + +void CDebOutWriterPlugin::ConstructL() + { + // second phase constructor, anything that may leave must be constructed here + + LOGTEXT(_L("CDebOutWriterPlugin::ConstructL() - entry")); + iWriterHandler = CDebOutWriterHandler::NewL(this); + User::LeaveIfError(iErrorStatus.Attach(KEngineStatusPropertyCat, EProfilerErrorStatus)); + + LOGTEXT(_L("CDebOutWriterPlugin::ConstructL() - exit")); + } + +TInt CDebOutWriterPlugin::Start() + { + LOGTEXT(_L("CDebOutWriterPlugin::Start() - entry")); + +#ifdef OST_TRACE_COMPILER_IN_USE + TInt err(KErrNone); + // activate traces on TraceCore + RTcDriverParameters tcdp_ThreadIdentification; + tcdp_ThreadIdentification.iComponentId = KOstTraceComponentID; + tcdp_ThreadIdentification.iGroupId = CDEBOUTWRITERPLUGIN_PRINTDESCRIPTORASBASE64START; + err = tcldd.ActivateTrace(tcdp_ThreadIdentification); + + tcdp_ThreadIdentification.iGroupId = CDEBOUTWRITERPLUGIN_PRINTDESCRIPTORASBASE64LINE; + err = tcldd.ActivateTrace(tcdp_ThreadIdentification); + + tcdp_ThreadIdentification.iGroupId = CDEBOUTWRITERPLUGIN_PRINTDESCRIPTORASBASE64FIN; + err = tcldd.ActivateTrace(tcdp_ThreadIdentification); + + tcdp_ThreadIdentification.iGroupId = CDEBOUTWRITERPLUGIN_PRINTDESCRIPTORASBASE64END; + err = tcldd.ActivateTrace(tcdp_ThreadIdentification); + + RDebug::Print(_L("Debug output activated")); + if(err != KErrNone) + RDebug::Print(_L("TraceCore LDD API responded: %d"), err); +#endif + + LOGTEXT(_L("CDebOutWriterPlugin::Start() - exit")); + return KErrNone; + } + +void CDebOutWriterPlugin::Stop() + { + LOGTEXT(_L("CDebOutWriterPlugin::Stop() - entry")); + iWriterHandler->Stop(); +#ifdef OST_TRACE_COMPILER_IN_USE + TInt err(KErrNone); + // activate traces on TraceCore + RTcDriverParameters tcdp_ThreadIdentification; + tcdp_ThreadIdentification.iComponentId = KOstTraceComponentID; + tcdp_ThreadIdentification.iGroupId = CDEBOUTWRITERPLUGIN_PRINTDESCRIPTORASBASE64START; + err = tcldd.DeactivateTrace(tcdp_ThreadIdentification); + + tcdp_ThreadIdentification.iGroupId = CDEBOUTWRITERPLUGIN_PRINTDESCRIPTORASBASE64LINE; + err = tcldd.DeactivateTrace(tcdp_ThreadIdentification); + + tcdp_ThreadIdentification.iGroupId = CDEBOUTWRITERPLUGIN_PRINTDESCRIPTORASBASE64FIN; + err = tcldd.DeactivateTrace(tcdp_ThreadIdentification); + + tcdp_ThreadIdentification.iGroupId = CDEBOUTWRITERPLUGIN_PRINTDESCRIPTORASBASE64END; + err = tcldd.DeactivateTrace(tcdp_ThreadIdentification); + + RDebug::Print(_L("Debug output deactivated")); + if(err != KErrNone) + RDebug::Print(_L("TraceCore LDD API responded: %d"), err); +#endif + LOGTEXT(_L("CDebOutWriterPlugin::Stop() - exit")); + } + +TUid CDebOutWriterPlugin::Id() const + { + LOGSTRING2("CDebOutWriterPlugin::Id(): 0x%X", KDebOutWriterPluginUid.iUid ); + return KDebOutWriterPluginUid; + //return iDtor_ID_Key; + } + +TBool CDebOutWriterPlugin::GetEnabled() + { + return isEnabled; + } + +void CDebOutWriterPlugin::SetValue( const TWriterPluginValueKeys aKey, + TDes& aValue ) + { + TRAP_IGNORE( SetValueL( aKey, aValue ) ); + } + + +void CDebOutWriterPlugin::GetValue( const TWriterPluginValueKeys aKey, + TDes& aValue ) + { + TRAP_IGNORE( GetValueL( aKey, aValue ) ); + } + + + +void CDebOutWriterPlugin::SetValueL( const TWriterPluginValueKeys aKey, TDes& /*aValue*/ ) +{ + LOGTEXT(_L("CDebOutWriterPlugin::SetValueL - entry")); + + switch( aKey ) + { + case EWriterPluginEnabled: + isEnabled = ETrue; + LOGTEXT(_L("CDebOutWriterPlugin::SetValueL - plugin enabled")); + break; + case EWriterPluginDisabled: + isEnabled = EFalse; + LOGTEXT(_L("CDebOutWriterPlugin::SetValueL - plugin disabled")); + break; + case EWriterPluginSettings: + //result = StringLoader::LoadL(PROFILER_KERNEL_MODE_SAMPLER); + LOGTEXT(_L("CDebOutWriterPlugin::SetValueL - setting plugin settings")); + break; + default: + break; + } + LOGTEXT(_L("CDebOutWriterPlugin::SetValueL - exit")); + +} + +TUint32 CDebOutWriterPlugin::GetWriterType() + { + return iWriterType; + } + + +void CDebOutWriterPlugin::GetValueL( const TWriterPluginValueKeys aKey, TDes& aValue ) + { + switch( aKey ) + { + case EWriterPluginVersion: + + GetWriterVersion(&aValue); + break; + case EWriterPluginType: + break; + default: + break; + } + } + +void CDebOutWriterPlugin::GetWriterVersion(TDes* aDes) + { + _LIT(KDebugOutputWriterVersion, "1.0.0"); + aDes->Append(KDebugOutputWriterVersion); + } + +void CDebOutWriterPlugin::DoCancel() +{ + LOGTEXT(_L("CDebOutWriterPlugin::DoCancel - entry")); +} + +void CDebOutWriterPlugin::WriteData() + { + // Activate handler to write data from buffer to output + LOGTEXT(_L("CDiskWriterPlugin::WriteData() - entry")); + TRAP_IGNORE(iWriterHandler->StartL()); + LOGTEXT(_L("CDiskWriterPlugin::WriteData() - exit")); + } + +void CDebOutWriterPlugin::HandleError(TInt aError) + { + TInt err(KErrNone); + err = iErrorStatus.Set(aError); + if(err != KErrNone) + { + RDebug::Print(_L("CDiskWriterPlugin::HandleError() - error: %d"), err); + } + } + +void CDebOutWriterPlugin::PrintDescriptorAsBase64( TDesC8& aDes, + TRequestStatus* aStatus, + TUint32 sampleTime, + TBool aEmptying) +{ + LOGTEXT(_L("CDebOutWriterPlugin::PrintDescriptorAsBase64() - entry")); + TUint len = aDes.Length(); + + // we must wait for the sample tick to be printed, in case + // prints are performed at user side, otherwise the kernel + // prints will corrupt the data + if(sampleTime != 0xffffffff) + { + TUint32 remains = sampleTime%1000; + + if(remains > 800) + { + TTimeIntervalMicroSeconds32 timeToWait = ((1050-remains)*1000); + User::After(timeToWait); + } + } + + TBuf16<75> buf; + + // Header +#ifdef OST_TRACE_COMPILER_IN_USE + OstTrace0( PIPROFILER_TRACE_OUT, CDEBOUTWRITERPLUGIN_PRINTDESCRIPTORASBASE64START, + "<PIPROF>=================================================================" ); +#else + RDebug::Print(_L("<PIPROF>=================================================================")); +#endif + buf.Zero(); + + // base64 encoding table + const char uu_base64[64] = + { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/' + }; + + TChar byte1, byte2, byte3, byte4; + TUint8 count = 0x30; + // base64 encoding + for(TUint i = 0, j = 0; i < len; i += 3, j = (j + 1) % 18) + { + // byte 1 + byte1 = uu_base64[(aDes[i] >> 2) & 0x3F]; + + // byte 2 + if(i+1 < len) + byte2 = uu_base64[(aDes[i] << 4) & 0x3f | (aDes[i+1] >> 4)]; + else + byte2 = uu_base64[(aDes[i] << 4) & 0x3f]; + + // byte 3 + if(i+1 < len && i+2 < len) + byte3 = uu_base64[(aDes[i+1] << 2) & 0x3f | (aDes[i+2] >> 6)]; + else if(i+1 < len) + byte3 = uu_base64[(aDes[i+1] << 2) & 0x3f]; + else + byte3 = '='; + + // byte 4 + if(i+2 < len) + byte4 = uu_base64[aDes[i+2] & 0x3f]; + else + byte4 = '='; + + // append to buffer + buf.Append(byte1); + buf.Append(byte2); + buf.Append(byte3); + buf.Append(byte4); + + // output 72 chars / line + if(j == 17) + { + // add check number at the end of line + buf.Append(count); +#ifdef OST_TRACE_COMPILER_IN_USE + OstTraceExt1( PIPROFILER_TRACE_OUT, CDEBOUTWRITERPLUGIN_PRINTDESCRIPTORASBASE64LINE, "<PIPROF>%S", &buf ); +#else + RDebug::Print(_L("<PIPROF>%S"),&buf); +#endif + count++; + if(count > 0x39) + count = 0x30; + buf.Zero(); + } + } + +#ifdef OST_TRACE_COMPILER_IN_USE + OstTraceExt1( PIPROFILER_TRACE_OUT, CDEBOUTWRITERPLUGIN_PRINTDESCRIPTORASBASE64FIN, "<PIPROF>%S", &buf ); +#else + RDebug::Print(_L("<PIPROF>%S"),&buf); +#endif + buf.Zero(); + + // footer +#ifdef OST_TRACE_COMPILER_IN_USE + OstTrace0( PIPROFILER_TRACE_OUT, CDEBOUTWRITERPLUGIN_PRINTDESCRIPTORASBASE64END, + "<PIPROF>=================================================================" ); +#else + RDebug::Print(_L("<PIPROF>=================================================================")); +#endif + + if(!aEmptying) + { + if(aStatus != 0) + User::RequestComplete(aStatus,0); + } + + LOGTEXT(_L("CDebOutWriterPlugin::PrintDescriptorAsBase64() - exit")); +} + + + +/* + * + * Implementation of class CDebOutWriterHandler + * + */ +CDebOutWriterHandler::CDebOutWriterHandler(CDebOutWriterPlugin* aWriter) : + CActive(EPriorityStandard) + { + LOGTEXT(_L("CDebOutWriterHandler::CDebOutWriterHandler - entry")); + iWriter = aWriter; + + // set initial mode to non-stopping + iStopping = EFalse; + + // add the handler to the active scheduler + CActiveScheduler::Add(this); + LOGTEXT(_L("CDebOutWriterHandler::CDebOutWriterHandler - exit")); + } + +CDebOutWriterHandler* CDebOutWriterHandler::NewL(CDebOutWriterPlugin* aWriter) +{ + LOGTEXT(_L("CDebOutWriterHandler::NewL() - entry")); + CDebOutWriterHandler* self = new (ELeave) CDebOutWriterHandler(aWriter); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + LOGTEXT(_L("CDebOutWriterHandler::NewL() - exit")); + return self; +} + +CDebOutWriterHandler::~CDebOutWriterHandler() + { + LOGTEXT(_L("CDebOutWriterHandler::~CDebOutWriterHandler - entry")); + + LOGTEXT(_L("CDebOutWriterHandler::~CDebOutWriterHandler - exit")); + } + +void CDebOutWriterHandler::ConstructL() + { + + } + +void CDebOutWriterHandler::StartL() + { + LOGTEXT(_L("CDebOutWriterHandler::StartL - entry")); + if(!IsActive()) + { + LOGTEXT(_L("CDiskWriterHandler::StartL - is not active")); + + TBapBuf* nextBuf = iWriter->iStream->GetNextFilledBuffer(); + LOGSTRING2("CDiskWriterHandler::StartL - got next filled 0x%x",nextBuf); + + if(nextBuf != 0) + { + LOGTEXT(_L("CDiskWriterHandler::StartL - writing to file")); + WriteBufferToOutput(nextBuf); + } + } + LOGTEXT(_L("CDebOutWriterHandler::StartL - entry")); + } + +void CDebOutWriterHandler::Stop() + { + LOGTEXT(_L("CDebOutWriterHandler::Stop - entry")); + + // do write once more to write the logged data to output + // set to stopping mode, needed for emptying the remaining full buffers + iStopping = ETrue; + + // stop the timer + Reset(); + + // set mode back to non-stopping + iStopping = EFalse; + LOGTEXT(_L("CDebOutWriterHandler::Stop - exit")); + } + +void CDebOutWriterHandler::Reset() + { + + // start writing new buffer if there is one available + TBapBuf* nextBuf = iWriter->iStream->GetNextFilledBuffer(); + + // empty the rest of the buffers synchronously + while(nextBuf != 0) + { + if(nextBuf->iDataSize != 0) + { + LOGTEXT(_L("CDiskWriterHandler::Reset - writing to file")); + iWriter->PrintDescriptorAsBase64(*(nextBuf->iBufDes),&iStatus,0xffffffff, iStopping); + } + + // empty buffers when profiling stopped + iWriter->iStream->AddToFreeBuffers(nextBuf); + + LOGTEXT(_L("CDiskWriterHandler::Reset - get next full buffer")); + // start writing new buffer if there is one available + nextBuf = iWriter->iStream->GetNextFilledBuffer(); + LOGSTRING2("CDiskWriterHandler::Reset - got next filled 0x%x",nextBuf); + } + } + +void CDebOutWriterHandler::HandleFullBuffers() + { + LOGTEXT(_L("CDiskWriterHandler::HandleFullBuffers - entry")); + // previous write operation has finished + // release the previous buffer + iWriter->iStream->AddToFreeBuffers(iBufferBeingWritten); + + LOGTEXT(_L("CDiskWriterHandler::HandleFullBuffers - get next full buffer")); + // start writing new buffer if there is one available + TBapBuf* nextBuf = iWriter->iStream->GetNextFilledBuffer(); + + if(nextBuf != 0) + { + LOGTEXT(_L("CDiskWriterHandler::HandleFullBuffers - writing to file")); + if(nextBuf->iDataSize != 0) + { + WriteBufferToOutput(nextBuf); + } + } + LOGTEXT(_L("CDiskWriterHandler::HandleFullBuffers - exit")); + } + +void CDebOutWriterHandler::RunL() + { + // call function to complete full buffer handling + HandleFullBuffers(); + } + +void CDebOutWriterHandler::DoCancel() + { + + } + +void CDebOutWriterHandler::WriteBufferToOutput(TBapBuf* aBuf) + { + LOGTEXT(_L("CDebOutWriterHandler::WriteBufferToOutput - entry")); + iBufferBeingWritten = aBuf; + + // set the data length just to be sure + iBufferBeingWritten->iBufDes->SetLength(aBuf->iDataSize); + + LOGTEXT(_L("CDiskWriterPlugin::WriteBufferToOutput - writing to file")); +// PrintBufferToOutput(iBufferBeingWritten, iStatus); + iWriter->PrintDescriptorAsBase64(*(iBufferBeingWritten->iBufDes),&iStatus,0xffffffff, iStopping); + // set AO back to active, until filled buffers are emptied + SetActive(); + + LOGTEXT(_L("CDebOutWriterHandler::WriteBufferToOutput - exit")); + } + +// private +void CDebOutWriterHandler::PrintBufferToOutput(TBapBuf* aBuffer, TRequestStatus& aStatus) + { + LOGTEXT(_L("CDebOutWriterHandler::WriteBufferToOutput() - debug out writer tick activated")); + + TPtrC8& aDes = (TPtrC8&)*(aBuffer->iBufDes); +#ifdef BAPPEA_SAMPLE_MARKS + TUint32 time = iSampler->GetSampleTime(); +#else + TUint32 time = 0xffffffff; +#endif + iWriter->PrintDescriptorAsBase64(aDes,&aStatus,time, iStopping); + } + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/DebugOutputWriterPlugin/src/DebOutWriterPluginImplementationTable.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/DebugOutputWriterPlugin/src/DebOutWriterPluginImplementationTable.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,39 @@ +/* +* 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: +* +*/ + + +// INCLUDE FILES +#include <e32std.h> +#include <ecom/implementationproxy.h> + +#include "DebOutWriterPlugin.h" + + +// Provides a key value pair table, this is used to identify +// the correct construction function for the requested interface. +const TImplementationProxy ImplementationTable[] = +{ + IMPLEMENTATION_PROXY_ENTRY(0x2001E5BA, CDebOutWriterPlugin::NewL) +}; + +// Function used to return an instance of the proxy table. +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) +{ + aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); + return ImplementationTable; +} + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/DiskWriterPlugin/data/2001E5BB.rss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/DiskWriterPlugin/data/2001E5BB.rss Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,51 @@ +/* +* 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: +* +*/ + + +#include <ecom/registryinfo.rh> + +// Declares info for two implementations +RESOURCE REGISTRY_INFO theInfo + { + // UID for the DLL. See mmp files + //__SERIES60_3X__ can't be used in resource files + dll_uid = 0x2001E5BB; + + // Declare array of interface info. This dll contains implementations for + // only one interface (CSamplerInterfaceDefinition). + interfaces = + { + INTERFACE_INFO + { + // UID of interface that is implemented + interface_uid = 0x2001E5BD; + + implementations = + { + IMPLEMENTATION_INFO + { + implementation_uid = 0x2001E5BB; + + version_no = 1; + display_name = "Disk output writer implementation"; + default_data = "dsw"; + opaque_data = "0"; + } + }; + } + }; + } diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/DiskWriterPlugin/group/DiskWriterPlugin.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/DiskWriterPlugin/group/DiskWriterPlugin.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,50 @@ +/* +* 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: +* +*/ + + +#include <platform_paths.hrh> + + +TARGET PIProfilerDiskWriter.dll +TARGETTYPE PLUGIN +UID 0x10009D8D 0x2001E5BB +#ifdef WINSCW +VENDORID 0 +#else +VENDORID VID_DEFAULT +#endif +CAPABILITY ALL -TCB // AllFiles ReadDeviceData ReadUserData UserEnvironment WriteDeviceData WriteUserData +SMPSAFE + +OS_LAYER_SYSTEMINCLUDE +USERINCLUDE ../inc +SOURCEPATH ../src + +START RESOURCE ../data/2001E5BB.rss +TARGET piprofilerdiskwriter.rsc +END + +SOURCE DiskWriterPlugin.cpp +SOURCE DiskWriterPluginImplementationTable.cpp + +LIBRARY sysutil.lib +LIBRARY euser.lib +LIBRARY ECom.lib +LIBRARY EFSRV.LIB +LIBRARY commonengine.lib +LIBRARY flogger.lib + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/DiskWriterPlugin/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/DiskWriterPlugin/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,20 @@ +/* +* 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: +* +*/ + + +PRJ_MMPFILES +DiskWriterPlugin.mmp diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/DiskWriterPlugin/inc/DiskWriterPlugin.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/DiskWriterPlugin/inc/DiskWriterPlugin.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,133 @@ +/* +* 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: +* +*/ + + +#ifndef __DISKWRITERPLUGIN_H__ +#define __DISKWRITERPLUGIN_H__ + +// Include Files +#include <w32std.h> +#include <piprofiler/WriterPluginInterface.h> +#include <piprofiler/ProfilerGenericClassesUsr.h> +#include <e32base.h> // CBase +#include <e32std.h> // TBuf +#include <e32property.h> + +_LIT(KFileOutShortName, "dsw"); + +// forward declarations +class CDiskWriterHandler; +class CProfilerSampleStream; + +// Class Definitions + +class CDiskWriterPlugin : public CWriterPluginInterface + { +public: + // new function + static CDiskWriterPlugin* NewL(const TUid aImplementationUid, TAny* aInitParams); + ~CDiskWriterPlugin(); + + void DoCancel(); + + +public: // new functions + + TInt Start(); + + void Stop(); + + void GetValue( const TWriterPluginValueKeys aKey, TDes& aValue ); + + void SetValue( const TWriterPluginValueKeys aKey, TDes& aValue ); + + TUid Id() const; + + void GetWriterVersion(TDes* aDes); + + TUint32 GetWriterType(); + + void HandleError(TInt aError); + + void WriteData(); + + void SetStream(CProfilerSampleStream& aStream) { iStream = &aStream; } + +private: // new functions + CDiskWriterPlugin(const TUid aImplementationUid); + void ConstructL(); + + void GetValueL( const TWriterPluginValueKeys aKey, TDes& aValue ); + void SetValueL( const TWriterPluginValueKeys aKey, TDes& aValue ); + TBool GetEnabled(); + + TInt DisplayNotifier(const TDesC& aLine1, const TDesC& aLine2, const TDesC& aButton1, const TDesC& aButton2); +public: + CProfilerSampleStream* iStream; +private: // data + + TBuf<256> iFileName; + TInt iWriterType; + TInt iWriterId; + CDiskWriterHandler* iWriterHandler; + RProperty iErrorStatus; + }; + +/* + * + * Definition of class CDiskWriterHandler + * + */ +class CDiskWriterHandler : public CActive //CBase + { +public: + + + static CDiskWriterHandler* NewL(CDiskWriterPlugin* aWriter); + ~CDiskWriterHandler(); + + void StartL(); + + void Stop(); + void RunL(); + TInt RunError(TInt aError); + + void DoCancel(); + void WriteBufferToOutput(TBapBuf* aBuf); + void Reset(); + + TInt TestFile(const TDesC& totalPrefix); +private: + CDiskWriterHandler(CDiskWriterPlugin* aWriter); + + void ConstructL(); + void WriteMemBufferToFile(TDesC8& aDes, TRequestStatus& aStatus); + static TInt Write(TAny* aObject); + void HandleFullBuffers(); + void DoWrite(); + +private: + RFile iFile; + RFs iFs; + TBuf<256> iFileName; + CDiskWriterPlugin* iWriter; + TBapBuf* iBufferBeingWritten; + TBool iStopping; + }; + +#endif // __DEBOUTWRITERPLUGIN_H__ + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/DiskWriterPlugin/sis/DiskWriterPlugin_EKA2.pkg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/DiskWriterPlugin/sis/DiskWriterPlugin_EKA2.pkg Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,36 @@ +; +; 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: +; +; Installation file for DebOutWriterPlugin dll +; +; This is an auto-generated PKG file by Carbide. +; This file uses variables specific to Carbide builds that will not work +; on command-line builds. If you want to use this generated PKG file from the +; command-line tools you will need to modify the variables with the appropriate +; values: $(EPOCROOT), $(PLATFORM), $(TARGET) + +; +; UID is the dll's UID +; +#{"DebOutWriterPlugin DLL"},(0x00DA58C7),1,0,0 + + +;Localised Vendor name +%{"Vendor-EN"} + +;Unique Vendor name +:"Vendor" + +"$(EPOCROOT)Epoc32\release\$(PLATFORM)\$(TARGET)\DebOutWriterPlugin.dll" -"!:\sys\bin\DebOutWriterPlugin.dll" diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/DiskWriterPlugin/src/DiskWriterPlugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/DiskWriterPlugin/src/DiskWriterPlugin.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,476 @@ +/* +* 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: +* +*/ + + +// Include Files + +#include "DiskWriterPlugin.h" // CDiskWriterPlugin +#include <e32base.h> +#include <sysutil.h> +//#include <piprofiler/EngineUIDs.h> + +// constants +const TUid KDiskWriterPluginUid = { 0x2001E5BB }; // own UID + +// engine properties +const TUid KEngineStatusPropertyCat={0x2001E5AD}; +enum TEnginePropertyKeys + { + EProfilerEngineStatus = 8, + EProfilerErrorStatus + }; + +/* + * + * Class CDiskWriterPlugin implementation + * + */ + +// Member Functions +CDiskWriterPlugin* CDiskWriterPlugin::NewL(const TUid /*aImplementationUid*/, TAny* /*aInitParams*/) + { + LOGTEXT(_L("CDiskWriterPlugin::NewL() - entry")); + CDiskWriterPlugin* self = new (ELeave) CDiskWriterPlugin(KDiskWriterPluginUid); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + LOGTEXT(_L("CDiskWriterPlugin::NewL() - exit")); + return self; + } + +CDiskWriterPlugin::CDiskWriterPlugin(const TUid aImplementationUid) : + iWriterType(aImplementationUid.iUid) + { + LOGTEXT(_L("CDiskWriterPlugin::CDiskWriterPlugin - entry")); + isEnabled = EFalse; + iWriterId = Id().iUid; + LOGTEXT(_L("CDiskWriterPlugin::CDiskWriterPlugin - exit")); + } + +CDiskWriterPlugin::~CDiskWriterPlugin() + { + LOGTEXT(_L("CDiskWriterPlugin::~CDiskWriterPlugin - entry")); + + iErrorStatus.Close(); + + if(iWriterHandler) + { + iWriterHandler->Cancel(); + delete iWriterHandler; + } + LOGTEXT(_L("CDiskWriterPlugin::~CDiskWriterPlugin - exit")); + } + +void CDiskWriterPlugin::ConstructL() + { + // second phase constructor, anything that may leave must be constructed here + LOGTEXT(_L("CDiskWriterPlugin::ConstructL() - entry")); + iWriterHandler = CDiskWriterHandler::NewL(this); + User::LeaveIfError(iErrorStatus.Attach(KEngineStatusPropertyCat, EProfilerErrorStatus)); + LOGTEXT(_L("CDiskWriterPlugin::ConstructL() - exit")); + } + +TUid CDiskWriterPlugin::Id() const + { + LOGSTRING2("CDiskWriterPlugin::Id():0x%X", KDiskWriterPluginUid.iUid ); + return KDiskWriterPluginUid; + } + +void CDiskWriterPlugin::GetWriterVersion(TDes* aDes) + { + _LIT(KDiskWriterVersion, "1.0.0"); + aDes->Append(KDiskWriterVersion); + } + +TInt CDiskWriterPlugin::Start() + { +// if(isEnabled) +// { +// TRAPD(err, iWriterHandler->StartL()); +// if( err != KErrNone) +// { +// LOGTEXT(_L("Could not start writer plugin")); +// return err; +// } +// } + return KErrNone; + } + +void CDiskWriterPlugin::Stop() + { + // stop writer handler normally + iWriterHandler->Stop(); + } + +TBool CDiskWriterPlugin::GetEnabled() + { + return isEnabled; + } + +TUint32 CDiskWriterPlugin::GetWriterType() + { + return iWriterType; + } + + +void CDiskWriterPlugin::SetValue( const TWriterPluginValueKeys aKey, + TDes& aValue ) + { + TRAP_IGNORE( SetValueL( aKey, aValue ) ); + } + + +void CDiskWriterPlugin::GetValue( const TWriterPluginValueKeys aKey, + TDes& aValue ) + { + TRAP_IGNORE( GetValueL( aKey, aValue ) ); + } + +void CDiskWriterPlugin::SetValueL( const TWriterPluginValueKeys aKey, TDes& aValue ) + { + TInt error(KErrNone); + + switch( aKey ) + { + case EWriterPluginEnabled: + isEnabled = ETrue; + LOGTEXT(_L("CDebOutWriterPlugin::SetValueL - plugin enabled")); + break; + case EWriterPluginDisabled: + isEnabled = EFalse; + LOGTEXT(_L("CDebOutWriterPlugin::SetValueL - plugin disabled")); + break; + case EWriterPluginSettings: // file name in case of disk writer plugin + iFileName.Zero(); + iFileName.Append(aValue); + error = iWriterHandler->TestFile(iFileName); + User::LeaveIfError(error); + break; + default: + break; + } + } + +void CDiskWriterPlugin::GetValueL( const TWriterPluginValueKeys aKey, TDes& aValue ) + { + switch( aKey ) + { + case EWriterPluginVersion: + GetWriterVersion(&aValue); + break; + case EWriterPluginType: + break; + case EWriterPluginSettings: // file name in disk writer case + aValue.Copy(iFileName); + default: + break; + } + } + +void CDiskWriterPlugin::DoCancel() + { + LOGTEXT(_L("CDebOutWriterPlugin::DoCancel - entry")); + } + +void CDiskWriterPlugin::WriteData() + { + // Activate handler to write data from buffer to output + LOGTEXT(_L("CDiskWriterPlugin::WriteData() - entry")); + TRAP_IGNORE(iWriterHandler->StartL()); + LOGTEXT(_L("CDiskWriterPlugin::WriteData() - exit")); + } + +void CDiskWriterPlugin::HandleError(TInt aError) + { + TInt err(KErrNone); + RDebug::Print(_L("CDiskWriterPlugin::HandleError() - error received: %d"), aError); + err = iErrorStatus.Set(aError); + if(err != KErrNone) + { + RDebug::Print(_L("CDiskWriterPlugin::HandleError() - error in updating property: %d"), err); + } + } + +/* + * + * Implementation of class CDiskWriterHandler + * + */ + +CDiskWriterHandler* CDiskWriterHandler::NewL(CDiskWriterPlugin* aWriter) + { + LOGTEXT(_L("CDiskWriterHandler::NewL() - entry")); + CDiskWriterHandler* self = new (ELeave) CDiskWriterHandler(aWriter); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + LOGTEXT(_L("CDiskWriterHandler::NewL() - exit")); + return self; + } + +CDiskWriterHandler::CDiskWriterHandler(CDiskWriterPlugin* aWriter) : + CActive(EPriorityStandard) + { + LOGTEXT(_L("CDiskWriterHandler::CDiskWriterHandler - entry")); + + iWriter = aWriter; + + // set initial mode to non-stopping + iStopping = EFalse; + + // add the handler to the active scheduler + CActiveScheduler::Add(this); + + LOGTEXT(_L("CDiskWriterHandler::CDiskWriterHandler - exit")); + } + + +CDiskWriterHandler::~CDiskWriterHandler() + { + LOGTEXT(_L("CDiskWriterHandler::~CDiskWriterHandler - entry")); + + LOGTEXT(_L("CDiskWriterHandler::~CDiskWriterHandler - exit")); + } + +void CDiskWriterHandler::ConstructL() + { + } + +TInt CDiskWriterHandler::TestFile(const TDesC& totalPrefix) + { + TParse parse; + + TInt err(KErrNone); + if((err = parse.Set(totalPrefix, NULL, NULL)) != KErrNone) + return err; + + err = iFs.Connect(); + if(err != KErrNone) + { + LOGTEXT(_L("CDiskWriterHandler::TestFile() - Failed to open a session to file server")); + return KErrNotFound; + } + + iFs.MkDirAll(parse.FullName()); + + err = iFile.Replace(iFs,parse.FullName(),EFileWrite); + if(err != KErrNone) + { + iFs.Close(); + return KErrNotFound; + } + + iFileName.Copy(parse.FullName()); + + return KErrNone; + } + +void CDiskWriterHandler::Reset() + { + // cancel active object + Cancel(); + + // start writing new buffer if there is one available + TBapBuf* nextBuf = iWriter->iStream->GetNextFilledBuffer(); + + // empty the rest of the buffers synchronously + while(nextBuf != 0) + { + LOGTEXT(_L("CDiskWriterHandler::Reset - writing to file")); + if(nextBuf->iDataSize != 0) + { + LOGTEXT(_L("CDiskWriterHandler::Reset - writing to file")); + WriteMemBufferToFile(*(nextBuf->iBufDes),iStatus); + } + + // empty buffers when profiling stopped + iWriter->iStream->AddToFreeBuffers(nextBuf); + + LOGTEXT(_L("CDiskWriterHandler::Reset - get next full buffer")); + // start writing new buffer if there is one available + nextBuf = iWriter->iStream->GetNextFilledBuffer(); + LOGSTRING2("CDiskWriterHandler::Reset - got next filled 0x%x",nextBuf); + } + } + +void CDiskWriterHandler::HandleFullBuffers() + { + LOGTEXT(_L("CDiskWriterHandler::HandleFullBuffers - entry")); + // previous write operation has finished + // release the previous buffer + iWriter->iStream->AddToFreeBuffers(iBufferBeingWritten); + + LOGTEXT(_L("CDiskWriterHandler::HandleFullBuffers - get next full buffer")); + // start writing new buffer if there is one available + TBapBuf* nextBuf = iWriter->iStream->GetNextFilledBuffer(); + + if(nextBuf != 0) + { + LOGTEXT(_L("CDiskWriterHandler::HandleFullBuffers - writing to file")); + if(nextBuf->iDataSize != 0) + { + WriteBufferToOutput(nextBuf); + } + } + LOGTEXT(_L("CDiskWriterHandler::HandleFullBuffers - exit")); + } + +void CDiskWriterHandler::RunL() + { + LOGTEXT(_L("CDiskWriterHandler::RunL - entry")); + // call function to complete full buffer handling + HandleFullBuffers(); + LOGTEXT(_L("CDiskWriterHandler::RunL - exit")); + } + +void CDiskWriterHandler::DoCancel() + { + + } + +//----------------------------------------------------------------------------- +// CPIProfilerTraceCoreLauncher::RunError(TInt aError) +// Handle leaves from RunL(). +//----------------------------------------------------------------------------- +TInt CDiskWriterHandler::RunError(TInt aError) + { + // no reason to continue if disk full or removed + iFile.Close(); + // close handle to file server too + iFs.Close(); + iFileName.Zero(); + + iWriter->HandleError(KErrDiskFull); + return aError; + } + +void CDiskWriterHandler::WriteMemBufferToFile(TDesC8& aDes, TRequestStatus& aStatus) + { + LOGTEXT(_L("CDiskWriterPlugin::WriteMemBufferToFile - entry")); + + TUint sampleSize(aDes.Length()); + TInt err(KErrNone); + TInt drive(0); + TDriveInfo info; + TBool noDiskSpace(EFalse); + + err = iFile.Drive(drive,info); + + // test available disk space + TRAP_IGNORE((noDiskSpace = SysUtil::DiskSpaceBelowCriticalLevelL(&iFs, sampleSize, drive))); + // check first if still space on disk + if(noDiskSpace) + { + // set error to disk full + err = KErrDiskFull; + LOGTEXT(_L("CDiskWriterPlugin::WriteMemBufferToFile - disk full, cannot write")); + } + else + { + // check if profiling in stopping mode + if(iStopping) + { + // RDebug::Print(_L("CDiskWriterPlugin::WriteMemBufferToFile - data written, length %d, stopping"), aDes.Length()); + // write to file without status + err = iFile.Write(aDes); + } + else + { + // RDebug::Print(_L("CDiskWriterPlugin::WriteMemBufferToFile - data written, length %d"), aDes.Length()); + // write to file with status + iFile.Write(aDes,aStatus); + } + } + + // check if error in write + if(err != KErrNone) + { + // stop writer handler (and its timer) immediately, DO NOT try write data! + Cancel(); + + // no reason to continue if disk full or removed + // end of stream detected, file can be closed + iFile.Close(); + // close handle to file server too + iFs.Close(); + iFileName.Zero(); + + // set error status for engine to read + iWriter->HandleError(err); + } + LOGTEXT(_L("CDiskWriterPlugin::WriteMemBufferToFile - exit")); + } + +void CDiskWriterHandler::WriteBufferToOutput(TBapBuf* aBuf) + { + LOGTEXT(_L("CDiskWriterPlugin::WriteBufferToOutput - entry")); + iBufferBeingWritten = aBuf; + + // set the data length just to be sure + iBufferBeingWritten->iBufDes->SetLength(aBuf->iDataSize); + + LOGTEXT(_L("CDiskWriterPlugin::WriteBufferToOutput - writing to file")); + WriteMemBufferToFile(*(iBufferBeingWritten->iBufDes), iStatus); + + // set AO back to active, until filled buffers are emptied + SetActive(); + + LOGTEXT(_L("CDiskWriterPlugin::WriteBufferToOutput - exit")); + } + +void CDiskWriterHandler::StartL() + { + LOGTEXT(_L("CDiskWriterHandler::StartL - entry")); + if(!IsActive()) + { + LOGTEXT(_L("CDiskWriterHandler::StartL - is not active")); + + TBapBuf* nextBuf = iWriter->iStream->GetNextFilledBuffer(); + LOGSTRING2("CDiskWriterHandler::StartL - got next filled 0x%x",nextBuf); + + if(nextBuf != 0) + { + LOGTEXT(_L("CDiskWriterHandler::StartL - writing to file")); + WriteBufferToOutput(nextBuf); + } + } + LOGTEXT(_L("CDiskWriterHandler::StartL - exit")); + } + +void CDiskWriterHandler::Stop() + { + LOGTEXT(_L("CDiskWriterHandler::Stop - entry")); + + // set to stopping mode, needed for emptying the remaining full buffers + iStopping = ETrue; + + // stop the timer + Reset(); + + // end of stream detected, file can be closed + iFile.Close(); + // close handle to file server too + iFs.Close(); + iFileName.Zero(); + + // set mode back to non-stopping + iStopping = EFalse; + + LOGTEXT(_L("CDiskWriterHandler::Stop - exit")); + } + +// end of file diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/DiskWriterPlugin/src/DiskWriterPluginImplementationTable.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/DiskWriterPlugin/src/DiskWriterPluginImplementationTable.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,39 @@ +/* +* 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: +* +*/ + + +// INCLUDE FILES +#include <e32std.h> +#include <ecom/implementationproxy.h> + +#include "DiskWriterPlugin.h" + + +// Provides a key value pair table, this is used to identify +// the correct construction function for the requested interface. +const TImplementationProxy ImplementationTable[] = +{ + IMPLEMENTATION_PROXY_ENTRY(0x2001E5BB, CDiskWriterPlugin::NewL) +}; + +// Function used to return an instance of the proxy table. +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) +{ + aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); + return ImplementationTable; +} + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/data/2001E5B2.rss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/data/2001E5B2.rss Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,51 @@ +/* +* 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: +* +*/ + + +#include <ecom/registryinfo.rh> + +// Declares info for two implementations +RESOURCE REGISTRY_INFO theInfo + { + // UID for the DLL. See mmp files + //__SERIES60_3X__ can't be used in resource files + dll_uid = 0x2001E5B2; + + // Declare array of interface info. This dll contains implementations for + // only one interface (CSamplerInterfaceDefinition). + interfaces = + { + INTERFACE_INFO + { + // UID of interface that is implemented + interface_uid = 0x2001E5BC; + + implementations = + { + IMPLEMENTATION_INFO + { + implementation_uid = 0x2001E5B2; + + version_no = 1; + display_name = "General Samplers; GPP, ITT, GFC, MEM, PRI"; + default_data = "gen"; + opaque_data = "0"; // the order number + } + }; + } + }; + } diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/group/GeneralsPlugin.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/group/GeneralsPlugin.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,52 @@ +/* +* 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: +* +*/ + + +#include <platform_paths.hrh> + + +TARGET PIProfilerGenerals.dll +TARGETTYPE PLUGIN +UID 0x10009D8D 0x2001E5B2 +VENDORID VID_DEFAULT +CAPABILITY ALL -TCB +SMPSAFE + +EPOCSTACKSIZE 0x10000 + +OS_LAYER_SYSTEMINCLUDE +USERINCLUDE ../inc +SOURCEPATH ../src + +START RESOURCE ../data/2001E5B2.rss +TARGET PIProfilerGenerals.rsc +END + +SOURCE GeneralsPluginImplementationTable.cpp +SOURCE GeneralsPlugin.cpp + +LIBRARY euser.lib +LIBRARY bafl.lib +LIBRARY ECom.lib +LIBRARY apparc.lib +LIBRARY cone.lib +LIBRARY ws32.lib +LIBRARY charconv.lib +LIBRARY commonengine.lib +LIBRARY flogger.lib + +epocallowdlldata diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/group/GeneralsSampler.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/group/GeneralsSampler.mmp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,52 @@ +/* +* 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: +* +*/ + + +#include <platform_paths.hrh> +#include "kernel/kern_ext.mmh" + +TARGET PIProfilerGeneralsSampler.ldd +CAPABILITY ALL +TARGETTYPE LDD +UID 0x100000AF 0x2001E5B3 +VENDORID VID_DEFAULT +SMPSAFE + +OS_LAYER_KERNEL_SYSTEMINCLUDE +USERINCLUDE ../inc +SOURCEPATH ../src + +SOURCE GeneralsDriver.cpp +SOURCE GeneralsSampler.cia +SOURCE GppSamplerImpl.cpp +SOURCE IttEventHandler.cpp +SOURCE IttSamplerImpl.cpp +SOURCE MemoryEventHandler.cpp +SOURCE MemSamplerImpl.cpp +SOURCE PriSamplerImpl.cpp + +#ifdef SMP +LIBRARY ekernsmp.lib +#else +LIBRARY ekern.lib +#endif + +epocallowdlldata + +start wins +win32_headers +end diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/group/bld.inf Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,25 @@ +/* +* 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: +* +*/ + +//PRJ_PLATFORMS +//DEFAULT ARMV5SMP + +PRJ_MMPFILES +#ifdef MARM + GeneralsPlugin.mmp + GeneralsSampler.mmp +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/inc/GeneralsConfig.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/inc/GeneralsConfig.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,99 @@ +/* +* 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: +* +*/ + + +#ifndef GENERALS_CONFIG_H +#define GENERALS_CONFIG_H + + + // change this to reflect the ISA task amount + #define PROFILER_ISA_OS_TASK_AMOUNT 50 + + // don't change these definitions + #define PROFILER_DEFINE_ISA_TASK_NAME_ARRAY TBuf8<64> isaTaskNames[PROFILER_ISA_OS_TASK_AMOUNT]; + #define PROFILER_DEFINE_ISA_TASK_NAME(name,number) isaTaskNames[number].Append(_L8(name)); + + // change these to reflect the real ISA task names and numbers + // the last number must be PROFILER_ISA_OS_TASK_AMOUNT-1 + + #define PROFILER_ISA_TASK_NAMES PROFILER_DEFINE_ISA_TASK_NAME("SRVSCKT_TASK",0)\ + PROFILER_DEFINE_ISA_TASK_NAME("CSD_SRV_TASK",1) \ + PROFILER_DEFINE_ISA_TASK_NAME("CSD_NTB_TASK",2) \ + PROFILER_DEFINE_ISA_TASK_NAME("CSD_WTB_TASK",3) \ + PROFILER_DEFINE_ISA_TASK_NAME("PH_TASK",4) \ + PROFILER_DEFINE_ISA_TASK_NAME("L2_TASK",5) \ + PROFILER_DEFINE_ISA_TASK_NAME("RR_TASK",6) \ + PROFILER_DEFINE_ISA_TASK_NAME("GPRS_RLC_TASK",7) \ + PROFILER_DEFINE_ISA_TASK_NAME("GPRS_MAC_TASK",8) \ + PROFILER_DEFINE_ISA_TASK_NAME("RANC_TASK",9) \ + PROFILER_DEFINE_ISA_TASK_NAME("MM_TASK",10) \ + PROFILER_DEFINE_ISA_TASK_NAME("CC_TASK",11) \ + PROFILER_DEFINE_ISA_TASK_NAME("SMS_TASK",12) \ + PROFILER_DEFINE_ISA_TASK_NAME("RM_CONTROL_TASK",13) \ + PROFILER_DEFINE_ISA_TASK_NAME("GSS_SERVER_TASK",14) \ + PROFILER_DEFINE_ISA_TASK_NAME("CS_MAIN_TASK",15) \ + PROFILER_DEFINE_ISA_TASK_NAME("GPRS_TASK",16) \ + PROFILER_DEFINE_ISA_TASK_NAME("WMAC_TASK",17) \ + PROFILER_DEFINE_ISA_TASK_NAME("WMHS_TASK",18) \ + PROFILER_DEFINE_ISA_TASK_NAME("WRRC_TASK",19) \ + PROFILER_DEFINE_ISA_TASK_NAME("WRLC_UL_TASK",20) \ + PROFILER_DEFINE_ISA_TASK_NAME("WRLC_DL_TASK",21) \ + PROFILER_DEFINE_ISA_TASK_NAME("WPH_TASK",22) \ + PROFILER_DEFINE_ISA_TASK_NAME("WRAN_TASK",23) \ + PROFILER_DEFINE_ISA_TASK_NAME("SSOM_TASK",24) \ + PROFILER_DEFINE_ISA_TASK_NAME("ACCESSORY_TASK",25) \ + PROFILER_DEFINE_ISA_TASK_NAME("ADL_TASK",26) \ + PROFILER_DEFINE_ISA_TASK_NAME("AUDIO_TASK",27) \ + PROFILER_DEFINE_ISA_TASK_NAME("PN_TASK",28) \ + PROFILER_DEFINE_ISA_TASK_NAME("CORE_HI_TASK",29) \ + PROFILER_DEFINE_ISA_TASK_NAME("CORE_LO_TASK",30) \ + PROFILER_DEFINE_ISA_TASK_NAME("ENERGY_TASK",31) \ + PROFILER_DEFINE_ISA_TASK_NAME("FBUS_TASK",32) \ + PROFILER_DEFINE_ISA_TASK_NAME("PMM_FILE2_TASK",33) \ + PROFILER_DEFINE_ISA_TASK_NAME("MDI_RCV_TASK",34) \ + PROFILER_DEFINE_ISA_TASK_NAME("MDI_SEND_TASK",35) \ + PROFILER_DEFINE_ISA_TASK_NAME("MONITOR_TASK",36) \ + PROFILER_DEFINE_ISA_TASK_NAME("MTC_CTRL_TASK",37) \ + PROFILER_DEFINE_ISA_TASK_NAME("MTC_WD_TASK",38) \ + PROFILER_DEFINE_ISA_TASK_NAME("OBEX_TASK",39) \ + PROFILER_DEFINE_ISA_TASK_NAME("APDU_SERVER_TASK",40) \ + PROFILER_DEFINE_ISA_TASK_NAME("SIMSON_SERVER_TASK",41) \ + PROFILER_DEFINE_ISA_TASK_NAME("SIMLOCK_TASK",42) \ + PROFILER_DEFINE_ISA_TASK_NAME("SOS_USB_MM_TASK",43) \ + PROFILER_DEFINE_ISA_TASK_NAME("SOS_PROXY_AUX_TASK",44) \ + PROFILER_DEFINE_ISA_TASK_NAME("TERMINAL_ADAPTER_TASK",45) \ + PROFILER_DEFINE_ISA_TASK_NAME("XTI_RECEIVE_TASK",46) \ + PROFILER_DEFINE_ISA_TASK_NAME("XTI_SEND_TASK",47) \ + PROFILER_DEFINE_ISA_TASK_NAME("STARTUP_AND_BACKGROUND_TASK",48) \ + PROFILER_DEFINE_ISA_TASK_NAME("OS_IDLE_TASK",49) + + // old definitions + #define PROFILER_GENERALS_SAMPLER_ID 100 + #define PROFILER_GPP_SAMPLER_ID 1 + #define PROFILER_GFC_SAMPLER_ID 2 + #define PROFILER_ITT_SAMPLER_ID 3 + #define PROFILER_MEM_SAMPLER_ID 4 + #define PROFILER_PRI_SAMPLER_ID 5 + + #define PROFILER_GPP_SAMPLER_NAME _L("GPP") + #define PROFILER_GFC_SAMPLER_NAME _L("GFC") + #define PROFILER_ITT_SAMPLER_NAME _L("ITT") + #define PROFILER_MEM_SAMPLER_NAME _L("MEM") + #define PROFILER_PRI_SAMPLER_NAME _L("PRI") + + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/inc/GeneralsDriver.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/inc/GeneralsDriver.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,59 @@ +/* +* 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: +* +*/ + + +#ifndef __GENERALSSAMPLER_H__ +#define __GENERALSSAMPLER_H__ + +/* + * The user-interface to the sampling device driver sued by the profiling engine + */ +#include <piprofiler/PluginSampler.h> + +#ifndef __KERNEL_MODE__ +#include <utf.h> +#endif + + +/** + * The user device driver class for controlling the plugin sampler. + */ + +class RGeneralsSampler : public RPluginSampler +{ + public: + #ifndef __KERNEL_MODE__ + + /** Open a channel to the sampling device **/ + inline TInt Open(); + + #endif // !__KERNEL_MODE__ +}; + +_LIT(KPluginSamplerName,"PIProfilerGeneralsSampler"); + +#ifndef __KERNEL_MODE__ + +inline TInt RGeneralsSampler::Open() +{ + return DoCreate(KPluginSamplerName,TVersion(1,0,1),KNullUnit,NULL,NULL); +} + + +#endif +#endif + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/inc/GeneralsPlugin.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/inc/GeneralsPlugin.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,147 @@ +/* +* 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: +* +*/ + + +#ifndef PROFILER_GENERALSECOM_SAMPLER_H +#define PROFILER_GENERALSECOM_SAMPLER_H + +#include <w32std.h> + +#include "GeneralsDriver.h" +#include "GeneralsConfig.h" +#include <piprofiler/SamplerPluginInterface.h> +#include <piprofiler/ProfilerGenericClassesUsr.h> + +// constants +const TUint KDefaultOutputCombination = 3; + +const TUint KSubSamplerCount = 5; + +// parent itself +_LIT(KGENShortName, "gen"); +_LIT(KGENMediumName, "Generic samplers plug-in"); +_LIT(KGENLongName, "Generic samplers plug-in"); + +// gpp caption definitions +_LIT8(KGPPShortName, "gpp"); +#ifdef CARBIDE_NAMES +_LIT8(KGPPLongName, "Address/Thread sampling"); +#else +_LIT8(KGPPLongName, "CPU load sampler"); +#endif +_LIT8(KGPPDescription, "CPU load sampler\nSampling thread and process load\nHW dep: N/A\nSW dep: S60 3.0\n"); + +// gfc caption definitions +_LIT8(KGFCShortName, "gfc"); +#ifdef CARBIDE_NAMES +_LIT8(KGFCLongName, "Function call sampling"); +#else +_LIT8(KGFCLongName, "Function call sampler"); +#endif +_LIT8(KGFCDescription, "Function call sampler\nCapturing function call info\nHW dep: N/A\nSW dep: S60 3.0\n"); + +// itt caption definitions +_LIT8(KITTShortName, "itt"); +#ifdef CARBIDE_NAMES +_LIT8(KITTLongName, "Dynamic binary support"); +#else +_LIT8(KITTLongName, "Dynamic binary sampler"); +#endif +_LIT8(KITTDescription, "Dynamic binary sampler\nTracing dynamically loaded binaries, e.g. from ROFS\nHW dep: N/A\nSW dep: S60 3.0\n"); + +// mem caption definitions +_LIT8(KMEMShortName, "mem"); +#ifdef CARBIDE_NAMES +_LIT8(KMEMLongName, "Memory usage sampler"); +#else +_LIT8(KMEMLongName, "Memory trace sampler"); +#endif +_LIT8(KMEMDescription, "Memory trace sampler\nTracing memory, i.e. stack and chunk usage\nHW dep: N/A\nSW dep: S60 3.0\n"); + +// pri caption definitions +_LIT8(KPRIShortName, "pri"); +#ifdef CARBIDE_NAMES +_LIT8(KPRILongName, "Thread priority sampling"); +#else +_LIT8(KPRILongName, "Priority trace sampler"); +#endif +_LIT8(KPRIDescription, "Priority trace sampler\nTracing thread priorities\nHW dep: N/A\nSW dep: S60 3.0\n"); + + +// forward definitions +class CConfigInfoArray; +class CProfilerBufferHandler; +class CProfilerSampleStream; +class TSamplerAttributes; + +class CGeneralsPlugin : public CSamplerPluginInterface +{ +public: + static CGeneralsPlugin* NewL(const TUid aImplementationUid, TAny* /*aInitParams*/); + ~CGeneralsPlugin(); + + TUint32 GetSampleTime(); + + /* + * Sub sampler specific functions + * + */ + + // from CSamplerPluginInterface + TInt ResetAndActivateL(CProfilerSampleStream& aStream); + TInt StopSampling(); + TBool Enabled() { return iEnabled; } + + TUid Id( TInt aSubId ) const; + TInt SubId( TUid aSubId ) const; // internal + + void GetAttributesL(CArrayFixFlat<TSamplerAttributes>* aAttributes); + TInt SetAttributesL(TSamplerAttributes aAttributes); + void InitiateSamplerAttributesL(); + + TInt ConvertRawSettingsToAttributes(CDesC8ArrayFlat* aSingleSettingArray); + TInt DoSetSamplerSettings(CDesC8ArrayFlat* aAllSettings, TDesC8& aSamplerName, TInt aIndex); + void SaveSettingToAttributes(const TDesC8& aSetting, TInt aIndex); + + TInt GetSamplerType(); + + void InstallStreamForActiveTraces(RGeneralsSampler& sampler, CProfilerSampleStream& aStream); + +private: + CGeneralsPlugin(); + void ConstructL(); + + TInt InitiateSamplerL(); + TInt CleanSampler(); + void SetSettingsToSamplers(); + +private: + TUint8 iVersion[20]; + TPtr8 iVersionDescriptor; + + RGeneralsSampler iGeneralsSampler; + + CProfilerBufferHandler* iBufferHandler; + + CArrayFixFlat<TSamplerAttributes>* iSamplerAttributes; + + TBuf8<9> iSearchTexts; +public: + TUint32* iSampleTime; +}; + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/inc/GfcSamplerImpl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/inc/GfcSamplerImpl.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,249 @@ +/* +* 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: +* +*/ + + +#ifndef PROFILER_GFC_SAMPLER_H +#define PROFILER_GFC_SAMPLER_H + + +#include "GeneralsConfig.h" + +#include <kern_priv.h> + +#include <piprofiler/ProfilerGenericClassesKrn.h> +#include <piprofiler/ProfilerTraces.h> +#include "GppSamplerImpl.h" + +extern void UsrModLr(TUint32*); + + +/* + * + * GFC sampler definition + * + */ + +template <int BufferSize> +class DProfilerGfcSampler : public DProfilerGenericSampler<BufferSize> +{ +public: + DProfilerGfcSampler(struct TProfilerGppSamplerData* ); + ~DProfilerGfcSampler(); + + void Sample(); + TInt Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset); +private: + struct TProfilerGppSamplerData* gppSamplerData; + TUint32 gfcSample[3]; + + TUint8 encodedSample[15]; + TUint32 repeat; +}; + +/* + * + * GFC sampler implementation + * + */ + +template <int BufferSize> +DProfilerGfcSampler<BufferSize>::DProfilerGfcSampler(struct TProfilerGppSamplerData* gppSamplerDataIn) : + DProfilerGenericSampler<BufferSize>(PROFILER_GFC_SAMPLER_ID) +{ + this->gppSamplerData = gppSamplerDataIn; + LOGSTRING2("CProfilerGfcSampler<%d>::CProfilerGfcSampler",BufferSize); +} + +template <int BufferSize> +TInt DProfilerGfcSampler<BufferSize>::Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset) +{ + LOGSTRING2("CProfilerGfcSampler<BufferSize> - entry",BufferSize); + + this->repeat = 0; + for(TInt i(0);i<3;i++) + { + this->gfcSample[i] = 0; + } + + LOGSTRING2("CProfilerGfcSampler<%d>::Reset - calling superclass reset",BufferSize); + DProfilerGenericSampler<BufferSize>::Reset(aStream); + LOGSTRING2("CProfilerGfcSampler<%d>::Reset - called superclass reset",BufferSize); + + // add the first sample, indicating the gfc trace version + TUint8 firstSample[33]; + TPtr8 firstSampleDesc(&(firstSample[1]),32); + firstSampleDesc.Zero(); + + firstSampleDesc.Append(_L8("Bappea_V")); + firstSampleDesc.Append(PROFILER_GFC_SAMPLER_VERSION); + firstSampleDesc.Append(_L8("_GFC")); + firstSample[0] = firstSampleDesc.Size(); + + this->iSampleBuffer->AddSample(firstSample,(firstSample[0]+1)); + + LOGSTRING2("CProfilerGfcSampler<BufferSize> - exit",BufferSize); + + return KErrNone; +} + +template <int BufferSize> +void DProfilerGfcSampler<BufferSize>::Sample() +{ + LOGSTRING2("CProfilerGfcSampler<%d>::Sample",BufferSize); + + TUint32 usr_mod_link_reg; + + UsrModLr(&usr_mod_link_reg); + + TUint32 pc(gppSamplerData->lastPcValue); + TUint32 lr(usr_mod_link_reg); + TUint32 sa(gppSamplerData->sampleNumber); + + if(pc == gfcSample[0] && lr == gfcSample[1] && sa == gfcSample[2]+1) + { + // encode repeat + repeat++; + gfcSample[2] = sa; + LOGSTRING2("CProfilerGfcSampler<%d>::Sample - repeat",BufferSize); + return; + } + else if(repeat > 0) + { + TUint8 repeatSample[3]; + repeatSample[0] = 0xff; + repeatSample[1] = (TUint8)(repeat>>8); + repeatSample[2] = (TUint8)repeat; + this->iSampleBuffer->AddSample(repeatSample,3); + + LOGSTRING3("CProfilerGfcSampler<%d>::Sample - Encoded repeat %d",BufferSize,repeat); + + repeat = 0; + } + + TInt ptr(3); + + // encode program counter value + if(pc>=gfcSample[0]) + { + pc = (pc-gfcSample[0]); + encodedSample[0] = 0x80; + } + else + { + pc = (gfcSample[0]-pc); + encodedSample[0] = 0x00; + } + + if(pc <= (TUint32)0xff) + { + encodedSample[0] |= 1; + encodedSample[ptr] = (TUint8)pc;ptr++; + } + else if(pc <= (TUint32)0xffff) + { + encodedSample[0] |= 2; + encodedSample[ptr] = (TUint8)pc;ptr++; + encodedSample[ptr] = (TUint8)(pc>>8);ptr++; + } + else if(pc <= (TUint32)0xffffff) + { + encodedSample[0] |= 3; + encodedSample[ptr] = (TUint8)pc;ptr++; + encodedSample[ptr] = (TUint8)(pc>>8);ptr++; + encodedSample[ptr] = (TUint8)(pc>>16);ptr++; + } + else + { + encodedSample[0] |= 4; + encodedSample[ptr] = (TUint8)pc;ptr++; + encodedSample[ptr] = (TUint8)(pc>>8);ptr++; + encodedSample[ptr] = (TUint8)(pc>>16);ptr++; + encodedSample[ptr] = (TUint8)(pc>>24);ptr++; + } + + // encode link register value + if(lr>=gfcSample[1]) + { + lr = (lr-gfcSample[1]); + encodedSample[1] = 0x80; + } + else + { + lr = (gfcSample[1]-lr); + encodedSample[1] = 0x00; + } + + if(lr <= (TUint32)0xff) + { + encodedSample[1] |= 1; + encodedSample[ptr] = (TUint8)lr;ptr++; + } + else if(lr <= (TUint32)0xffff) + { + encodedSample[1] |= 2; + encodedSample[ptr] = (TUint8)lr;ptr++; + encodedSample[ptr] = (TUint8)(lr>>8);ptr++; + } + else if(lr <= (TUint32)0xffffff) + { + encodedSample[1] |= 3; + encodedSample[ptr] = (TUint8)lr;ptr++; + encodedSample[ptr] = (TUint8)(lr>>8);ptr++; + encodedSample[ptr] = (TUint8)(lr>>16);ptr++; + } + else + { + encodedSample[1] |= 4; + encodedSample[ptr] = (TUint8)lr;ptr++; + encodedSample[ptr] = (TUint8)(lr>>8);ptr++; + encodedSample[ptr] = (TUint8)(lr>>16);ptr++; + encodedSample[ptr] = (TUint8)(lr>>24);ptr++; + } + + // endcode sample number difference + if( (sa - gfcSample[2]) < (TUint8)0xff) + { + encodedSample[2] = (sa-gfcSample[2]); + } + else + { + encodedSample[2] = 0xff; + encodedSample[ptr] = (TUint8)sa;ptr++; + encodedSample[ptr] = (TUint8)(sa>>8);ptr++; + encodedSample[ptr] = (TUint8)(sa>>16);ptr++; + encodedSample[ptr] = (TUint8)(sa>>24);ptr++; + } + + // store the values for the next sample + gfcSample[0] = gppSamplerData->lastPcValue; + gfcSample[1] = usr_mod_link_reg; + gfcSample[2] = gppSamplerData->sampleNumber; + + this->iSampleBuffer->AddSample(encodedSample,ptr); + + LOGSTRING3("CProfilerGfcSampler<%d>::Sample Size %d",BufferSize,ptr); + + return; + +} + +template <int BufferSize> +DProfilerGfcSampler<BufferSize>::~DProfilerGfcSampler() +{ + LOGSTRING2("CProfilerGfcSampler<%d>::~CProfilerGfcSampler",BufferSize); +} +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/inc/GppSamplerImpl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/inc/GppSamplerImpl.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,251 @@ +/* +* 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: +* +*/ + + +#ifndef PROFILER_GPP_SAMPLER_H +#define PROFILER_GPP_SAMPLER_H + +#include "GeneralsConfig.h" + +#include <e32cmn.h> + +#include <piprofiler/ProfilerGenericClassesKrn.h> +#include <piprofiler/ProfilerTraces.h> + +// for RPropertyRef +#include <sproperty.h> +#include <e32cmn.h> + +/* + * + * GPP sampler definition + * + */ +class DGppSamplerImpl //: public DBase +{ +public: + + DGppSamplerImpl(); + ~DGppSamplerImpl(); + + TUint8* EncodeTag(TUint8* aPtr); + TUint8* EncodeInt(TUint8* aPtr,TInt aValue); + TUint8* EncodeUint(TUint8* aPtr,TUint aValue); + TUint8* EncodeText(TUint8* aPtr, const TDesC& aDes); + + TUint8* EncodeName(TUint8* aPtr, DObject& aObject,TUint32 id); + TUint8* EncodeThread(TUint8* aPtr, DThread& aThread); + + TBool IsaTaskKnown(TUint8 task); + TUint8* EncodeIsaTask(TUint8* aPtr, TUint task); + TUint8* EncodeIsaName(TUint8* aPtr, TUint task,TBool process); + + TUint8* EncodeRepeat(TUint8* aPtr); + + TInt CreateFirstSample(); + TInt SampleImpl(); +#ifdef __SMP__ + TSpinLock* LockPtr(); +#endif + TInt iGppSamplingPeriod; + TUint8 tempBuf[512]; + TUint iLastPc; + + TBool iIsaSample; + TInt knownIsaTasks[256]; + TUint8 knownIsaTaskCount; + TInt* isaOsTaskRunningAddr; + void Reset(); + TUint32 iSampleCount; +#ifdef __SMP__ + TInt iCpuNumber; + TUint32 iStartTime; +#endif + PROFILER_DEFINE_ISA_TASK_NAME_ARRAY + +private: + enum TState {EStop,ERunning,EStopping}; + + const TUint* iInterruptStack; + + TUint iLastThread; + TUint iRepeat; +#ifndef __SMP__ + TUint32 iStartTime; +#endif + RPropertyRef iIsaStartAddr; + RPropertyRef iIsaEndAddr; + RPropertyRef iIsaPluginStatus; + RPropertyRef iIsaOsTaskRunning; + TInt iIsaStatus; + TInt iIsaStart; + TInt iIsaEnd; + TUint32 iMask; + TUint32 iCpuSelector; +}; + +struct TProfilerGppSamplerData +{ +//public: + TUint32 lastPcValue; + TUint32 sampleNumber; + TInt samplingPeriod; +}; + +template <int BufferSize> +class DProfilerGppSampler : public DProfilerGenericSampler<BufferSize> +{ +public: +#ifndef __SMP__ + DProfilerGppSampler(); +#else + DProfilerGppSampler(TInt aCpuNumber); +#endif + ~DProfilerGppSampler(); + + struct TProfilerGppSamplerData* GetExportData(); + void Sample(); + TInt Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset); + TInt GetPeriod(); + +private: + DGppSamplerImpl gppSamplerImpl; + struct TProfilerGppSamplerData exportData; +#ifdef __SMP__ + TInt iCpuNumber; +#endif +}; + +/* + * + * GPP sampler implementation + * + */ +#ifndef __SMP__ +template <int BufferSize> +DProfilerGppSampler<BufferSize>::DProfilerGppSampler() : + DProfilerGenericSampler<BufferSize>(PROFILER_GPP_SAMPLER_ID) + { + LOGSTRING2("CProfilerGppSampler<%d>::CProfilerGppSampler",BufferSize); + } +#else +template <int BufferSize> +DProfilerGppSampler<BufferSize>::DProfilerGppSampler(TInt aCpuNumber) : + DProfilerGenericSampler<BufferSize>(PROFILER_GPP_SAMPLER_ID+(aCpuNumber*20)), iCpuNumber(aCpuNumber) + { + LOGSTRING2("CProfilerGppSampler<%d>::CProfilerGppSampler",BufferSize); + } +#endif + +template <int BufferSize> +DProfilerGppSampler<BufferSize>::~DProfilerGppSampler() + { + LOGSTRING2("CProfilerGppSampler<%d>::~CProfilerGppSampler",BufferSize); + } + +template <int BufferSize> +TInt DProfilerGppSampler<BufferSize>::Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset) + { + LOGSTRING2("CProfilerGppSampler<%d>::Reset - calling superclass reset",BufferSize); + DProfilerGenericSampler<BufferSize>::Reset(aStream, 0); + LOGSTRING2("CProfilerGppSampler<%d>::Reset - called superclass reset",BufferSize); + + this->gppSamplerImpl.Reset(); + +#ifdef __SMP__ + this->gppSamplerImpl.iCpuNumber = this->iCpuNumber; + + // set common start time for all CPU samplers + this->gppSamplerImpl.iStartTime = aSyncOffset; +#endif + this->gppSamplerImpl.iGppSamplingPeriod = this->iSamplingPeriod; + this->gppSamplerImpl.iSampleCount = 0; + this->exportData.sampleNumber = 0; + this->exportData.lastPcValue = 0; + this->exportData.samplingPeriod = this->gppSamplerImpl.iGppSamplingPeriod; + + TInt length = gppSamplerImpl.CreateFirstSample(); + LOGSTRING3("CProfilerGPPSampler<%d>::Reset - got first sample, size %d",BufferSize,length); + + this->iSampleBuffer->AddSample(gppSamplerImpl.tempBuf,length); + + // check if sampling period > 1 ms + // NOTE: feature supported in Performance Investigator 2.01 and above + if(this->gppSamplerImpl.iGppSamplingPeriod > 1) + { + // For Address/Thread (GPP) version 2.01 or above, the first word is the sampling period in milliseconds + TUint8* w = gppSamplerImpl.tempBuf; + + (*w++) = (this->gppSamplerImpl.iGppSamplingPeriod >> 24) & 0xFF; + (*w++) = (this->gppSamplerImpl.iGppSamplingPeriod >> 16) & 0xFF; + (*w++) = (this->gppSamplerImpl.iGppSamplingPeriod >> 8) & 0xFF; + (*w++) = (this->gppSamplerImpl.iGppSamplingPeriod) & 0xFF; + + this->iSampleBuffer->AddSample(gppSamplerImpl.tempBuf,4); + } + + LOGSTRING2("CProfilerGPPSampler<%d>::Reset finished",BufferSize); + return KErrNone; + } + +template <int BufferSize> +void DProfilerGppSampler<BufferSize>::Sample() + { + LOGSTRING2("CProfilerGppSampler<%d>::Sample",BufferSize); +// if(this->gppSamplerImpl.iSampleCount % 1000 == 0) +// { +//#ifdef __SMP__ +// if(this->iCpuNumber == 0) // print sample tick only from CPU 0 context +// { +//#endif +// Kern::Printf(("PIPROF SAMPLE TICK, #%d"),exportData.sampleNumber); +//#ifdef __SMP__ +// } +//#endif +// } + + TInt length(gppSamplerImpl.SampleImpl()); + + this->gppSamplerImpl.iSampleCount++; + this->exportData.sampleNumber += this->gppSamplerImpl.iGppSamplingPeriod; + this->exportData.lastPcValue = gppSamplerImpl.iLastPc; + + if(length > 0) + { + this->iSampleBuffer->AddSample(gppSamplerImpl.tempBuf,length); + } + + LOGSTRING3("CProfilerGppSampler<%d>::Sample - length %d",BufferSize,length); + + return; + } + + +template <int BufferSize> +struct TProfilerGppSamplerData* DProfilerGppSampler<BufferSize>::GetExportData() + { + LOGSTRING2("CProfilerGppSampler<%d>::GetExportData",BufferSize); + return &(this->exportData); + } + +template <int BufferSize> +TInt DProfilerGppSampler<BufferSize>::GetPeriod() + { + return this->gppSamplerImpl.iGppSamplingPeriod; + } + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/inc/IttEventHandler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/inc/IttEventHandler.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,65 @@ +/* +* 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: Event based ITT sampler skeleton copypasted from MemoryEventHandler.h +* +*/ +#include "IttSamplerImpl.h" + +#ifndef __PI_ITT_EVENT_HANDLER__ +#define __PI_ITT_EVENT_HANDLER__ + +#include <piprofiler/ProfilerGenericClassesKrn.h> + +// CONSTANTS +const TInt KITTBufferSize = 256; + +class DProfilerSampleBuffer; + +/* + * ITT event handler for listaning kernel events + */ +class DIttEventHandler : public DKernelEventHandler + { +public: + // constructor + DIttEventHandler(DProfilerSampleBuffer* aSampleBuffer, TProfilerGppSamplerData* aGppSamplerDataIn); + TInt Create(); + ~DIttEventHandler(); + TInt Start(); + TInt Stop(); + TBool Tracking() {return iTracking;} + + TBool SampleNeeded(); + +private: + static TUint EventHandler(TKernelEvent aEvent, TAny* a1, TAny* a2, TAny* aThis); + TUint HandleEvent(TKernelEvent aType, TAny* a1, TAny* a2); + // handle code segments + TBool HandleAddCodeSeg(DCodeSeg* aSeg); + TBool HandleRemoveCodeSeg(DCodeSeg* aSeg); + +private: + /** Lock serialising calls to event handler */ + DMutex* iLock; + TBool iTracking; + DProfilerSampleBuffer* iSampleBuffer; + + TUint32 iCount; + + TUint8 iSample[KITTBufferSize]; + TPtr8 iSampleDescriptor; + TProfilerGppSamplerData* gppSamplerData; + }; + +#endif //__PI_ITT_EVENT_HANDLER__ diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/inc/IttSamplerImpl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/inc/IttSamplerImpl.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,327 @@ +/* +* 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: +* +*/ + +#ifndef PROFILER_ITT_SAMPLER_H +#define PROFILER_ITT_SAMPLER_H + +#include "GeneralsConfig.h" + +#include <kern_priv.h> + +#include <piprofiler/ProfilerGenericClassesKrn.h> +#include <piprofiler/ProfilerTraces.h> +#include "GppSamplerImpl.h" +#include "IttEventHandler.h" + +// CONSTANTS +const TInt KITTSampleBufferSize = 256; + +// flags +#define ITT_EVENT_HANDLER // enable event based ITT sampling + +/* + * + * ITT sampler definition + * + */ +class DIttEventHandler; + +/* + * User side ITT sampler + */ +class IttSamplerImpl +{ +public: + IttSamplerImpl(); + ~IttSamplerImpl(); + + TInt SampleImpl(TUint32 pc,TUint32 sampleNum); + TBool SampleNeeded(TUint32 sampleNum); + TInt CreateFirstSample(); + void Reset(); + TInt ProcessEvent(); + + TUint8* itt_sample; + TInt iIttSamplingPeriod; + TInt iIttSamplingPeriodDiv2; + TBool iTimeToSample; +#ifdef ITT_EVENT_HANDLER + TBool iEventReceived; + TBool iFirstSampleTaken; +#endif + +private: +#ifdef ITT_EVENT_HANDLER + TInt iCount; +#endif + TInt currentLibCount; + TInt currentProcCount; + + TUint8 sample[KITTSampleBufferSize ]; + TPtr8 sampleDescriptor; + + TBuf8<64> iVersionData; + SDblQue* codeSegList; + +}; + +/* + * ITT sampler kernel part + * + */ +template <int BufferSize> +class DProfilerIttSampler : public DProfilerGenericSampler<BufferSize> +{ +public: + DProfilerIttSampler(struct TProfilerGppSamplerData* gppSamplerDataIn); + ~DProfilerIttSampler(); + + void Sample(); + TInt Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset); + TInt PostSample(); + TBool PostSampleNeeded(); + +private: +#ifdef ITT_EVENT_HANDLER + DIttEventHandler* iEventHandler; +#endif + IttSamplerImpl ittSamplerImpl; + struct TProfilerGppSamplerData* gppSamplerData; + TBool sampleInProgress; + TBool sampleNeeded; +}; + +/* + * ITT sampler implementation + * + */ +template <int BufferSize> +DProfilerIttSampler<BufferSize>::DProfilerIttSampler(struct TProfilerGppSamplerData* gppSamplerDataIn) : + DProfilerGenericSampler<BufferSize>(PROFILER_ITT_SAMPLER_ID) +{ + this->gppSamplerData = (struct TProfilerGppSamplerData*)gppSamplerDataIn; + this->sampleInProgress = false; + LOGSTRING2("CProfilerIttSampler<%d>::CProfilerIttSampler",BufferSize); +} + +/* + * DProfilerIttSampler::Reset() + * + * @param DProfilerSampleStream* sample stream + * @param TUint32 Offset + */ +template <int BufferSize> +TInt DProfilerIttSampler<BufferSize>::Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset) +{ + Kern::Printf("DProfilerIttSampler<%d>::Reset - calling superclass reset",BufferSize); + DProfilerGenericSampler<BufferSize>::Reset(aStream); + + // check if reset called in stop (by driver) + if(aSyncOffset != 999999) + { +#ifdef ITT_EVENT_HANDLER + // Itt event handler + if(iEventHandler) + { + // stop previous sampling if still running + Kern::Printf("Stopping DIttEventHandler"); + iEventHandler->Stop(); + iEventHandler->Close(); + iEventHandler = NULL; + } + + Kern::Printf("Initiating DIttEventHandler"); + iEventHandler = new DIttEventHandler(this->iSampleBuffer, this->gppSamplerData); + if(iEventHandler) + { + Kern::Printf("Creating DIttEventHandler"); + TInt err(iEventHandler->Create()); + if(err != KErrNone) + { + Kern::Printf("Error in creation of DIttEventHandler, error %d", err); + return err; + } + } + else + { + Kern::Printf("Could not initiate DIttEventHandler"); + return KErrGeneral; + } + + // set first sample at the 10 ms, should be enough + this->ittSamplerImpl.iIttSamplingPeriod = 10; +#else + this->ittSamplerImpl.iIttSamplingPeriod = this->iSamplingPeriod; +#endif + this->ittSamplerImpl.iIttSamplingPeriodDiv2 = (TInt)(this->ittSamplerImpl.iIttSamplingPeriod / 2); + LOGSTRING3("CProfilerIttSampler<%d>::Reset - set ITT sampling period to %d", + BufferSize,this->ittSamplerImpl.iIttSamplingPeriod); + } + else + { + LOGSTRING2("DProfilerIttSampler<%d>::Reset - reset in stop", BufferSize); +#ifdef ITT_EVENT_HANDLER + // destroy memory event handler + if(iEventHandler) + { + // stop previous sampling if still running + iEventHandler->Stop(); + iEventHandler->Close(); + iEventHandler = NULL; + } +#endif + return KErrNone; // return if reset called in stop + } + + TInt length(ittSamplerImpl.CreateFirstSample()); + this->iSampleBuffer->AddSample((TUint8*)&length,1); + this->iSampleBuffer->AddSample(ittSamplerImpl.itt_sample, length); + this->sampleInProgress = false; + this->sampleNeeded = false; + //LOGSTRING("DProfilerIttSampler::Reset - exit"); + this->ittSamplerImpl.Reset(); + return KErrNone; + +} + +/* + * DProfilerIttSampler::PostSample + * + * Function for finishing sample + */ +template <int BufferSize> +TInt DProfilerIttSampler<BufferSize>::PostSample() +{ +#ifdef ITT_EVENT_HANDLER + if(!ittSamplerImpl.iFirstSampleTaken) // if we haven't read the initial state + { +#endif + if(sampleNeeded) + { + this->sampleNeeded = false; + //LOGSTRING3("CProfilerIttSampler<%d>::PostSample - state %d",BufferSize,this->iSampleBuffer->GetBufferStatus()); + //Kern::Printf("DProfilerIttSampler<%d>::PostSample - state %d",BufferSize,this->iSampleBuffer->GetBufferStatus()); + + TInt length = this->ittSamplerImpl.SampleImpl(this->gppSamplerData->lastPcValue, + this->gppSamplerData->sampleNumber); + if(length != 0) + { + LOGSTRING("ITT sampler PostSample - starting to sample"); + + while(length > 0) + { + this->iSampleBuffer->AddSample(ittSamplerImpl.itt_sample,length); + length = this->ittSamplerImpl.SampleImpl( this->gppSamplerData->lastPcValue, + this->gppSamplerData->sampleNumber ); + if(length == 0) + { + LOGSTRING("MEM sampler PostSample - all samples generated!"); + } + } + LOGSTRING("ITT sampler PostSample - finished sampling"); + } + this->sampleInProgress = false; + } +#ifdef ITT_EVENT_HANDLER + } + if(!iEventHandler->Tracking()) + { + iEventHandler->Start(); + Kern::Printf("DProfilerITTSampler<%d>::PostSample - ITT handler started",BufferSize); + } + +#endif + + LOGSTRING2("ITT sampler PostSample - finished sampling, time: %d", gppSamplerData->sampleNumber); + + // finally perform superclass postsample + TInt i(this->DProfilerGenericSampler<BufferSize>::PostSample()); + return i; +} + +/* + * DProfilerIttSampler::PostSampleNeeded() + * + * Function for deciding if sample handling is needed + */ +template <int BufferSize> +TBool DProfilerIttSampler<BufferSize>::PostSampleNeeded() +{ + LOGSTRING3("CProfilerIttSampler<%d>::PostSampleNeeded - state %d",BufferSize,this->iSampleBuffer->GetBufferStatus()); + + TUint32 status = this->iSampleBuffer->iBufferStatus; + + if(status == DProfilerSampleBuffer::BufferCopyAsap || status == DProfilerSampleBuffer::BufferFull || this->sampleNeeded == true) + { + return true; + } + + return false; +} + +/* + * DProfilerIttSampler::Sample + * + * Function for initiating sampling + */ +template <int BufferSize> +void DProfilerIttSampler<BufferSize>::Sample() +{ + LOGSTRING2("CProfilerIttSampler<%d>::Sample",BufferSize); + + //#ifdef ITT_TEST + LOGSTRING2("CProfilerIttSampler<%d>::Sample",BufferSize); + + if(ittSamplerImpl.SampleNeeded(this->gppSamplerData->sampleNumber) && this->sampleInProgress == false) + { + this->sampleInProgress = true; + this->sampleNeeded = true; + + LOGSTRING2("CProfilerIttSampler<%d>::Sample - sample needed",BufferSize); + } +#ifdef ITT_EVENT_HANDLER + // call this to increase the time stamp + else if(iEventHandler->SampleNeeded()) + { + // set the flag for post sampling + this->sampleNeeded = true; + } +#endif + + LOGSTRING2("CProfilerIttSampler<%d>::Sample",BufferSize); + return; +} + +/* + * Destructor + */ +template <int BufferSize> +DProfilerIttSampler<BufferSize>::~DProfilerIttSampler() +{ + LOGSTRING2("CProfilerIttSampler<%d>::~CProfilerIttSampler",BufferSize); +#ifdef ITT_EVENT_HANDLER + if(iEventHandler) + { + // stop previous sampling if still running + iEventHandler->Stop(); + iEventHandler->Close(); + iEventHandler = NULL; + } +#endif +} +#endif +// end of file diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/inc/MemSamplerImpl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/inc/MemSamplerImpl.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,427 @@ +/* +* 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: +* +*/ + + +#ifndef PROFILER_MEM_SAMPLER_H +#define PROFILER_MEM_SAMPLER_H + +#include "GeneralsConfig.h" + +#include <kern_priv.h> + +#include <piprofiler/ProfilerGenericClassesKrn.h> +#include <piprofiler/ProfilerTraces.h> +#include "GppSamplerImpl.h" +#include "MemoryEventHandler.h" +#include <e32btrace.h> + + +// constants +// defines the maximum thread amount that is assumed to +// be possible with MEM trace +const TInt KSampleBufferSize = 257; +const TInt KProfilerMaxThreadsAmount = 512; +const TInt KProfilerMaxChunksAmount = 1024; +const TInt KProfilerMaxLibrariesAmount = 1024; +const TInt KProfilerTotalMemorySamplePeriod = 100; + +// flags +#define MEM_EVENT_HANDLER +//#define MEM_EVENT_HANDLER_LIBRARY_EVENTS + +/* + * + * MEM sampler definition + * + */ + +class DMemoryEventHandler; + +class DMemSamplerImpl //: public DBase +{ +public: + enum EProcessingState + { + EStartingToProcess, + EProcessingNames, + EProcessingData, + ENothingToProcess + }; +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + enum ESampleType + { + ESampleChunks, + ESampleThreads, + ESampleLibraries + }; +#endif + + DMemSamplerImpl(); + ~DMemSamplerImpl(); + + TInt CreateFirstSample(); + TInt SampleImpl(); + TBool SampleNeeded(); + void Reset(); + TInt ProcessChunks(); + TInt ProcessThreads(); + TInt GatherChunks(); + TInt GatherThreads(); + +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + TInt GatherLibraries(); + TInt ProcessLibraries(); +#endif + + TInt EncodeChunkData(DChunk& chunk); + TInt EncodeChunkName(DChunk& chunk); + TInt EncodeChunkData(DThread& thread); + TInt EncodeChunkName(DThread& thread); +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + TInt EncodeChunkData(DLibrary& library); + TInt EncodeChunkName(DLibrary& library); +#endif + + TInt EncodeTotalMemoryName(); + TInt EncodeTotalMemory(); + + TInt EncodeNameCode(); + TInt EncodeDataCode(); + + DChunk* heapChunksToSample[KProfilerMaxChunksAmount]; + DChunk* heapChunkNamesToReport[KProfilerMaxChunksAmount]; + TInt iCount; + TInt iChunkCount; + TInt iNewChunkCount; + TBuf8<0x50> name; + DThread* threadsToSample[KProfilerMaxThreadsAmount]; + DThread* threadNamesToReport[KProfilerMaxThreadsAmount]; + TInt iThreadCount; + TInt iNewThreadCount; +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + DLibrary* librariesToSample[KProfilerMaxLibrariesAmount]; + DLibrary* libraryNamesToReport[KProfilerMaxLibrariesAmount]; + TInt iLibraryCount; + TInt iNewLibraryCount; + TInt iLibrariesProcessing; +#endif + + TInt iChunksProcessing; + TInt iThreadsProcessing; + TInt iMemSamplingPeriod; + TInt iMemSamplingPeriodDiv2; + TInt iMemSamplingPeriodDiv3; + +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + ESampleType iSampleType; +#else + TBool iSampleThreads; +#endif + + TBool iTimeToSample; + + TBool iTotalMemoryOk; + TBool iTotalMemoryNameOk; + + TUint8 sample[KSampleBufferSize]; + TPtr8 sampleDescriptor; + + // test +#ifdef MEM_EVENT_HANDLER +// DMemoryEventHandler* iEventHandler; + TBool iChunksGathered; + TBool iThreadsGathered; +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + TBool iLibrariesGathered; +#endif +#endif +}; + + +template <int BufferSize> +class DProfilerMemSampler : public DProfilerGenericSampler<BufferSize> +{ +public: + DProfilerMemSampler(struct TProfilerGppSamplerData*, TInt id); + ~DProfilerMemSampler(); + + void Sample(); + TInt Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset); + TInt PostSample(); + TBool PostSampleNeeded(); + +private: +#ifdef MEM_EVENT_HANDLER + DMemoryEventHandler* iEventHandler; +#endif + DMemSamplerImpl memSamplerImpl; + struct TProfilerGppSamplerData* gppSamplerData; + TBool sampleNeeded; +}; + +/* + * + * MEM sampler implementation + * + */ + +template <int BufferSize> +DProfilerMemSampler<BufferSize>::DProfilerMemSampler(struct TProfilerGppSamplerData* gppSamplerDataIn, TInt id) : + DProfilerGenericSampler<BufferSize>(PROFILER_MEM_SAMPLER_ID) + { + LOGSTRING2("DProfilerMemSampler<%d>::CProfilerMemSampler",BufferSize); + this->gppSamplerData = gppSamplerDataIn; + this->iSamplingPeriod = 3000; // set default setting + } + +template <int BufferSize> +TInt DProfilerMemSampler<BufferSize>::Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset) + { +//#ifdef MEM_EVENT_HANDLER +// Kern::Printf("DProfilerMemSampler<%d>::Reset - calling superclass reset",BufferSize); + +//#endif + // check if reset called in stop (by driver) + if(aSyncOffset != 999999) + { + DProfilerGenericSampler<BufferSize>::Reset(aStream); + memSamplerImpl.Reset(); + +#ifdef MEM_EVENT_HANDLER + // reset member variables + this->memSamplerImpl.iThreadsGathered = false; + this->memSamplerImpl.iChunksGathered = false; +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + this->memSamplerImpl.iLibrariesGathered = false; +#endif + + // memory event handler + if(iEventHandler) + { + // stop previous sampling if still running +// Kern::Printf("Stopping DMemoryEventHandler"); + iEventHandler->Stop(); + iEventHandler->Close(); + iEventHandler = NULL; + } + +// Kern::Printf("Initiating DMemoryEventHandler"); + iEventHandler = new DMemoryEventHandler(this->iSampleBuffer); + if(iEventHandler) + { +// Kern::Printf("Creating DMemoryEventHandler"); + TInt err(iEventHandler->Create()); + if(err != KErrNone) + { + Kern::Printf("Error in creation of DMemoryEventHandler, error %d", err); + return err; + } + } + else + { + Kern::Printf("Could not initiate DMemoryEventHandler"); + return KErrGeneral; + } + + // set first chunk&thread memory lookup at the 5 ms, should be enough +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + this->memSamplerImpl.iMemSamplingPeriod = 45; +#else + this->memSamplerImpl.iMemSamplingPeriod = 10; +#endif + +#else + this->memSamplerImpl.iMemSamplingPeriod = this->iSamplingPeriod; +#endif + this->memSamplerImpl.iMemSamplingPeriodDiv2 = (TInt)(this->memSamplerImpl.iMemSamplingPeriod / 2); +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + this->memSamplerImpl.iMemSamplingPeriodDiv3 = (TInt)(this->memSamplerImpl.iMemSamplingPeriod / 3); +#endif + + LOGSTRING3("CProfilerMemSampler<%d>::Reset - set mem sampling period to %d", + BufferSize,this->memSamplerImpl.iMemSamplingPeriod); + } + else + { + LOGSTRING2("DProfilerMemSampler<%d>::Reset - reset in stop", BufferSize); +#ifdef MEM_EVENT_HANDLER + // destroy memory event handler + if(iEventHandler) + { + // stop previous sampling if still running +// Kern::Printf("Stopping DMemoryEventHandler"); + iEventHandler->Stop(); + iEventHandler->Close(); + iEventHandler = NULL; + } +#endif + return KErrNone; // return if reset called in stop + } + + // add MEM sample header + TInt length(memSamplerImpl.CreateFirstSample()); + this->iSampleBuffer->AddSample(memSamplerImpl.sample,length); + + this->sampleNeeded = false; + LOGSTRING("DProfilerMemSampler::Reset - exit"); + return KErrNone; + } + +template <int BufferSize> +TInt DProfilerMemSampler<BufferSize>::PostSample() + { + this->sampleNeeded = false; + + LOGSTRING3("DProfilerMemSampler<%d>::PostSample - state %d",BufferSize,this->iSampleBuffer->GetBufferStatus()); + +#ifdef MEM_EVENT_HANDLER + // check if all threads and chunks (and libraries) are gathered +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + if(!memSamplerImpl.iThreadsGathered || !memSamplerImpl.iChunksGathered || !memSamplerImpl.iLibrariesGathered) +#else + if(!memSamplerImpl.iThreadsGathered || !memSamplerImpl.iChunksGathered) +#endif + { +#endif + // disable interrupts for checking the kernel containers (EChunk, EThread) +// TInt interruptLevel(NKern::DisableInterrupts(0)); + + // first collect chunk data + TInt length(this->memSamplerImpl.SampleImpl()); + if(length != 0) + { + // then, encode the sample to the buffer until no further data available + while(length > 0) + { + this->iSampleBuffer->AddSample(memSamplerImpl.sample,length); + length = this->memSamplerImpl.SampleImpl(); + + // indicate that the whole MEM sample ends by having a 0x00 in the end + if(length == 0) + { + TUint8 number(0); + LOGSTRING("MEM sampler PostSample - all samples generated!"); + + this->iSampleBuffer->AddSample(&number,1); + LOGSTRING2("MEM sampler PostSample - end mark added, time: %d", gppSamplerData->sampleNumber); + } + } + } + // restore interrupts and continue normal execution +// NKern::RestoreInterrupts(interruptLevel); +#ifdef MEM_EVENT_HANDLER + } + // check if all threads and chunks are gathered +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + if(memSamplerImpl.iThreadsGathered && memSamplerImpl.iChunksGathered && memSamplerImpl.iLibrariesGathered) +#else + if(memSamplerImpl.iThreadsGathered && memSamplerImpl.iChunksGathered) +#endif + { + // start memory event tracking after checking the current memory status + if(!iEventHandler->Tracking()) + { + iEventHandler->Start(); +// Kern::Printf("DProfilerMemSampler<%d>::PostSample - memory event handler started",BufferSize); + } + + } +#endif + + LOGSTRING2("MEM sampler PostSample - finished sampling, time: %d", gppSamplerData->sampleNumber); + + // finally perform superclass postsample + TInt i(this->DProfilerGenericSampler<BufferSize>::PostSample()); + return i; + } + +template <int BufferSize> +TBool DProfilerMemSampler<BufferSize>::PostSampleNeeded() + { + LOGSTRING3("DProfilerMemSampler<%d>::PostSampleNeeded - state %d",BufferSize,this->iSampleBuffer->GetBufferStatus()); + + TUint32 status(this->iSampleBuffer->iBufferStatus); + + if(status == DProfilerSampleBuffer::BufferCopyAsap || status == DProfilerSampleBuffer::BufferFull || this->sampleNeeded == true) + { + return true; + } + + return false; + } + +template <int BufferSize> +void DProfilerMemSampler<BufferSize>::Sample() + { + LOGSTRING2("DProfilerMemSampler<%d>::Sample",BufferSize); + + // check if sample is needed, i.e. the sampling interval is met + if(memSamplerImpl.SampleNeeded()) + { + // set the flag for post sampling + this->sampleNeeded = true; + + // start the MEM sample with the sample time + TUint8 number(4); // mem sampler id + this->iSampleBuffer->AddSample(&number,1); + this->iSampleBuffer->AddSample((TUint8*)&(gppSamplerData->sampleNumber),4); + + // leave the rest of the processing for PostSample() + } + +#ifdef MEM_EVENT_HANDLER + // call this to increase the time stamp + else if(iEventHandler->SampleNeeded()) + { + // set the flag for post sampling + this->sampleNeeded = true; + } + +// // check if time stamp is divibable with +// if((memSamplerImpl.iCount % KProfilerTotalMemorySamplePeriod) == 0 && +// memSamplerImpl.iCount > 0) +// { +// // sample total memory once per 100 ms +// memSamplerImpl.EncodeTotalMemory(); +// +// // add end mark +// TUint8 number(0); +// this->iSampleBuffer->AddSample(&number,1); +// } +#endif + + LOGSTRING2("CProfilerMemSampler<%d>::Sample",BufferSize); + return; + } + +template <int BufferSize> +DProfilerMemSampler<BufferSize>::~DProfilerMemSampler() + { + LOGSTRING2("CProfilerMemSampler<%d>::~CProfilerMemSampler",BufferSize); +#ifdef MEM_EVENT_HANDLER + // memory event handler + if(iEventHandler) + { + // stop previous sampling if still running +// Kern::Printf("Stopping DMemoryEventHandler"); + iEventHandler->Stop(); + iEventHandler->Close(); + iEventHandler = NULL; + } +#endif + } +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/inc/MemoryEventHandler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/inc/MemoryEventHandler.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,91 @@ +/* +* 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: +* +*/ +#include "MemSamplerImpl.h" + +#ifndef __PI_MEMORY_EVENT_HANDLER__ +#define __PI_MEMORY_EVENT_HANDLER__ + +#include <piprofiler/ProfilerGenericClassesKrn.h> + +// CONSTANTS +const TInt KEventBufferSize = 257; + +class DProfilerSampleBuffer; + +class DMemoryEventHandler : public DKernelEventHandler + { +public: + // constructor + DMemoryEventHandler(DProfilerSampleBuffer* aSampleBuffer); + TInt Create(); + ~DMemoryEventHandler(); + TInt Start(); + TInt Stop(); + TBool Tracking() {return iTracking;} + + TBool SampleNeeded(); + +private: + static TUint EventHandler(TKernelEvent aEvent, TAny* a1, TAny* a2, TAny* aThis); + TUint HandleEvent(TKernelEvent aType, TAny* a1, TAny* a2); + // handle chunk activity + TBool HandleAddChunk(DChunk* aChunk); + TBool HandleUpdateChunk(DChunk* aChunk); + TBool HandleDeleteChunk(DChunk* aChunk); + // handle chunk activity + TBool HandleAddThread(DThread* aThread); + TBool HandleUpdateThread(DThread* aThread); + TBool HandleDeleteThread(DThread* aThread); + // handle chunk activity + TBool HandleAddProcess(DProcess* aProcess); + TBool HandleUpdateProcess(DProcess* aProcess); + TBool HandleDeleteProcess(DProcess* aProcess); + // handle library activity + TBool HandleAddLibrary(DLibrary* aLibrary, DThread* aThread); + TBool HandleDeleteLibrary(DLibrary* aLibrary); + + // data handling + TInt AddHeader(); + TInt AddFooter(); + TInt EncodeTotalMemory(); + TInt EncodeNameCode(); + TInt EncodeNewCode(); + TInt EncodeUpdateCode(); + TInt EncodeRemoveCode(); + TInt EncodeChunkName(DThread& t); + TInt EncodeChunkName(DChunk& c); + TInt EncodeChunkName(DLibrary& l); + TInt EncodeChunkData(DThread& t); + TInt EncodeChunkData(DChunk& c); + TInt EncodeChunkData(DLibrary& l, DThread& t); +private: + /** Lock serialising calls to event handler */ + DMutex* iLock; + TBool iTracking; + + DProfilerSampleBuffer* iSampleBuffer; + TInt iCounters[EEventLimit]; + + TUint32 iCount; + + TUint8 iSample[KEventBufferSize]; + TPtr8 iSampleDescriptor; + + TUint32 iPreviousCount; + }; + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/inc/PriSamplerImpl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/inc/PriSamplerImpl.h Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,245 @@ +/* +* 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: +* +*/ + + +#ifndef PROFILER_PRI_SAMPLER_H +#define PROFILER_PRI_SAMPLER_H + +#include "GeneralsConfig.h" + +#include <kern_priv.h> + +#include <piprofiler/ProfilerGenericClassesKrn.h> +#include <piprofiler/ProfilerTraces.h> +#include "GppSamplerImpl.h" + +// defines the maximum thread amount that is assumed to +// be possible with PRI trace +const TInt KProfilerMaxThreadAmount = 512; + +/* + * + * PRI sampler definition + * + */ + +class DPriSamplerImpl //: public DBase +{ +public: + enum EProcessingState + { + EStartingToProcess, + EProcessingNames, + EProcessingData, + ENothingToProcess + }; + + DPriSamplerImpl(); + ~DPriSamplerImpl(); + + TInt CreateFirstSample(); + TInt SampleImpl(); + TBool SampleNeeded(); + void Reset(); + TInt ProcessChunks(); + + TInt EncodeChunkData(DThread& thread); + TInt EncodeChunkName(DThread& thread); + + TInt EncodeNameCode(); + TInt EncodeDataCode(); + + TInt iCountti; + DThread* threadsToSample[KProfilerMaxThreadAmount]; + DThread* threadNamesToReport[KProfilerMaxThreadAmount]; + + TInt iThreadCount; + TInt iNewThreadCount; + + TInt iProcessing; + TInt iPriSamplingPeriod; + + TUint8 sample[257]; + TPtr8 sampleDescriptor; +#ifdef __SMP__ + TInt iCpuNumber; + TUint32 iStartTime; +#endif + +}; + +template <int BufferSize> +class DProfilerPriSampler : public DProfilerGenericSampler<BufferSize> +{ +public: + DProfilerPriSampler(struct TProfilerGppSamplerData*, TInt id); + ~DProfilerPriSampler(); + + void Sample(); + TInt Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset); + TInt PostSample(); + TBool PostSampleNeeded(); + +private: + DPriSamplerImpl priSamplerImpl; + struct TProfilerGppSamplerData* gppSamplerData; + TBool sampleNeeded; + TBool sampleInProgress; +#ifdef __SMP__ + TInt iCpuNumber; +#endif +}; + +/* + * + * PRI sampler implementation + * + */ +//#ifndef __SMP__ +template <int BufferSize> +DProfilerPriSampler<BufferSize>::DProfilerPriSampler(struct TProfilerGppSamplerData* gppSamplerDataIn, TInt id) : + DProfilerGenericSampler<BufferSize>(PROFILER_PRI_SAMPLER_ID) + { + LOGSTRING2("CProfilerPriSampler<%d>::CProfilerPriSampler",BufferSize); + this->gppSamplerData = gppSamplerDataIn; + this->sampleInProgress = false; + this->iSamplingPeriod = 3000; // set default setting + } +//#else +//template <int BufferSize> +//DProfilerPriSampler<BufferSize>::DProfilerPriSampler(struct TProfilerGppSamplerData* gppSamplerDataIn, TInt id, TInt aCpuNumber) : +// DProfilerGenericSampler<BufferSize>(PROFILER_PRI_SAMPLER_ID+(aCpuNumber*20)), iCpuNumber(aCpuNumber) +// { +// LOGSTRING2("CProfilerGppSampler<%d>::CProfilerGppSampler",BufferSize); +// } +//#endif + +template <int BufferSize> +TInt DProfilerPriSampler<BufferSize>::Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset) + { + LOGSTRING2("CProfilerPriSampler<%d>::Reset - calling superclass reset",BufferSize); + DProfilerGenericSampler<BufferSize>::Reset(aStream); + LOGSTRING2("CProfilerPriSampler<%d>::Reset - called superclass reset",BufferSize); + priSamplerImpl.Reset(); + +#ifdef __SMP__ +// this->priSamplerImpl.iCpuNumber = this->iCpuNumber; +// +// // set common start time for all CPU samplers +// this->priSamplerImpl.iStartTime = aSyncOffset; +#endif + this->priSamplerImpl.iPriSamplingPeriod = this->iSamplingPeriod; + + + LOGSTRING3("CProfilerPriSampler<%d>::Reset - set pri sampling period to", + BufferSize,this->priSamplerImpl.iPriSamplingPeriod); + + TInt length(priSamplerImpl.CreateFirstSample()); + this->iSampleBuffer->AddSample(priSamplerImpl.sample,length); + + this->sampleInProgress = false; + this->sampleNeeded = false; + + return KErrNone; + } + +template <int BufferSize> +TInt DProfilerPriSampler<BufferSize>::PostSample() + { + if(sampleNeeded) + { + this->sampleNeeded = false; + + LOGSTRING3("CProfilerPriSampler<%d>::PostSample - state %d",BufferSize,this->sampleBuffer->GetBufferStatus()); + + //TInt interruptLevel = NKern::DisableInterrupts(0); + + TInt length(this->priSamplerImpl.SampleImpl()); + if(length != 0) + { + LOGSTRING("PRI sampler PostSample - starting to sample"); + + // then, encode the sample to the buffer + while(length > 0) + { + this->iSampleBuffer->AddSample(priSamplerImpl.sample,length); + length = this->priSamplerImpl.SampleImpl(); + // indicate that the whole PRI sample ends by having a 0x00 in the end + if(length == 0) + { + TUint8 number(0); + LOGSTRING("PRI sampler PostSample - all samples generated!"); + + this->iSampleBuffer->AddSample(&number,1); + LOGSTRING("PRI sampler PostSample - end mark added"); + } + } + LOGSTRING("PRI sampler PostSample - finished sampling"); + } + this->sampleInProgress = false; + + //NKern::RestoreInterrupts(interruptLevel); + } + + // finally perform superclass postsample + TInt i(this->DProfilerGenericSampler<BufferSize>::PostSample()); + return i; + } + +template <int BufferSize> +TBool DProfilerPriSampler<BufferSize>::PostSampleNeeded() + { + LOGSTRING3("CProfilerPriSampler<%d>::PostSampleNeeded - state %d",BufferSize,this->sampleBuffer->GetBufferStatus()); + + TUint32 status = this->iSampleBuffer->iBufferStatus; + + if(status == DProfilerSampleBuffer::BufferCopyAsap || status == DProfilerSampleBuffer::BufferFull || this->sampleNeeded == true) + { + return true; + } + + return false; + } + + +template <int BufferSize> +void DProfilerPriSampler<BufferSize>::Sample() + { + LOGSTRING2("CProfilerPriSampler<%d>::Sample",BufferSize); + + if(priSamplerImpl.SampleNeeded() && this->sampleInProgress == false) + { + this->sampleInProgress = true; + this->sampleNeeded = true; + // start the PRI sample with the sample time + TUint8 number(4); + this->iSampleBuffer->AddSample(&number,1); + this->iSampleBuffer->AddSample((TUint8*)&(gppSamplerData->sampleNumber),4); + + // leave the rest of the processing for PostSample() + } + + LOGSTRING2("CProfilerPriSampler<%d>::Sample",BufferSize); + return; + } + +template <int BufferSize> +DProfilerPriSampler<BufferSize>::~DProfilerPriSampler() + { + LOGSTRING2("CProfilerPriSampler<%d>::~CProfilerPriSampler",BufferSize); + } +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/src/GeneralsDriver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/src/GeneralsDriver.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,1152 @@ +/* +* 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: +* +*/ + + +// +// LDD for thread time profiling +// + +#include <kern_priv.h> +#include <platform.h> +#include <arm.h> + +#ifdef __SMP__ +#include <assp/naviengine/naviengine.h> +#include <nkernsmp/arm/arm_gic.h> +#include <nkernsmp/arm/arm_tmr.h> +#endif + +#include "GeneralsDriver.h" +#include <piprofiler/PluginDriver.h> +#include <piprofiler/PluginSampler.h> +#include <piprofiler/ProfilerTraces.h> + +#include "GppSamplerImpl.h" +#include "GfcSamplerImpl.h" +#include "IttSamplerImpl.h" +#include "MemSamplerImpl.h" +#include "PriSamplerImpl.h" + + +#ifndef __SMP__ +extern TUint* IntStackPtr(); +extern void UsrModLr(TUint32*); +#endif +// for security check +#define KProfilerExeSecurUid 0x2001E5AD +static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy); +static _LIT_SECURITY_POLICY_FAIL( KDenyAllPolicy ); + +#define SEPARATE_DFC_QUEUE +// CONSTANTS + +//_LIT(DProfilerThread,"DProfilerThread"); +//const TInt KDProfilerThreadPriority = 27; + +#ifdef SEPARATE_DFC_QUEUE +const TInt KGeneralsDriverThreadPriority = 24; +_LIT(KGeneralsDriverThread, "PIGeneralsDriver"); + +#endif + +// global Dfc Que +//TDynamicDfcQue* gDfcQ; + +//#ifdef __SMP__ +// +//enum TNaviEngineAsspInterruptIdExtension +//{ +// KIntProfilerBase = 99 // Sampling profiler interrupt base. +// // Each CPU is assigned a sampling interrupt from this base +// // CPU-0's sampling interrupt is KIntIdSamplingBase + 0 +// // CPU-n's sampling interrupt is KIntIdSamplingBase + n +//}; +//#endif + +/* + * + * + * Class DGfcProfilerFactory definition + * + * + */ + +class DGeneralsProfilerFactory : public DLogicalDevice +{ + public: + DGeneralsProfilerFactory(); + ~DGeneralsProfilerFactory(); + + public: + virtual TInt Install(); + virtual void GetCaps(TDes8& aDes) const; + virtual TInt Create(DLogicalChannelBase*& aChannel); +}; + +/* + * + * + * Class DGfcDriver definition + * + * + */ +class DPluginDriver; + +class DGeneralsDriver : public DPluginDriver +{ + +public: + DGeneralsDriver(); + ~DGeneralsDriver(); + +private: + TInt NewStart(TInt aRate); + static void NewDoProfilerProfile(TAny*); + static void NewDoDfc(TAny*); + + // called by each core + static void Sample(TAny*); + + TInt GetSampleTime(TUint32* time); + //TInt Test(TUint32 testCase); + + TInt StartSampling(); + TInt StopSampling(); + + void InitialiseSamplerList(); + + DProfilerSamplerBase* GetSamplerForId(TInt samplerId); + TInt GetSamplerVersion(TDes* aDes); + +#ifdef __SMP__ + void UnbindInterrupts(); +#endif + TInt ProcessStreamReadRequest(TBapBuf* aBuf,TRequestStatus* aStatus); + + TInt MarkTraceActive(TInt samplerIdToActivate); + TInt MarkTraceInactive(TInt samplerIdToDisable); + TInt OutputSettingsForTrace(TInt samplerId,TInt settings); + TInt AdditionalTraceSettings(TInt samplerId,TInt settings); + TInt AdditionalTraceSettings2(TInt samplerId,TInt settings); + TInt SetSamplingPeriod(TInt /*samplerId*/,TInt settings); +private: + // create the driver in EKA-2 version + TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); + + // receive commands and control in EKA-2 version + void HandleMsg(TMessageBase* aMsg); +private: + // timer mechanism in EKA-2 version + NTimer iTimer; + TDfc iNewDfc; + TInt iCount; + TInt iLastPcVal; + TInt iPeriod; + + // sync sample number property for synchronizing other samplers + RPropertyRef iSampleStartTimeProp; + TInt iSampleStartTime; + + DProfilerGppSampler<10000> gppSampler; +#ifdef __SMP__ + DProfilerGppSampler<10000> gppSampler2; + DProfilerGppSampler<10000> gppSampler3; + DProfilerGppSampler<10000> gppSampler4; +#endif + DProfilerGfcSampler<10000> gfcSampler; + DProfilerIttSampler<10000> ittSampler; + DProfilerMemSampler<40000> memSampler; + DProfilerPriSampler<10000> priSampler; +#ifdef __SMP__ +// DProfilerPriSampler<10000> priSampler2; +// DProfilerPriSampler<10000> priSampler3; +// DProfilerPriSampler<10000> priSampler4; +#endif + +#ifndef __SMP__ + static const TInt KSamplerAmount = 5; +#else + static const TInt KSamplerAmount = 8; +#endif + DProfilerSamplerBase* iSamplers[KSamplerAmount]; + TInt iMaxCpus; + TUint32 iStartTime; + +#ifdef SEPARATE_DFC_QUEUE + TDynamicDfcQue* iDfcQ; +#endif +}; + +/* + * + * + * Class DGeneralsProfilerFactory implementation + * + * + */ + +DECLARE_STANDARD_LDD() + { + return new DGeneralsProfilerFactory(); + } + +TInt DGeneralsProfilerFactory::Create(DLogicalChannelBase*& aChannel) + { + aChannel = new DGeneralsDriver; + return aChannel?KErrNone:KErrNoMemory; + } + + +DGeneralsProfilerFactory::DGeneralsProfilerFactory() + { + // major, minor, and build version number + iVersion=TVersion(1,0,1); + } + +DGeneralsProfilerFactory::~DGeneralsProfilerFactory() + { +// if (gDfcQ) +// { +// gDfcQ->Destroy(); +// } + } + +TInt DGeneralsProfilerFactory::Install() + { + return(SetName(&KPluginSamplerName)); + } + +void DGeneralsProfilerFactory::GetCaps(TDes8& aDes) const + { + TCapsSamplerV01 b; + + b.iVersion=TVersion(1,0,1); + + aDes.FillZ(aDes.MaxLength()); + aDes.Copy((TUint8*)&b,Min(aDes.MaxLength(),sizeof(b))); + } + +/* + * + * + * Class DGeneralsDriver implementation + * + * + */ + +DGeneralsDriver::DGeneralsDriver() : + iTimer(NewDoProfilerProfile,this), + iNewDfc(NewDoDfc,this,NULL,7), +#ifdef __SMP__ + gppSampler(0), + gppSampler2(1), + gppSampler3(2), + gppSampler4(3), +#endif + gfcSampler(gppSampler.GetExportData()), + ittSampler(gppSampler.GetExportData()), + memSampler(gppSampler.GetExportData(), PROFILER_MEM_SAMPLER_ID), + priSampler(gppSampler.GetExportData(), PROFILER_PRI_SAMPLER_ID) +#ifdef __SMP__ +// ,priSampler2(gppSampler.GetExportData(), PROFILER_PRI_SAMPLER_ID), +// priSampler3(gppSampler.GetExportData(), PROFILER_PRI_SAMPLER_ID), +// priSampler4(gppSampler.GetExportData(), PROFILER_PRI_SAMPLER_ID) +#endif + { + LOGSTRING("DGeneralsDriver::DGeneralsDriver()"); + + iState = EStopped; + iEndRequestStatus = 0; + doingDfc = 0; + sampleRunning = 0; + iSyncOffset = 0; + iStartTime = 0; + InitialiseSamplerList(); + } + +/* + * + * This method has to be changed for each new sampler + * + */ +void DGeneralsDriver::InitialiseSamplerList() + { + // initialize all samplers to zero + for(TInt i(0);i<KSamplerAmount;i++) + { + iSamplers[i] = 0; + } + + TInt i(0); + iSamplers[i] = &gppSampler;i++; +#ifdef __SMP__ + iSamplers[i] = &gppSampler2;i++; + iSamplers[i] = &gppSampler3;i++; + iSamplers[i] = &gppSampler4;i++; +#endif + iSamplers[i] = &gfcSampler;i++; + iSamplers[i] = &ittSampler;i++; + iSamplers[i] = &memSampler;i++; + iSamplers[i] = &priSampler;i++; + +#ifdef __SMP__ + // get the number of cpus + iMaxCpus = NKern::NumberOfCpus(); +#else + iMaxCpus = 0; +#endif + + // initialize synchronizing property + LOGSTRING("DGeneralsDriver::InitialiseSamplerList() - initializing property"); + TInt r(iSampleStartTimeProp.Attach(KGppPropertyCat, EGppPropertySyncSampleNumber)); + if (r!=KErrNone) + { + LOGSTRING2("DGeneralsDriver::InitialiseSamplerList() - error in attaching counter property, error %d", r); + } + LOGSTRING("DGeneralsDriver::InitialiseSamplerList() - defining properties"); + r = iSampleStartTimeProp.Define(RProperty::EInt, KAllowAllPolicy, KDenyAllPolicy, 0, NULL); + if (r!=KErrNone) + { + LOGSTRING2("DGeneralsDriver::InitialiseSamplerList() - error in defining counter property, error %d", r); + } + } + + +DProfilerSamplerBase* DGeneralsDriver::GetSamplerForId(TInt samplerIdToGet) + { + for(TInt i(0);i<KSamplerAmount;i++) + { + if(iSamplers[i]->iSamplerId == samplerIdToGet) + { + return iSamplers[i]; + } + } + return (DProfilerSamplerBase*)0; + } + +TInt DGeneralsDriver::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer) + { + TUint8 err(KErrNone); + + if (!Kern::QueryVersionSupported(TVersion(1,0,1),aVer)) + return KErrNotSupported; + + // just for testing +#ifndef __SMP__ + LOGTEXT("Initializing the stack pointer"); + stackTop=(TUint32*)IntStackPtr(); + LOGSTRING2("Got stack pointer 0x%x",(TUint32)stackTop); +#endif + + iClient = &Kern::CurrentThread(); + err = iClient->Open(); + + DProcess* clientProcess(iClient->iOwningProcess); + if (clientProcess) + { + //Require Power Management and All Files to use this driver + // Not ideal, but better than nothing + if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by GeneralsDriver.ldd"))) + return KErrPermissionDenied; + if(!Kern::CurrentThreadHasCapability(ECapabilityAllFiles,__PLATSEC_DIAGNOSTIC_STRING("Checked by GeneralsDriver.ldd"))) + return KErrPermissionDenied; + + SSecurityInfo secureInfo = clientProcess->iS; + if (secureInfo.iSecureId != KProfilerExeSecurUid) + { + return KErrPermissionDenied; + } + } + + // initiate sample stream ready for collecting the trace data + iSampleStream.InsertCurrentClient(iClient); + + iTimer.Cancel(); + iNewDfc.Cancel(); + + Kern::SetThreadPriority(24); + +#ifdef SEPARATE_DFC_QUEUE + err = Kern::DynamicDfcQCreate(iDfcQ, KGeneralsDriverThreadPriority, TBuf8<32>( KGeneralsDriverThread )); + if (KErrNone == err) + { + SetDfcQ(iDfcQ); + iNewDfc.SetDfcQ(iDfcQ); + iMsgQ.Receive(); + return err; + } +#else + SetDfcQ(Kern::DfcQue0()); + iNewDfc.SetDfcQ(iDfcQ); + iMsgQ.Receive(); +#endif + return err; + } + +DGeneralsDriver::~DGeneralsDriver() + { + if (iState!=EStopped) + iTimer.Cancel(); + iNewDfc.Cancel(); + +#ifdef SEPARATE_DFC_QUEUE + if(iDfcQ) + iDfcQ->Destroy(); +#endif + + iSampleStartTimeProp.Close(); + Kern::SafeClose((DObject*&)iClient,NULL); + } + + +TInt DGeneralsDriver::GetSampleTime(TUint32* time) + { + LOGSTRING("DGeneralsDriver::GetSampleTime - entry"); + + Kern::ThreadRawWrite( iClient,(TAny*)time, + (TAny*)&gppSampler.GetExportData()->sampleNumber, + 4, iClient); + + LOGSTRING("DGeneralsDriver::GetSampleTime - exit"); + + return KErrNone; + } + + +TInt DGeneralsDriver::GetSamplerVersion(TDes* aDes) + { + LOGSTRING2("DGeneralsDriver::GetSamplerVersion - 0x%x",aDes); + + TBuf8<16> aBuf; + aBuf.Append(PROFILER_SAMPLER_VERSION); + Kern::ThreadDesWrite(iClient,aDes,aBuf,0,KChunkShiftBy0,iClient); + LOGSTRING("DGeneralsDriver::GetSamplerVersion - written client descriptor"); + return KErrNone; + } + +TInt DGeneralsDriver::NewStart(TInt aDelay) + { + LOGSTRING("DGeneralsDriver::NewStart"); + iEndRequestStatus = 0; + + aDelay = Min(KMaxDelay, Max(KMinDelay, aDelay)); + + // always use this rate + iPeriod = aDelay; + +#ifdef __SMP__ + /* + * Bind and enable the sampling interupts associated with each core. + */ + TInt err(0); + + TUint32 flags = NKern::EIrqBind_Count; + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase - 32=%d", KIntProfilerBase -32 ); + err = NKern::InterruptBind( KIntProfilerBase - 32 , DGeneralsDriver::Sample, this, flags, 0); + if(err < 0) + Kern::Printf(" InterruptBind KIntProfilerBase - 32 ret = %d", err ); + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 1 - 32=%d", KIntProfilerBase + 1-32 ); + err = NKern::InterruptBind( KIntProfilerBase + 1 - 32 , DGeneralsDriver::Sample, this, flags, 0); + if(err < 0) + Kern::Printf(" InterruptBind KIntProfilerBase + 1 - 32 ret = %d", err ); + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 2 - 32=%d", KIntProfilerBase + 2 - 32 ); + err = NKern::InterruptBind(KIntProfilerBase + 2 - 32 , DGeneralsDriver::Sample, this, flags, 0); + if(err < 0) + Kern::Printf(" InterruptBind KIntProfilerBase + 2 - 32 ret = %d", err ); + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 3 - 32=%d", KIntProfilerBase + 3 - 32 ); + err = NKern::InterruptBind(KIntProfilerBase + 3 - 32 , DGeneralsDriver::Sample, this, flags, 0); + if(err < 0) + Kern::Printf(" InterruptBind KIntProfilerBase + 3 - 32 ret = %d", err ); + + + err = NKern::InterruptEnable(KIntProfilerBase - 32); + if(err < 0) + Kern::Printf(" InterruptEnable KIntProfilerBase - 32 ret = %d", err ); + + err = NKern::InterruptEnable(KIntProfilerBase + 1 - 32); + if(err < 0) + Kern::Printf(" InterruptEnable KIntProfilerBase + 1 - 32 ret = %d", err ); + + err = NKern::InterruptEnable(KIntProfilerBase + 2 - 32); + if(err < 0) + Kern::Printf(" InterruptEnable KIntProfilerBase + 2 - 32 ret = %d", err ); + + err = NKern::InterruptEnable(KIntProfilerBase + 3 - 32); + if(err < 0) + Kern::Printf(" InterruptEnable KIntProfilerBase + 3 - 32 ret = %d", err ); + +#endif + + iTimer.OneShot(aDelay); + + iState = ERunning; + + return KErrNone; + } + +/* + * This function is run in each interrupt + */ +// EKA-2 implementation of the sampler method + +void DGeneralsDriver::NewDoProfilerProfile(TAny* aPtr) + { + LOGSTRING("DGeneralsDriver::NewDoProfilerProfile - entry"); + +#ifdef __SMP__ + TInt currCpu(NKern::CurrentCpu()); +#endif + TInt8 postSampleNeeded(0); + DGeneralsDriver& d=*(DGeneralsDriver*)aPtr; + + if (d.iState == ERunning && d.sampleRunning == 0) + { + // start timer again + d.iTimer.Again(d.iPeriod); + d.sampleRunning++; + +#ifdef __SMP__ + // print out the sample tick + if(d.gppSampler.GetExportData()->sampleNumber% 1000 == 0) + { + Kern::Printf(("PIPROF SAMPLE TICK, #%d"), d.gppSampler.GetExportData()->sampleNumber); + } + // call the actual CPU sampling function for CPU 0 (in NaviEngine), later may be on any of the CPUs + Sample(aPtr); + + // post-sampling for NTimer interrupted CPU + postSampleNeeded += d.iSamplers[currCpu]->PostSampleNeeded(); + + /* + This is the master sampler from the watchdog timer, so + send interrupts to the other CPUs + */ + TScheduler *theSched = TScheduler::Ptr(); + GicDistributor* gicDist = (GicDistributor* )theSched->i_GicDistAddr; + + for( TInt nCpu(0); nCpu < d.iMaxCpus; nCpu++ ) + { + if( nCpu != currCpu ) + { + gicDist->iSoftIrq = ( 0x10000 << nCpu ) | (KIntProfilerBase + nCpu); + } + // post-sampling for CPUs with specifically generated interrupts + postSampleNeeded += d.iSamplers[nCpu]->PostSampleNeeded(); + } + arm_dsb(); +#endif + // then sample the rest of non-cpu samplers + for(TInt i(d.iMaxCpus);i<KSamplerAmount;i++) + { + if(d.iSamplers[i]->iEnabled) + { + d.iSamplers[i]->Sample(); + postSampleNeeded += d.iSamplers[i]->PostSampleNeeded(); + } + } + + if(postSampleNeeded > 0 && d.doingDfc == 0) + { + d.doingDfc++; + d.iNewDfc.Add(); + + d.sampleRunning--; + return; + } + d.sampleRunning--; + } + else if (d.iState == EStopping && d.sampleRunning == 0) + { + // add a dfc for this final time + d.iNewDfc.Add(); + Kern::Printf("DGeneralsDriver::Sample - sampling added to dfc queue"); + } + else + { + // the previous sample has not finished, + Kern::Printf("DGeneralsDriver::NewDoProfilerProfile - Profiler Sampler Error - interrupted before finished sampling!!"); + } + LOGSTRING("DGeneralsDriver::NewDoProfilerProfile - exit"); + } + + + +void DGeneralsDriver::Sample(TAny* aPtr) + { + LOGSTRING("DGeneralsDriver::Sample - entry"); + +#ifdef __SMP__ + DGeneralsDriver& d=*(DGeneralsDriver*)aPtr; + +// TInt currCpu(NKern::CurrentCpu()); + + // sample the current cpu load +// if(d.iSamplers[currCpu]->iEnabled) +// { + d.iSamplers[NKern::CurrentCpu()]->Sample(); +// postSampleNeeded += d.iSamplers[currCpu]->PostSampleNeeded(); +// } +#endif + LOGSTRING("DGeneralsDriver::Sample - exit"); + } +/* + * This function is run when any of the samplers + * requires post sampling + */ +void DGeneralsDriver::NewDoDfc(TAny* pointer) + { + DGeneralsDriver& d(*((DGeneralsDriver*)pointer)); + + if(d.iState == ERunning) + { + // for all enabled samplers, perform + // post sample if needed + for(TInt i(0);i<KSamplerAmount;i++) + { + if(d.iSamplers[i]->iEnabled) + { + if(d.iSamplers[i]->PostSampleNeeded()) + { + d.iSamplers[i]->PostSample(); + } + } + } + d.doingDfc--; + } + + else if(d.iState == EStopping) + { + // for all enabled samplers, + // perform end sampling + TBool releaseBuffer(false); + for(TInt i(0);i<KSamplerAmount;i++) + { + if(d.iSamplers[i]->iEnabled) + { + LOGSTRING("DGeneralsDriver::NewDoDfc() - ending"); + // perform end sampling for all samplers + // stream mode samplers may be pending, if they + // are still waiting for another client buffer + if(d.iSamplers[i]->EndSampling() == KErrNotReady) + { + LOGSTRING("DGeneralsDriver::NewDoDfc() - stream data pending"); + releaseBuffer = true; + } + else + { + LOGSTRING("DGeneralsDriver::NewDoDfc() - no data pending"); + releaseBuffer = true; + } + } + } + + // At the end, once all the samplers are gone through, the buffer should be released + if (true == releaseBuffer) + { + LOGSTRING("DGeneralsDriver::NewDoDfc() - release the buffer"); + d.iSampleStream.ReleaseIfPending(); + } + + d.iState = EStopped; + if(d.iEndRequestStatus != 0 && d.iClient != 0) + { + // sampling has ended + Kern::RequestComplete(d.iClient,d.iEndRequestStatus,KErrNone); + } + } + } + + +/* + * All controls are handled here + */ + +void DGeneralsDriver::HandleMsg(TMessageBase* aMsg) + { + TInt r(KErrNone); + TThreadMessage& m(*(TThreadMessage*)aMsg); + + LOGSTRING5("DGeneralsDriver::HandleMsg 0x%x 0x%x 0x%x 0x%x",m.Int0(),m.Int1(),m.Int2(),m.Int3()); + + if(m.iValue == (TInt)ECloseMsg) + { + LOGSTRING("DGeneralsDriver::HandleMsg - received close message"); + iTimer.Cancel(); + iNewDfc.Cancel(); + + m.Complete(KErrNone,EFalse); + iMsgQ.CompleteAll(KErrServerTerminated); + LOGSTRING("DGeneralsDriver::HandleMsg - cleaned up the driver!"); + return; + } + + if (m.Client()!=iClient) + { + LOGSTRING("DGeneralsDriver::HandleMsg - ERROR, wrong client"); + m.PanicClient(_L("GENERALSSAMPLER"),EAccessDenied); + return; + } + + TInt id(m.iValue); + switch(id) + { + //Controls are handled here + case RPluginSampler::EMarkTraceActive: + LOGSTRING("DGeneralsDriver::HandleMsg - EMarkTraceActive"); + r = MarkTraceActive((TInt)m.Int0()); + break; + + case RPluginSampler::EOutputSettingsForTrace: + LOGSTRING("DGeneralsDriver::HandleMsg - EOutputSettingsForTrace"); + r = OutputSettingsForTrace((TInt)m.Int0(),(TInt)m.Int1()); + break; + + case RPluginSampler::EAdditionalTraceSettings: + LOGSTRING("DGeneralsDriver::HandleMsg - EAdditionalTraceSettings"); + r = AdditionalTraceSettings((TInt)m.Int0(),(TInt)m.Int1()); + break; + + case RPluginSampler::EAdditionalTraceSettings2: + LOGSTRING("DGeneralsDriver::HandleMsg - EAdditionalTraceSettings2"); + r = AdditionalTraceSettings2((TInt)m.Int0(),(TInt)m.Int1()); + break; + + case RPluginSampler::ESetSamplingPeriod: + LOGSTRING2("DGeneralsDriver::HandleMsg - ESetSamplingPeriod %d", (TInt)m.Int1()); + r = SetSamplingPeriod((TInt)m.Int0(),(TInt)m.Int1()); + break; + + case RPluginSampler::EMarkTraceInactive: + LOGSTRING("DGeneralsDriver::HandleMsg - EMarkTraceInactive"); + r = MarkTraceInactive((TInt)m.Int0()); + break; + + case RPluginSampler::ESample: + LOGSTRING("DGeneralsDriver::HandleMsg - ESample"); + //r = Sample(); // hack. Original implementation of sample just returned 0 + r = 0; + break; + + case RPluginSampler::EStartSampling: + LOGSTRING("DGeneralsDriver::HandleMsg - EStartSampling"); + r = StartSampling(); + break; + + case RPluginSampler::EGetSampleTime: + LOGSTRING("DGeneralsDriver::HandleMsg - EGetSampleTime"); + r = GetSampleTime(reinterpret_cast<TUint32*>(m.Ptr0())); + break; + + case RPluginSampler::EGetSamplerVersion: + LOGSTRING("DGeneralsDriver::HandleMsg - EGetSamplerVersion"); + r = GetSamplerVersion(reinterpret_cast<TDes*>(m.Ptr0())); + break; + + case RPluginSampler::ECancelStreamRead: + LOGSTRING("DGeneralsDriver::HandleMsg - ECancelStreamRead"); + iStreamReadCancelStatus = reinterpret_cast<TRequestStatus*>(m.Ptr0()); + r = ProcessStreamReadCancel(); + break; + + + // Requests are handled here + + case ~RPluginSampler::EStopAndWaitForEnd: + LOGSTRING("DGeneralsDriver::HandleMsg - EStopAndWaitForEnd"); + iEndRequestStatus = reinterpret_cast<TRequestStatus*>(m.Ptr0()); + r = StopSampling(); +#ifdef __SMP__ + UnbindInterrupts(); +#endif + break; + + case ~RPluginSampler::ERequestFillThisStreamBuffer: + LOGSTRING("DGeneralsDriver::HandleMsg - ERequestFillThisStreamBuffer"); + r = ProcessStreamReadRequest( reinterpret_cast<TBapBuf*>(m.Ptr1()), + reinterpret_cast<TRequestStatus*>(m.Ptr0())); + break; + + default: + LOGSTRING2("DGeneralsDriver::HandleMsg - ERROR, unknown command %d",id); + r = KErrNotSupported; + break; + } + + LOGSTRING("DGeneralsDriver::HandleMsg - Completed"); + m.Complete(r,ETrue); + } + +#ifdef __SMP__ +inline void DGeneralsDriver::UnbindInterrupts() + { + TInt err(0); + + // disable interrupts when sampling stops, enabled again on start + err = NKern::InterruptDisable(KIntProfilerBase - 32); + if(err < 0) + Kern::Printf(" InterruptDisable KIntProfilerBase - 32 ret = %d", err ); + + err = NKern::InterruptDisable(KIntProfilerBase + 1 - 32); + if(err < 0) + Kern::Printf(" InterruptDisable KIntProfilerBase + 1 - 32 ret = %d", err ); + + err = NKern::InterruptDisable(KIntProfilerBase + 2 - 32); + if(err < 0) + Kern::Printf(" InterruptDisable KIntProfilerBase + 2 - 32 ret = %d", err ); + + err = NKern::InterruptDisable(KIntProfilerBase + 3 - 32); + if(err < 0) + Kern::Printf(" InterruptDisable KIntProfilerBase + 3 - 32 ret = %d", err ); + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase - 32=%d", KIntProfilerBase -32 ); + err = NKern::InterruptUnbind( KIntProfilerBase - 32); + if(err < 0) + Kern::Printf(" InterruptUnbind KIntProfilerBase - 32 ret = %d", err ); + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 1 - 32=%d", KIntProfilerBase + 1-32 ); + err = NKern::InterruptUnbind( KIntProfilerBase + 1 - 32); + if(err < 0) + Kern::Printf(" InterruptUnbind KIntProfilerBase + 1 - 32 ret = %d", err ); + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 2 - 32=%d", KIntProfilerBase + 2 - 32 ); + err = NKern::InterruptUnbind(KIntProfilerBase + 2 - 32); + if(err < 0) + Kern::Printf(" InterruptUnbind KIntProfilerBase + 2 - 32 ret = %d", err ); + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 3 - 32=%d", KIntProfilerBase + 3 - 32 ); + err = NKern::InterruptUnbind(KIntProfilerBase + 3 - 32); + if(err < 0) + Kern::Printf(" InterruptUnbind KIntProfilerBase + 3 - 32 ret = %d", err ); + + } +#endif + +inline TInt DGeneralsDriver::ProcessStreamReadRequest(TBapBuf* aBuf,TRequestStatus* aStatus) + { + LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest - entry"); + + // a new sample buffer has been received from the client + iSampleStream.AddSampleBuffer(aBuf,aStatus); + + // check if we are waiting for the last data to be written to the client + if(iState == EStopped) + { + LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest state = EStopped"); + + // sampling has stopped and stream read cancel is pending + // try to perform the end sampling procedure again + TBool releaseBuffer(false); + for(TInt i(0);i<KSamplerAmount;i++) + { + // only for all enabled samplers that have stream output mode + if(iSamplers[i]->iEnabled /*&& samplers[i]->outputMode == 2*/) + { + //TInt pending = 0; + // stream mode samplers may be pending, if they + // are still waiting for another client buffer, + // in that case, the request should be completed already + if(iSamplers[i]->EndSampling() == KErrNotReady) + { + LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest - still data pending"); + releaseBuffer = true; + } + else + { + LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest - no data pending"); + releaseBuffer = true; + } + } + } + // At the end, once all the samplers are gone through, the buffer should be released + if (true == releaseBuffer) + { + LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest - all data copied, release the buffer"); + iSampleStream.ReleaseIfPending(); + } + } + LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest - exit"); + + return KErrNone; + } + + +/* + * Mark traces active or inactive, this can be done + * only if sampling is not running + */ + +inline TInt DGeneralsDriver::MarkTraceActive(TInt samplerIdToActivate) + { + LOGSTRING2("DGeneralsDriver::MarkTraceActive %d",samplerIdToActivate); + + TInt cpus(0); +#ifdef __SMP__ + cpus = NKern::NumberOfCpus(); + if( samplerIdToActivate == PROFILER_GPP_SAMPLER_ID ) + { + for(TInt cpu(0);cpu<cpus;cpu++) + { + Kern::Printf("DGeneralsDriver::MarkTraceActive - activating CPU %d",cpu); + iSamplers[cpu]->SetEnabledFlag(true); + } + return KErrNone; + } +#endif + for(TInt i(cpus);i<KSamplerAmount;i++) + { + if(iSamplers[i]->iSamplerId == samplerIdToActivate) + { + iSamplers[i]->SetEnabledFlag(true); + return KErrNone; + } + } + + LOGSTRING2("DGeneralsDriver::MarkTraceActive - %d not supported",samplerIdToActivate); + return KErrNotSupported; + } + +inline TInt DGeneralsDriver::MarkTraceInactive(TInt samplerIdToDisable) + { + LOGSTRING2("DGeneralsDriver::MarkTraceInactive %d",samplerIdToDisable); + + TInt cpus(0); +#ifdef __SMP__ + cpus = NKern::NumberOfCpus(); + if( samplerIdToDisable == PROFILER_GPP_SAMPLER_ID ) + { + for(TInt cpu(0);cpu<cpus;cpu++) + { + iSamplers[cpu]->SetEnabledFlag(false); + } + return KErrNone; + } +#endif + for(TInt i(cpus);i<KSamplerAmount;i++) + { + if(iSamplers[i]->iSamplerId == samplerIdToDisable) + { + iSamplers[i]->SetEnabledFlag(false); + return KErrNone; + } + } + + LOGSTRING2("DGeneralsDriver::MarkTraceInactive - %d not supported",samplerIdToDisable); + return KErrNotSupported; + } + +/* + * Set output settings for a trace + */ + +inline TInt DGeneralsDriver::OutputSettingsForTrace(TInt samplerId,TInt settings) + { + LOGSTRING3("DGeneralsDriver::OutputSettingsForTrace id:%d set:%d",samplerId,settings); + + TInt cpus(0); +#ifdef __SMP__ + cpus = NKern::NumberOfCpus(); + if( samplerId == PROFILER_GPP_SAMPLER_ID ) + { + for(TInt cpu(0);cpu<cpus;cpu++) + { + iSamplers[cpu]->SetOutputCombination(settings); + } + return KErrNone; + } +#endif + for(TInt i(cpus);i<KSamplerAmount;i++) + { + if(iSamplers[i]->iSamplerId == samplerId) + { + iSamplers[i]->SetOutputCombination(settings); + return KErrNone; + } + } + + return KErrNotSupported; + } + +/* + * Set additional settings for a trace + */ + +inline TInt DGeneralsDriver::AdditionalTraceSettings(TInt samplerId,TInt settings) + { + LOGSTRING3("DGeneralsDriver::SetAdditionalTraceSettings id:%d set:%d",samplerId,settings); + + TInt cpus(0); +#ifdef __SMP__ + cpus = NKern::NumberOfCpus(); + if( samplerId == PROFILER_GPP_SAMPLER_ID ) + { + for(TInt cpu(0);cpu<cpus;cpu++) + { + iSamplers[cpu]->SetAdditionalSettings(settings); + } + return KErrNone; + } +#endif + for(TInt i(cpus);i<KSamplerAmount;i++) + { + if(iSamplers[i]->iSamplerId == samplerId) + { + iSamplers[i]->SetAdditionalSettings(settings); + return KErrNone; + } + } + + return KErrNotSupported; + } + +inline TInt DGeneralsDriver::AdditionalTraceSettings2(TInt samplerId,TInt settings) + { + LOGSTRING3("DGeneralsDriver::SetAdditionalTraceSettings id:%d set:%d",samplerId,settings); + + TInt cpus(0); +#ifdef __SMP__ + cpus = NKern::NumberOfCpus(); + if( samplerId == PROFILER_GPP_SAMPLER_ID ) + { + for(TInt cpu(0);cpu<cpus;cpu++) + { + iSamplers[cpu]->SetAdditionalSettings2(settings); + } + return KErrNone; + } +#endif + for(TInt i(cpus);i<KSamplerAmount;i++) + { + if(iSamplers[i]->iSamplerId == samplerId) + { + iSamplers[i]->SetAdditionalSettings2(settings); + return KErrNone; + } + } + + return KErrNotSupported; + } + +inline TInt DGeneralsDriver::SetSamplingPeriod(TInt samplerId,TInt settings) + { + LOGSTRING2("DGeneralsDriver::SetSamplingPeriod - set:%d",settings); + + TInt cpus(0); +#ifdef __SMP__ + cpus = NKern::NumberOfCpus(); + if( samplerId == PROFILER_GPP_SAMPLER_ID ) + { + for(TInt cpu(0);cpu<cpus;cpu++) + { + iSamplers[cpu]->SetSamplingPeriod(settings); + } + return KErrNone; + } +#endif + for(TInt i(cpus);i<KSamplerAmount;i++) + { + if(iSamplers[i]->iSamplerId == samplerId) + { + iSamplers[i]->SetSamplingPeriod(settings); + return KErrNone; + } + } + + return KErrNotSupported; + } + +/* + * Mark traces active or inactive, this can be done + * only if sampling is not running + */ + +TInt DGeneralsDriver::StartSampling() + { + LOGSTRING("DGeneralsDriver::StartSampling"); + + if(iState == EStopped) + { + // reset iSampleStartTimeProp property value + iSampleStartTime = NKern::TickCount(); // get the system tick value for sync purposes +#ifdef __SMP__ + iStartTime = (iSampleStartTime & 0xfffffff0); +#endif + TInt r(iSampleStartTimeProp.Set(iSampleStartTime)); + + Kern::Printf(("PIPROF SAMPLE TICK, #0")); // for remote profiling with Profiler Activator + + // reset all enabled samplers + for(TInt i(0);i<KSamplerAmount;i++) + { + if(iSamplers[i]->iEnabled) + { + // reset with stream option +#ifndef __SMP__ + Kern::Printf(("DGeneralsDriver::StartSampling - stream reset for generals driver, sync offset %d"), 0); + iSamplers[i]->Reset(&iSampleStream, 0); +#else + Kern::Printf(("DGeneralsDriver::StartSampling - stream reset for generals driver, start time %d"), iStartTime); + iSamplers[i]->Reset(&iSampleStream, iStartTime); +#endif + } + } + + NewStart(gppSampler.GetPeriod()); + return KErrNone; + } + else + { + return KErrGeneral; + } + } + +/* + * Mark traces active or inactive, this can be done + * only if sampling is not running + */ + +TInt DGeneralsDriver::StopSampling() + { + LOGSTRING("DGeneralsDriver::StopSampling"); + + if(iState == ERunning) + { + this->iState = EStopping; + // reset all enabled samplers + for(TInt i(0);i<KSamplerAmount;i++) + { + // do the reset only for memory sampler + if(iSamplers[i]->iEnabled && iSamplers[i]->iSamplerId == 4) + { + // reset with stream option + LOGTEXT(("DGeneralsDriver::StopSampling - stream reset for samplers")); + iSamplers[i]->Reset(&iSampleStream, 999999); + } + } + + return KErrNone; + } + else + { + return KErrGeneral; + } + } + + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/src/GeneralsPlugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/src/GeneralsPlugin.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,577 @@ +/* +* 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: +* +*/ + + +#include "GeneralsPlugin.h" +//#include <piprofiler/EngineUIDs.h> +#include <piprofiler/ProfilerTraces.h> + +const TInt KMaxSamplerAmount = 20; + +// LITERALS +_LIT8(KSamplingPeriod, "sampling_period_ms"); + +// CONSTANTS +// GeneralsPlugin UID: +const TUid KSamplerGeneralsPluginUid = { 0x2001E5B2 }; + +// Gpp sub-sampler UID: +const TUid KSamplerGppPluginUid = { 0x2001E570 }; + +// Gfc sub-sampler UID: +const TUid KSamplerGfcPluginUid = { 0x2001E571 }; + +// Itt sub-sampler UID: +const TUid KSamplerIttPluginUid = { 0x2001E572 }; + +// Mem sub-sampler UID: +const TUid KSamplerMemPluginUid = { 0x2001E573 }; + +// Pri sub-sampler UID: +const TUid KSamplerPriPluginUid = { 0x2001E574 }; + +/* + * + * class CGeneralsPlugin implementation + * + */ + +CGeneralsPlugin* CGeneralsPlugin::NewL(const TUid aImplementationUid, TAny* /*aInitParams*/) + { + LOGTEXT(_L("CGeneralsPlugin::NewL() - entry")); + CGeneralsPlugin* self = new (ELeave) CGeneralsPlugin(); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + LOGTEXT(_L("CGeneralsPlugin::NewL() - exit")); + return self; + } + +CGeneralsPlugin::CGeneralsPlugin() : + iVersionDescriptor(&(this->iVersion[1]),0,19) + { + iSamplerType = PROFILER_KERNEL_MODE_SAMPLER; + iSamplerId = PROFILER_GENERALS_SAMPLER_ID; + iBufferHandler = NULL; + iEnabled = EFalse; + LOGTEXT(_L("CGeneralsPlugin::CGeneralsPlugin() - constructor")); + } + +void CGeneralsPlugin::ConstructL() + { + LOGTEXT(_L("CGeneralsPlugin::ConstructL() - entry")); + + // create attribute array + iSamplerAttributes = new(ELeave) CArrayFixFlat<TSamplerAttributes>(KSubSamplerCount); + + TInt err = InitiateSamplerL(); + if( err != KErrNone ) + { + LOGTEXT(_L("CGeneralsPlugin::ConstructL - LEAVING, failed to load open sampler device")); + User::Leave(err); + } + + // initiate sampler attributes, i.e. settings for modification + InitiateSamplerAttributesL(); + + LOGTEXT(_L("CGeneralsPlugin::ConstructL() - exit")); + } + + +CGeneralsPlugin::~CGeneralsPlugin() + { + // clean all the members + CleanSampler(); // clean the created sampler + } + +TInt CGeneralsPlugin::InitiateSamplerL() + { + RThread me; + + LOGTEXT(_L("CGeneralsPlugin::InitiateSamplerL - #1")); + + me.SetPriority(EPriorityRealTime); + + LOGTEXT(_L("CGeneralsPlugin::InitiateSamplerL - #2")); + + // create + User::FreeLogicalDevice(KPluginSamplerName); + TInt err(KErrGeneral); + + LOGTEXT(_L("CGeneralsPlugin::InitiateSamplerL - #3")); + + err = User::LoadLogicalDevice(KPluginSamplerName); + if(err != KErrNone) + { + User::Leave(err); + } + + LOGTEXT(_L("CGeneralsPlugin::InitiateSamplerL - #4")); + + err = KErrGeneral; + + err = iGeneralsSampler.Open(); + if(err != KErrNone) + { + LOGSTRING2("CGeneralsPlugin::InitiateSamplerL - Could not open sampler device - waiting and trying again: %d", err); + User::Leave(err); + } + + LOGTEXT(_L("CGeneralsPlugin::InitiateSamplerL - #5")); + + return err; + } + +/* + * + * Default sampler attributes + * + */ +void CGeneralsPlugin::InitiateSamplerAttributesL() + { + + // + for(TInt i(0);i<KMaxSamplerAmount;i++) + { + switch(i) + { +// Usage: +// TSamplerAttributes(TUint32 aUid, +// const TDesC8& aShortName, +// const TDesC& aName, +// const TDesC& aDescription, +// TInt aSampleRate, +// TBool aEnabled, +// TBool aHidden, +// TUint32 aItemCount); + case PROFILER_GPP_SAMPLER_ID: + { + TSamplerAttributes attr(KSamplerGppPluginUid.iUid, + KGPPShortName(), + KGPPLongName(), + KGPPDescription(), + 1, + ETrue, + ETrue, + 0); + iSamplerAttributes->AppendL(attr); + break; + } + case PROFILER_GFC_SAMPLER_ID: + { + TSamplerAttributes attr2(KSamplerGfcPluginUid.iUid, + KGFCShortName(), + KGFCLongName(), + KGFCDescription(), + -1, + EFalse, + EFalse, + 0); + this->iSamplerAttributes->AppendL(attr2); + break; + } + case PROFILER_ITT_SAMPLER_ID: + { + TSamplerAttributes attr3(KSamplerIttPluginUid.iUid, + KITTShortName(), + KITTLongName(), + KITTDescription(), + -1, + ETrue, + EFalse, + 0); + this->iSamplerAttributes->AppendL(attr3); + break; + } + case PROFILER_MEM_SAMPLER_ID: + { + TSamplerAttributes attr4(KSamplerMemPluginUid.iUid, + KMEMShortName(), + KMEMLongName(), + KMEMDescription(), + -1, + EFalse, + EFalse, + 0); +// // select event or sampling based +// attr4.iSettingItem1.iSettingDescription.Copy(KMEM1Desc); +// attr4.iSettingItem1.iType = TSettingItem::ESettingItemTypeBool; +// attr4.iSettingItem1.iValue.AppendNum(0, EDecimal); +// attr4.iSettingItem1.iUIText.Copy(KMEM1UIText); +// attr4.iSettingItem1.iSettingText.Copy(KMemCounter1); + + this->iSamplerAttributes->AppendL(attr4); + break; + } + case PROFILER_PRI_SAMPLER_ID: + { + TSamplerAttributes attr5(KSamplerPriPluginUid.iUid, + KPRIShortName(), + KPRILongName(), + KPRIDescription(), + 3000, + EFalse, + EFalse, + 0); + this->iSamplerAttributes->AppendL(attr5); + break; + } + } + } + } + +TInt CGeneralsPlugin::CleanSampler() + { + LOGTEXT(_L("CGeneralsPlugin::CleanSampler() - deleting buffer handler")); + // release the buffer handler + if(iBufferHandler) + { + iBufferHandler->Cancel(); + delete iBufferHandler; + iBufferHandler = NULL; + } + + LOGTEXT(_L("CGeneralsPlugin::CleanSampler() - closing sampler")); + iGeneralsSampler.Close(); + + LOGTEXT(_L("CGeneralsPlugin::CleanSampler() - Freeing sampler device")); + User::FreeLogicalDevice(KPluginSamplerName); + + // release attribute array + if(iSamplerAttributes) + { + iSamplerAttributes->Reset(); + } + delete iSamplerAttributes; + iSamplerAttributes = NULL; + + LOGTEXT(_L("CGeneralsPlugin::CleanSampler() - exit")); + + return KErrNone; + } + +// returns setting array +void CGeneralsPlugin::GetAttributesL(CArrayFixFlat<TSamplerAttributes>* aAttributes) + { + TInt count(iSamplerAttributes->Count()); + // append all sampler attributes to aAttributes array + for(TInt i(0);i<count;i++) + { + aAttributes->AppendL(iSamplerAttributes->At(i)); + } + } + +TInt CGeneralsPlugin::SetAttributesL(TSamplerAttributes aAttributes) + { + TSamplerAttributes attr; + + TInt count(iSamplerAttributes->Count()); + // loop the sub sampler attributes (by UID) + for(TInt i(0);i<count;i++) + { + attr = iSamplerAttributes->At(i); + // if UIDs match replace the old + if(attr.iUid == aAttributes.iUid) + { + // replace the old attribute container + iSamplerAttributes->Delete(i); + iSamplerAttributes->InsertL(i, aAttributes); + return KErrNone; + } + } + return KErrNotFound; + } + +/* + * Method for parsing and transforming text array settings into TSamplerAttributes (per each sub sampler), + * called by CSamplerController class + * + * @param array of raw text setting lines, e.g. [gpp]\nenabled=true\nsampling_period_ms=1\n + */ +TInt CGeneralsPlugin::ConvertRawSettingsToAttributes(CDesC8ArrayFlat* aAllSettingsArray) + { + // local literals + _LIT8(KGPPShort, "gpp"); + _LIT8(KGFCShort, "gfc"); + _LIT8(KITTShort, "itt"); + _LIT8(KMEMShort, "mem"); + _LIT8(KPRIShort, "pri"); + + TInt err(KErrNone); + + TBuf8<16> samplerSearchName; + + // loop previous settings, update value if changed + for(TInt i(0);i<KSubSamplerCount;i++) + { + // go through all the sub samplers + switch (i) + { + case 0: + samplerSearchName.Copy(KGPPShort); + break; + case 1: + samplerSearchName.Copy(KGFCShort); + break; + case 2: + samplerSearchName.Copy(KITTShort); + break; + case 3: + samplerSearchName.Copy(KMEMShort); + break; + case 4: + samplerSearchName.Copy(KPRIShort); + break; + } + + // get sampler specific settings + err = DoSetSamplerSettings(aAllSettingsArray, samplerSearchName, i); + } + + // returns KErrNone if settings found, otherwise KErrNotFound + return err; + } + +/** + * Method for searching sampler specific settings among all settings (raw setting lines read from settings file) + * + * @param aAllSettings array of all settings from settings file + * @param aSamplerName short name of sampler to be searched among the settings + * @param aIndex index number of sampler specific sampler attributes (TSamplerAttributes) + * @return KErrNone if settings found ok else KErrNotFound + */ +TInt CGeneralsPlugin::DoSetSamplerSettings(CDesC8ArrayFlat* aAllSettings, TDesC8& aSamplerName, TInt aIndex) + { + // sampler name to be searched among the all settings + TBuf8<16> samplerSearch; + samplerSearch.Copy(KBracketOpen); + samplerSearch.Append(aSamplerName); + samplerSearch.Append(KBracketClose); + + // read a line from ALL settings array + for (TInt i(0); i<aAllSettings->MdcaCount(); i++) + { + // check if this line has a setting block start, i.e. contains [xxx] in it + if (aAllSettings->MdcaPoint(i).CompareF(samplerSearch) == 0) + { + // right settings block found, now loop until the next block is found + for(TInt j(i+1);j<aAllSettings->MdcaCount();j++) + { + // check if the next settings block was found + if(aAllSettings->MdcaPoint(j).Left(1).CompareF(KBracketOpen) != 0) + { + // save found setting value directly to its owners attributes + SaveSettingToAttributes(aAllSettings->MdcaPoint(j), aIndex); + } + else + { + // next block found, return KErrNone + return KErrNone; + } + } + } + } + // no settings found for specific sampler + return KErrNotFound; + } + +/** + * Method for setting a specific descriptor (from settings file) to attribute structure + * + * @param aSetting + * @param aName + */ +void CGeneralsPlugin::SaveSettingToAttributes(const TDesC8& aSetting, TInt aIndex) + { + // local literals + _LIT8(KSettingItemSeparator, "="); + + // find the equal mark from the setting line + TInt sepPos = aSetting.Find(KSettingItemSeparator); + // check that '=' is found + if (sepPos > 0) + { + // check that the element matches + if (aSetting.Left(sepPos).CompareF(KEnabled) == 0) + { + TBool en; + CSamplerPluginInterface::Str2Bool(aSetting.Right(aSetting.Length()-sepPos-1), en); + if(en != iSamplerAttributes->At(aIndex).iEnabled) + { + iSamplerAttributes->At(aIndex).iEnabled = en; + } + } + else if (aSetting.Left(sepPos).CompareF(KSamplingPeriod) == 0) + { + TInt sr; + CSamplerPluginInterface::Str2Int(aSetting.Right(aSetting.Length()-sepPos-1), sr); + if(sr != iSamplerAttributes->At(aIndex).iSampleRate) + { + iSamplerAttributes->At(aIndex).iSampleRate = sr; + } + } + } + } + + +TUid CGeneralsPlugin::Id(TInt aSubId) const + { + if(aSubId == PROFILER_GPP_SAMPLER_ID) + return KSamplerGppPluginUid; + else if (aSubId == PROFILER_GFC_SAMPLER_ID) + return KSamplerGfcPluginUid; + else if (aSubId == PROFILER_ITT_SAMPLER_ID) + return KSamplerIttPluginUid; + else if (aSubId == PROFILER_MEM_SAMPLER_ID) + return KSamplerMemPluginUid; + else if (aSubId == PROFILER_PRI_SAMPLER_ID) + return KSamplerPriPluginUid; + else + return KSamplerGeneralsPluginUid; + } + +TInt CGeneralsPlugin::SubId(TUid aId) const + { +/* definitions from ProfilerConfig.h: + * #define PROFILER_GPP_SAMPLER_ID 1 + #define PROFILER_GFC_SAMPLER_ID 2 + #define PROFILER_ITT_SAMPLER_ID 3 + #define PROFILER_MEM_SAMPLER_ID 4 + #define PROFILER_PRI_SAMPLER_ID 5 + */ + + if(aId == KSamplerGppPluginUid) + return PROFILER_GPP_SAMPLER_ID; + else if (aId == KSamplerGfcPluginUid) + return PROFILER_GFC_SAMPLER_ID; + else if (aId == KSamplerIttPluginUid) + return PROFILER_ITT_SAMPLER_ID; + else if (aId == KSamplerMemPluginUid) + return PROFILER_MEM_SAMPLER_ID; + else if (aId == KSamplerPriPluginUid) + return PROFILER_PRI_SAMPLER_ID; + else + return KErrNotFound; + } + +TInt CGeneralsPlugin::GetSamplerType() + { + return iSamplerType; + } + + +void CGeneralsPlugin::InstallStreamForActiveTraces(RGeneralsSampler& sampler, CProfilerSampleStream& aStream) + { + // output mode for this trace is stream + if(!iBufferHandler) + { + // stream object has not been created yet + LOGTEXT(_L("CGeneralsPlugin::InstallStreamForActiveTraces - creating stream for trace")); + + // use a 32KB buffer to transfer data from sampler to client + // commonStream = new RProfilerSampleStream(sampler,totalPrefix,32768); + TRAPD(err, iBufferHandler = CProfilerBufferHandler::NewL(aStream, sampler)); + if(err != KErrNone) + { + LOGTEXT(_L("CGeneralsPlugin::InstallStreamForActiveTraces() - No memory")); + return; + } + } + + // initiate receiving of data from the sampler device driver + if(iBufferHandler) + { + iBufferHandler->StartReceivingData(); + } +} + +void CGeneralsPlugin::SetSettingsToSamplers() + { + TSamplerAttributes attr; + + // loop through the setting attributes + for(TInt i(0);i<iSamplerAttributes->Count();i++) + { + // get the attribute container + attr = iSamplerAttributes->At(i); + + // make changes according to right sampler, NOTE! The old IDs of sub samplers (i+1)! + if(attr.iEnabled) + { + iGeneralsSampler.MarkTraceActive(i+1); + + // set enabled + iEnabled = ETrue; + } + else + { + iGeneralsSampler.MarkTraceInactive(i+1); + } + // set sampling period if available + if(attr.iSampleRate != KErrNotFound) + { + iGeneralsSampler.SetSamplingPeriod(i+1, attr.iSampleRate); + } + } + } + +TInt CGeneralsPlugin::ResetAndActivateL(CProfilerSampleStream& aStream) + { + // the sampler starting functionality + LOGTEXT(_L("CGeneralsPlugin::ResetAndActivate() - entry")); + + // now before starting the latest settings must be set to samplers itself + SetSettingsToSamplers(); + + if(Enabled()) + { + LOGTEXT(_L("CGeneralsPlugin::ResetAndActivate() - starting sampling...")); + // start sampling process of enabled sub samplers + iGeneralsSampler.StartSampling(); + LOGTEXT(_L("CGeneralsPlugin::ResetAndActivate() - installing stream for an active trace...")); + + // install the trace for enabled samplers + InstallStreamForActiveTraces(iGeneralsSampler, aStream); + LOGSTRING2("CGeneralsPlugin::ResetAndActivate() - stream installed: 0x%x", aStream); + } + + LOGTEXT(_L("CGeneralsPlugin::ResetAndActivate() - exit")); + return KErrNone; + } + +TInt CGeneralsPlugin::StopSampling() + { + // RDebug::Print(_L("CGeneralsPlugin::StopSampling() - Stopping sampler LDD")); + iGeneralsSampler.StopSampling(); + // RDebug::Print(_L("CGeneralsPlugin::StopSampling() - Sampler LDD stopped")); + + // check if bufferhandler has died + if(iBufferHandler) + { + // RDebug::Print(_L("CGeneralsPlugin::StopSampling() - Canceling the buffer handler")); + iBufferHandler->Cancel(); + delete iBufferHandler; + iBufferHandler = NULL; + } + // set enabled + iEnabled = EFalse; + // RDebug::Print(_L("CGeneralsPlugin::StopSampling() - exit")); + return KErrNone; + } + + + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/src/GeneralsPluginImplementationTable.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/src/GeneralsPluginImplementationTable.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,39 @@ +/* +* 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: +* +*/ + + +// INCLUDE FILES +#include <e32std.h> +#include <ecom/implementationproxy.h> + +#include "GeneralsPlugin.h" + + +// Provides a key value pair table, this is used to identify +// the correct construction function for the requested interface. +const TImplementationProxy ImplementationTable[] = +{ + IMPLEMENTATION_PROXY_ENTRY(0x2001E5B2, CGeneralsPlugin::NewL) +}; + +// Function used to return an instance of the proxy table. +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) +{ + aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); + return ImplementationTable; +} + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/src/GeneralsSampler.cia --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/src/GeneralsSampler.cia Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,91 @@ +/* +* 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: +* +*/ + + +#include <platform.h> + +#include "GeneralsDriver.h" +#include <kern_priv.h> //temporary + +#ifdef __SMP__ +#include <e32cia.h> +#include <arm.h> +#include <arm_gic.h> +#include <arm_tmr.h> +#endif + +#if defined(__GCC32__) +// CIA symbol macros for Gcc98r2 +#define CSM__ZN5NKern14CurrentContextEv " CurrentContext__5NKern" +#elif defined(__ARMCC__) +// CIA symbol macros for RVCT +#define CSM__ZN5NKern14CurrentContextEv " __cpp(NKern::CurrentContext)" +#else +// CIA symbol macros for EABI assemblers +#define CSM__ZN5NKern14CurrentContextEv " _ZN5NKern14CurrentContextEv" +#endif + +#ifdef __WINS__ +__NAKED__ TUint* IntStackPtr() +{ + return 0; +} + +__NAKED__ TUint32 SPSR() +{ + return 0; +} +__NAKED__ void UsrModLr(TUint32* a) +{ + *a = 0; +} +#else + +__NAKED__ TUint* IntStackPtr() +{ +#ifdef __SMP__ + asm("stmfd sp!, {r0-r12,lr} "); +#endif + asm("mrs r1, cpsr "); // copy current program status register (cpsr) to R1 + asm("bic r3, r1, #0x1f "); // compare to 0x1f, i.e. make sure that spsr is available? +#ifdef __SMP__ + __ASM_CLI_MODE(MODE_IRQ); // disable all interrupts and set to irq mode (we are in NTimer interrupt) +#else + asm("orr r3, r3, #0xd2 "); // mode_irq, all interrupts off + asm("msr cpsr, r3 "); // write result on R3 back to cpsr, irqs disabled +#endif + asm("mov r0, sp "); // read stack pointer to R0, mode r0=sp_irq + asm("msr cpsr, r1 "); // restore interrupts +#ifdef __SMP__ + asm("ldmfd sp!, {r0-r12,pc} "); +#endif + __JUMP(,lr); +} + +__NAKED__ TUint32 SPSR() +{ + asm("mrs r0, spsr "); + __JUMP(,lr); +} +__NAKED__ void UsrModLr(TUint32*) +{ + // r0 = address to store + asm ("stmia r0,{lr}^"); + __JUMP(,lr); +} + +#endif diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/src/GppSamplerImpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/src/GppSamplerImpl.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,572 @@ +/* +* 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: +* +*/ + + +#include <piprofiler/ProfilerVersion.h> +#include <piprofiler/ProfilerTraces.h> +#include <kern_priv.h> +#include <arm.h> + +#include "GppSamplerImpl.h" + +extern TUint* IntStackPtr(); +#define TAG(obj) (*(TUint32*)&(obj.iAsyncDeleteNext)) + +// properties for ISA task parsing +const TUid KIsaPropertyCat={0x2001E5AD}; +enum TIsaPropertyKeys + { + EIsaPropertyIsaTaskParserStatus = 1, + EIsaPropertyIsaTaskAddressStart, + EIsaPropertyIsaTaskAddressEnd, + EIsaPropertyIsaTaskAddress, + EIsaPropertyIsaOsTaskRunningAddress, + EIsaPropertyIsaTaskParsedName + }; + + +DGppSamplerImpl::DGppSamplerImpl() + { + LOGTEXT("GppSamplerImpl::GppSamplerImpl"); + iInterruptStack = (TUint*)IntStackPtr(); + + LOGTEXT("GppSamplerImpl::GppSamplerImpl - attaching to properties"); + + TInt err = iIsaStartAddr.Attach(KIsaPropertyCat, EIsaPropertyIsaTaskAddressStart); + if(err != KErrNone) + LOGTEXT("GppSamplerImpl::GppSamplerImpl() - Property EIsaPropertyIsaTaskAddressStart not available"); + err = iIsaEndAddr.Attach(KIsaPropertyCat, EIsaPropertyIsaTaskAddressEnd); + if(err != KErrNone) + LOGTEXT("GppSamplerImpl::GppSamplerImpl() - Property EIsaPropertyIsaTaskAddressEnd not available"); + err = iIsaPluginStatus.Attach(KIsaPropertyCat, EIsaPropertyIsaTaskParserStatus); + if(err != KErrNone) + LOGTEXT("GppSamplerImpl::GppSamplerImpl() - Property EIsaPropertyIsaTaskParserStatus not available"); + err = iIsaOsTaskRunning.Attach(KIsaPropertyCat, EIsaPropertyIsaOsTaskRunningAddress); + if(err != KErrNone) + LOGTEXT("GppSamplerImpl::GppSamplerImpl() - Property EIsaPropertyIsaOsTaskRunningAddress not available"); + + PROFILER_ISA_TASK_NAMES + + Reset(); + } + +DGppSamplerImpl::~DGppSamplerImpl() + { + iIsaStartAddr.Close(); + iIsaEndAddr.Close(); + iIsaPluginStatus.Close(); + iIsaOsTaskRunning.Close(); + } + +void DGppSamplerImpl::Reset() + { + LOGTEXT("GppSamplerImpl::Reset"); + iLastPc = 0; + iLastThread = 0; + iRepeat = 0; + iIsaStatus = 0; + iIsaStart = 0; + iIsaEnd = 0; +// isaOsTaskRunningAddr = 0; + + // in SMP start time common with all CPUs, provided by DGeneralsDriver class +#ifndef __SMP__ + iStartTime = ( NKern::TickCount() & 0xfffffffc ); +#endif + + TPropertyStatus status; + TInt osAddr = 0; + + LOGTEXT("GppSamplerImpl::Reset - getting status"); + + // get status of ISA plug-in + if(iIsaPluginStatus.GetStatus(status)) + { + iIsaPluginStatus.Get(iIsaStatus); + LOGSTRING2("GppSamplerImpl::Reset - ISA plug-in status %d", iIsaStatus); + } + + if(iIsaStatus > 0) + { + LOGTEXT("GppSamplerImpl::Reset - get isa start address"); + iIsaStartAddr.Get(iIsaStart); + LOGTEXT("GppSamplerImpl::Reset - get isa end address"); + iIsaEndAddr.Get(iIsaEnd); + LOGTEXT("GppSamplerImpl::Reset - get isa os_task_running address"); + iIsaOsTaskRunning.Get(osAddr); + isaOsTaskRunningAddr = reinterpret_cast<TInt*>(osAddr); + LOGSTRING2("GppSamplerImpl::Reset - got isa os_task_running address 0x%X", osAddr); + } + + LOGTEXT("GppSamplerImpl::Reset - initializing isa task list"); + + iIsaSample = false; + + for(TInt i=0;i<256;i++) + knownIsaTasks[i] = -1; + + knownIsaTaskCount = 0; + + iCpuSelector = 0x3; +#ifndef __SMP__ + iMask = 0xfffffffc; +#else + iMask = 0xfffffff0; + switch(iCpuNumber) + { + case 0: + iCpuSelector = 0x1; + break; + case 1: + iCpuSelector = 0x2; + break; + case 2: + iCpuSelector = 0x4; + break; + case 3: + iCpuSelector = 0x8; + break; + } +#endif + } + +TUint8* DGppSamplerImpl::EncodeTag(TUint8* aPtr) +// +// Encode a tag and version to the trace data. This allows the offline analyser to +// identify the sample data. +// +{ + _LIT(KGppSamplerVersion,"Bappea_GPP_V"); + _LIT(KProfilerVersion,"#Prof#"); + _LIT(KSamplerVersion,"#Samp#"); +#ifdef __SMP__ + _LIT(KCPUNumberText,"#CPU#"); +#endif + + TBuf<64> buf; + buf.Zero(); + buf.Append(KGppSamplerVersion); + buf.Append(PROFILER_GPP_SAMPLER_VERSION); + buf.Append(KProfilerVersion); + buf.Append(PROFILER_VERSION_SHORT); + buf.Append(KSamplerVersion); + buf.Append(PROFILER_SAMPLER_VERSION); +#ifdef __SMP__ + buf.Append(KCPUNumberText); + buf.AppendNum(iCpuNumber); +#endif + aPtr = EncodeText(aPtr, buf); + return aPtr; +} + +TUint8* DGppSamplerImpl::EncodeInt(TUint8* aPtr,TInt aValue) +{ + LOGSTRING2("Encoding int 0x%x",aPtr); + + LOGSTRING2("TIint = 0x%x",aValue); + + TUint byte; + for (;;) + { + byte = aValue & 0x7f; + if ((aValue >> 6) == (aValue >> 7)) + break; + aValue >>= 7; + *aPtr++ = byte; + } + *aPtr++ = byte | 0x80; + + LOGSTRING2("Encoded int 0x%x",aPtr); + + return aPtr; +} + +TUint8* DGppSamplerImpl::EncodeUint(TUint8* aPtr,TUint aValue) +{ + LOGSTRING2("Encoding Uint 0x%x",aPtr); + + LOGSTRING2("TUint = 0x%x",aValue); + + + TUint byte; + for (;;) + { + byte = aValue & 0x7f; + aValue >>= 7; + if (aValue == 0) + break; + *aPtr++ = byte; + } + *aPtr++ = byte | 0x80; + + LOGSTRING2("Encoded Uint 0x%x",aPtr); + + return aPtr; +} + +TUint8* DGppSamplerImpl::EncodeText(TUint8* aPtr, const TDesC& aDes) +// +// Encode a descriptor into the data stream +// This is currently limited to a descriptor that is up to 255 characters in length, +// and Unicode characters are truncated to 8 bits +// +{ + LOGSTRING2("Encoding text 0x%x",aPtr); + TInt len=aDes.Length(); + *aPtr++ = TUint8(len); + const TText* p = aDes.Ptr(); + while (--len >= 0) + { + *aPtr++ = TUint8(*p++); + } + + LOGSTRING2("Encoded text 0x%x",aPtr); + return aPtr; +} + + +TUint8* DGppSamplerImpl::EncodeName(TUint8* aPtr, DObject& aObject,TUint32 id) +// +// Encode the name of a kernel object +// +{ + LOGSTRING2("Encoding name 0x%x",aPtr); + TBuf8<0x5f> name; + aObject.TraceAppendName(name,false); + + if(id != 0xffffffff) + { + name.Append('['); + name.AppendNum(id,EHex); + name.Append(']'); + } + else + { + name.Append('['); + name.AppendNum((TUint32)((void*)&(((DThread*)&aObject)->iNThread)),EHex); + name.Append(']'); + } + + aPtr = EncodeText(aPtr,name); + LOGSTRING2("Encoded name 0x%x",aPtr); + return aPtr; +} + +TUint8* DGppSamplerImpl::EncodeThread(TUint8* aPtr, DThread& aThread) +// +// Encode a thread name in the data stream. +// The thread is identified by its name, and the identity of its owning process. +// If the process has not been identified in the data stream already, it's name is +// also encoded. +// +{ + LOGSTRING2("Encoding thread 0x%x",aPtr); + + DProcess& p = *aThread.iOwningProcess; + + aPtr = EncodeUint(aPtr, p.iId); + +#ifdef __SMP__ + // check if first time founding + if ((TAG(p) & iMask) != iStartTime) + { + // mark tagged for this CPU + TAG(p) = (iStartTime | iCpuSelector); + + // The thread is 'unknown' to this sample, so encode the thread name + aPtr = EncodeName(aPtr, p, p.iId); + } + // check if thread appeared already on this CPU + else if((TAG(p) & iCpuSelector) != iCpuSelector) + { + TAG(p) = (TAG(p) | iCpuSelector); + // The thread is 'unknown' to this sample, so encode the thread name + aPtr = EncodeName(aPtr, p, p.iId); + } +#else + if (TAG(p) != iStartTime) + { + TAG(p) = iStartTime; + // Provide the name matching this process ID + aPtr = EncodeName(aPtr, p, p.iId); + } +#endif + aPtr = EncodeName(aPtr, aThread,0xffffffff); + + LOGSTRING2("Encoded thread 0x%x",aPtr); + + return aPtr; + } + +TUint8* DGppSamplerImpl::EncodeRepeat(TUint8* aPtr) +// +// Encode a repeated sequence of samples +// +{ + LOGSTRING2("Encoding repeat, 0x%x",iRepeat); + + aPtr = EncodeInt(aPtr, 0); + aPtr = EncodeUint(aPtr, iRepeat); + iRepeat = 0; + + LOGSTRING2("Encoded repeat, 0x%x",iRepeat); + + return aPtr; +} + +TInt DGppSamplerImpl::CreateFirstSample() +{ + LOGTEXT("GppSamplerImpl::CreateFirstSample"); + Reset(); + + TUint8* w = this->tempBuf; + w = EncodeTag(w); + + TInt length = w-tempBuf; + + LOGSTRING2("TAG encoded, length %d",length); + return length; +} + +TBool DGppSamplerImpl::IsaTaskKnown(TUint8 task) +{ + for(TInt i=0;i<256;i++) + { + if(knownIsaTasks[i] == -1) + { + knownIsaTasks[i] = task; + knownIsaTaskCount++; + return false; + } + else if(knownIsaTasks[i] == task) + { + return true; + } + } + + return false; +} + +TUint8* DGppSamplerImpl::EncodeIsaTask(TUint8* aPtr, TUint task) + +{ + LOGSTRING2("Encoding ISA task 0x%x",aPtr); + + aPtr = EncodeUint(aPtr,task); + // use the task name as the process name + aPtr = EncodeIsaName(aPtr,task,true); + // then encode the task name + aPtr = EncodeIsaName(aPtr,task,false); + + LOGSTRING2("Encoded ISA task 0x%x",aPtr); + + return aPtr; +} + +TUint8* DGppSamplerImpl::EncodeIsaName(TUint8* aPtr, TUint task,TBool process) +// +// Encode a descriptor into the data stream +// This is currently limited to a descriptor that is up to 255 characters in length, +// and Unicode characters are truncated to 8 bits +// +{ + TBuf8<256> aDes; + +// #ifdef NCP_COMMON_PROFILER_ISA_TASKS + if(iIsaStatus > 0) + { + // resolve the isa task name from the task name array + if((task-100000) < PROFILER_ISA_OS_TASK_AMOUNT && process == false) + { + aDes.Append(isaTaskNames[(task-100000)]); + } + else + { + aDes.Append(_L8("NativeOS_Task")); + } + } + else + { + aDes.Append(_L8("NativeOS_Task")); + } + + aDes.Append('['); + aDes.AppendNum((task-100000),EHex); + aDes.Append(']'); + + LOGSTRING2("Encoding ISA name 0x%x",aPtr); + TInt len=aDes.Length(); + *aPtr++ = TUint8(len); + const TText* p = aDes.Ptr(); + while (--len >= 0) + { + *aPtr++ = TUint8(*p++); + } + + LOGSTRING2("Encoded ISA name 0x%x",aPtr); + return aPtr; +} + + +TInt DGppSamplerImpl::SampleImpl() +// +// ISR for the profile timer +// This extracts the thread and PC that was current when the interrupt went off and +// encodes it into the sample data buffer. If enough data has been generated, the +// DFC is triggered to complete a read request +// + { + TUint8* w(this->tempBuf); + +// Kern::Printf(("Got thread 0x%08x"), &t); +#ifdef __SMP__ + // get the program counter of irq mode + TUint32 pc = (TUint32)Arm::IrqReturnAddress(); +#else + // get program counter of irq mode + TUint32 pc = iInterruptStack[-1]; +#endif + //LOGSTRING3("pc value 0x%x sp 0x%x",pc,iInterruptStack); + + // ignore the low bit being set for THUMB mode - we use for something else + pc &= ~1; + TInt diff = pc - iLastPc; + iLastPc = pc; + + if(iIsaStatus > 0) + { + if((TUint32)pc > (TUint32)iIsaStart && (TUint32)pc < (TUint32)iIsaEnd) + { + LOGSTRING2("Identified ISA execution at 0x%x",pc); + iIsaSample = true; + } + else + { + LOGSTRING2("Normal sample at 0x%x",pc); + iIsaSample = false; + } + } + + // request for current thread from kernel + DThread& t = ((DThread&)*Kern::NThreadToDThread(NKern::CurrentThread())); + + TUint tid; + TUint8 isaTask = 0; + if(iIsaSample) + { + LOGSTRING2("Reading ISA task number from 0x%x",isaOsTaskRunningAddr); + + // if we don't get reasonable ISA address to read, skip ISA task handling + if(isaOsTaskRunningAddr == 0) + { + tid = 100000; // to tell the difference from SOS threads + iIsaSample = false; + } + else // normal ISA task parsing process + { + isaTask = *isaOsTaskRunningAddr; + LOGSTRING2("ISA task = %d",isaTask); + tid = isaTask; + // this will make sure we don't mix ISA tasks and normal tasks + tid += 100000; + } + + } + else + { + tid = t.iId; + } + + if (tid != iLastThread) + { + // Change of thread is marked in the low bit of the PC difference + diff |= 1; + } + TUint rp = iRepeat; + if (diff == 0) + { + // Identical sample, bump up the repeat count + iRepeat = rp + 1; + } + else + { + if (rp) + { + // Encode the repeat data + w = EncodeRepeat(w); + } + // Encode the PC difference + w = EncodeInt(w, diff); + if (diff & 1) + { + // Encode the new thread ID + if(iIsaSample) + { + iLastThread = tid; + w = EncodeUint(w,tid); + + if(!this->IsaTaskKnown(isaTask)) + { + w = EncodeIsaTask(w,iLastThread); + } + //LOGSTRING2("Sample total length: %d",w-tempBuf); + TInt length = w-tempBuf; + // encoded isa task, return here + return length; + } + + iLastThread = tid; + w = EncodeUint(w, tid); + +#ifdef __SMP__ + // iStartTime format: 0xXXXXXXX0, the last byte set to zero + // iMask = 0xfffffff0(0b111....1110000) + // iCpuSelector = 0x1(0b0001), 0x2(0b0010), 0x4(0b0100) or 0x8(0b1000) + + // check first time founding + if ((TAG(t) & iMask) != iStartTime) + { + // mark tagged for this CPU + TAG(t) = (iStartTime | iCpuSelector); + + // The thread is 'unknown' to this sample, so encode the thread name + w = EncodeThread(w, t); + } + // check if thread appeared on this CPU + else if((TAG(t) & iCpuSelector) != iCpuSelector) + { + TAG(t) = (TAG(t) | iCpuSelector); + // The thread is 'unknown' to this sample, so encode the thread name + w = EncodeThread(w, t); + } +#else + // check if tag has not been set, neither original nor + if ((TAG(t) & 0xfffffffc) != iStartTime) + { + TAG(t) = ((TAG(t) & 0x3) | iStartTime); + // The thread is 'unknown' to this sample, so encode the thread name + w = EncodeThread(w, t); + } +#endif + } + } + LOGSTRING2("Sample total length: %d",w-tempBuf); + TInt length = w-tempBuf; + + return length; +} + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/src/IttEventHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/src/IttEventHandler.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,174 @@ +/* +* 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: Event based ITT sampler skeleton copypasted from MemoryEventHandler.cpp +* +*/ + +#include <e32def.h> +#include <e32cmn.h> +#include <arm.h> +#include <kernel.h> +#include <kern_priv.h> +#include <nk_trace.h> + +#include "IttEventHandler.h" + +/* + * Constructor + * + * @param DProfilerSampleBuffer* pointer to sample buffer + */ +DIttEventHandler::DIttEventHandler(DProfilerSampleBuffer* aSampleBuffer, TProfilerGppSamplerData* aGppSamplerDataIn) + : DKernelEventHandler(EventHandler, this), + iSampleBuffer(aSampleBuffer), + iSampleDescriptor(&(this->iSample[1]),0,KITTBufferSize), + gppSamplerData(aGppSamplerDataIn) + { + //Kern::Printf("DIttEventHandler::DIttEventHandler()"); + + } + +/* + * DIttEventHandler::Create() + */ +TInt DIttEventHandler::Create() + { + Kern::Printf("DIttEventHandler::Create()"); + + TInt err(Kern::MutexCreate(iLock, _L("IttEventHandlerLock"), KMutexOrdDebug)); + if (err != KErrNone) + return err; + + return Add(); + } + +/* + * Destructor + */ +DIttEventHandler::~DIttEventHandler() + { + //Kern::Printf("DIttEventHandler::~DIttEventHandler()"); + + if (iLock) + iLock->Close(NULL); + } + + +TInt DIttEventHandler::Start() + { + //Kern::Printf("DIttEventHandler::Start()"); + + iTracking = ETrue; + return KErrNone; + } + + +TInt DIttEventHandler::Stop() + { + //Kern::Printf("DIttEventHandler::Stop()"); + + iTracking = EFalse; + return KErrNone; + } + +TBool DIttEventHandler::SampleNeeded() + { + LOGTEXT("DIttEventHandler::SampleNeeded()"); + + // increase the counter by one on each round + iCount++; + + // check if event handler was not running + if(!iTracking) + return false; + + return true; + } + + +TUint DIttEventHandler::EventHandler(TKernelEvent aType, TAny* a1, TAny* a2, TAny* aThis) + { + //Kern::Printf("DIttEventHandler::EventHandler()"); + return ((DIttEventHandler*)aThis)->HandleEvent(aType, a1, a2); + } + + + +TUint DIttEventHandler::HandleEvent(TKernelEvent aType, TAny* a1, TAny* a2) + { + //Kern::Printf("DIttEventHandler::HandleEvent()"); + //Kern::Printf("New kernel event received, %d", aType); + + if (iTracking/* && iCount != iPreviousCount*/) + { + switch (aType) + { + + case EEventAddCodeSeg: + //Kern::Printf("DCodeSeg added: 0x%08x", (DCodeSeg*)a1); + HandleAddCodeSeg((DCodeSeg*)a1); + break; + + case EEventRemoveCodeSeg: + //Kern::Printf("DCodeSeg deleted: 0x%08x", (DCodeSeg*)a1); + HandleRemoveCodeSeg((DCodeSeg*)a1); + break; + + default: + break; + } + } +// else if(iTracking && iCount == iPreviousCount) +// { +// // if time stamp is not updated profiling has stopped +// Stop(); +// } + return DKernelEventHandler::ERunNext; + } + +/* + * + */ +TBool DIttEventHandler::HandleAddCodeSeg(DCodeSeg* aSeg) + { + iSampleDescriptor.Zero(); + //Kern::Printf("DLL ADD: NM %S : RA:0x%x SZ:0x%x SN:0x%x",aSeg->iFileName,aSeg->iRunAddress,aSeg->iSize, this->gppSamplerData->sampleNumber); + + iSample[0] = aSeg->iFileName->Length(); + iSampleDescriptor.Append(*aSeg->iFileName); + iSampleDescriptor.Append((TUint8*)&(aSeg->iRunAddress),4); + iSampleDescriptor.Append((TUint8*)&(aSeg->iSize),4); + iSampleDescriptor.Append((TUint8*)&(this->gppSamplerData->sampleNumber),4); + iSample[0] = iSampleDescriptor.Size(); + + iSampleBuffer->AddSample(iSample,iSampleDescriptor.Size()+1); + return ETrue; + } + +TBool DIttEventHandler::HandleRemoveCodeSeg(DCodeSeg* aSeg) + { + iSampleDescriptor.Zero(); + //Kern::Printf("DLL REM: NM %S : RA:0x%x SZ:0x%x SN:0x%x",aSeg->iFileName,aSeg->iRunAddress,aSeg->iSize, this->gppSamplerData->sampleNumber); + + iSample[0] = aSeg->iFileName->Length(); + iSampleDescriptor.Append(*aSeg->iFileName); + iSampleDescriptor.Append((TUint8*)&(aSeg->iRunAddress),4); + iSampleDescriptor.Append((TUint8*)&(aSeg->iSize),4); + iSampleDescriptor.Append((TUint8*)&(this->gppSamplerData->sampleNumber),4); + iSample[0] = iSampleDescriptor.Size(); + + iSampleBuffer->AddSample(iSample,iSampleDescriptor.Size()+1); + return ETrue; + } +// end of file diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/src/IttSamplerImpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/src/IttSamplerImpl.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,244 @@ +/* +* 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: +* +*/ + + +#include <piprofiler/ProfilerVersion.h> + +#include <kern_priv.h> +#include <plat_priv.h> + +#include "IttSamplerImpl.h" + +#ifdef ITT_EVENT_HANDLER +_LIT8(KIttVersion, "2.00"); +#else +_LIT8(KIttVersion, "1.22"); +#endif + +/* + * ITT sampler definition + * + */ +IttSamplerImpl::IttSamplerImpl(): + sampleDescriptor(&(this->sample[1]),0,KITTSampleBufferSize) +{ + this->currentLibCount = 0; + iTimeToSample = EFalse; + this->Reset(); +} + +/* + * destructor + */ +IttSamplerImpl::~IttSamplerImpl() +{ + +} + +/* + * IttSamplerImpl::CreateFirstSample() + * + * Function for creating the first sample to the log file + */ +TInt IttSamplerImpl::CreateFirstSample() +{ + Kern::Printf("ittSamplerImpl::createFirstSample\n"); + this->iVersionData.Zero(); + this->iVersionData.Append(_L8("Bappea_ITT_V")); + this->iVersionData.Append(KIttVersion); + this->itt_sample = (TUint8*)iVersionData.Ptr(); + return iVersionData.Length(); +} + +/* + * IttSamplerImpl::SampleNeeded(TUint32 sampleNum) + * + * @param TUint32 Sample number + * + */ +TBool IttSamplerImpl::SampleNeeded(TUint32 sampleNum) +{ +#ifdef ITT_EVENT_HANDLER + iCount++; + if (iCount <= iIttSamplingPeriod && ((iCount % iIttSamplingPeriod) == 0 || (iCount % iIttSamplingPeriodDiv2) == 0)) + { + LOGSTRING2("IttSamplerImpl::SampleNeeded - time: %d", iCount); + iTimeToSample = true; +#else + // no need to do anything, always a good time to sample. + // Sample time filtering is done in IttSamplerImpl:SampleImpl() function +#endif + return true; +#ifdef ITT_EVENT_HANDLER + } + else + { + return false; + } +#endif +} + +/* + * IttSamplerImpl::SampleImpl(TUint32 pc, TUint32 sampleNum) + * + * @param TUint32 program counter + * @param TUint32 sample number + */ +TInt IttSamplerImpl::SampleImpl(TUint32 pc,TUint32 sampleNum) +{ + // in order to avoid overloading the interrupt + // only one dynamic file in each 50ms is added to the stream + // with the application of the tool in mind, this is + // a reasonable measure + + // encode a process binary + sampleDescriptor.Zero(); + // original + if((sampleNum % 20) != 0) return 0; + if((sampleNum % 40) == 0) + { + // encode a library binary + sampleDescriptor.Zero(); + DObjectCon* libs = Kern::Containers()[ELibrary]; + TInt libCount = libs->Count(); + + // go 20 binaries through at a time + for(TInt i=0;i<20;i++) + { + if(currentLibCount >= libCount) + { + currentLibCount = 0; + } + + DLibrary* lib = (DLibrary*)(*libs)[currentLibCount]; + currentLibCount++; + + DCodeSeg* seg = lib->iCodeSeg; + if(seg != 0) + { + if( (seg->iMark & 0x80) == 0) + { + this->sample[0] = seg->iFileName->Length(); + sampleDescriptor.Append(*(seg->iFileName)); + sampleDescriptor.Append((TUint8*)&(seg->iRunAddress),4); + sampleDescriptor.Append((TUint8*)&(seg->iSize),4); +#ifdef ITT_EVENT_HANDLER + sampleDescriptor.Append((TUint8*)&(sampleNum),4); + //Kern::Printf("DLL: NM %S : RA:0x%x SZ:0x%x, SN:0x%x",seg->iFileName,seg->iRunAddress,seg->iSize, sampleNum); + this->iFirstSampleTaken = ETrue; +#else + //Kern::Printf("DLL: NM %S : RA:0x%x SZ:0x%x",seg->iFileName,seg->iRunAddress,seg->iSize); +#endif + seg->iMark = (seg->iMark | 0x80); + + this->sample[0] = sampleDescriptor.Size(); + return sampleDescriptor.Size()+1; + } + } + } + } else + { + SDblQue* codeSegList = Kern::CodeSegList(); + //Kern::Printf("PI"); + //TUint c = 0; + // the global list + for (SDblQueLink* codeseg= codeSegList->First(); codeseg!=(SDblQueLink*) codeSegList; codeseg=codeseg->iNext) + { + DCodeSeg* seg = _LOFF(codeseg, DCodeSeg, iLink); + if(seg != 0) + { + if( (seg->iMark & 0x80) == 0) + { + this->sample[0] = seg->iFileName->Length(); + sampleDescriptor.Append(*(seg->iFileName)); + sampleDescriptor.Append((TUint8*)&(seg->iRunAddress),4); + sampleDescriptor.Append((TUint8*)&(seg->iSize),4); +#ifdef ITT_EVENT_HANDLER + sampleDescriptor.Append((TUint8*)&(sampleNum),4); + //Kern::Printf("EXE2: NM %S : RA:0x%x SZ:0x%x, time: %d",seg->iFileName,seg->iRunAddress,seg->iSize, sampleNum); + this->iFirstSampleTaken = ETrue; +#else + //Kern::Printf("EXE2: NM %S : RA:0x%x SZ:0x%x, time: %d",seg->iFileName,seg->iRunAddress,seg->iSize, sampleNum); +#endif + seg->iMark = (seg->iMark | 0x80); + + this->sample[0] = sampleDescriptor.Size(); + return sampleDescriptor.Size()+1; + } + } + } + } + return 0; +} + +/* + * IttSamplerImpl::Reset() + */ +void IttSamplerImpl::Reset() +{ + iTimeToSample = EFalse; +#ifdef ITT_EVENT_HANDLER + iFirstSampleTaken = EFalse; +#endif + this->currentLibCount = 0; + this->itt_sample = (TUint8*)&(this->sample[0]); + sampleDescriptor.Zero(); + +// #ifdef ITT_TEST + SDblQue* codeSegList = Kern::CodeSegList(); + // the global list + for (SDblQueLink* codeseg= codeSegList->First(); codeseg!=(SDblQueLink*) codeSegList; codeseg=codeseg->iNext) + { + DCodeSeg* seg = _LOFF(codeseg,DCodeSeg, iLink); + //if(seg != 0) + { + if( (seg->iMark & 0x80) > 0) + { + seg->iMark = (seg->iMark & ~0x80); + } + } + } + // the garbage list + DObjectCon* libs = Kern::Containers()[ELibrary]; + TInt libCount = libs->Count(); + for(TInt i=0;i<libCount;i++) + { + DLibrary* lib = (DLibrary*)(*libs)[i]; + DCodeSeg* seg = lib->iCodeSeg; + if( (seg->iMark & 0x80) > 0) + { + seg->iMark = (seg->iMark & ~0x80); + } + } + + DObjectCon* procs = Kern::Containers()[EProcess]; + TInt procCount = procs->Count(); + for(TInt i=0;i<procCount;i++) + { + DProcess* pro = (DProcess*)(*procs)[i]; + DCodeSeg* seg = pro->iCodeSeg; + if(seg != 0) + { + if( (seg->iMark & 0x80) > 0) + { + seg->iMark = (seg->iMark & ~0x80); + } + } + } + //#endif //ITT_TEST +} +// end of file diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/src/MemSamplerImpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/src/MemSamplerImpl.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,976 @@ +/* +* 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: +* +*/ + + +#include <piprofiler/ProfilerVersion.h> +#include <piprofiler/ProfilerTraces.h> + +#include <kern_priv.h> +#include <plat_priv.h> + +#include "MemSamplerImpl.h" + +// for testing precise stack utilization tracing... +// crashes at the moment + +#include <nk_cpu.h> + +#if !defined(__NKERN_H__) +#include <nkern.h> +#endif + +#define TAG(obj) (*(TUint32*)&(obj->iAsyncDeleteNext)) +#define PROFILER_CHUNK_MARK ((TUint32)0x00001000) +#define PROFILER_MEM_THREAD_MARK ((TUint32)0x00000001) +#define PROFILER_LIBRARY_MARK ((TUint32)0x10000000) +#define PROFILER_MEM_THREAD_UNMARK ~PROFILER_MEM_THREAD_MARK + +#ifdef MEM_EVENT_HANDLER +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS +_LIT8(KMemVersion,"2.03"); +#else +_LIT8(KMemVersion, "2.02"); +#endif +#else +_LIT8(KMemVersion, "1.56"); +#endif + +DMemSamplerImpl::DMemSamplerImpl() : + sampleDescriptor(&(this->sample[1]),0,256) + { + LOGSTRING("MemSamplerImpl::MemSamplerImpl() - konstruktori"); + + iCount = 0; + +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + iSampleType = ESampleThreads; +#else + iSampleThreads = true; +#endif + iTimeToSample = false; + + iTotalMemoryOk = false; + iTotalMemoryNameOk = false; + + iNewChunkCount = 0; + iChunkCount = 0; + iChunksProcessing = ENothingToProcess; + iThreadsProcessing = ENothingToProcess; + + iNewThreadCount = 0; + iThreadCount = 0; + + // reset data structures + for(TInt i(0);i<KProfilerMaxChunksAmount;i++) + { + // heap chunks + this->heapChunksToSample[i] = 0; + this->heapChunkNamesToReport[i] = 0; + } + + for(TInt i(0);i<KProfilerMaxThreadsAmount;i++) + { + // threads + this->threadsToSample[i] = 0; + this->threadNamesToReport[i] = 0; + } + +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + iLibrariesProcessing = ENothingToProcess; + iNewLibraryCount = 0; + iLibraryCount = 0; + + for(TInt i(0); i<KProfilerMaxLibrariesAmount; i++) + { + // libraries + this->librariesToSample[i] = 0; + this->libraryNamesToReport[i] = 0; + } +#endif + + } + +DMemSamplerImpl::~DMemSamplerImpl() + { + + } + +TInt DMemSamplerImpl::CreateFirstSample() + { + LOGSTRING("MemSamplerImpl::CreateFirstSample - entry"); + + this->sampleDescriptor.Zero(); + this->sampleDescriptor.Append(_L8("Bappea_V")); + this->sampleDescriptor.Append(KMemVersion); + this->sampleDescriptor.Append(_L8("_MEM")); + + sample[0] = this->sampleDescriptor.Size(); + + LOGSTRING("MemSamplerImpl::CreateFirstSample - exit"); + + return (TInt)(sample[0]+1); + } + +TBool DMemSamplerImpl::SampleNeeded() + { + iCount++; +#ifdef MEM_EVENT_HANDLER + // make the collection of chunks/threads only once, rest will be collected with mem event handler +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + if (iCount <= iMemSamplingPeriod && ((iCount % iMemSamplingPeriod) == 0 || (iCount % iMemSamplingPeriodDiv3) == 0)) +#else + if (iCount <= iMemSamplingPeriod && ((iCount % iMemSamplingPeriod) == 0 || (iCount % iMemSamplingPeriodDiv2) == 0)) +#endif +#else + if ((iCount % iMemSamplingPeriod) == 0 || (iCount % iMemSamplingPeriodDiv2) == 0) +#endif + { + LOGSTRING2("MemSamplerImpl::SampleNeeded - time: %d", iCount); + iTimeToSample = true; + return true; + } + else + { + return false; + } + + } +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS +TInt DMemSamplerImpl::SampleImpl() + { + // Sample threads: + if( iSampleType == ESampleThreads ) + { + if(this->iThreadsProcessing == ENothingToProcess ) + { + if(!iTimeToSample) + { + return 0; + } + else + { + iTimeToSample = false; + // gather first all thread stacks + return GatherThreads(); + } + } + else + { + // process now thread stack list + TInt length = this->ProcessThreads(); + + if(length == 0) + { + this->iThreadsProcessing = ENothingToProcess; + // switch to collect chunk data + iSampleType = ESampleChunks; + } + return length; + } + } + + // Sample chunks: + if( iSampleType == ESampleChunks ) + { + if(this->iChunksProcessing == ENothingToProcess) + { + if(!iTimeToSample) + { + return 0; + } + else + { + iTimeToSample = false; + // gather first all chunks + return GatherChunks(); + } + } + else + { + // still something to go through in lists + TInt length = this->ProcessChunks(); + + if(length == 0) + { + this->iChunksProcessing = ENothingToProcess; + // switch to collect library data + iSampleType = ESampleLibraries; + //iSampleThreads = true; + } + return length; + } + } + + // Sample libraries: + if( iSampleType == ESampleLibraries ) + { + if(this->iLibrariesProcessing == ENothingToProcess ) + { + if(!iTimeToSample) + { + return 0; + } + else + { + iTimeToSample = false; + // gather libraries + return GatherLibraries(); + } + } + else + { + // process now thread stack list + TInt length = this->ProcessLibraries(); + if(length == 0) + { + this->iLibrariesProcessing = ENothingToProcess; + // switch to collect chunk data + iSampleType = ESampleThreads; + } + return length; + } + } + + // should not reach this point... + return 0; + } +#else +TInt DMemSamplerImpl::SampleImpl() + { + // check if either chunk or thread lists have unprocessed items + if(this->iChunksProcessing == ENothingToProcess && !iSampleThreads) + { + if(!iTimeToSample) + { + return 0; + } + else + { + iTimeToSample = false; + // gather first all chunks + return GatherChunks(); + } + } + else if(!iSampleThreads) + { + // still something to go through in lists + TInt length = this->ProcessChunks(); + + if(length == 0) + { + this->iChunksProcessing = ENothingToProcess; + // switch to collect thread data + iSampleThreads = true; + } + return length; + } + + if(this->iThreadsProcessing == ENothingToProcess && iSampleThreads) + { + if(!iTimeToSample) + { + return 0; + } + else + { + iTimeToSample = false; + // gather first all thread stacks + return GatherThreads(); + } + } + + else if(iSampleThreads) + { + // process now thread stack list + TInt length = this->ProcessThreads(); + + if(length == 0) + { + this->iThreadsProcessing = ENothingToProcess; + // switch to collect chunk data + iSampleThreads = false; + } + return length; + } + + // should not reach this point... + return 0; + } +#endif + +inline TInt DMemSamplerImpl::GatherChunks() + { + // encode a process binary + name.Zero(); + + NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex + DObjectCon& chunks = *Kern::Containers()[EChunk]; + chunks.Wait(); // Obtain the container mutex so the list does get changed under us + + this->iChunkCount = 0; + this->iNewChunkCount = 0; + this->iTotalMemoryOk = false; + TInt totalChunkCount(chunks.Count()); + DChunk* c; + + for(TInt i(0);i<totalChunkCount;i++) + { + c = (DChunk*)(chunks)[i]; + + LOGSTRING3("Processing chunk %d, tag: 0x%x",i,TAG(c)); + + if( (TAG(c) & 0x0000ffff) != PROFILER_CHUNK_MARK) + { + LOGSTRING4("Marking chunk %d/%d, old tag 0x%x",i,(totalChunkCount-1), TAG(c)); + // this chunk has not been tagged yet + name.Zero(); + c->TraceAppendName(name,false); + const TUint8* ptr = name.Ptr(); + + TAG(c) = (PROFILER_CHUNK_MARK); + this->heapChunkNamesToReport[iNewChunkCount] = c; + iNewChunkCount++; + } + + // the chunk has been tagged, add heap chunks to the list + this->heapChunksToSample[this->iChunkCount] = c; + this->iChunkCount++; + LOGSTRING2("Added chunk %d to Chunks",i); + } + + if(this->iChunkCount > 0 || this->iNewChunkCount > 0) + { + this->iChunksProcessing = EStartingToProcess; + + // process the first sample + TInt length = this->ProcessChunks(); + + if(length == 0) + { + this->iChunksProcessing = ENothingToProcess; + } + + chunks.Signal(); // Release the container mutex + NKern::ThreadLeaveCS(); // End of critical section + return length; + } + + LOGTEXT("MemSamplerImpl::SampleImpl - Error, no threads"); + chunks.Signal(); // Release the container mutex + NKern::ThreadLeaveCS(); // End of critical section + return 0; + } + +inline TInt DMemSamplerImpl::GatherThreads() + { + // The thread memory consumption + + NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex + DObjectCon& threads = *Kern::Containers()[EThread]; + threads.Wait(); // Obtain the container mutex so the list does get changed under us + + this->iThreadCount = 0; + this->iNewThreadCount = 0; + this->iTotalMemoryOk = false; + + TInt totalThreadCount = threads.Count(); + + for(TInt i(0);i<totalThreadCount;i++) + { + DThread* t = (DThread*)(threads)[i]; + + LOGSTRING3("Processing thread %d, tag: 0x%x",i,TAG(t)); + + if( (TAG(t) & PROFILER_MEM_THREAD_MARK) == 0) + { + LOGSTRING4("Marking thread %d/%d, old tag 0x%x",i,(totalThreadCount-1), TAG(t)); + // this thread's chunk has not been reported yet + this->threadNamesToReport[iNewThreadCount] = t; + iNewThreadCount++; + // tag the thread + TAG(t) |= PROFILER_MEM_THREAD_MARK; + } + + // the chunk has been tagged, add heap chunks to the list + this->threadsToSample[this->iThreadCount] = t; + this->iThreadCount++; + LOGSTRING2("Added thread %d to threads to sample",i); + } + + if(this->iThreadCount > 0 || this->iNewThreadCount > 0) + { + this->iThreadsProcessing = EStartingToProcess; + + // process the first sample + TInt length = this->ProcessThreads(); + + if(length == 0) + { + this->iThreadsProcessing = ENothingToProcess; + } + threads.Signal(); // Release the container mutex + NKern::ThreadLeaveCS(); // End of critical section + return length; + } + + LOGTEXT("MemSamplerImpl::SampleImpl - Error, no threads"); + threads.Signal(); // Release the container mutex + NKern::ThreadLeaveCS(); // End of critical section + return 0; + } + +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + +inline TInt DMemSamplerImpl::GatherLibraries() + { + LOGTEXT("MemSamplerImpl::GatherLibraries() - entry"); + // encode a process binary + name.Zero(); + + NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex + DObjectCon& libs = *Kern::Containers()[ELibrary]; + libs.Wait(); // Obtain the container mutex so the list does get changed under us + + this->iLibraryCount = 0; + this->iNewLibraryCount = 0; + this->iTotalMemoryOk = false; + TInt totalLibCount(libs.Count()); + DLibrary* l; + + for(TInt i(0);i<totalLibCount;i++) + { + l = (DLibrary*)(libs)[i]; + + LOGSTRING3("Processing library %d, tag: 0x%x",i,TAG(l)); + + if( (TAG(l) & 0xffffffff) != PROFILER_LIBRARY_MARK) + { + LOGSTRING4("Marking library %d/%d, old tag 0x%x",i,(totalLibCount-1), TAG(l)); + // this library has not been tagged yet + name.Zero(); + l->TraceAppendName(name,false); + const TUint8* ptr = name.Ptr(); + + TAG(l) = (PROFILER_LIBRARY_MARK); + this->libraryNamesToReport[iNewLibraryCount] = l; + iNewLibraryCount++; + } + + // the library has been tagged, add library to the list + this->librariesToSample[this->iLibraryCount] = l; + this->iLibraryCount++; + LOGSTRING2("Added library %d to Libraries",i); + } + + if(this->iLibraryCount > 0 || this->iNewLibraryCount > 0) + { + this->iLibrariesProcessing = EStartingToProcess; + + // process the first sample + TInt length = this->ProcessLibraries(); + + if(length == 0) + { + this->iLibrariesProcessing = ENothingToProcess; + } + + libs.Signal(); // Release the container mutex + NKern::ThreadLeaveCS(); // End of critical section + return length; + } + + LOGTEXT("MemSamplerImpl::SampleImpl - Error, no libraries"); + libs.Signal(); // Release the container mutex + NKern::ThreadLeaveCS(); // End of critical section + return 0; + } +#endif + +inline TInt DMemSamplerImpl::ProcessChunks() + { + if(iNewChunkCount > 0) + { + if(this->iChunksProcessing == EStartingToProcess) + { + // this is the first sample, encode a code for names + this->iChunksProcessing = EProcessingNames; + return EncodeNameCode(); + } + + if(iTotalMemoryNameOk == false) + { + return EncodeTotalMemoryName(); + } + + // there are new chunk names to report + iNewChunkCount--; + DChunk* c = this->heapChunkNamesToReport[iNewChunkCount]; + return EncodeChunkName(*c); + + } + else if(iChunkCount > 0) + { + if(this->iChunksProcessing == EProcessingNames || this->iChunksProcessing == EStartingToProcess) + { + // this is the first data sample, encode a code for data + this->iChunksProcessing = EProcessingData; + return EncodeDataCode(); + } + + if(this->iTotalMemoryOk == false) + { + return EncodeTotalMemory(); + } + + // there are no new chunks to report + // thus generate the real report + iChunkCount--; + DChunk* c = this->heapChunksToSample[iChunkCount]; + return EncodeChunkData(*c); + } + else + { + // everything is processed + LOGSTRING2(" Chunks processed! Chunk count = %d", iChunkCount); +#ifdef MEM_EVENT_HANDLER + this->iChunksGathered = true; + Kern::Printf("MemSamplerImpl::ProcessChunks() - chunks gathered! Time: %d",iCount); +#endif + return 0; + } + } + +inline TInt DMemSamplerImpl::ProcessThreads() + { + + if(iNewThreadCount > 0) + { + if(this->iThreadsProcessing == EStartingToProcess) + { + // this is the first sample, encode a code for names + this->iThreadsProcessing = EProcessingNames; + return EncodeNameCode(); + } + + if(iTotalMemoryNameOk == false) + { + return EncodeTotalMemoryName(); + } + + iNewThreadCount--; + DThread* t = this->threadNamesToReport[iNewThreadCount]; + return EncodeChunkName(*t); + } + else if(iThreadCount > 0) + { + if(this->iThreadsProcessing == EProcessingNames || this->iThreadsProcessing == EStartingToProcess) + { + // this is the first data sample, encode a code for data + this->iThreadsProcessing = EProcessingData; + return EncodeDataCode(); + } + + if(this->iTotalMemoryOk == false) + { + return EncodeTotalMemory(); + } + + // there are no new threads to report + // thus generate the real report + iThreadCount--; + DThread* t = this->threadsToSample[iThreadCount]; + return EncodeChunkData(*t); + } + else + { + // everything is processed + LOGSTRING2(" Threads processed! Thread count = %d", iThreadCount); +#ifdef MEM_EVENT_HANDLER + this->iThreadsGathered = true; + Kern::Printf("MemSamplerImpl::ProcessThreads() - threads gathered! Time: %d", iCount); +#endif + return 0; + } + } +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS +inline TInt DMemSamplerImpl::ProcessLibraries() + { + LOGTEXT("ProcessLibraries - entry"); + if(iNewLibraryCount > 0) + { + if(this->iLibrariesProcessing == EStartingToProcess) + { + // this is the first sample, encode a code for names + this->iLibrariesProcessing = EProcessingNames; + return EncodeNameCode(); + } + + if(iTotalMemoryNameOk == false) + { + return EncodeTotalMemoryName(); + } + + // there are new library names to report + iNewLibraryCount--; + DLibrary* l = this->libraryNamesToReport[iNewLibraryCount]; + return EncodeChunkName(*l); + + } + else if(iLibraryCount > 0) + { + if(this->iLibrariesProcessing == EProcessingNames || this->iLibrariesProcessing == EStartingToProcess) + { + // this is the first data sample, encode a code for data + this->iLibrariesProcessing = EProcessingData; + return EncodeDataCode(); + } + + if(this->iTotalMemoryOk == false) + { + return EncodeTotalMemory(); + } + + // there are no new libraries to report + // thus generate the real report + iLibraryCount--; + DLibrary* l = this->librariesToSample[iLibraryCount]; + return EncodeChunkData(*l); + } + else + { + // everything is processed + LOGSTRING2(" Libraries processed! Library count = %d", iLibraryCount); + + this->iLibrariesGathered = true; + Kern::Printf("MemSamplerImpl::ProcessLibraries() - libraries gathered! Time: %d",iCount); + + return 0; + } + } +#endif +inline TInt DMemSamplerImpl::EncodeNameCode() + { + sample[0] = 1; + sample[1] = 0xaa; + return 2; + } + +inline TInt DMemSamplerImpl::EncodeDataCode() + { + sample[0] = 1; + sample[1] = 0xdd; + return 2; + } + +inline TInt DMemSamplerImpl::EncodeTotalMemoryName() + { + this->iTotalMemoryNameOk = true; + + TUint8* size = &sample[0]; + *size = 0; + + // encode name + this->sampleDescriptor.Zero(); + this->sampleDescriptor.Append(_L("TOTAL_MEMORY")); + *size += this->sampleDescriptor.Size(); + + // add id here + TUint32 id(0xbabbeaaa); + this->sampleDescriptor.Append((TUint8*)&(id),sizeof(TUint32)); + *size += sizeof(TUint32); + + // the size is the descriptor length + the size field + return ((TInt)(*size))+1; + } + +inline TInt DMemSamplerImpl::EncodeTotalMemory() + { + + TUint8* size = &sample[0]; + *size = 0; + + NKern::LockSystem(); + TInt freeRam = Kern::FreeRamInBytes(); + TInt totalRam = Kern::SuperPage().iTotalRamSize; + NKern::UnlockSystem(); + + this->sampleDescriptor.Zero(); + + TUint32 id(0xbabbeaaa); + TInt zero(0); + + this->sampleDescriptor.Append((TUint8*)&(id),sizeof(TUint32)); + *size += sizeof(TUint); + + this->sampleDescriptor.Append((TUint8*)&(totalRam),sizeof(TInt)); + *size += sizeof(TInt); + + // append the cell amount allocated + this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + + // append the chunk size + this->sampleDescriptor.Append((TUint8*)&(freeRam),sizeof(TInt)); + *size += sizeof(TInt); + + // append the thread user stack size + this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + + this->iTotalMemoryOk = true; + + return ((TInt)(*size))+1; + } + +inline TInt DMemSamplerImpl::EncodeChunkName(DChunk& c) + { + // the size of the following name is in the first byte + TUint8* size = &sample[0]; + *size = 0; + + // encode chunk name + this->sampleDescriptor.Zero(); + this->sampleDescriptor.Append(_L("C_")); + c.TraceAppendFullName(this->sampleDescriptor,false); + *size += this->sampleDescriptor.Size(); + + // add chunk object address here + TUint32 chunkAddr((TUint32)&c); + this->sampleDescriptor.Append((TUint8*)&(chunkAddr),sizeof(TUint32)); + *size += sizeof(TUint32); + + // the size is the descriptor length + the size field + LOGSTRING2("Non-Heap Chunk Name - %d",*size); + return ((TInt)(*size))+1; + } + +inline TInt DMemSamplerImpl::EncodeChunkName(DThread& t) + { + // the size of the following name is in the first byte + TUint8* size = &sample[0]; + *size = 0; + this->sampleDescriptor.Zero(); + + this->sampleDescriptor.Append(_L("T_")); + t.TraceAppendFullName(this->sampleDescriptor,false); + *size += this->sampleDescriptor.Size(); + + // copy the 4 bytes from the thread id field + this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint)); + *size += sizeof(TUint); + + // the size is the descriptor length + the size field + LOGSTRING2("Name - %d",*size); + return ((TInt)(*size))+1; + } +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS +inline TInt DMemSamplerImpl::EncodeChunkName(DLibrary& l) + { + // the size of the following name is in the first byte + TUint8* size = &sample[0]; + *size = 0; + + // encode library name + this->sampleDescriptor.Zero(); + this->sampleDescriptor.Append(_L("L_")); + l.TraceAppendFullName(this->sampleDescriptor,false); + *size += this->sampleDescriptor.Size(); + + // add chunk object address here + TUint32 libAddr((TUint32)&l); + this->sampleDescriptor.Append((TUint8*)&(libAddr),sizeof(TUint32)); + *size += sizeof(TUint32); + + // the size is the descriptor length + the size field + LOGSTRING2("Name - %d",*size); + return ((TInt)(*size))+1; + } +#endif +inline TInt DMemSamplerImpl::EncodeChunkData(DChunk& c) + { + // the size of the following name is in the first byte + TUint8* size = &sample[0]; + *size = 0; + this->sampleDescriptor.Zero(); + TInt zero(0); + + TUint32 address((TUint32)&c); + + this->sampleDescriptor.Append((TUint8*)&address,sizeof(TUint32)); + *size += sizeof(TUint); + + // copy the total amount of memory allocated + this->sampleDescriptor.Append((TUint8*)&(c.iSize),sizeof(TInt)); + *size += sizeof(TInt); + + // append the cell amount allocated + this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + + // append the chunk size + this->sampleDescriptor.Append((TUint8*)&(c.iSize),sizeof(TUint)); + *size += sizeof(TUint); + + // append the thread user stack size + this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + + LOGSTRING2("Data - %d",*size); + return ((TInt)(*size))+1; + + } + +inline TInt DMemSamplerImpl::EncodeChunkData(DThread& t) + { + LOGTEXT("MemSamplerImpl::EncodeChunkData - entry"); + //LOGSTRING2("MemSamplerImpl::EncodeChunkData - processing thread 0x%x ",&t); + + // the size of the following name is in the first byte + TUint8* size = &sample[0]; + *size = 0; + this->sampleDescriptor.Zero(); + + LOGTEXT("MemSamplerImpl::EncodeChunkData - cleared"); + + this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint)); + *size += sizeof(TUint); + + // copy the total amount of memory allocated for user side stack + this->sampleDescriptor.Append((TUint8*)&(t.iUserStackSize),sizeof(TInt)); + *size += sizeof(TInt); + + TInt zero(0); + // append the cell amount allocated (zero, not in use here) + this->sampleDescriptor.Append((TUint8*)&zero,sizeof(TInt)); + *size += sizeof(TInt); + + // append the chunk size (this is not a chunk) + this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TUint)); + *size += sizeof(TUint); + + // append user stack (max) size + this->sampleDescriptor.Append((TUint8*)&(t.iUserStackSize),sizeof(TInt)); + *size += sizeof(TInt); + + LOGSTRING2("Data -> %d",*size); + return ((TInt)(*size))+1; + } +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS +inline TInt DMemSamplerImpl::EncodeChunkData(DLibrary& l) + { + LOGTEXT("MemSamplerImpl::EncodeChunkData (Library) - entry"); + // the size of the following name is in the first byte + TUint8* size = &sample[0]; + *size = 0; + this->sampleDescriptor.Zero(); + + TUint32 address((TUint32)&l); + + this->sampleDescriptor.Append((TUint8*)&address,sizeof(TUint32)); + *size += sizeof(TUint); + + this->sampleDescriptor.Append((TUint8*)&(l.iCodeSeg->iSize),sizeof(TUint32)); + *size += sizeof(TInt); + + this->sampleDescriptor.Append((TUint8*)&(l.iMapCount),sizeof(TInt)); + *size += sizeof(TInt); + + TInt zero(0); + this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + + this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + + LOGSTRING2("LData - %d",*size); + return ((TInt)(*size))+1; + + } +#endif +void DMemSamplerImpl::Reset() + { + Kern::Printf("MemSamplerImpl::Reset"); + iCount = 0; // sample threads 1 cycle after actual MEM sample time... + this->iTimeToSample = false; + this->iChunkCount = 0; + this->iNewChunkCount = 0; + + this->iTotalMemoryOk = false; + this->iTotalMemoryNameOk = false; + + this->iChunksProcessing = ENothingToProcess; + this->iThreadsProcessing = ENothingToProcess; +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + this->iLibrariesProcessing = ENothingToProcess; + this->iSampleType = ESampleThreads; +#else + this->iSampleThreads = true; +#endif + + this->sampleDescriptor.Zero(); + + // clear all chunk tags + NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex + DObjectCon* chunks = Kern::Containers()[EChunk]; + chunks->Wait(); // Obtain the container mutex so the list does get changed under us + + TInt totalChunkCount = chunks->Count(); + for(TInt i=0;i<totalChunkCount;i++) + { + DChunk* c = (DChunk*)(*chunks)[i]; + TAG(c) = 0; + } + chunks->Signal(); // Release the container mutex + + Kern::Printf("MemSamplerImpl::Reset"); + this->iThreadCount = 0; + this->iNewThreadCount = 0; + this->sampleDescriptor.Zero(); + + // clear all chunk tags + DObjectCon* threads = Kern::Containers()[EThread]; + threads->Wait(); // Obtain the container mutex so the list does get changed under us + + TInt totalThreadCount = threads->Count(); + for(TInt i=0;i<totalThreadCount;i++) + { + DThread* t = (DThread*)(*threads)[i]; + TAG(t) = (TAG(t) & 0xfffffffe); + } + threads->Signal(); // Release the container mutex + +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + this->iLibraryCount = 0; + this->iNewLibraryCount = 0; + this->sampleDescriptor.Zero(); + + // clear all library tags + DObjectCon* libs = Kern::Containers()[ELibrary]; + libs->Wait(); // Obtain the container mutex so the list does get changed under us + + TInt totalLibraryCount = libs->Count(); + for(TInt i=0; i<totalLibraryCount; i++) + { + DLibrary* l = (DLibrary*)(*libs)[i]; + TAG(l) = (TAG(l) & 0xefffffff); + } + libs->Signal(); // Release the container mutex +#endif + + NKern::ThreadLeaveCS(); // End of critical section + } + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/src/MemoryEventHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/src/MemoryEventHandler.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,724 @@ +/* +* 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: +* +*/ + +#include <e32def.h> +#include <e32cmn.h> +#include <arm.h> +#include <kernel.h> +#include <kern_priv.h> +#include <nk_trace.h> + +#include "MemoryEventHandler.h" + + +DMemoryEventHandler::DMemoryEventHandler(DProfilerSampleBuffer* aSampleBuffer) + : DKernelEventHandler(EventHandler, this), + iSampleBuffer(aSampleBuffer), + iSampleDescriptor(&(this->iSample[1]),0,256) + { +// Kern::Printf("DMemoryEventHandler::DMemoryEventHandler()"); + iCount = 0; + iPreviousCount = 0; + } + + +TInt DMemoryEventHandler::Create() + { +// Kern::Printf("DMemoryEventHandler::Create()"); + + TInt err(Kern::MutexCreate(iLock, _L("MemoryEventHandlerLock"), KMutexOrdGeneral0)); + if (err != KErrNone) + return err; + + return Add(); + } + + +DMemoryEventHandler::~DMemoryEventHandler() + { +// Kern::Printf("DMemoryEventHandler::~DMemoryEventHandler()"); + + if (iLock) + iLock->Close(NULL); + + } + + +TInt DMemoryEventHandler::Start() + { +// Kern::Printf("DMemoryEventHandler::Start()"); + + iTracking = ETrue; + return KErrNone; + } + + +TInt DMemoryEventHandler::Stop() + { +// Kern::Printf("DMemoryEventHandler::Stop()"); + + iTracking = EFalse; + return KErrNone; + } + +TBool DMemoryEventHandler::SampleNeeded() + { + LOGTEXT("DMemoryEventHandler::SampleNeeded()"); + + // increase the coutner by one on each round + iCount++; + + // check if event handler was not running +// if(!iTracking) +// return false; // return false + + return true; + } + + +TUint DMemoryEventHandler::EventHandler(TKernelEvent aType, TAny* a1, TAny* a2, TAny* aThis) + { + return ((DMemoryEventHandler*)aThis)->HandleEvent(aType, a1, a2); + } + + + +TUint DMemoryEventHandler::HandleEvent(TKernelEvent aType, TAny* a1, TAny* a2) + { + // debug +// Kern::Printf("New kernel event received, %d", aType); + + if (iTracking/* && iCount != iPreviousCount*/) + { +// iPreviousCount = iCount; + iCounters[aType]++; + switch (aType) + { + // capture only chunk creation, updates and destroyal + case EEventNewChunk: + { + DChunk* chunk = (DChunk*)a1; + HandleAddChunk(chunk); + break; + } + case EEventUpdateChunk: + HandleUpdateChunk((DChunk*)a1); + break; + case EEventDeleteChunk: + HandleDeleteChunk((DChunk*)a1); + break; +// case EEventAddProcess: +// Kern::Printf("Process added: 0x%08x", (DProcess*)a1); +// break; +// case EEventUpdateProcess: +// Kern::Printf("DProcess updated: 0x%08x", (DProcess*)a1); +// break; +// case EEventRemoveProcess: +// Kern::Printf("DProcess removed: 0x%08x", (DProcess*)a1); +// break; +// case EEventAddCodeSeg: +// Kern::Printf("DCodeSeg added: 0x%08x", (DCodeSeg*)a1); +// break; +// case EEventRemoveCodeSeg: +// Kern::Printf("DCodeSeg deleted: 0x%08x", (DCodeSeg*)a1); +// break; + case EEventAddThread: + HandleAddThread((DThread*)a1); + break; + case EEventUpdateThread: // thread renaming + HandleUpdateThread((DThread*)a1); + break; +// case EEventKillThread: + case EEventRemoveThread: + HandleDeleteThread((DThread*)a1); + break; +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + case EEventAddLibrary: + HandleAddLibrary((DLibrary*)a1, (DThread*)a2); + break; + case EEventRemoveLibrary: + HandleDeleteLibrary((DLibrary*)a1); + break; +#endif + + // ignore exception events + case EEventSwExc: + case EEventHwExc: + + default: + break; + } + } +// else if(iTracking && iCount == iPreviousCount) +// { +// // if time stamp is not updated profiling has stopped +// Stop(); +// } + return DKernelEventHandler::ERunNext; + } + +TInt DMemoryEventHandler::EncodeNameCode() + { + iSample[0] = 1; + iSample[1] = 0xaa; + return 2; + } + +// encode mark for new chunk or thread +TInt DMemoryEventHandler::EncodeNewCode() + { + iSample[0] = 1; + iSample[1] = 0xda; + return 2; + } + +// encode mark for update of chunk or thread +TInt DMemoryEventHandler::EncodeUpdateCode() + { + iSample[0] = 1; + iSample[1] = 0xdb; + return 2; + } + +// encode mark for removal of chunk or thread +TInt DMemoryEventHandler::EncodeRemoveCode() + { + iSample[0] = 1; + iSample[1] = 0xdc; + return 2; + } + +// encode the memory sample header in all memory changes +TInt DMemoryEventHandler::AddHeader() + { + TInt err(KErrNone); + + TUint8 number(4); // mem sampler id + + // check if iCount bigger than previous, i.e. at least 1 ms has passed from the previous sample + if(iCount > iPreviousCount) + { + err = this->iSampleBuffer->AddSample(&number,1); + err = this->iSampleBuffer->AddSample((TUint8*)&(iCount),4); + + // add data chunk header + TInt length(EncodeUpdateCode()); + err = iSampleBuffer->AddSample(iSample, length); + + // add total memory sample in the beginning of each sample + length = EncodeTotalMemory(); + err = iSampleBuffer->AddSample(iSample, length); + AddFooter(); // end mark for total memory sample + } + iPreviousCount = iCount; + + // add actual sample + err = this->iSampleBuffer->AddSample(&number,1); + err = this->iSampleBuffer->AddSample((TUint8*)&(iCount),4); + + return err; + } + +// encode the memory sample header in all memory changes +TInt DMemoryEventHandler::AddFooter() + { + TInt err(KErrNone); + + TUint8 number(0); // end mark + err = this->iSampleBuffer->AddSample(&number,1); + + return err; + } + +TInt DMemoryEventHandler::EncodeTotalMemory() + { + + TUint8* size(&iSample[0]); + *size = 0; + + NKern::LockSystem(); + TInt freeRam(Kern::FreeRamInBytes()); + TInt totalRam(Kern::SuperPage().iTotalRamSize); + NKern::UnlockSystem(); + + iSampleDescriptor.Zero(); + + TUint32 id(0xbabbeaaa); + TInt zero(0); + + iSampleDescriptor.Append((TUint8*)&(id),sizeof(TUint32)); + *size += sizeof(TUint); + + iSampleDescriptor.Append((TUint8*)&(totalRam),sizeof(TInt)); + *size += sizeof(TInt); + + // append the cell amount allocated + iSampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + + // append the chunk size + iSampleDescriptor.Append((TUint8*)&(freeRam),sizeof(TInt)); + *size += sizeof(TInt); + + // append the thread user stack size + iSampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + + return ((TInt)(*size))+1; + } + +// handle chunk activity +TBool DMemoryEventHandler::HandleAddChunk(DChunk* aChunk) + { +// Kern::Printf("New DChunk created: 0x%08x, time: %d", aChunk, iCount); + + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + // add header first + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // new chunk, add name of it + TInt length(EncodeNameCode()); + iSampleBuffer->AddSample(iSample, length); + + // new chunk, add name of it + length = EncodeChunkName(*aChunk); + iSampleBuffer->AddSample(iSample, length); + + // add new chunk tag + length = EncodeNewCode(); + iSampleBuffer->AddSample(iSample, length); + + length = EncodeChunkData(*aChunk); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +TBool DMemoryEventHandler::HandleUpdateChunk(DChunk* aChunk) + { +// Kern::Printf("DChunk updated: 0x%08x, time: %d", aChunk, iCount); + + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + // add header first + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // add new chunk tag + TInt length(EncodeUpdateCode()); + iSampleBuffer->AddSample(iSample, length); + + length = EncodeChunkData(*aChunk); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +TBool DMemoryEventHandler::HandleDeleteChunk(DChunk* aChunk) + { +// Kern::Printf("DChunk deleted: 0x%08x, time: %d", aChunk, iCount); + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + // add header first + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // add new chunk tag + TInt length(EncodeRemoveCode()); + iSampleBuffer->AddSample(iSample, length); + + length = EncodeChunkData(*aChunk); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +// handle process activity +TBool DMemoryEventHandler::HandleAddProcess(DProcess *aProcess) + { + return ETrue; + } + +TBool DMemoryEventHandler::HandleUpdateProcess(DProcess *aProcess) + { + return ETrue; + } + +TBool DMemoryEventHandler::HandleDeleteProcess(DProcess *aProcess) + { + return ETrue; + } + +// handle thread activity +TBool DMemoryEventHandler::HandleAddThread(DThread* aThread) + { +// Kern::Printf("DThread added: 0x%08x, time: %d", aThread->iId, iCount); + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + // add header first + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // new thread, add name of it + TInt length(EncodeNameCode()); + iSampleBuffer->AddSample(iSample, length); + + // new chunk, add name of it + length = EncodeChunkName(*aThread); + iSampleBuffer->AddSample(iSample, length); + + // add new chunk tag + length = EncodeNewCode(); + iSampleBuffer->AddSample(iSample, length); + + length = EncodeChunkData(*aThread); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +TBool DMemoryEventHandler::HandleUpdateThread(DThread* aThread) + { +// Kern::Printf("DThread updated: 0x%08x, time: %d", aThread->iId, iCount); + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + // add header first + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // add new chunk tag + TInt length(EncodeUpdateCode()); + iSampleBuffer->AddSample(iSample, length); + + length = EncodeChunkData(*aThread); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +TBool DMemoryEventHandler::HandleDeleteThread(DThread* aThread) + { +// Kern::Printf("DThread deleted: 0x%08x, time: %d", aThread->iId, iCount); + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + // add header first + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // add new chunk tag + TInt length(EncodeRemoveCode()); + iSampleBuffer->AddSample(iSample, length); + + length = EncodeChunkData(*aThread); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +TBool DMemoryEventHandler::HandleAddLibrary(DLibrary* aLibrary, DThread* aThread) + { + LOGTEXT("DMemoryEventHandler::HandleAddLibrary"); + Kern::Printf("DLibrary added: 0x%08x, time: %d", aLibrary, iCount); + // add header first + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // new library, add name of it + TInt length(EncodeNameCode()); + iSampleBuffer->AddSample(iSample, length); + + // new chunk, add name of it + length = EncodeChunkName(*aLibrary); + iSampleBuffer->AddSample(iSample, length); + + // add new chunk tag + length = EncodeNewCode(); + iSampleBuffer->AddSample(iSample, length); + + length = EncodeChunkData(*aLibrary, *aThread); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +TBool DMemoryEventHandler::HandleDeleteLibrary(DLibrary* aLibrary) + { + Kern::Printf("DLibrary deleted: 0x%08x, time: %d", aLibrary, iCount); + NKern::ThreadEnterCS(); + Kern::MutexWait(*iLock); + // add header first + TInt err(AddHeader()); + + if(err != KErrNone) + { + return EFalse; + } + + // add new chunk tag + TInt length(EncodeRemoveCode()); + iSampleBuffer->AddSample(iSample, length); + + DThread* nullPointer = NULL; + length = EncodeChunkData(*aLibrary, *nullPointer); + iSampleBuffer->AddSample(iSample, length); + + // add end mark + AddFooter(); + Kern::MutexSignal(*iLock); + NKern::ThreadLeaveCS(); + return ETrue; + } + +// encode chunk name +TInt DMemoryEventHandler::EncodeChunkName(DChunk& c) + { + // the size of the following name is in the first byte + TUint8* size(&iSample[0]); + *size = 0; + + // encode chunk name + iSampleDescriptor.Zero(); + iSampleDescriptor.Append(_L("C_")); + c.TraceAppendFullName(iSampleDescriptor,false); + *size += iSampleDescriptor.Size(); + + // add chunk object address here + TUint32 chunkAddr((TUint32)&c); + iSampleDescriptor.Append((TUint8*)&(chunkAddr),sizeof(TUint32)); + *size += sizeof(TUint32); + + // the size is the descriptor length + the size field + LOGSTRING2("Non-Heap Chunk Name - %d",*size); + return ((TInt)(*size))+1; + } + +// encode chunk name +TInt DMemoryEventHandler::EncodeChunkName(DThread& t) + { + // the size of the following name is in the first byte + TUint8* size(&iSample[0]); + *size = 0; + iSampleDescriptor.Zero(); + + iSampleDescriptor.Append(_L("T_")); + t.TraceAppendFullName(iSampleDescriptor,false); + *size += iSampleDescriptor.Size(); + + // copy the 4 bytes from the thread id field + iSampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint)); + *size += sizeof(TUint); + + // the size is the descriptor length + the size field + LOGSTRING2("Name - %d",*size); + return ((TInt)(*size))+1; + } + +// encode chunk name +TInt DMemoryEventHandler::EncodeChunkName(DLibrary& l) + { + LOGTEXT("DMemoryEventHandler::EncodeChunkName (LIBRARY)"); + // the size of the following name is in the first byte + TUint8* size(&iSample[0]); + *size = 0; + iSampleDescriptor.Zero(); + + iSampleDescriptor.Append(_L("L_")); + l.TraceAppendFullName(iSampleDescriptor,false); + *size += iSampleDescriptor.Size(); + + // copy the library address here + TUint32 libAddr((TUint32)&l); + iSampleDescriptor.Append((TUint8*) &libAddr,sizeof(TUint32)); + *size += sizeof(TUint32); + + // the size is the descriptor length + the size field + LOGSTRING2("Name - %d",*size); + return ((TInt)(*size))+1; + } + +// record thread stack changes +TInt DMemoryEventHandler::EncodeChunkData(DThread& t) + { + LOGSTRING("DMemoryEventHandler::EncodeChunkDataT - entry"); + + // the size of the following name is in the first byte + TUint8* size(&iSample[0]); + *size = 0; + iSampleDescriptor.Zero(); + + iSampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint)); + *size += sizeof(TUint); + + // copy the total amount of memory allocated for user side stack + iSampleDescriptor.Append((TUint8*)&(t.iUserStackSize),sizeof(TInt)); + *size += sizeof(TInt); + + TInt zero(0); + // append the cell amount allocated (zero, not in use here) + iSampleDescriptor.Append((TUint8*)&zero,sizeof(TInt)); + *size += sizeof(TInt); + + // append the chunk size (this is not a chunk) + iSampleDescriptor.Append((TUint8*)&(zero),sizeof(TUint)); + *size += sizeof(TUint); + + // append user stack (max) size + iSampleDescriptor.Append((TUint8*)&(t.iUserStackSize),sizeof(TInt)); + *size += sizeof(TInt); + +// Kern::Printf("TData -> %d",*size); + return ((TInt)(*size))+1; + } + +// record chunk changes +TInt DMemoryEventHandler::EncodeChunkData(DChunk& c) + { + LOGSTRING("DMemoryEventHandler::EncodeChunkDataC - entry"); + + // the size of the following name is in the first byte + TUint8* size(&iSample[0]); + *size = 0; + iSampleDescriptor.Zero(); + TInt zero(0); + + TUint32 address((TUint32)&c); + + iSampleDescriptor.Append((TUint8*)&address,sizeof(TUint32)); + *size += sizeof(TUint); + + // copy the total amount of memory allocated + iSampleDescriptor.Append((TUint8*)&(c.iSize),sizeof(TInt)); + *size += sizeof(TInt); + + // append the cell amount allocated + iSampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + + // append the chunk size + iSampleDescriptor.Append((TUint8*)&(c.iSize),sizeof(TUint)); + *size += sizeof(TUint); + + // append the thread user stack size + iSampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + +// Kern::Printf("CData - %d",*size); + return ((TInt)(*size))+1; + } + +// record loaded libraries changes +TInt DMemoryEventHandler::EncodeChunkData(DLibrary& l, DThread& t) + { + LOGSTRING("DMemoryEventHandler::EncodeChunkDataL - entry"); + + // the size of the following name is in the first byte + TUint8* size(&iSample[0]); + *size = 0; + iSampleDescriptor.Zero(); + TInt zero(0); + + TUint32 address((TUint32)&l); + + iSampleDescriptor.Append((TUint8*)&address,sizeof(TUint32)); + *size += sizeof(TUint); + + // append amount of memory that library is allocated + iSampleDescriptor.Append((TUint8*)&(l.iCodeSeg->iSize),sizeof(TUint32)); + *size += sizeof(TInt); + + // append count of how many times librarys is allocated + iSampleDescriptor.Append((TUint8*)&(l.iMapCount),sizeof(TInt)); + *size += sizeof(TInt); + + if(&t != NULL) + { + // created by thread + iSampleDescriptor.Append((TUint8*)&(t),sizeof(TUint32)); + } + else + { + // removed + iSampleDescriptor.Append((TUint8*)&(zero),sizeof(TUint32)); + } + *size += sizeof(TUint); + + // append the thread user stack size + iSampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt)); + *size += sizeof(TInt); + return ((TInt)(*size))+1; + } + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/plugins/GeneralsPlugin/src/PriSamplerImpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/src/PriSamplerImpl.cpp Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,312 @@ +/* +* 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: +* +*/ + + +#include <piprofiler/ProfilerVersion.h> +#include <piprofiler/ProfilerTraces.h> + +#include <kern_priv.h> +#include <plat_priv.h> + +#include "PriSamplerImpl.h" + +#if !defined(__NKERN_H__) +#include <nkern.h> +#endif + +#define TAG(obj) (*(TUint32*)&(obj->iAsyncDeleteNext)) +#define PROFILER_THREAD_MARK ((TUint32)0x00000002) + + +DPriSamplerImpl::DPriSamplerImpl() : + sampleDescriptor(&(this->sample[1]),0,256) + { + LOGTEXT("PriSamplerImpl::PriSamplerImpl() - konstruktori"); + + iCountti = 50; // sample threads 16 cycles before actual MEM and PRI sample time... + iNewThreadCount = 0; + iThreadCount = 0; + iProcessing = ENothingToProcess; + + for(TInt i=0;i<KProfilerMaxThreadAmount;i++) + { + this->threadsToSample[i] = 0; + this->threadNamesToReport[i] = 0; + } + + } + +DPriSamplerImpl::~DPriSamplerImpl() + { + + } + +TInt DPriSamplerImpl::CreateFirstSample() + { + LOGTEXT("PriSamplerImpl::CreateFirstSample - entry"); + + this->sampleDescriptor.Zero(); + this->sampleDescriptor.Append(_L8("Bappea_V")); + this->sampleDescriptor.Append(PROFILER_PRI_SAMPLER_VERSION); + this->sampleDescriptor.Append(_L8("_PRI")); + + sample[0] = this->sampleDescriptor.Size(); + + LOGTEXT("PriSamplerImpl::CreateFirstSample - exit"); + + return (TInt)(sample[0]+1); + } + +TBool DPriSamplerImpl::SampleNeeded() + { + iCountti++; + if(iCountti % (iPriSamplingPeriod) == 0) + { + LOGTEXT("PriSamplerImpl::SampleNeeded - true"); + return true; + } + else + { + return false; + } + } + + +TInt DPriSamplerImpl::SampleImpl() + { + /* + * + * EKA-2 implementation of PRI trace + * + */ + if(this->iProcessing == ENothingToProcess) + { + if((iCountti % iPriSamplingPeriod) != 0 ) return 0; + + LOGTEXT("Processing threads..."); + + DObjectCon& threads = *Kern::Containers()[EThread]; + + // PRI trace variables + this->iThreadCount = 0; + this->iNewThreadCount = 0; + TInt totalThreadCount = threads.Count(); + + for(TInt i=0;i<totalThreadCount;i++) + { + DThread* t = (DThread*)(threads)[i]; + LOGSTRING3("Processing thread %d, tag: 0x%x",i,TAG(t)); + + if( (TAG(t) & PROFILER_THREAD_MARK) == 0) + { + LOGSTRING2("Marking thread %d",i); + // this thread's chunk has not been reported yet + this->threadNamesToReport[iNewThreadCount] = t; + iNewThreadCount++; + // tag the thread + TAG(t) |= PROFILER_THREAD_MARK; + LOGSTRING2("New Thread %d",i); + } + else + { + LOGSTRING3("Thread %d marked already - 0x%x",i,TAG(t)); + } + + // the thread has been tagged, add heap chunks to the list + this->threadsToSample[this->iThreadCount] = t; + this->iThreadCount++; + LOGSTRING2("Added thread %d to threads to sample",i); + } + + if(this->iThreadCount > 0 || this->iNewThreadCount > 0) + { + this->iProcessing = EStartingToProcess; + + // process the first sample + TInt length = this->ProcessChunks(); + + if(length == 0) + { + this->iProcessing = ENothingToProcess; + } + + return length; + } + else + { + // there were no threads, should not take place + LOGTEXT("PriSamplerImpl::SampleImpl - Error, no threads"); + return 0; + } + } + else + { + TInt length = this->ProcessChunks(); + if(length == 0) + { + this->iProcessing = ENothingToProcess; + } + return length; + } + } + +inline TInt DPriSamplerImpl::ProcessChunks() + { + /* + * + * EKA-2 implementation of PRI trace + * + */ + + if(iNewThreadCount > 0) + { + if(this->iProcessing == EStartingToProcess) + { + // this is the first sample, encode a code for names + this->iProcessing = EProcessingNames; + return EncodeNameCode(); + } + + // there are new thread names to report + iNewThreadCount--; + DThread* t = this->threadNamesToReport[iNewThreadCount]; + return EncodeChunkName(*t); + } + else if(iThreadCount > 0) + { + if(this->iProcessing == EProcessingNames || this->iProcessing == EStartingToProcess) + { + // this is the first data sample, encode a code for data + this->iProcessing = EProcessingData; + return EncodeDataCode(); + } + + // there are no new chunks to report + // thus generate the real report + iThreadCount--; + DThread* t = this->threadsToSample[iThreadCount]; + LOGSTRING2("PriSamplerImpl::ProcessChunks - starting to process thread 0x%x",t); + return EncodeChunkData(*t); + } + else + { + // everything is processed + return 0; + } + } + +inline TInt DPriSamplerImpl::EncodeNameCode() + { + sample[0] = 1; + sample[1] = 0xbb; // pri trace name code + return 2; + } + +inline TInt DPriSamplerImpl::EncodeDataCode() + { + sample[0] = 1; + sample[1] = 0xee; // pri trace data code + return 2; + } + + +inline TInt DPriSamplerImpl::EncodeChunkName(DThread& t) + { + // the size of the following name is in the first byte + TUint8* size = &sample[0]; + *size = 0; + this->sampleDescriptor.Zero(); + + t.TraceAppendFullName(this->sampleDescriptor,false); + *size += this->sampleDescriptor.Size(); + + // copy the 4 bytes from the thread id field + this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint)); + *size += sizeof(TUint); + + // the size is the descriptor length + the size field + LOGSTRING2("Name size - %d",*size); + return ((TInt)(*size))+1; + } + + +inline TInt DPriSamplerImpl::EncodeChunkData(DThread& t) + { + LOGTEXT("PriSamplerImpl::EncodeChunkData - entry"); + LOGSTRING2("PriSamplerImpl::EncodeChunkData - processing thread 0x%x ",&t); + + // the size of the following name is in the first byte + TUint8* size = &sample[0]; + *size = 0; + this->sampleDescriptor.Zero(); + + LOGTEXT("PriSamplerImpl::EncodeChunkData - cleared"); + + // append the thread id + this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint)); + *size += sizeof(TUint); + +// NKern::LockSystem(); +// TInt priority(-1); +// if(&t && t.Open()== KErrNone) +// { +// priority = t.iDefaultPriority; +// } +// NKern::UnlockSystem(); + + // append the priority of the nanokernel fast semaphore +// this->sampleDescriptor.Append((TUint8*)&priority,sizeof(TUint8)); + // append the priority of the nanokernel fast semaphore + this->sampleDescriptor.Append((TUint8*)&(t.iNThread.iPriority),sizeof(TUint8)); + // add space because EKA-1 implementation needs it + this->sampleDescriptor.Append((TUint8)0x0); + *size += 2*sizeof(TUint8); + + LOGTEXT("PriSamplerImpl::EncodeChunkData - appended priority"); + + + LOGSTRING2("Data size - %d",*size); + return ((TInt)(*size))+1; + } + + +void DPriSamplerImpl::Reset() + { + /* + * + * EKA-2 implementation of PRI trace + * + */ + + LOGTEXT("PriSamplerImpl::Reset"); + iCountti = 50; // sample threads 16 cycles before actual MEM and PRI sample time... + this->iThreadCount = 0; + this->iNewThreadCount = 0; + this->iProcessing = ENothingToProcess; + this->sampleDescriptor.Zero(); + + + // clear all thread tags + DObjectCon* threads = Kern::Containers()[EThread]; + TInt totalThreadCount = threads->Count(); + for(TInt i=0;i<totalThreadCount;i++) + { + DThread* t = (DThread*)(*threads)[i]; + TAG(t) = (TAG(t) & 0xfffffffd); + } + } + diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/rom/piprofiler.iby --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/rom/piprofiler.iby Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,38 @@ +/* +* 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: +* +*/ + + +#ifndef __PIPROFILER__ +#define __PIPROFILER__ + +// PI Profiler Engine itself +file=ABI_DIR\BUILD_DIR\PIProfilerEngine.exe sys\bin\PIProfilerEngine.exe +file=ABI_DIR\BUILD_DIR\PIProfiler.exe sys\bin\PIProfiler.exe +data=ZSYSTEM\Install\PIProfiler_stub.sis system\install\PIProfiler_stub.sis + +// sampler plugins +// NOTE: Mandatory kernel driver included in piprofiler_ldd.iby +ECOM_PLUGIN(PIProfilerGenerals.dll, PIProfilerGenerals.rsc) + +ECOM_PLUGIN(PIProfilerBUP.dll, PIProfilerBUP.rsc) +file=ABI_DIR\BUILD_DIR\PIProfilerTouchEventAnim.dll sys\bin\PIProfilerTouchEventAnim.dll + +// Writer plugins +ECOM_PLUGIN(piprofilerdebugwriter.dll, piprofilerdebugwriter.rsc) +ECOM_PLUGIN(piprofilerdiskwriter.dll, piprofilerdiskwriter.rsc) + +#endif //__PIPROFILER__ diff -r ccab7f1f8266 -r a71a3e32a2ae piprofiler/rom/piprofiler_ldd.iby --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/rom/piprofiler_ldd.iby Thu May 13 23:59:27 2010 +0300 @@ -0,0 +1,25 @@ +/* +* 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: +* +*/ + + +#ifndef __PIPROFILER_LDD__ +#define __PIPROFILER_LDD__ + +// kernel side driver +device[VARID]=KERNEL_DIR\BUILD_DIR\PIProfilerGeneralsSampler.ldd sys\bin\PIProfilerGeneralsSampler.ldd + +#endif //__PIPROFILER_LDD__ diff -r ccab7f1f8266 -r a71a3e32a2ae stif/Parser/src/StifParser.cpp --- a/stif/Parser/src/StifParser.cpp Mon May 03 13:58:41 2010 +0300 +++ b/stif/Parser/src/StifParser.cpp Thu May 13 23:59:27 2010 +0300 @@ -845,7 +845,7 @@ // // Method: HandleSpecialMarks // -// Description: Handles special marks.( '\/\/', '\/\*' and '*/\/' ). This +// Description: Handles special marks.( '\/' and '\*' ). This // is used when ECStyleComments comment type is used. // // Parameters: TPtr& aBuf: inout: section to parsed @@ -862,68 +862,28 @@ { TLex lex( aBuf ); TInt firstPos( 0 ); - TInt secondPos( 0 ); - - // // => \/\/ => // - // /* => \/\* => /* - // */ => \*\/ => */ - + + // Replace \/ with / + // Replace \* with * + do { + //RDebug::Print( _L("Print : %S"), &aBuf ); firstPos = lex.Offset(); TChar get = lex.Get(); // Check is '\' if( get == '\\' ) { - // Peek next character( '/' ) - if( lex.Peek() == '/' ) + firstPos = (lex.Offset()-1); + // Peek next character( '/' or '*' ) + if( lex.Peek() == '/' || lex.Peek() == '*') { - lex.Inc(); - secondPos = lex.Offset(); - // Peek next character( '\' ) - if( lex.Peek() == '\\' ) - { - lex.Inc(); - // Peek next character( '/' ) - if( lex.Peek() == '/' ) - { - // Delete mark '\/\/' and replace this with '//' - aBuf.Delete( secondPos, 1 ); - aBuf.Delete( firstPos, 1 ); - lex = aBuf; - } - // Peek next character( '/' ) - else if( lex.Peek() == '*' ) - { - // Delete mark '\/\*' and replace this with '/*' - aBuf.Delete( secondPos, 1 ); - aBuf.Delete( firstPos, 1 ); - lex = aBuf; - } - } - } - // Peek next character( '/' ) - else if( lex.Peek() == '*' ) - { - lex.Inc(); - secondPos = lex.Offset(); - // Peek next character( '\' ) - if( lex.Peek() == '\\' ) - { - lex.Inc(); - // Peek next character( '/' ) - if( lex.Peek() == '/' ) - { - // Delete mark '\*\/' and replace this with '*\' - aBuf.Delete( secondPos, 1 ); - aBuf.Delete( firstPos, 1 ); - lex = aBuf; - } - } + aBuf.Delete (firstPos,1); + lex = aBuf; } } + firstPos = 0; - secondPos = 0; } while ( !lex.Eos() ); } diff -r ccab7f1f8266 -r a71a3e32a2ae stif/StifKernelTestClassBase/group/StifKernelTestClassBase.mmp --- a/stif/StifKernelTestClassBase/group/StifKernelTestClassBase.mmp Mon May 03 13:58:41 2010 +0300 +++ b/stif/StifKernelTestClassBase/group/StifKernelTestClassBase.mmp Thu May 13 23:59:27 2010 +0300 @@ -27,7 +27,6 @@ SECUREID 0x102073DD EPOCALLOWDLLDATA - TARGET StifKernelTestClassBase.dll TARGETTYPE kdll UID 0x1000008D 0x101FB3E3 @@ -43,9 +42,4 @@ SOURCE StifKernelTestClassBase.cpp -LIBRARY ekern.lib - - - LANG SC - diff -r ccab7f1f8266 -r a71a3e32a2ae stif/group/ReleaseNote.txt --- a/stif/group/ReleaseNote.txt Mon May 03 13:58:41 2010 +0300 +++ b/stif/group/ReleaseNote.txt Thu May 13 23:59:27 2010 +0300 @@ -1,5 +1,5 @@ ======================================================================== -RELEASE NOTE FOR STIF - STIF_201012 (7.3.29) +RELEASE NOTE FOR STIF - STIF_201018 (7.3.32) SUPPORTING SERIES 60 3.0 -> ======================================================================== diff -r ccab7f1f8266 -r a71a3e32a2ae stif/inc/version.h --- a/stif/inc/version.h Mon May 03 13:58:41 2010 +0300 +++ b/stif/inc/version.h Thu May 13 23:59:27 2010 +0300 @@ -20,9 +20,9 @@ #define STIF_MAJOR_VERSION 7 #define STIF_MINOR_VERSION 3 -#define STIF_BUILD_VERSION 29 +#define STIF_BUILD_VERSION 32 -#define STIF_REL_DATE "23th Mar 2010" +#define STIF_REL_DATE "04th May 2010" #define TO_UNICODE(text) _L(text) diff -r ccab7f1f8266 -r a71a3e32a2ae stif/sis/Stif_31.sis Binary file stif/sis/Stif_31.sis has changed