diff -r 000000000000 -r f0f2b8682603 memana/analyzetoolclient/commandlineengine/internal/src/cataddr2lineserver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memana/analyzetoolclient/commandlineengine/internal/src/cataddr2lineserver.cpp Thu Feb 11 15:51:35 2010 +0200 @@ -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; +}