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