memana/analyzetoolclient/commandlineengine/internal/src/cataddr2lineserver.cpp
changeset 0 f0f2b8682603
--- /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;
+}