analyzetool/commandlineengine/src/cataddr2line.cpp
branchRCL_3
changeset 13 da2cedce4920
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/analyzetool/commandlineengine/src/cataddr2line.cpp	Tue May 25 14:22:58 2010 +0300
@@ -0,0 +1,388 @@
+/*
+* 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:  Main module for addr2line pinpointing.
+*
+*/
+
+#include "../inc/cataddr2line.h"
+#include "../inc/CATMemoryAddress.h"
+#include "../inc/CATBase.h"
+#include "../inc/CATDatParser.h"
+
+#define ASCII_CHAR_CARRIAGE_RETURN 0x0D
+
+CATAddr2line::CATAddr2line()
+{
+	LOG_FUNC_ENTRY("CATAddr2line::CATAddr2line");
+}
+
+bool CATAddr2line::Open( const string& sParameter, const unsigned long /* iLong */ )
+{
+	LOG_FUNC_ENTRY("CATAddr2line::Open");
+	//Debugging for addr2line task.
+	//debug.open( "addr2line-lines.txt", ios_base::trunc );
+
+	m_sMapFileName.clear();
+	// Add .map extendsion
+	m_sMapFileName.append( sParameter );
+	m_sMapFileName.append( ".map" );
+
+	ReadMapFileArmv5();
+
+	//Make symfile path+name
+	string sFullPathToSymFile(sParameter);
+	sFullPathToSymFile.erase( sFullPathToSymFile.find_last_of( "." ), string::npos );
+	sFullPathToSymFile.append( ".sym" );
+
+	// Check with extension + .sym also.
+	if ( ! CATBase::FileExists( sFullPathToSymFile.c_str() ) )
+	{
+		sFullPathToSymFile.clear();
+		sFullPathToSymFile.append( sParameter );
+		sFullPathToSymFile.append( ".sym" );
+	}
+
+	return server.Initialize( sFullPathToSymFile );
+}
+
+string CATAddr2line::GetError( void )
+{
+	LOG_FUNC_ENTRY("CATAddr2line::GetError");
+	string s;
+	return s;
+}
+
+bool CATAddr2line::Close( void )
+{
+	LOG_FUNC_ENTRY("CATAddr2line::Close");
+	//Debugging for addr2line task.
+	//debug.close();
+	return true;
+}
+
+bool CATAddr2line::AddressToLine( CATMemoryAddress* result )
+{
+	LOG_FUNC_ENTRY("CATAddr2line::AddressToLine");
+	
+	result->SetAddressToLineState( CATMemoryAddress::OUT_OF_RANGE);
+
+	if( !server.GetProcessCreatedState() )
+		return false;
+	//Count address
+	ULONG uStartA = result->GetModuleStartAddress();
+	ULONG uMemoryA = result->GetAddress();
+	ULONG uCountedA = uMemoryA - uStartA;
+	uCountedA += FUNCTIONS_OFFSET_IN_GCCE;
+
+	string sTemp = CATBase::NumberToHexString( uCountedA );
+    //Remove "0x"
+    size_t iCounter = sTemp.find_first_of('x');
+    if( iCounter != string::npos )
+    {
+		sTemp.erase( 0, (int)iCounter+1 );
+    }
+	// Write to pipe that is the standard input for a child process.
+	server.WriteToPipe( sTemp ); 
+ 
+	// Read from pipe that is the standard output for child process.
+    string s = server.ReadFromPipe();
+
+	//If output not empty, parse output
+	if( !s.empty() )
+	{
+		//Debugging code for addr2line task.
+		//debug.write( "##########\n", 12 );
+		//debug.write( s.c_str(), s.size() );
+		result->SetAddressToLineState( CATMemoryAddress::EXACT );
+
+		string s2;
+		size_t iLocation = s.find_first_of( ASCII_CHAR_CARRIAGE_RETURN );
+
+		bool bFunctionNameFoundUsingAddr2line = false;
+
+		//Function name
+		
+		if(iLocation != string::npos )
+		{
+			s2 = s.substr( 0, iLocation );
+			//All characters ascii?
+			if( CATBase::IsAscii( s2.c_str(), (int)s2.length() ) )
+			{
+				//addr2line returns $x if function name not found
+				//length must over 2 to be real function name
+				if( s2.length() > 2 )
+				{
+					bFunctionNameFoundUsingAddr2line = true;
+					result->SetFunctionName( s2 );
+					s.erase( 0, iLocation+2 );
+				}
+			}
+		}
+		//If function name not found using addr2line find it from map file
+		if( !bFunctionNameFoundUsingAddr2line )
+		{
+			string sFuncName( GetFunctionNameUsingAddress( uCountedA ) );
+			//If function name empty, print "???"
+			if( sFuncName.empty() )
+			{
+				s2 = "???";
+				result->SetFunctionName( s2 );
+				if(iLocation != string::npos )
+				{
+					s.erase( 0, iLocation+2 );
+				}
+			}
+			else
+				result->SetFunctionName( sFuncName );
+		}
+		iLocation = s.find_first_of( ':' );
+
+		//Filename and location
+
+		if(iLocation != string::npos )
+		{
+			s2 = s.substr( 0, iLocation );
+			result->SetFileName( s2 );
+			s.erase( 0, iLocation+1 );
+		}
+
+		//Exact line number
+
+		s2 = s.substr( 0, s.find_first_of( ASCII_CHAR_CARRIAGE_RETURN ) );
+		result->SetExactLineNumber( atoi( s2.c_str() ) );
+	}
+	return true;
+}
+
+bool CATAddr2line::ReadMapFileArmv5()
+{
+	LOG_FUNC_ENTRY("CATModule2::ReadMapFileArmv5");
+	// Open .map file
+	ifstream in( m_sMapFileName.c_str() );
+	// File open ok?
+	if( ! in.good() )
+	{
+		in.close();
+		return false;
+	}
+	char cTemp[MAX_LINE_LENGTH];
+	bool bFirstFuncFound = false;
+	bool bFirstLine = true;
+	// Get all lines where is "Thumb"
+	do
+	{
+		// Load one line from .map file
+		in.getline( cTemp, MAX_LINE_LENGTH );
+		if( bFirstLine )
+		{
+			bFirstLine = false;
+			if( strstr( cTemp, "ARM Linker" ) == NULL )
+				return false;
+		}
+		// Find _E32Startup
+		if( !bFirstFuncFound && ( strstr( cTemp, "_E32Startup" ) != NULL) )
+		{
+			bFirstFuncFound = true;
+		}
+		else if( !bFirstFuncFound && ( strstr( cTemp, "_E32Dll" ) != NULL) )
+		{
+			bFirstFuncFound = true;
+		}
+		else if( !bFirstFuncFound )
+			// Skip if _E32Startup not found
+			continue;
+
+		if( strstr( cTemp, "Thumb Code" ) != NULL || strstr( cTemp, "ARM Code" ) != NULL)
+		{
+			MAP_FUNC_INFO structMapFileLineInfo;
+			structMapFileLineInfo.sWholeLine.append( cTemp );
+
+			// Get memory string address from line
+			char* pStart = strstr( cTemp, "0x" );
+			// Check did strstr return null.
+			if ( pStart == NULL )
+				continue;
+			char* pTemp = pStart;
+			char TempString[MAX_LINE_LENGTH];
+			TempString[0] = 0;
+			size_t iLength = 0;
+			while( *pTemp != ' ' )
+			{
+				TempString[iLength] = *pTemp;
+				pTemp++;
+				iLength++;
+			}
+			TempString[iLength] = 0;
+
+			structMapFileLineInfo.iAddress = CATDatParser::_httoi( TempString );
+
+			pTemp = cTemp;
+			TempString[0] = 0;
+			
+			// Get function name
+
+			// Skip spaces
+			while( *pTemp == ' ' )
+			{
+				pTemp++;
+			}
+			iLength = 0;
+			// Find end of function name
+			string sTemp( pTemp );
+
+			// Location of character ')'
+			iLength = sTemp.find_first_of(')');
+
+			// Location of character ' '
+			size_t iLength2 = sTemp.find_first_of(' ');
+			
+			// If ')' character is the last char and
+			// character ' ' is closer than ')' use location of ' '
+			if( ( iLength + 1 ) == sTemp.length() && iLength2 < iLength )
+				iLength = iLength2 - 1;
+			
+			if( iLength != string::npos )
+				sTemp.resize( (iLength + 1) );
+
+			structMapFileLineInfo.sFunctionName.append( sTemp.c_str() );
+
+			bool bARM = false;
+			// Find function length
+			pStart = strstr( cTemp, "Thumb Code" );
+			if( pStart == NULL )
+			{
+				pStart = strstr( cTemp, "ARM Code" );
+				bARM = true;
+			}
+			if( pStart != NULL )
+			{
+				if( bARM )
+					pStart += 8;
+				else
+					pStart += 10;
+				while(*pStart == ' ')
+				{
+					pStart++;
+				}
+				sTemp.clear();
+				sTemp.append( pStart );
+				size_t iSize = sTemp.find_first_of(' ');
+				if( iSize != string::npos )
+					sTemp.resize( iSize );
+			}
+
+			structMapFileLineInfo.iFuncLength = atoi( sTemp.c_str() );
+			if( bFirstFuncFound && structMapFileLineInfo.iFuncLength > 0 )
+				// Save to list
+				m_vMapFileFuncList.push_back( structMapFileLineInfo );
+		}
+	}
+	while( in.good() );
+	in.close();
+	return true;
+}
+
+// Find function name of given address
+string CATAddr2line::GetFunctionNameUsingAddress( unsigned long iAddress )
+{
+	LOG_LOW_FUNC_ENTRY("CATAddr2line::GetSymbolIndexUsingAddress");
+	string sRet;
+	for( size_t i = 0; i < m_vMapFileFuncList.size(); i++ )
+	{
+		unsigned long iStart = m_vMapFileFuncList.at( i ).iAddress;
+		unsigned long iEnd = ( m_vMapFileFuncList.at( i ).iAddress
+			+ m_vMapFileFuncList.at( i ).iFuncLength );
+
+		if ( iAddress >= iStart && iAddress < iEnd )
+			return m_vMapFileFuncList.at( i ).sFunctionName;
+	}
+	return sRet;
+}
+
+//Note: New filtering functions commented out until they are taken into use.
+/**
+* Filter string out of unwanted characters.
+*/
+/*
+void CATAddr2line::FilterString( string &sString )
+{
+	LOG_LOW_FUNC_ENTRY("CATAddr2line::FilterString");
+	string sFiltered("");
+	for( size_t i = 0 ; i < sString.length() ; i++ )
+	{
+		const char p = sString.at( i );
+		if ( p != 0 && strchr( ADDR2LINEALLOWEDCHARS, p ) != 0 )
+			sFiltered.push_back( p );
+	}
+	sString = sFiltered;
+}
+*/
+/**
+* Find line feed position from string.
+*/
+/*
+size_t CATAddr2line::FindLineFeed( const string& sString )
+{
+	LOG_LOW_FUNC_ENTRY("CATAddr2line::FindLineFeed");
+	size_t iLineFeed1 = sString.find( 12 );
+	size_t iLineFeed2 = sString.find( 15 );
+	if ( iLineFeed1 < iLineFeed2 && iLineFeed1 != string::npos )
+		return iLineFeed1;
+	else if ( iLineFeed2 != string::npos )
+		return iLineFeed2;
+	else
+		return string::npos;
+}
+*/
+/**
+* Erase characters from start of the string until other char than linefeed found.
+*/
+/*
+void CATAddr2line::EraseUntilNoLineFeed( string& sString )
+{
+	LOG_LOW_FUNC_ENTRY("CATAddr2line::EraseUntilNoLineFeed");
+	for ( size_t i = 0 ; i < sString.length() ; i++ )
+	{
+		if ( sString.at( i ) != 15 && sString.at( i ) != 12 )
+			break;
+	}
+	sString.erase( 0, i );
+}
+*/
+/**
+* Split multiple line string with unexpected line feeds to vector of strings.
+*/
+/*
+vector<string> CATAddr2line::SplitToStrings( string& sMultiLineString )
+{
+	LOG_LOW_FUNC_ENTRY("CATAddr2line::SplitToStrings");
+    vector<string> vLines;
+	while ( 1 )
+	{
+		size_t iLineFeed = FindLineFeed( sMultiLineString );
+		if ( iLineFeed == string::npos )
+			break;
+		string sCell = sMultiLineString.substr(0, iLineFeed );
+		sMultiLineString.erase(0, iLineFeed );
+		EraseUntilNoLineFeed( sMultiLineString );
+		FilterString( sCell );
+		vLines.push_back( sCell );
+	}
+	// If no lines were found set single one.
+	if ( vLines.size() == 0 )
+		vLines.push_back( sMultiLineString );
+	return vLines;
+}
+*/
+//EOF