memana/analyzetoolclient/commandlineengine/internal/src/catromsymbol.cpp
changeset 0 f0f2b8682603
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/memana/analyzetoolclient/commandlineengine/internal/src/catromsymbol.cpp	Thu Feb 11 15:51:35 2010 +0200
@@ -0,0 +1,656 @@
+/*
+* 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:  Reads rom symbol file and provides interface to acquire
+*               binary and function information using memory addresss.
+*
+*/
+
+#include "../inc/ATCommonDefines.h"
+#include "../inc/catromsymbol.h"
+#include "../inc/catfilereader.h"
+#include "../inc/CATBase.h"
+#include "../inc/CATMemoryAddress.h"
+
+// -----------------------------------------------------------------------------
+// RofsBinary::RofsBinary
+// Default construcor
+// -----------------------------------------------------------------------------
+RofsBinary::RofsBinary()
+{
+	LOG_LOW_FUNC_ENTRY("RofsBinary::RofsBinary");
+	m_sBinary = "";
+	vSymbols.clear();
+}
+
+// -----------------------------------------------------------------------------
+// RofsBinary::RofsBinary
+// Construcor
+// -----------------------------------------------------------------------------
+RofsBinary::RofsBinary( const string& sBinary )
+{
+	LOG_LOW_FUNC_ENTRY("RofsBinary::RofsBinary");
+	m_sBinary = sBinary;
+	vSymbols.clear();
+}
+
+// -----------------------------------------------------------------------------
+// RofsBinary::~RofsBinary
+// Destructor
+// -----------------------------------------------------------------------------
+RofsBinary::~RofsBinary()
+{
+	LOG_LOW_FUNC_ENTRY("RofsBinary::~RofsBinary");
+	for ( vector<Symbol*>::iterator it = vSymbols.begin() ; it != vSymbols.end() ; it++ )
+		delete *it;
+	vSymbols.clear();
+}
+
+// -----------------------------------------------------------------------------
+// CATRomSymbol::CATRomSymbol
+// Constructor.
+// -----------------------------------------------------------------------------
+CATRomSymbol::CATRomSymbol()
+{
+	LOG_FUNC_ENTRY("CATRomSymbol::CATRomSymbol");
+	m_bSymbolsRead = false;
+	m_iRomEndAddress = 0;
+	m_iRomStartAddress = 0;
+	m_vRomFiles.clear();
+	m_sErrorMessage = "";
+	m_vRomCache.clear();
+	m_vRomSymbols.clear();
+	m_bShowProgressMessages = false;
+}
+
+// -----------------------------------------------------------------------------
+// CATRomSymbol::~CATRomSymbol
+// Destructor.
+// -----------------------------------------------------------------------------
+CATRomSymbol::~CATRomSymbol()
+{
+	LOG_FUNC_ENTRY("CATRomSymbol::~CATRomSymbol");
+	// Rom
+	for ( vector<Symbol*>::iterator it = m_vRomSymbols.begin() ; it != m_vRomSymbols.end() ; it++ )
+	{
+		delete *it;
+	}
+	m_vRomSymbols.clear();
+	// Rofs
+	for ( vector<RofsBinary*>::iterator it = m_vRofsBinaries.begin() ; it != m_vRofsBinaries.end() ; it++ )
+	{
+		delete *it;
+	}
+	m_vRofsBinaries.clear();
+}
+
+// -----------------------------------------------------------------------------
+// CATRomSymbol::Open
+// This funtion should not be used anymore since
+// we support multiple rom/rofs files.
+// -----------------------------------------------------------------------------
+bool CATRomSymbol::Open( const string& /*sString*/, const unsigned long /*iLong*/)
+{
+	LOG_FUNC_ENTRY("CATRomSymbol::Open");
+	return false;
+}
+
+// -----------------------------------------------------------------------------
+// CATRomSymbol::SetSymbols
+// Set symbol file(s) to be used.
+// This also checks that files exists and identifies them as rom/rofs.
+// -----------------------------------------------------------------------------
+bool CATRomSymbol::SetSymbols( const vector<string>& vSymbols )
+{
+	LOG_FUNC_ENTRY("CATRomSymbol::SetSymbols");
+	bool ok = true;
+	// Check no same symbol defined twice.
+	for( vector<string>::const_iterator it = vSymbols.begin() ;
+		it != vSymbols.end(); it++ )
+	{
+		for( vector<string>::const_iterator it2 = vSymbols.begin() ;
+			it2 != vSymbols.end(); it2++ )
+		{
+			if ( it == it2 )
+				continue;
+			if ( _stricmp( (*it).c_str(), (*it2).c_str() ) == 0 )
+			{
+				m_sErrorMessage.append( "Same symbol file defined twice (" );
+				m_sErrorMessage.append( (*it) );
+				m_sErrorMessage.append( ")\n" );
+				return false;
+			}
+		}
+	}
+	// Loop given symbol files.
+	for( vector<string>::const_iterator it = vSymbols.begin() ;
+		it != vSymbols.end(); it++ )
+	{
+		// Symbol file exists?
+		if ( ! CATBase::FileExists( (*it).c_str() ) )
+		{
+			ok = false;
+			m_sErrorMessage.append( "Symbol file does not exists (" );
+			m_sErrorMessage.append( *it );
+			m_sErrorMessage.append( ").\n");
+			continue;
+		}
+		// Identify symbol file.
+		int type = IdentifySymbolFile( *it );
+		// Depending on type move it correct vector.
+		switch( type )
+		{
+		case SYMBOL_FILE_INVALID:
+			ok = false;
+			m_sErrorMessage.append( "Symbol file with invalid content (" );
+			m_sErrorMessage.append( *it );
+			m_sErrorMessage.append( ").\n");
+			break;
+		case SYMBOL_FILE_ROM:
+			m_vRomFiles.push_back( *it );
+			break;
+		case SYMBOL_FILE_ROFS:
+			m_vRofsFiles.push_back( *it );
+			break;
+		default:
+			ok = false;
+			LOG_STRING("IdentifySymbolFile returned unknown type.");
+			break;
+		}
+	}
+	if ( ok )
+	{
+		// Read symbols.
+		if ( m_vRomFiles.size() > 0 )
+		{
+			if ( ! ReadRomFiles() )
+				ok = false;
+			else
+				m_bSymbolsRead = true;
+		}
+		if ( m_vRofsFiles.size() > 0 )
+		{
+			if ( ! ReadRofsFiles() )
+				ok = false;
+			else
+				m_bSymbolsRead = true;
+		}
+	}
+	return ok;
+}
+
+// -----------------------------------------------------------------------------
+// CATRomSymbol::IdentifySymbolFile
+// Identify given file is it rom / rofs.
+// -----------------------------------------------------------------------------
+int CATRomSymbol::IdentifySymbolFile( const string& sFile )
+{
+	LOG_FUNC_ENTRY("CATRomSymbol::IdentifySymbolFile");
+	// Set type as invalid.
+	int iType = SYMBOL_FILE_INVALID;
+	// Line counter.
+	int iLineCount = 0;
+	// Minimun line length to identify it.
+	size_t iLineMinLength = MAX_LINE_LENGTH;
+	if ( ROFS_SYMBOL_IDENTIFY_STRING.length() > ROM_SYMBOL_IDENTIFY_STRING.length() )
+		iLineMinLength = ROFS_SYMBOL_IDENTIFY_STRING.length();
+	else
+		iLineMinLength = ROM_SYMBOL_IDENTIFY_STRING.length();
+	try {
+		ifstream in;
+		in.open( sFile.c_str(), ios::in );
+		if ( ! in.good() )
+			return SYMBOL_FILE_INVALID;
+		char cLine[MAX_LINE_LENGTH];
+		do {
+			// Dont read too many lines. (File might be contain invalid data).
+			iLineCount++;
+			if ( iLineCount > IDENTIFY_MAX_LINES_READ )
+				break;
+
+			// Get line -> string.
+			in.getline( cLine, MAX_LINE_LENGTH );
+			string sLine(cLine);
+			
+			// Check its not too short.
+			if( sLine.length() < iLineMinLength )
+				continue;
+
+			// Take substring from start of line to identify it to rofs/rom.
+			if ( ! sLine.substr( 0, ROFS_SYMBOL_IDENTIFY_STRING.length() ).compare( ROFS_SYMBOL_IDENTIFY_STRING ) )
+			{
+				iType = SYMBOL_FILE_ROFS;
+				break;
+			}
+			else if ( ! sLine.substr( 0, ROM_SYMBOL_IDENTIFY_STRING.length() ).compare( ROM_SYMBOL_IDENTIFY_STRING ) )
+			{
+				iType = SYMBOL_FILE_ROM;
+				break;
+			}
+		} while ( in.good() );
+		in.close();
+	}
+	catch(...)
+	{
+		LOG_STRING("CATRomSymbol::IdentifySymbolFile unhandled exception.");
+	}
+	return iType;
+}
+
+// -----------------------------------------------------------------------------
+// CATRomSymbol::ReadRomFiles
+// Reads rom file(s) and creates symbols to vector.
+// -----------------------------------------------------------------------------
+bool CATRomSymbol::ReadRomFiles()
+{
+	LOG_FUNC_ENTRY("CATRomSymbol::ReadRomFile");
+
+	// Clear symbols.
+	for ( vector<Symbol*>::iterator it = m_vRomSymbols.begin() ; it != m_vRomSymbols.end() ; it++ )
+	{
+		delete *it;
+	}
+	m_vRomSymbols.clear();
+	
+	// Clear cache. note cache is just pointers dont delete them.
+	m_vRomCache.clear();
+
+	// Any errors?
+	bool ok = true;
+
+	for( vector<string>::iterator it = m_vRomFiles.begin();
+		it != m_vRomFiles.end() ; it++ )
+		ok = ReadRomFile( *it );
+	
+	// If size smaller than 1 it is not good rom file(s).
+	if ( m_vRomSymbols.size() < 1  || ok != true)
+		return false;
+
+	// Rom start and end addresses.
+	m_iRomStartAddress = (*m_vRomSymbols.begin())->iStartAddress;
+	m_iRomEndAddress = (*m_vRomSymbols.rbegin())->iEndAddress;
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+// CATRomSymbol::ReadRofsFiles
+// Read rofs files.
+// -----------------------------------------------------------------------------
+bool CATRomSymbol::ReadRofsFiles()
+{
+	LOG_FUNC_ENTRY("CATRomSymbol::ReadRofsFiles");
+	// Clear.
+	for ( vector<RofsBinary*>::iterator it = m_vRofsBinaries.begin() ; it != m_vRofsBinaries.end() ; it++ )
+	{
+		delete *it;
+	}
+	m_vRofsBinaries.clear();
+	
+	// Any errors?
+	bool ok = true;
+
+	for( vector<string>::iterator it = m_vRofsFiles.begin();
+		it != m_vRofsFiles.end() ; it++ )
+		ok = ReadRofsFile( *it );
+	
+	// If size smaller than 1 it is not good rofs file(s).
+	if ( m_vRofsBinaries.size() < 1  || ok != true)
+		return false;
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+// CATRomSymbol::ReadRomFile
+// Read given rom file
+// -----------------------------------------------------------------------------
+bool CATRomSymbol::ReadRomFile( const string& sFile )
+{
+	LOG_FUNC_ENTRY("CATRomSymbol::ReadRomfile");
+	// Open rom file.
+	CATFileReader* reader = new CATFileReader();
+	// Show progress message if flag set.
+	if ( m_bShowProgressMessages )
+		cout << AT_MSG << "Reading rom symbol file: " << sFile << "..." << endl;
+	if ( ! reader->Open( sFile.c_str() ) )
+	{
+		reader->Close();
+		delete reader;
+		return false;
+	}
+
+	// Show progress message if flag set.
+	if ( m_bShowProgressMessages )
+		cout << AT_MSG << "Parsing rom symbol file: " << sFile << "..." << endl;
+
+	// Loop thrue lines.
+	string sLine("");
+	string sBinary("");
+	while( reader->GetLine( sLine ) )
+	{
+		// From rom we just read symbols that have lenght, no need to separate them into diff binaries.
+		try {
+			if ( sLine.size() < 2 )
+			{
+				continue;
+			}
+			else if ( sLine.at(0) == '8' )
+			{
+				// Create new item.
+				Symbol* symbol = new Symbol();
+				ParseSymbolFromLine( sLine, symbol);
+				// Ignore symbols which have same start & end address (zero length).
+				if ( symbol->iStartAddress != symbol->iEndAddress )
+					m_vRomSymbols.push_back( symbol );
+				else
+					delete symbol;
+			}
+		} catch(...)
+		{
+			// Catch all possible exception here so analyze will succeed even rom file invalid.
+			m_sErrorMessage.append( "Unhandled exception parsing rom symbol file.\n" );
+			// Close and delete reader.
+			reader->Close();
+			delete reader;
+			return false;
+		}
+	}
+	// Close and delete reader.
+	reader->Close();
+	delete reader;
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+// CATRomSymbol::ReadRofsFile
+// Read given rofs file
+// -----------------------------------------------------------------------------
+bool CATRomSymbol::ReadRofsFile( const string& sFile )
+{
+	LOG_FUNC_ENTRY("CATRomSymbol::ReadRofsFile");
+	// open/read rofs file.
+	CATFileReader* reader = new CATFileReader();
+	// Show progress message if flag set.
+	if ( m_bShowProgressMessages )
+		cout << AT_MSG << "Reading rofs symbol file: " << sFile << "..." << endl;
+	if ( ! reader->Open( sFile.c_str() ) )
+	{
+		reader->Close();
+		delete reader;
+		return false;
+	}
+
+	// Show progress message if flag set.
+	if ( m_bShowProgressMessages )
+		cout << AT_MSG << "Parsing rofs symbol file: " << sFile << "..." << endl;
+
+	// Loop thrue lines.
+	string sLine("");
+	string sBinary("");
+	RofsBinary* rb = NULL;
+	while( reader->GetLine( sLine ) )
+	{
+		try {
+			if ( sLine.size() < 2 )
+			{
+				continue;
+			}
+			else if ( sLine.at(0) == 'F' )
+			{
+				if ( rb != NULL )
+				{
+					// Check last binary if no symbols in it dont add it.
+					if ( rb->vSymbols.size() == 0 )
+					{
+						delete rb;
+						rb = NULL;
+					}
+					else
+						m_vRofsBinaries.push_back( rb );
+				}
+				// new binary name.
+				size_t i = sLine.rfind("\\");
+				sLine.erase(0, i+1);
+				rb = new RofsBinary( sLine );
+
+			}
+			else if ( sLine.at(0) == '0' )
+			{
+				// Cannot pickup symbols if no binary defined.
+				if ( rb == NULL )
+					continue;
+				// Create new item.
+				Symbol* symbol = new Symbol();
+				ParseSymbolFromLine( sLine, symbol);
+				// Ignore symbols which have same start & end address (zero length).
+				if ( symbol->iStartAddress != symbol->iEndAddress )
+					rb->vSymbols.push_back( symbol );
+				else
+					delete symbol;
+			}
+		} catch(...)
+		{
+			// Catch all possible exception here so analyze will succeed even rofs file invalid.
+			m_sErrorMessage.append( "Unhandled exception parsing rofs symbol file.\n" );
+			// Close and delete reader.
+			reader->Close();
+			delete reader;
+			return false;
+		}
+	}
+	// Last added binary.
+	if ( rb != NULL )
+	{
+		if ( rb->vSymbols.size() == 0 )
+		{
+			delete rb;
+			rb = NULL;
+		}
+		else
+			m_vRofsBinaries.push_back( rb );
+	}
+	// Close and delete reader.
+	reader->Close();
+	delete reader;
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+// CATRomSymbol::ParseSymbolFromLine
+// Parses given line into given symbol.
+// -----------------------------------------------------------------------------
+void CATRomSymbol::ParseSymbolFromLine( const string& sLine, Symbol* pSymbol )
+{
+	LOG_LOW_FUNC_ENTRY("CATRomSymbol::ParseSymbolFromLine");
+	if ( pSymbol == NULL )
+		return;
+	size_t s,x;
+	string temp;
+	// address.
+	x = sLine.find( ' ' );
+	temp = sLine.substr( 0, x );
+	pSymbol->iStartAddress = CATBase::_httoi( temp.c_str() );
+	// "Erase spaces" move starting point.
+	s = x;
+	s = sLine.find_first_not_of( ' ', s );
+	// length.
+	x = sLine.find( ' ', s );
+	temp = sLine.substr(s,x-s);
+	unsigned long length = CATBase::_httoi( temp.c_str() );
+	pSymbol->iEndAddress = pSymbol->iStartAddress + length;
+	// "Erase spaces" move starting point.
+	s = x;
+	s = sLine.find_first_not_of( ' ', s);
+	// function. Function might have spaces so we find 2 spaces which indicates end of it.
+	x = sLine.find( "  ", s );
+	temp = sLine.substr( s, x-s );
+	pSymbol->sFunction = temp;
+}
+
+// -----------------------------------------------------------------------------
+// CATRomSymbol::GetError
+// Get error string if error occured in other methods.
+// -----------------------------------------------------------------------------
+string CATRomSymbol::GetError( void )
+{
+	LOG_FUNC_ENTRY("CATRomSymbol::GetError");
+	return m_sErrorMessage;
+}
+
+// -----------------------------------------------------------------------------
+// CATRomSymbol::Close
+// Close (stop using).
+// -----------------------------------------------------------------------------
+bool CATRomSymbol::Close( void )
+{
+	LOG_FUNC_ENTRY("CATRomSymbol::Close");
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+// CATRomSymbol::AddressToLine
+// Try locate binary and function name for given memory address.
+// -----------------------------------------------------------------------------
+bool CATRomSymbol::AddressToLine( CATMemoryAddress* result )
+{
+	LOG_LOW_FUNC_ENTRY("CATRomSymbol::AddressToLine");
+	// Have symbols been read.
+	if ( ! m_bSymbolsRead )
+		return false;
+	// check that its lenght > 2
+	if ( result->GetAddressString().size() < 2 )
+		return false;
+	/* Check first is address in range of rom */
+	if ( result->GetAddress() < m_iRomStartAddress
+		|| result->GetAddress() > m_iRomEndAddress )
+	{
+		return AddressToLineRofs( result );		
+	}
+	return AddressToLineRom( result );
+}
+
+// -----------------------------------------------------------------------------
+// CATRomSymbol::AddressToLineRom
+// Locate function from rom address range.
+// -----------------------------------------------------------------------------
+bool CATRomSymbol::AddressToLineRom( CATMemoryAddress* result )
+{
+	LOG_LOW_FUNC_ENTRY( "CATRomSymbol::AddressToLineRom" );
+	// Address to find in integer & string.
+	unsigned long iAddressToFind = result->GetAddress();
+	string sAddressToFind = result->GetAddressString();
+	
+	// Find symbol.
+	Symbol* pFound = NULL;
+
+	// Check from cache first.
+	vector<Symbol*>::iterator it;
+	for ( it = m_vRomCache.begin(); it != m_vRomCache.end(); it++ )
+	{
+		if ( iAddressToFind >= (*it)->iStartAddress
+			&& (*it)->iEndAddress > iAddressToFind )
+		{
+			pFound = *it;
+			break;
+		}
+	}
+	
+	if ( pFound == NULL )
+	{
+		// From all symbols.
+		bool reverse = false;
+		int offSetFromStart = iAddressToFind - m_iRomStartAddress;
+		int offSetFromEnd = m_iRomEndAddress - iAddressToFind;
+		if ( offSetFromEnd < offSetFromStart ) 
+			reverse = true;
+		
+		if ( reverse )
+		{
+			// Iterate vector in reverse.
+			vector<Symbol*>::reverse_iterator it;
+			for ( it = m_vRomSymbols.rbegin(); it != m_vRomSymbols.rend(); ++it )
+			{
+				if ( iAddressToFind >= (*it)->iStartAddress
+					&& (*it)->iEndAddress > iAddressToFind )
+				{
+					pFound = *it;
+					break;
+				}
+			}
+		}
+		else
+		{
+			// Iterate vector normal direction.
+			vector<Symbol*>::iterator it;
+			for ( it = m_vRomSymbols.begin(); it != m_vRomSymbols.end(); it++ )
+			{
+				if ( iAddressToFind >= (*it)->iStartAddress
+					&& (*it)->iEndAddress > iAddressToFind )
+				{
+					pFound = *it;
+					break;
+				}
+			}
+		}
+	}
+
+	// Set result if found.
+	if ( pFound != NULL )
+	{
+		result->SetFunctionName( pFound->sFunction );
+		result->SetAddressToLineState( CATMemoryAddress::SYMBOL );
+		// Add found symbols pointer to cache.
+		m_vRomCache.push_back( pFound );
+		return true;
+	}
+	return false;
+}
+
+// -----------------------------------------------------------------------------
+// CATRomSymbol::AddressToLineRofs
+// Locate function from rofs address range.
+// -----------------------------------------------------------------------------
+bool CATRomSymbol::AddressToLineRofs( CATMemoryAddress* result)
+{
+	LOG_LOW_FUNC_ENTRY("CATRomSymbol::AddressToLineRofs");
+	// Check that binary name is defined in memory address.
+	string sBinary = result->GetModuleName();
+	if ( sBinary.empty() )
+		return false;
+	// Try find that named module.
+	vector<RofsBinary*>::iterator rofs = m_vRofsBinaries.begin();
+	while( rofs != m_vRofsBinaries.end() )
+	{
+		if ( (*rofs)->m_sBinary.compare( sBinary ) == 0 )
+			break;
+		rofs++;
+	}
+	if ( rofs == m_vRofsBinaries.end() )
+		return false;
+
+	// Offset what we are looking from binary
+	unsigned long offSet = result->GetAddress();
+	offSet -= result->GetModuleStartAddress();
+	for( vector<Symbol*>::iterator it = (*rofs)->vSymbols.begin() ;
+		it != (*rofs)->vSymbols.end(); it++ )
+	{
+		if ( (*it)->iStartAddress <= offSet && offSet < (*it)->iEndAddress )
+		{
+			result->SetFunctionName( (*it)->sFunction );
+			result->SetAddressToLineState( CATMemoryAddress::SYMBOL );
+			return true;
+		}
+	}
+	return false;
+}
+
+//EOF