kerneltest/e32utils/analyse/symbols.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32utils/analyse/symbols.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,243 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+//
+
+#include "analyse.h"
+#include "symbols.h"
+
+#ifdef __MSVCDOTNET__
+#include <fstream>
+#else //!__MSVCDOTNET__
+#include <fstream.h>
+#endif //__MSVCDOTNET__
+
+namespace {
+unsigned ParseHex(const char* aText, int aLength)
+	{
+	unsigned value = 0;
+	const char* end = aText + aLength;
+	do
+		{
+		unsigned c = *aText++ - '0';
+		if (c > 9)
+			c -= 'a' - '0' - 10;
+		value = (value << 4) + c;
+		} while (aText < end);
+	return value;
+	}
+};
+
+
+// class SymbolFile
+
+SymbolFile::SymbolFile(const char* aSymbolFile, bool aRofs)
+	:iText(0), iTextLower(0)
+	{
+	ifstream file;
+#ifdef __MSVCDOTNET__
+	file.open(aSymbolFile, ios::binary);
+#else //!__MSVCDOTNET__
+	file.open(aSymbolFile, ios::nocreate | ios::binary);
+#endif //__MSVCDOTNET__
+	if (!file)
+		{
+		cerr << "Unable to open ROM symbol file '" << aSymbolFile << '\'' << endl;
+		Analyse::Abort();
+		}
+//
+	file.seekg(0, ios::end);
+	iLength = file.tellg();
+//
+	iText = new char[iLength+1];
+	file.seekg(0, ios::beg);
+	file.read(iText, iLength);
+	iText[iLength] = '\0';
+//
+	file.close();
+
+	if (aRofs)
+		{
+		iTextLower = new char[iLength+1];
+		for(char *p = iTextLower, *c = iText, *end = iText + iLength;c < end;c++, p++) 
+			*p = tolower(*c);
+		}
+	}
+
+SymbolFile::~SymbolFile()
+	{
+	delete [] iText;
+	if (iTextLower)
+		delete [] iTextLower;
+	}
+
+bool SymbolFile::Parse(SymbolFile::Parser& aParser, const char* aModuleName, PC aAddress, PC aModuleLength, int aModuleId) const
+	{
+	char* text = 0;
+	PC first_pc_limit = 0, last_pc_limit = 0;
+	TState state = EPreFile;
+	PC lastPC = 0;
+	bool inSyms = false;
+	const char *prevName = 0;
+	int lastLen = 0;
+
+	if (aModuleName) // should parse only one module 
+		{
+		bool not_found = false;
+		char * name = strstr(iTextLower, aModuleName);
+		if (name)
+			{
+			for(char * p = name; p != iTextLower && *p != '\n';p--);
+			if (*p == '\n' || p == iTextLower) 
+				{
+				name = ++p;
+				text = iText + (name - iTextLower);
+				}
+			else
+				not_found = true;
+			}
+		else
+			not_found = true;
+
+		if (not_found)
+			return false;
+
+		state = EFile;
+		}
+	else
+		text = iText;
+		
+	const char* end = iText + iLength;
+	while (text < end && state != EError)
+		{
+		char* endl = strchr(text, '\r');
+		if (endl == 0)
+			{
+			if (!aModuleName)
+				{
+				state = EError;
+				break;
+				}
+			else
+				{
+				char* p = text + strlen(text);
+				if (*(p+1) == '\n')
+					endl = p;
+				else
+					{
+					state = EError;
+					break;
+					}
+				}
+			}
+		switch (state)
+			{
+		case EPreFile:
+			if (endl != text)
+				state = EError;
+			else
+				state = EFile;
+			break;
+		case EFile:
+			if (strncmp(text, "From", 4) != 0)
+				state = EError;
+			else
+				{
+				*endl = '\0';
+				char* name = strrchr(text, '\\');
+				if (name == 0)
+					name = text + 8;
+				else
+					++name;
+				aParser.File(name);
+				state = EPostFile;
+				}
+			break;
+		case EPostFile:
+			if (endl != text)
+				state = EError;
+			else
+				state = ESymbol;
+			break;
+		case ESymbol:
+			if (text == endl)
+				{
+				if (aModuleName)
+					goto Quit; 
+				else
+					state = EFile;
+				}
+			else
+				{
+				PC pc = ParseHex(text, 8);
+				pc &= ~1; // should be odd address, error in symbol table
+
+				if(aModuleName)
+					pc += aAddress;
+
+				*endl = '\0';
+
+				char* codeType = strrchr(text+20, '(');
+
+				if ( codeType == NULL || (strcmp(codeType,"(.data)") != 0 &&
+					 strcmp(codeType,"(.bss)") != 0 &&
+					 strcmp(codeType,"(.init_array)") != 0 &&
+					 strcmp(codeType,"(linker$$defined$$symbols)") != 0 &&
+					 strcmp(codeType,"(ExportTable)") != 0) )
+					{
+					if(inSyms && (pc > (lastPC + lastLen)))
+						{
+						memcpy((void *)(prevName - 15), "<static> after ", 15);
+						aParser.Symbol(prevName - 15, lastPC + lastLen, pc - (lastPC + lastLen));
+						}
+
+					int length = ParseHex(text + 12, 4);
+
+					if(pc >= lastPC + lastLen)
+						{
+						bool is_added = aParser.Symbol(text + 20, pc, length);
+						if (is_added && aModuleName && !first_pc_limit) 
+							{
+							first_pc_limit = pc + length;
+							last_pc_limit = pc + aModuleLength;
+							}
+						}
+
+					prevName = text + 20;
+					if(pc + length > lastPC + lastLen)
+						{
+						lastLen = length;
+						lastPC = pc;
+						}
+					inSyms = true;
+					}
+				}
+			break;
+		case EError:
+			break;
+			}
+		text = endl + 2;
+		}
+	if (state == EError)
+		Analyse::Abort("Bad ROM symbol file format");
+
+Quit:
+	if(aModuleName && lastPC == first_pc_limit && (lastPC + lastLen) < last_pc_limit)
+		{
+		memcpy((void *)(prevName - 10), "<anon> in ", 10);
+		aParser.Symbol(prevName - 10, lastPC + lastLen, last_pc_limit - (lastPC + lastLen));
+		}
+	aParser.Done(first_pc_limit, last_pc_limit, aModuleId);
+
+	return true;
+	}