memana/analyzetoolclient/commandlineengine/internal/src/cataddr2line.cpp
changeset 2 6a82cd05fb1e
parent 1 3ff3fecb12fe
equal deleted inserted replaced
1:3ff3fecb12fe 2:6a82cd05fb1e
     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:  Main module for addr2line pinpointing.
       
    15 *
       
    16 */
       
    17 
       
    18 #include "../inc/cataddr2line.h"
       
    19 #include "../inc/CATMemoryAddress.h"
       
    20 #include "../inc/CATBase.h"
       
    21 #include "../inc/CATDatParser.h"
       
    22 
       
    23 #define ASCII_CHAR_CARRIAGE_RETURN 0x0D
       
    24 
       
    25 CATAddr2line::CATAddr2line()
       
    26 {
       
    27 	LOG_FUNC_ENTRY("CATAddr2line::CATAddr2line");
       
    28 }
       
    29 
       
    30 bool CATAddr2line::Open( const string& sParameter, const unsigned long /* iLong */ )
       
    31 {
       
    32 	LOG_FUNC_ENTRY("CATAddr2line::Open");
       
    33 	//Debugging for addr2line task.
       
    34 	//debug.open( "addr2line-lines.txt", ios_base::trunc );
       
    35 
       
    36 	m_sMapFileName.clear();
       
    37 	// Add .map extendsion
       
    38 	m_sMapFileName.append( sParameter );
       
    39 	m_sMapFileName.append( ".map" );
       
    40 
       
    41 	ReadMapFileArmv5();
       
    42 
       
    43 	//Make symfile path+name
       
    44 	string sFullPathToSymFile(sParameter);
       
    45 	sFullPathToSymFile.erase( sFullPathToSymFile.find_last_of( "." ), string::npos );
       
    46 	sFullPathToSymFile.append( ".sym" );
       
    47 
       
    48 	// Check with extension + .sym also.
       
    49 	if ( ! CATBase::FileExists( sFullPathToSymFile.c_str() ) )
       
    50 	{
       
    51 		sFullPathToSymFile.clear();
       
    52 		sFullPathToSymFile.append( sParameter );
       
    53 		sFullPathToSymFile.append( ".sym" );
       
    54 	}
       
    55 
       
    56 	return server.Initialize( sFullPathToSymFile );
       
    57 }
       
    58 
       
    59 string CATAddr2line::GetError( void )
       
    60 {
       
    61 	LOG_FUNC_ENTRY("CATAddr2line::GetError");
       
    62 	string s;
       
    63 	return s;
       
    64 }
       
    65 
       
    66 bool CATAddr2line::Close( void )
       
    67 {
       
    68 	LOG_FUNC_ENTRY("CATAddr2line::Close");
       
    69 	//Debugging for addr2line task.
       
    70 	//debug.close();
       
    71 	return true;
       
    72 }
       
    73 
       
    74 bool CATAddr2line::AddressToLine( CATMemoryAddress* result )
       
    75 {
       
    76 	LOG_FUNC_ENTRY("CATAddr2line::AddressToLine");
       
    77 	
       
    78 	result->SetAddressToLineState( CATMemoryAddress::ADDRESS_TO_LINE_STATE::OUT_OF_RANGE);
       
    79 
       
    80 	if( !server.GetProcessCreatedState() )
       
    81 		return false;
       
    82 	//Count address
       
    83 	ULONG uStartA = result->GetModuleStartAddress();
       
    84 	ULONG uMemoryA = result->GetAddress();
       
    85 	ULONG uCountedA = uMemoryA - uStartA;
       
    86 	uCountedA += FUNCTIONS_OFFSET_IN_GCCE;
       
    87 
       
    88 	string sTemp = CATBase::NumberToHexString( uCountedA );
       
    89     //Remove "0x"
       
    90     size_t iCounter = sTemp.find_first_of('x');
       
    91     if( iCounter != string::npos )
       
    92     {
       
    93 		sTemp.erase( 0, (int)iCounter+1 );
       
    94     }
       
    95 	// Write to pipe that is the standard input for a child process.
       
    96 	server.WriteToPipe( sTemp ); 
       
    97  
       
    98 	// Read from pipe that is the standard output for child process.
       
    99     string s = server.ReadFromPipe();
       
   100 
       
   101 	//If output not empty, parse output
       
   102 	if( !s.empty() )
       
   103 	{
       
   104 		//Debugging code for addr2line task.
       
   105 		//debug.write( "##########\n", 12 );
       
   106 		//debug.write( s.c_str(), s.size() );
       
   107 		result->SetAddressToLineState( CATMemoryAddress::ADDRESS_TO_LINE_STATE::EXACT );
       
   108 
       
   109 		string s2;
       
   110 		size_t iLocation = s.find_first_of( ASCII_CHAR_CARRIAGE_RETURN );
       
   111 
       
   112 		bool bFunctionNameFoundUsingAddr2line = false;
       
   113 
       
   114 		//Function name
       
   115 		
       
   116 		if(iLocation != string::npos )
       
   117 		{
       
   118 			s2 = s.substr( 0, iLocation );
       
   119 			//All characters ascii?
       
   120 			if( CATBase::IsAscii( s2.c_str(), (int)s2.length() ) )
       
   121 			{
       
   122 				//addr2line returns $x if function name not found
       
   123 				//length must over 2 to be real function name
       
   124 				if( s2.length() > 2 )
       
   125 				{
       
   126 					bFunctionNameFoundUsingAddr2line = true;
       
   127 					result->SetFunctionName( s2 );
       
   128 					s.erase( 0, iLocation+2 );
       
   129 				}
       
   130 			}
       
   131 		}
       
   132 		//If function name not found using addr2line find it from map file
       
   133 		if( !bFunctionNameFoundUsingAddr2line )
       
   134 		{
       
   135 			string sFuncName( GetFunctionNameUsingAddress( uCountedA ) );
       
   136 			//If function name empty, print "???"
       
   137 			if( sFuncName.empty() )
       
   138 			{
       
   139 				s2 = "???";
       
   140 				result->SetFunctionName( s2 );
       
   141 				if(iLocation != string::npos )
       
   142 				{
       
   143 					s.erase( 0, iLocation+2 );
       
   144 				}
       
   145 			}
       
   146 			else
       
   147 				result->SetFunctionName( sFuncName );
       
   148 		}
       
   149 		iLocation = s.find_first_of( ':' );
       
   150 
       
   151 		//Filename and location
       
   152 
       
   153 		if(iLocation != string::npos )
       
   154 		{
       
   155 			s2 = s.substr( 0, iLocation );
       
   156 			result->SetFileName( s2 );
       
   157 			s.erase( 0, iLocation+1 );
       
   158 		}
       
   159 
       
   160 		//Exact line number
       
   161 
       
   162 		s2 = s.substr( 0, s.find_first_of( ASCII_CHAR_CARRIAGE_RETURN ) );
       
   163 		result->SetExactLineNumber( atoi( s2.c_str() ) );
       
   164 	}
       
   165 	return true;
       
   166 }
       
   167 
       
   168 bool CATAddr2line::ReadMapFileArmv5()
       
   169 {
       
   170 	LOG_FUNC_ENTRY("CATModule2::ReadMapFileArmv5");
       
   171 	// Open .map file
       
   172 	ifstream in( m_sMapFileName.c_str() );
       
   173 	// File open ok?
       
   174 	if( ! in.good() )
       
   175 	{
       
   176 		in.close();
       
   177 		return false;
       
   178 	}
       
   179 	char cTemp[MAX_LINE_LENGTH];
       
   180 	bool bFirstFuncFound = false;
       
   181 	bool bFirstLine = true;
       
   182 	// Get all lines where is "Thumb"
       
   183 	do
       
   184 	{
       
   185 		// Load one line from .map file
       
   186 		in.getline( cTemp, MAX_LINE_LENGTH );
       
   187 		if( bFirstLine )
       
   188 		{
       
   189 			bFirstLine = false;
       
   190 			if( strstr( cTemp, "ARM Linker" ) == NULL )
       
   191 				return false;
       
   192 		}
       
   193 		// Find _E32Startup
       
   194 		if( !bFirstFuncFound && ( strstr( cTemp, "_E32Startup" ) != NULL) )
       
   195 		{
       
   196 			bFirstFuncFound = true;
       
   197 		}
       
   198 		else if( !bFirstFuncFound && ( strstr( cTemp, "_E32Dll" ) != NULL) )
       
   199 		{
       
   200 			bFirstFuncFound = true;
       
   201 		}
       
   202 		else if( !bFirstFuncFound )
       
   203 			// Skip if _E32Startup not found
       
   204 			continue;
       
   205 
       
   206 		if( strstr( cTemp, "Thumb Code" ) != NULL || strstr( cTemp, "ARM Code" ) != NULL)
       
   207 		{
       
   208 			MAP_FUNC_INFO structMapFileLineInfo;
       
   209 			structMapFileLineInfo.sWholeLine.append( cTemp );
       
   210 
       
   211 			// Get memory string address from line
       
   212 			char* pStart = strstr( cTemp, "0x" );
       
   213 			// Check did strstr return null.
       
   214 			if ( pStart == NULL )
       
   215 				continue;
       
   216 			char* pTemp = pStart;
       
   217 			char TempString[MAX_LINE_LENGTH];
       
   218 			TempString[0] = 0;
       
   219 			size_t iLength = 0;
       
   220 			while( *pTemp != ' ' )
       
   221 			{
       
   222 				TempString[iLength] = *pTemp;
       
   223 				pTemp++;
       
   224 				iLength++;
       
   225 			}
       
   226 			TempString[iLength] = 0;
       
   227 
       
   228 			structMapFileLineInfo.iAddress = CATDatParser::_httoi( TempString );
       
   229 
       
   230 			pTemp = cTemp;
       
   231 			TempString[0] = 0;
       
   232 			
       
   233 			// Get function name
       
   234 
       
   235 			// Skip spaces
       
   236 			while( *pTemp == ' ' )
       
   237 			{
       
   238 				pTemp++;
       
   239 			}
       
   240 			iLength = 0;
       
   241 			// Find end of function name
       
   242 			string sTemp( pTemp );
       
   243 
       
   244 			// Location of character ')'
       
   245 			iLength = sTemp.find_first_of(')');
       
   246 
       
   247 			// Location of character ' '
       
   248 			size_t iLength2 = sTemp.find_first_of(' ');
       
   249 			
       
   250 			// If ')' character is the last char and
       
   251 			// character ' ' is closer than ')' use location of ' '
       
   252 			if( ( iLength + 1 ) == sTemp.length() && iLength2 < iLength )
       
   253 				iLength = iLength2 - 1;
       
   254 			
       
   255 			if( iLength != string::npos )
       
   256 				sTemp.resize( (iLength + 1) );
       
   257 
       
   258 			structMapFileLineInfo.sFunctionName.append( sTemp.c_str() );
       
   259 
       
   260 			bool bARM = false;
       
   261 			// Find function length
       
   262 			pStart = strstr( cTemp, "Thumb Code" );
       
   263 			if( pStart == NULL )
       
   264 			{
       
   265 				pStart = strstr( cTemp, "ARM Code" );
       
   266 				bARM = true;
       
   267 			}
       
   268 			if( pStart != NULL )
       
   269 			{
       
   270 				if( bARM )
       
   271 					pStart += 8;
       
   272 				else
       
   273 					pStart += 10;
       
   274 				while(*pStart == ' ')
       
   275 				{
       
   276 					pStart++;
       
   277 				}
       
   278 				sTemp.clear();
       
   279 				sTemp.append( pStart );
       
   280 				size_t iSize = sTemp.find_first_of(' ');
       
   281 				if( iSize != string::npos )
       
   282 					sTemp.resize( iSize );
       
   283 			}
       
   284 
       
   285 			structMapFileLineInfo.iFuncLength = atoi( sTemp.c_str() );
       
   286 			if( bFirstFuncFound && structMapFileLineInfo.iFuncLength > 0 )
       
   287 				// Save to list
       
   288 				m_vMapFileFuncList.push_back( structMapFileLineInfo );
       
   289 		}
       
   290 	}
       
   291 	while( in.good() );
       
   292 	in.close();
       
   293 	return true;
       
   294 }
       
   295 
       
   296 // Find function name of given address
       
   297 string CATAddr2line::GetFunctionNameUsingAddress( unsigned long iAddress )
       
   298 {
       
   299 	LOG_LOW_FUNC_ENTRY("CATAddr2line::GetSymbolIndexUsingAddress");
       
   300 	string sRet;
       
   301 	for( size_t i = 0; i < m_vMapFileFuncList.size(); i++ )
       
   302 	{
       
   303 		unsigned long iStart = m_vMapFileFuncList.at( i ).iAddress;
       
   304 		unsigned long iEnd = ( m_vMapFileFuncList.at( i ).iAddress
       
   305 			+ m_vMapFileFuncList.at( i ).iFuncLength );
       
   306 
       
   307 		if ( iAddress >= iStart && iAddress < iEnd )
       
   308 			return m_vMapFileFuncList.at( i ).sFunctionName;
       
   309 	}
       
   310 	return sRet;
       
   311 }
       
   312 
       
   313 //Note: New filtering functions commented out until they are taken into use.
       
   314 /**
       
   315 * Filter string out of unwanted characters.
       
   316 */
       
   317 /*
       
   318 void CATAddr2line::FilterString( string &sString )
       
   319 {
       
   320 	LOG_LOW_FUNC_ENTRY("CATAddr2line::FilterString");
       
   321 	string sFiltered("");
       
   322 	for( size_t i = 0 ; i < sString.length() ; i++ )
       
   323 	{
       
   324 		const char p = sString.at( i );
       
   325 		if ( p != 0 && strchr( ADDR2LINEALLOWEDCHARS, p ) != 0 )
       
   326 			sFiltered.push_back( p );
       
   327 	}
       
   328 	sString = sFiltered;
       
   329 }
       
   330 */
       
   331 /**
       
   332 * Find line feed position from string.
       
   333 */
       
   334 /*
       
   335 size_t CATAddr2line::FindLineFeed( const string& sString )
       
   336 {
       
   337 	LOG_LOW_FUNC_ENTRY("CATAddr2line::FindLineFeed");
       
   338 	size_t iLineFeed1 = sString.find( 12 );
       
   339 	size_t iLineFeed2 = sString.find( 15 );
       
   340 	if ( iLineFeed1 < iLineFeed2 && iLineFeed1 != string::npos )
       
   341 		return iLineFeed1;
       
   342 	else if ( iLineFeed2 != string::npos )
       
   343 		return iLineFeed2;
       
   344 	else
       
   345 		return string::npos;
       
   346 }
       
   347 */
       
   348 /**
       
   349 * Erase characters from start of the string until other char than linefeed found.
       
   350 */
       
   351 /*
       
   352 void CATAddr2line::EraseUntilNoLineFeed( string& sString )
       
   353 {
       
   354 	LOG_LOW_FUNC_ENTRY("CATAddr2line::EraseUntilNoLineFeed");
       
   355 	for ( size_t i = 0 ; i < sString.length() ; i++ )
       
   356 	{
       
   357 		if ( sString.at( i ) != 15 && sString.at( i ) != 12 )
       
   358 			break;
       
   359 	}
       
   360 	sString.erase( 0, i );
       
   361 }
       
   362 */
       
   363 /**
       
   364 * Split multiple line string with unexpected line feeds to vector of strings.
       
   365 */
       
   366 /*
       
   367 vector<string> CATAddr2line::SplitToStrings( string& sMultiLineString )
       
   368 {
       
   369 	LOG_LOW_FUNC_ENTRY("CATAddr2line::SplitToStrings");
       
   370     vector<string> vLines;
       
   371 	while ( 1 )
       
   372 	{
       
   373 		size_t iLineFeed = FindLineFeed( sMultiLineString );
       
   374 		if ( iLineFeed == string::npos )
       
   375 			break;
       
   376 		string sCell = sMultiLineString.substr(0, iLineFeed );
       
   377 		sMultiLineString.erase(0, iLineFeed );
       
   378 		EraseUntilNoLineFeed( sMultiLineString );
       
   379 		FilterString( sCell );
       
   380 		vLines.push_back( sCell );
       
   381 	}
       
   382 	// If no lines were found set single one.
       
   383 	if ( vLines.size() == 0 )
       
   384 		vLines.push_back( sMultiLineString );
       
   385 	return vLines;
       
   386 }
       
   387 */
       
   388 //EOF