diff -r d27dfa8884ad -r da2cedce4920 analyzetool/commandlineengine/src/CATDatParser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/CATDatParser.cpp Tue May 25 14:22:58 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* 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