memana/analyzetoolclient/commandlineengine/internal/src/cataddr2lineserver.cpp
changeset 0 f0f2b8682603
equal deleted inserted replaced
-1:000000000000 0:f0f2b8682603
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Class representing a server that uses addr2line.exe.
       
    15 *
       
    16 */
       
    17 
       
    18 #include "../inc/cataddr2lineserver.h"
       
    19 #include "../inc/CATBase.h"
       
    20 
       
    21 // ----------------------------------------------------------------------------
       
    22 // Constructor
       
    23 // ----------------------------------------------------------------------------
       
    24 CATAddr2lineServer::CATAddr2lineServer()
       
    25 {
       
    26 	LOG_FUNC_ENTRY("CATAddr2lineServer::CATAddr2lineServer");
       
    27 	m_bProcessCreated = false;
       
    28 
       
    29 	// Pipe handles.
       
    30 	m_hChildErroutRd = 0;
       
    31 	m_hChildErroutRdDup = 0;
       
    32 	m_hChildErroutWr = 0;
       
    33 	m_hChildStdinRd = 0;
       
    34 	m_hChildStdinWr = 0;
       
    35 	m_hChildStdinWrDup = 0;
       
    36 	m_hChildStdoutRd = 0;
       
    37 	m_hChildStdoutWr = 0;
       
    38 	m_hChildStdoutRdDup = 0;
       
    39 	
       
    40 	m_hSaveErrout = 0;
       
    41 	m_hSaveStdin = 0;
       
    42 	m_hSaveStdout = 0;
       
    43 
       
    44     // Set the bInheritHandle flag so pipe handles are inherited.
       
    45     m_saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
       
    46     m_saAttr.bInheritHandle = TRUE;
       
    47     m_saAttr.lpSecurityDescriptor = NULL;
       
    48 
       
    49 	// Symbol file.
       
    50 	m_sFullPathAndBinaryName = "";
       
    51 }
       
    52 // ----------------------------------------------------------------------------
       
    53 // Destructor
       
    54 // ----------------------------------------------------------------------------
       
    55 CATAddr2lineServer::~CATAddr2lineServer()
       
    56 {
       
    57 	LOG_FUNC_ENTRY("CATAddr2lineServer::~CATAddr2lineServer");
       
    58 	// Close the pipe handle so the child process stops reading.
       
    59     CloseHandle(m_hChildStdinWrDup);
       
    60     // Close the write end of the pipe
       
    61     CloseHandle(m_hChildStdoutWr);
       
    62     // Close the write end of the error pipe
       
    63 	CloseHandle(m_hChildErroutWr);
       
    64 }
       
    65 bool CATAddr2lineServer::Initialize( const string& sFullPathAndBinaryName )
       
    66 {
       
    67     LOG_FUNC_ENTRY("CATAddr2lineServer::Initialize");
       
    68 	BOOL fSuccess;
       
    69 	m_sFullPathAndBinaryName = sFullPathAndBinaryName;
       
    70 
       
    71     // The steps for redirecting child process's STDOUT:
       
    72     //     1. Save current STDOUT, to be restored later.
       
    73     //     2. Create anonymous pipe to be STDOUT for child process.
       
    74     //     3. Set STDOUT of the parent process to be write handle to
       
    75     //        the pipe, so it is inherited by the child process.
       
    76     //     4. Create a noninheritable duplicate of the read handle and
       
    77     //        close the inheritable read handle.
       
    78  
       
    79     // Save the handle to the current STDOUT. 
       
    80     m_hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
       
    81 
       
    82     // Create a pipe for the child process's STDOUT.
       
    83     if (! CreatePipe(&m_hChildStdoutRd, &m_hChildStdoutWr, &m_saAttr, 0))
       
    84 		return PrintErrorAndExit( "Stdout pipe creation failed\n" );
       
    85 
       
    86     // Set a write handle to the pipe to be STDOUT.
       
    87    if (! SetStdHandle(STD_OUTPUT_HANDLE, m_hChildStdoutWr))
       
    88 		return PrintErrorAndExit( "Redirecting STDOUT failed\n" );
       
    89 
       
    90     // Create noninheritable read handle and close the inheritable read
       
    91     // handle.
       
    92     fSuccess = DuplicateHandle(GetCurrentProcess(), m_hChildStdoutRd,
       
    93         GetCurrentProcess(), &m_hChildStdoutRdDup , 0,
       
    94         FALSE,
       
    95         DUPLICATE_SAME_ACCESS);
       
    96     if( !fSuccess )
       
    97 		return PrintErrorAndExit( "DuplicateHandle failed" );
       
    98     CloseHandle(m_hChildStdoutRd);
       
    99 
       
   100     // The steps for redirecting child process's STDIN:
       
   101     //     1.  Save current STDIN, to be restored later.
       
   102     //     2.  Create anonymous pipe to be STDIN for child process.
       
   103     //     3.  Set STDIN of the parent to be the read handle to the
       
   104     //         pipe, so it is inherited by the child process.
       
   105     //     4.  Create a noninheritable duplicate of the write handle,
       
   106     //         and close the inheritable write handle.
       
   107  
       
   108     // Save the handle to the current STDIN.
       
   109     m_hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
       
   110 
       
   111     // Create a pipe for the child process's STDIN.
       
   112     if (! CreatePipe(&m_hChildStdinRd, &m_hChildStdinWr, &m_saAttr, 0))
       
   113 		return PrintErrorAndExit( "Stdin pipe creation failed\n" );
       
   114  
       
   115     // Set a read handle to the pipe to be STDIN. 
       
   116     if (! SetStdHandle(STD_INPUT_HANDLE, m_hChildStdinRd)) 
       
   117 		return PrintErrorAndExit( "Redirecting Stdin failed\n" ); 
       
   118  
       
   119     // Duplicate the write handle to the pipe so it is not inherited. 
       
   120 	
       
   121     fSuccess = DuplicateHandle(GetCurrentProcess(), m_hChildStdinWr, 
       
   122         GetCurrentProcess(), &m_hChildStdinWrDup, 0, 
       
   123         FALSE,                  // not inherited 
       
   124         DUPLICATE_SAME_ACCESS); 
       
   125     if (! fSuccess) 
       
   126 		return PrintErrorAndExit( "DuplicateHandle failed\n" );
       
   127 
       
   128     CloseHandle(m_hChildStdinWr);
       
   129  
       
   130     // The steps for redirecting child process's ERROUT:
       
   131     //     1. Save current STDOUT, to be restored later.
       
   132     //     2. Create anonymous pipe to be STDOUT for child process.
       
   133     //     3. Set STDOUT of the parent process to be write handle to
       
   134     //        the pipe, so it is inherited by the child process.
       
   135     //     4. Create a noninheritable duplicate of the read handle and
       
   136     //        close the inheritable read handle.
       
   137  
       
   138     // Save the handle to the current STDOUT. 
       
   139     m_hSaveErrout = GetStdHandle( STD_ERROR_HANDLE ); 
       
   140 
       
   141     // Create a pipe for the child process's ERROUT.
       
   142     if (! CreatePipe(&m_hChildErroutRd, &m_hChildErroutWr, &m_saAttr, 0))
       
   143 		return PrintErrorAndExit( "Errout pipe creation failed\n" );
       
   144 
       
   145     // Set a write handle to the pipe to be ERROUT.
       
   146    if (! SetStdHandle(STD_ERROR_HANDLE, m_hChildErroutWr))
       
   147 		return PrintErrorAndExit( "Redirecting ERROUT failed\n" );
       
   148 
       
   149     // Create noninheritable read handle and close the inheritable read
       
   150     // handle.
       
   151    
       
   152     fSuccess = DuplicateHandle(GetCurrentProcess(), m_hChildErroutRd,
       
   153         GetCurrentProcess(), &m_hChildErroutRdDup , 0,
       
   154         FALSE,
       
   155         DUPLICATE_SAME_ACCESS);
       
   156     if( !fSuccess )
       
   157 		return PrintErrorAndExit( "DuplicateHandle failed" );
       
   158     
       
   159 	CloseHandle(m_hChildErroutRd);
       
   160 	CloseHandle(m_hChildErroutRdDup);
       
   161 	
       
   162 	// Now create the child process. 
       
   163     fSuccess = CreateChildProcess();
       
   164     if (!fSuccess )
       
   165 		return PrintErrorAndExit( "Create process failed\n" );
       
   166  
       
   167     // After process creation, restore the saved STDIN and STDOUT.
       
   168 	if (! SetStdHandle(STD_INPUT_HANDLE, m_hSaveStdin))
       
   169         return PrintErrorAndExit( "Re-redirecting Stdin failed\n" );
       
   170 
       
   171 	if (! SetStdHandle(STD_OUTPUT_HANDLE, m_hSaveStdout))
       
   172        return PrintErrorAndExit( "Re-redirecting Stdout failed\n" );
       
   173 
       
   174 	if (! SetStdHandle(STD_ERROR_HANDLE, m_hSaveErrout))
       
   175        return PrintErrorAndExit( "Re-redirecting Stderrout failed\n" );
       
   176 
       
   177 	m_bProcessCreated = true;
       
   178     return true;
       
   179 }
       
   180 BOOL CATAddr2lineServer::CreateChildProcess() 
       
   181 { 
       
   182     LOG_FUNC_ENTRY("CATAddr2lineServer::CreateChildProcess");
       
   183     PROCESS_INFORMATION piProcInfo; 
       
   184     STARTUPINFO siStartInfo;
       
   185     BOOL bFuncRetn = FALSE; 
       
   186  
       
   187     // Set up members of the PROCESS_INFORMATION structure.
       
   188     ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
       
   189  
       
   190 	// Set up members of the STARTUPINFO structure.
       
   191     ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
       
   192     siStartInfo.cb = sizeof(STARTUPINFO); 
       
   193  
       
   194 	//atool.exe:s path + filename
       
   195 	char buffer[MAX_PATH];
       
   196 
       
   197 	GetModuleFileName( NULL, buffer, MAX_PATH );
       
   198 
       
   199 	string sCommand( buffer );
       
   200 
       
   201 	//Remove 'atool.exe'
       
   202 	size_t tPos = sCommand.rfind( "\\" );
       
   203 	if ( tPos != string::npos )
       
   204 		sCommand.resize( sCommand.rfind( "\\" )+1 );
       
   205 	else
       
   206 		sCommand.clear();
       
   207 
       
   208 	sCommand.append( "addr2line.exe" );
       
   209 
       
   210 	//addr2line file exists
       
   211 	if( !CATBase::FileExists( sCommand.c_str() ) )
       
   212 		return PrintErrorAndExit( "File not found addr2line.exe\n" );
       
   213 
       
   214 	//Sym file exists
       
   215 	if( !CATBase::FileExists( m_sFullPathAndBinaryName.c_str() ) )
       
   216 	{
       
   217 		string sTemp( "File not found " );
       
   218 		sTemp.append( m_sFullPathAndBinaryName );
       
   219 		sTemp.append( "\n" );
       
   220 		return PrintErrorAndExit( sTemp );
       
   221 	}
       
   222 
       
   223 	sCommand.append(" -f -C -e ");
       
   224 	sCommand.append( m_sFullPathAndBinaryName );
       
   225 
       
   226 	// Create the child process. 
       
   227     bFuncRetn = CreateProcess(NULL,
       
   228 		(LPSTR)sCommand.c_str(), // command line
       
   229         NULL,          // process security attributes
       
   230         NULL,          // primary thread security attributes
       
   231         TRUE,          // handles are inherited
       
   232         0,             // creation flags
       
   233         NULL,          // use parent's environment
       
   234         NULL,          // use parent's current directory
       
   235         &siStartInfo,  // STARTUPINFO pointer
       
   236         &piProcInfo);  // receives PROCESS_INFORMATION
       
   237 
       
   238     if (bFuncRetn == 0)
       
   239     {
       
   240        //CreateProcess failed
       
   241        return false;
       
   242     }
       
   243     else
       
   244     {
       
   245        CloseHandle(piProcInfo.hProcess);
       
   246        CloseHandle(piProcInfo.hThread);
       
   247        return bFuncRetn;
       
   248     }
       
   249 }
       
   250 VOID CATAddr2lineServer::WriteToPipe( const string& sAddress ) 
       
   251 { 
       
   252 	LOG_LOW_FUNC_ENTRY("CATAddr2lineServer::WriteToPipe");
       
   253     DWORD dwRead, dwWritten;
       
   254     CHAR chBuf[2]; //This is for enter key
       
   255 
       
   256     //Write data to a pipe. 
       
   257     dwRead = (DWORD)sAddress.length();
       
   258 	WriteFile(m_hChildStdinWrDup, sAddress.c_str(), dwRead, &dwWritten, NULL);
       
   259 
       
   260 	chBuf[0] = 0x0A; //Enter
       
   261 	chBuf[1] = 0; //NULL
       
   262 	//Write enter key to a pipe
       
   263 	WriteFile(m_hChildStdinWrDup, chBuf, 1, &dwWritten, NULL);
       
   264 } 
       
   265 string CATAddr2lineServer::ReadFromPipe(VOID) 
       
   266 {
       
   267 	LOG_LOW_FUNC_ENTRY("CATAddr2lineServer::ReadFromPipe");
       
   268 	string s;
       
   269 	DWORD dwRead;
       
   270     CHAR chBuf[BUFSIZE];
       
   271     // Read output from the child process, and save data to string.
       
   272     ReadFile( m_hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead, NULL);
       
   273 	s.append( chBuf );
       
   274     return s;
       
   275 }
       
   276 bool CATAddr2lineServer::GetProcessCreatedState( void )
       
   277 {
       
   278 	LOG_LOW_FUNC_ENTRY("CATAddr2lineServer::GetProcessCreatedState");
       
   279 	return m_bProcessCreated;
       
   280 }
       
   281 bool CATAddr2lineServer::PrintErrorAndExit( const string sInput )
       
   282 {
       
   283 	LOG_FUNC_ENTRY("CATAddr2lineServer::PrintErrorAndExit");
       
   284 	cout << AT_MSG << sInput;
       
   285 	return false;
       
   286 }