kerneltest/e32utils/analyse/symbols.cpp
changeset 9 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     1 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "analyse.h"
       
    17 #include "symbols.h"
       
    18 
       
    19 #ifdef __MSVCDOTNET__
       
    20 #include <fstream>
       
    21 #else //!__MSVCDOTNET__
       
    22 #include <fstream.h>
       
    23 #endif //__MSVCDOTNET__
       
    24 
       
    25 namespace {
       
    26 unsigned ParseHex(const char* aText, int aLength)
       
    27 	{
       
    28 	unsigned value = 0;
       
    29 	const char* end = aText + aLength;
       
    30 	do
       
    31 		{
       
    32 		unsigned c = *aText++ - '0';
       
    33 		if (c > 9)
       
    34 			c -= 'a' - '0' - 10;
       
    35 		value = (value << 4) + c;
       
    36 		} while (aText < end);
       
    37 	return value;
       
    38 	}
       
    39 };
       
    40 
       
    41 
       
    42 // class SymbolFile
       
    43 
       
    44 SymbolFile::SymbolFile(const char* aSymbolFile, bool aRofs)
       
    45 	:iText(0), iTextLower(0)
       
    46 	{
       
    47 	ifstream file;
       
    48 #ifdef __MSVCDOTNET__
       
    49 	file.open(aSymbolFile, ios::binary);
       
    50 #else //!__MSVCDOTNET__
       
    51 	file.open(aSymbolFile, ios::nocreate | ios::binary);
       
    52 #endif //__MSVCDOTNET__
       
    53 	if (!file)
       
    54 		{
       
    55 		cerr << "Unable to open ROM symbol file '" << aSymbolFile << '\'' << endl;
       
    56 		Analyse::Abort();
       
    57 		}
       
    58 //
       
    59 	file.seekg(0, ios::end);
       
    60 	iLength = file.tellg();
       
    61 //
       
    62 	iText = new char[iLength+1];
       
    63 	file.seekg(0, ios::beg);
       
    64 	file.read(iText, iLength);
       
    65 	iText[iLength] = '\0';
       
    66 //
       
    67 	file.close();
       
    68 
       
    69 	if (aRofs)
       
    70 		{
       
    71 		iTextLower = new char[iLength+1];
       
    72 		for(char *p = iTextLower, *c = iText, *end = iText + iLength;c < end;c++, p++) 
       
    73 			*p = tolower(*c);
       
    74 		}
       
    75 	}
       
    76 
       
    77 SymbolFile::~SymbolFile()
       
    78 	{
       
    79 	delete [] iText;
       
    80 	if (iTextLower)
       
    81 		delete [] iTextLower;
       
    82 	}
       
    83 
       
    84 bool SymbolFile::Parse(SymbolFile::Parser& aParser, const char* aModuleName, PC aAddress, PC aModuleLength, int aModuleId) const
       
    85 	{
       
    86 	char* text = 0;
       
    87 	PC first_pc_limit = 0, last_pc_limit = 0;
       
    88 	TState state = EPreFile;
       
    89 	PC lastPC = 0;
       
    90 	bool inSyms = false;
       
    91 	const char *prevName = 0;
       
    92 	int lastLen = 0;
       
    93 
       
    94 	if (aModuleName) // should parse only one module 
       
    95 		{
       
    96 		bool not_found = false;
       
    97 		char * name = strstr(iTextLower, aModuleName);
       
    98 		if (name)
       
    99 			{
       
   100 			for(char * p = name; p != iTextLower && *p != '\n';p--);
       
   101 			if (*p == '\n' || p == iTextLower) 
       
   102 				{
       
   103 				name = ++p;
       
   104 				text = iText + (name - iTextLower);
       
   105 				}
       
   106 			else
       
   107 				not_found = true;
       
   108 			}
       
   109 		else
       
   110 			not_found = true;
       
   111 
       
   112 		if (not_found)
       
   113 			return false;
       
   114 
       
   115 		state = EFile;
       
   116 		}
       
   117 	else
       
   118 		text = iText;
       
   119 		
       
   120 	const char* end = iText + iLength;
       
   121 	while (text < end && state != EError)
       
   122 		{
       
   123 		char* endl = strchr(text, '\r');
       
   124 		if (endl == 0)
       
   125 			{
       
   126 			if (!aModuleName)
       
   127 				{
       
   128 				state = EError;
       
   129 				break;
       
   130 				}
       
   131 			else
       
   132 				{
       
   133 				char* p = text + strlen(text);
       
   134 				if (*(p+1) == '\n')
       
   135 					endl = p;
       
   136 				else
       
   137 					{
       
   138 					state = EError;
       
   139 					break;
       
   140 					}
       
   141 				}
       
   142 			}
       
   143 		switch (state)
       
   144 			{
       
   145 		case EPreFile:
       
   146 			if (endl != text)
       
   147 				state = EError;
       
   148 			else
       
   149 				state = EFile;
       
   150 			break;
       
   151 		case EFile:
       
   152 			if (strncmp(text, "From", 4) != 0)
       
   153 				state = EError;
       
   154 			else
       
   155 				{
       
   156 				*endl = '\0';
       
   157 				char* name = strrchr(text, '\\');
       
   158 				if (name == 0)
       
   159 					name = text + 8;
       
   160 				else
       
   161 					++name;
       
   162 				aParser.File(name);
       
   163 				state = EPostFile;
       
   164 				}
       
   165 			break;
       
   166 		case EPostFile:
       
   167 			if (endl != text)
       
   168 				state = EError;
       
   169 			else
       
   170 				state = ESymbol;
       
   171 			break;
       
   172 		case ESymbol:
       
   173 			if (text == endl)
       
   174 				{
       
   175 				if (aModuleName)
       
   176 					goto Quit; 
       
   177 				else
       
   178 					state = EFile;
       
   179 				}
       
   180 			else
       
   181 				{
       
   182 				PC pc = ParseHex(text, 8);
       
   183 				pc &= ~1; // should be odd address, error in symbol table
       
   184 
       
   185 				if(aModuleName)
       
   186 					pc += aAddress;
       
   187 
       
   188 				*endl = '\0';
       
   189 
       
   190 				char* codeType = strrchr(text+20, '(');
       
   191 
       
   192 				if ( codeType == NULL || (strcmp(codeType,"(.data)") != 0 &&
       
   193 					 strcmp(codeType,"(.bss)") != 0 &&
       
   194 					 strcmp(codeType,"(.init_array)") != 0 &&
       
   195 					 strcmp(codeType,"(linker$$defined$$symbols)") != 0 &&
       
   196 					 strcmp(codeType,"(ExportTable)") != 0) )
       
   197 					{
       
   198 					if(inSyms && (pc > (lastPC + lastLen)))
       
   199 						{
       
   200 						memcpy((void *)(prevName - 15), "<static> after ", 15);
       
   201 						aParser.Symbol(prevName - 15, lastPC + lastLen, pc - (lastPC + lastLen));
       
   202 						}
       
   203 
       
   204 					int length = ParseHex(text + 12, 4);
       
   205 
       
   206 					if(pc >= lastPC + lastLen)
       
   207 						{
       
   208 						bool is_added = aParser.Symbol(text + 20, pc, length);
       
   209 						if (is_added && aModuleName && !first_pc_limit) 
       
   210 							{
       
   211 							first_pc_limit = pc + length;
       
   212 							last_pc_limit = pc + aModuleLength;
       
   213 							}
       
   214 						}
       
   215 
       
   216 					prevName = text + 20;
       
   217 					if(pc + length > lastPC + lastLen)
       
   218 						{
       
   219 						lastLen = length;
       
   220 						lastPC = pc;
       
   221 						}
       
   222 					inSyms = true;
       
   223 					}
       
   224 				}
       
   225 			break;
       
   226 		case EError:
       
   227 			break;
       
   228 			}
       
   229 		text = endl + 2;
       
   230 		}
       
   231 	if (state == EError)
       
   232 		Analyse::Abort("Bad ROM symbol file format");
       
   233 
       
   234 Quit:
       
   235 	if(aModuleName && lastPC == first_pc_limit && (lastPC + lastLen) < last_pc_limit)
       
   236 		{
       
   237 		memcpy((void *)(prevName - 10), "<anon> in ", 10);
       
   238 		aParser.Symbol(prevName - 10, lastPC + lastLen, last_pc_limit - (lastPC + lastLen));
       
   239 		}
       
   240 	aParser.Done(first_pc_limit, last_pc_limit, aModuleId);
       
   241 
       
   242 	return true;
       
   243 	}