--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/perfsrv/analyzetool/commandlineengine/src/cataddr2lineserver.cpp Fri Sep 17 08:38:31 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;
+}