--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/analyzetool/commandlineengine/src/cataddr2line.cpp Thu May 27 14:26:55 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