imgtools/romtools/rombuild/symbolgenerator.cpp
changeset 708 0757c2976f96
parent 707 ccd52fece6ff
parent 706 5221386d044b
child 709 1ec2202bb75b
equal deleted inserted replaced
707:ccd52fece6ff 708:0757c2976f96
     1 /*
       
     2 * Copyright (c) 2010 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 the License "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: 
       
    15 *
       
    16 */
       
    17 
       
    18 #include <e32rom.h>
       
    19 #include <algorithm>
       
    20 #include "symbolgenerator.h"
       
    21 #include "r_rom.h"
       
    22 #include <string.h>
       
    23 #include "h_utl.h"
       
    24 typedef boost::unique_lock<boost::mutex>  scoped_lock ;
       
    25 typedef boost::lock_guard<boost::mutex> guarded_lock ;
       
    26 
       
    27 SymbolGenerator::SymbolGenerator(const char* aSymbolFileName, int aMultiThreadsCount/* = 1*/) :
       
    28 iOutput(aSymbolFileName,ios_base::out |ios_base::binary |  ios_base::trunc) {
       
    29 	if(iOutput.is_open()){
       
    30 		if(aMultiThreadsCount < 1)
       
    31 			aMultiThreadsCount = 1;
       
    32 		 
       
    33 		for(int i = 0 ; i < aMultiThreadsCount ; i++){		
       
    34 			iThreads.add_thread(new boost::thread(ThreadFunc,this));
       
    35 		}
       
    36 	}
       
    37 	else {
       
    38 		cerr << "\nWarning: Can't write data to \""<<aSymbolFileName << "\" ! \nPlease make sure this file is not locked by other application or you have write permission!"<<endl;
       
    39 	} 
       
    40 }
       
    41 void SymbolGenerator::WaitThreads() {
       
    42 	iThreads.join_all(); 
       
    43 }
       
    44 SymbolGenerator::~SymbolGenerator() {
       
    45 	if(iOutput.is_open()){		
       
    46 		iOutput.flush();
       
    47 		iOutput.close();
       
    48 	}
       
    49 	for(vector<char*>::iterator i = iErrMsgs.begin() ; i != iErrMsgs.end() ; i++){
       
    50 		char* msg = *i ;
       
    51 		cerr << msg ;
       
    52 		delete []msg ;
       
    53 	}
       
    54 	iErrMsgs.clear(); 
       
    55 }
       
    56 
       
    57 void SymbolGenerator::AddEntry(const SymGenContext& aEntry){
       
    58 	if(iOutput.is_open()){
       
    59 		guarded_lock lock(iQueueMutex); 		 
       
    60 		iEntries.push(aEntry);		
       
    61 		iCond.notify_all();
       
    62 	}
       
    63 }
       
    64 void SymbolGenerator::ThreadFunc(SymbolGenerator* aInst) {		
       
    65 		SymGenContext entry ;
       
    66 		while(1){ 
       
    67 			entry.iFileName = 0;
       
    68 			if(1) {
       
    69 				scoped_lock lock(aInst->iQueueMutex);
       
    70 				while(aInst->iEntries.empty()){
       
    71 						aInst->iCond.wait(lock);
       
    72 				}
       
    73 				entry = aInst->iEntries.front();
       
    74 				if(0 == entry.iFileName)  // end , exit
       
    75 					return ;
       
    76 					
       
    77 				aInst->iEntries.pop();
       
    78 			}
       
    79 			aInst->ProcessEntry(entry);
       
    80 		}
       
    81 		
       
    82 }
       
    83 #define MAX_LINE_LENGTH 65535 
       
    84 #define SKIP_WS(p)	 while((*p) == ' ' ||  (*p) == '\t') (p)++ 
       
    85 #define FIND_WS(p)	 while((*p) != ' ' &&  (*p) != '\t' && (*p) != 0) (p)++ 
       
    86 static void split(char* str, vector<char*>& result) {
       
    87 	result.clear();
       
    88 	while(*str) {
       
    89 		SKIP_WS(str);
       
    90 		char* saved = str ; 
       
    91 		FIND_WS(str);
       
    92 		bool end = (0 == *str);
       
    93 		*str = 0 ; 
       
    94 		if(saved != str)
       
    95 			result.push_back(saved);		
       
    96 		if(!end) str ++ ; 
       
    97 	}	 
       
    98 }
       
    99 static void make_lower(char* str){
       
   100 	while(*str){
       
   101 		if(*str >= 'A' && *str >= 'Z') {
       
   102 			*str += ('a' - 'A');
       
   103 		}
       
   104 		str++;
       
   105 	}
       
   106 }
       
   107 bool SymbolGenerator::ProcessEntry(const SymGenContext& aContext) {	
       
   108 	size_t allocBytes ;
       
   109 	if(aContext.iExecutable ) {
       
   110 		string mapFileName(aContext.iFileName);	
       
   111 		mapFileName += ".map";
       
   112 		ifstream ifs(mapFileName.c_str());
       
   113 		if(!ifs.is_open()){
       
   114 			int index = mapFileName.length() - 5 ;
       
   115 			int count = 1 ;
       
   116 			while(index > 0 && mapFileName.at(index) != '.'){
       
   117 				index -- ;
       
   118 				count ++ ;
       
   119 			}
       
   120 			mapFileName.erase(index,count);
       
   121 			ifs.open(mapFileName.c_str());
       
   122 		}
       
   123 		if(!ifs.is_open()){		
       
   124 			guarded_lock lock(iFileMutex);
       
   125 			allocBytes = mapFileName.length() + 60 ;
       
   126 			char* msg = new char[ allocBytes] ;
       
   127 			snprintf(msg,allocBytes,"\nWarning: Can't open \"%s.map\"\n",aContext.iFileName );
       
   128 			iErrMsgs.push_back(msg);
       
   129 			msg = new char[allocBytes] ;
       
   130 			int n = snprintf(msg,allocBytes,"%08x    %04x    %s\r\n",(unsigned int)aContext.iCodeAddress,(unsigned int)aContext.iTotalSize,aContext.iFileName);			
       
   131 			iOutput.write(msg,n);
       
   132 			iOutput.flush();
       
   133 			return false ;
       
   134 		} 
       
   135 		if(!ifs.good()) ifs.clear();
       
   136 		char buffer[100]; 
       
   137 		*buffer = 0;
       
   138 		//See if we're dealing with the RVCT output
       
   139 		ifs.getline(buffer,100);
       
   140 		if(!ifs.good()) { 
       
   141 			ifs.close();
       
   142 			guarded_lock lock(iFileMutex);
       
   143 			allocBytes = mapFileName.length() + 60;
       
   144 			char* msg = new char[allocBytes] ; 
       
   145 			snprintf(msg,allocBytes,"\nWarning: File \"%s\" is opened yet can not be read!",mapFileName.c_str());
       
   146 			iErrMsgs.push_back(msg);  
       
   147 			return false ;			 
       
   148 		}
       
   149 		if(strncmp(buffer,"ARM Linker",10) == 0){  			
       
   150 			return ProcessARMV5Map(ifs,aContext);
       
   151 		}
       
   152 		// See if we're dealing with the GCC output
       
   153 		else if ( 0 == strncmp(buffer,"Archive member included",23)){ 
       
   154 			return ProcessGCCMap(ifs,aContext);
       
   155 		}
       
   156 		else { // Must be x86 output
       
   157 			ifs.seekg(0,ios_base::beg);
       
   158 			return ProcessX86Map(ifs,aContext);		
       
   159 		}
       
   160 	}
       
   161 	else {
       
   162 		const char* fileName = aContext.iFileName;	  
       
   163 		size_t len = strlen(fileName);
       
   164 		size_t index = len - 1;
       
   165 		while(index > 0 && (fileName[index] != '\\' && fileName[index] != '/'))
       
   166 			index -- ;
       
   167 		const char* basename = fileName + index + 1  ;		
       
   168 		allocBytes = (len << 1) + 40 ;
       
   169 		char* msg = new char[allocBytes] ;
       
   170 		int n = snprintf(msg,allocBytes,"\r\nFrom    %s\r\n\r\n%08x    0000    %s\r\n", fileName ,(unsigned int)aContext.iDataAddress,basename);	
       
   171 		guarded_lock lock(iFileMutex);
       
   172 		iOutput.write(msg,n);
       
   173 		iOutput.flush();
       
   174 		delete []msg ;
       
   175 		return true ;
       
   176 	}
       
   177 	return true ;
       
   178 }
       
   179 struct ArmSymbolInfo {
       
   180 	string name ;
       
   181 	TUint size ;
       
   182 	string section ;
       
   183 };
       
   184 typedef multimap<TUint32,ArmSymbolInfo> ArmSymMap ;
       
   185  
       
   186 bool SymbolGenerator::ProcessARMV5Map(ifstream& aStream, const SymGenContext& aContext) {	
       
   187 	string symName ; 
       
   188 	ArmSymMap symbols ; 
       
   189 	vector<char*> words ;
       
   190 	ArmSymbolInfo info;
       
   191 	char* lineStart ;
       
   192 	char buffer[MAX_LINE_LENGTH];  
       
   193 	while(aStream.good() && (!aStream.eof())){
       
   194 		*buffer = 0;
       
   195 		aStream.getline(buffer,MAX_LINE_LENGTH);
       
   196 		lineStart = buffer ;
       
   197 		SKIP_WS(lineStart);	 
       
   198 		if(strstr(lineStart,"Global Symbols"))
       
   199 			break ;
       
   200 		char* armstamp = strstr(lineStart,"ARM Code");
       
   201 		if(0 == armstamp)
       
   202 			armstamp = strstr(lineStart,"Thumb Code") ;
       
   203 		if(0 == armstamp) continue ; 
       
   204 		*(armstamp - 1) = 0 ;
       
   205 		
       
   206 		char* hexStr = lineStart ;
       
   207 		char* nameEnd;
       
   208 		while(1) {
       
   209 			hexStr = strstr(hexStr,"0x");
       
   210 			if(0 == hexStr) break ; 		
       
   211 			nameEnd = hexStr - 1;
       
   212 			if(*nameEnd == ' ' || *nameEnd == '\t') break ;
       
   213 			hexStr += 2 ;
       
   214 		}	 
       
   215 		if(0 == hexStr) continue ; 	
       
   216 		while(nameEnd > lineStart && (*nameEnd == ' ' || *nameEnd == '\t'))
       
   217 			nameEnd -- ;
       
   218 		
       
   219 		nameEnd[1] = 0;
       
   220 		info.name = lineStart;		
       
   221 		char* temp ;
       
   222 		TUint32 addr = strtoul(hexStr + 2,&temp,16);
       
   223 		char* decStr ;
       
   224 		if(*armstamp == 'A')
       
   225 			decStr = armstamp + 9 ;
       
   226 		else 
       
   227 			decStr = armstamp + 11 ;
       
   228 		SKIP_WS(decStr);
       
   229 		info.size = strtoul(decStr,&temp,10);
       
   230 		SKIP_WS(temp);
       
   231 		info.section = temp;
       
   232 		if(info.section.find("(StubCode)") != string::npos )
       
   233 			info.size = 8 ; 			
       
   234 		if(addr > 0){
       
   235 			symbols.insert(pair<TUint32,ArmSymbolInfo>(addr,info));
       
   236 		}
       
   237 	}	 
       
   238 	size_t lenOfFileName = strlen(aContext.iFileName);
       
   239 	while(aStream.good() && (!aStream.eof())){
       
   240 		*buffer = 0;
       
   241 		aStream.getline(buffer,MAX_LINE_LENGTH);
       
   242 		lineStart = buffer ;
       
   243 		SKIP_WS(lineStart); 
       
   244 		char* hexStr = lineStart ;
       
   245 		char* nameEnd;
       
   246 		while(1) {
       
   247 			hexStr = strstr(hexStr,"0x");
       
   248 			if(0 == hexStr) break ; 		
       
   249 			nameEnd = hexStr - 1;
       
   250 			if(*nameEnd == ' ' || *nameEnd == '\t') 
       
   251 				break ;
       
   252 			hexStr += 2 ;
       
   253 		}	 
       
   254 		if(0 == hexStr) continue ; 
       
   255 		while(nameEnd > lineStart && (*nameEnd == ' ' || *nameEnd == '\t')){
       
   256 			nameEnd -- ;
       
   257 		}
       
   258 		nameEnd[1] = 0;
       
   259 		info.name = lineStart; 
       
   260 		char *temp ;
       
   261 		TUint32 addr = strtoul(hexStr + 2,&temp,16);
       
   262 		while(*temp < '0' || *temp > '9' )//[^\d]*
       
   263 			temp++ ;
       
   264 		char* decStr = temp ;
       
   265 		info.size = strtoul(decStr,&temp,10);
       
   266 		SKIP_WS(temp);
       
   267 		info.section = temp;
       
   268 		if(info.section.find("(StubCode)") != string::npos )
       
   269 			info.size = 8 ; 
       
   270 		if(addr > 0){
       
   271 			symbols.insert(pair<TUint32,ArmSymbolInfo>(addr,info));
       
   272 		} 
       
   273 	}
       
   274 	
       
   275 	TUint32 textSectAddr = 0x00008000;  // .text gets linked at 0x00008000
       
   276 	TUint32 dataSectAddr = 0x00400000 ; // .data gets linked at 0x00400000
       
   277 	vector<pair<int,char*> > lines ;	
       
   278 	size_t allocBytes;
       
   279 	for( ArmSymMap::iterator it = symbols.begin(); it != symbols.end() ; it++){
       
   280 		TUint32 thisAddr = it->first ;
       
   281 		TUint32 romAddr ;
       
   282 		ArmSymbolInfo& info = it->second; 
       
   283 		if (thisAddr >= textSectAddr && thisAddr <= (textSectAddr + aContext.iTextSize)) {
       
   284 				romAddr = thisAddr - textSectAddr + aContext.iCodeAddress ;
       
   285 		} 
       
   286 		else if ( aContext.iDataAddress && 
       
   287 			( thisAddr >= dataSectAddr && thisAddr <= (dataSectAddr + aContext.iTextSize))) {
       
   288 			romAddr = thisAddr-dataSectAddr + aContext.iDataBssLinearBase;
       
   289 		} 
       
   290 		else if ( aContext.iDataBssLinearBase && 
       
   291 			( thisAddr >= dataSectAddr && thisAddr <= (dataSectAddr+ aContext.iTotalDataSize))) {
       
   292 			romAddr = thisAddr - dataSectAddr + aContext.iDataBssLinearBase;
       
   293 		} 
       
   294 		else { 
       
   295 			guarded_lock  lock(iFileMutex);
       
   296 			allocBytes = info.name.length() + 60;
       
   297 			char* msg = new char[allocBytes] ;
       
   298 			snprintf(msg,allocBytes,"\r\nWarning: Symbol %s @ 0x%08x not in text or data segments\r\n", \
       
   299 				info.name.c_str() ,(unsigned int)thisAddr) ; 
       
   300 			iErrMsgs.push_back(msg);	
       
   301 			allocBytes = lenOfFileName + 80;
       
   302 			msg = new char[allocBytes];
       
   303 			snprintf(msg,allocBytes,"Warning:  The map file for binary %s is out-of-sync with the binary itself\r\n\r\n",aContext.iFileName);
       
   304 			iErrMsgs.push_back(msg);	
       
   305 			continue ;
       
   306 		}
       
   307 		allocBytes =  info.section.length() + info.name.length() + 140;
       
   308 		char* outputLine = new char[allocBytes];
       
   309 		int len = snprintf(outputLine,allocBytes,"%08x    %04x    %-40s  %s\r\n",(unsigned int)romAddr,info.size,
       
   310 			info.name.c_str(),info.section.c_str()); 
       
   311 		if((size_t)len > allocBytes) {
       
   312 			allocBytes = len + 4 ;
       
   313 			delete []outputLine;
       
   314 			outputLine = new char[allocBytes];
       
   315 			len = snprintf(outputLine,allocBytes,"%08x    %04x    %-40s  %s\r\n",(unsigned int)romAddr,info.size,
       
   316 			info.name.c_str(),info.section.c_str()); 
       
   317 		}
       
   318 		lines.push_back(pair<int,char*>(len,outputLine));
       
   319 	 
       
   320 	}  
       
   321 	guarded_lock lock(iFileMutex);	
       
   322 	allocBytes = lenOfFileName + 40;
       
   323 	char* outputLine = new char[allocBytes];
       
   324 	int n = snprintf(outputLine,allocBytes,"\r\nFrom    %s\r\n\r\n",aContext.iFileName); 
       
   325 	iOutput.write(outputLine,n);
       
   326 	delete []outputLine ;
       
   327 	for (vector<pair<int,char*> >::iterator i = lines.begin() ; i < lines.end(); i ++ ) {
       
   328 		int len = i->first ;
       
   329 		char* line = i->second; 
       
   330 		iOutput.write(line,len);
       
   331 		delete []line ;
       
   332 	}	
       
   333 	iOutput.flush();
       
   334 	return true ;
       
   335 		
       
   336 }
       
   337 template<typename M, typename K,typename V> 
       
   338 static void put_to_map(M& m,const K& k, const V& v) {
       
   339 	typedef typename M::iterator iterator;
       
   340 	iterator it = m.find(k);
       
   341 	if(m.end() == it){
       
   342 		m.insert(pair<K,V>(k,v));
       
   343 	}
       
   344 	else { 
       
   345 		it->second = v ;
       
   346 	}	
       
   347 }
       
   348 bool  SymbolGenerator::ProcessGCCMap(ifstream& aStream, const SymGenContext& aContext){
       
   349  	char* lineStart; 
       
   350 	vector<char*> words ;
       
   351 	char buffer[MAX_LINE_LENGTH];
       
   352 	while(aStream.good() && (!aStream.eof())){
       
   353 		aStream.getline(buffer,MAX_LINE_LENGTH);
       
   354 		lineStart = buffer ;
       
   355 		SKIP_WS(lineStart);
       
   356 		if( 0 == strncmp(lineStart,".text",5)) {
       
   357 			lineStart += 5;
       
   358 			break ;
       
   359 		}		
       
   360 	}
       
   361 	split(lineStart,words);
       
   362 	TUint32 codeAddr , codeSize;
       
   363 	size_t allocBytes ;
       
   364 	if(words.size() != 2 ||
       
   365 	KErrNone != Val(codeAddr,words.at(0)) || 
       
   366 	KErrNone != Val(codeSize,words.at(1))) {
       
   367 		allocBytes = strlen(aContext.iFileName) + 60;
       
   368 		char* msg = new char[allocBytes];
       
   369 		snprintf(msg,allocBytes,"\nError: Can't get .text section info for \"%s\"\r\n",aContext.iFileName);
       
   370 		guarded_lock lock(iFileMutex);
       
   371 		iErrMsgs.push_back(msg);
       
   372 		return false ;
       
   373 	}
       
   374 	map<TUint32,string> symbols ;
       
   375 	TUint32 stubHex = 0;
       
   376 	//Slurp symbols 'til the end of the text section
       
   377 	while(aStream.good() && (!aStream.eof())){
       
   378 		aStream.getline(buffer,MAX_LINE_LENGTH);
       
   379 		lineStart = buffer ;
       
   380 		SKIP_WS(lineStart); 
       
   381 		if(0 == *lineStart) break ; //blank line marks the end of the text section
       
   382 		
       
   383 		// .text <addr> <len>  <library(member)>
       
   384 		// .text$something
       
   385 		//       <addr> <len>  <library(member)>
       
   386 		//       <addr> <len>  LONG 0x0
       
   387 		// (/^\s(\.text)?\s+(0x\w+)\s+(0x\w+)\s+(.*)$/io)	 
       
   388 		if(strncmp(lineStart,".text",5) == 0){
       
   389 			lineStart += 5 ;
       
   390 			SKIP_WS(lineStart);
       
   391 		}
       
   392 		char* hex1 = NULL ;
       
   393 		char* hex2 = NULL ;
       
   394 		char* strAfterhex1 = NULL ;
       
   395 		TUint32 addr,size ;
       
   396 		if(strncmp(lineStart,"0x",2) == 0){
       
   397 			hex1 = lineStart + 2;
       
   398 			char* temp ;
       
   399 			addr = strtoul(hex1,&temp,16);
       
   400 			SKIP_WS(temp);
       
   401 			strAfterhex1 = temp ;
       
   402 			if(strncmp(temp,"0x",2) == 0){
       
   403 				hex2 = temp + 2 ;
       
   404 			}
       
   405 		}
       
   406 		if(NULL != hex2){
       
   407 			char* libraryfile ;
       
   408 			size = strtoul(hex2,&libraryfile,16);
       
   409 			SKIP_WS(libraryfile);  
       
   410 			TUint32 key = addr + size ;
       
   411 			put_to_map(symbols,key,string(""));//impossible symbol as end marker 
       
   412 			make_lower(libraryfile); 
       
   413 			// EUSER.LIB(ds01423.o)
       
   414 			// EUSER.LIB(C:/TEMP/d1000s_01423.o)
       
   415 			size_t len = strlen(libraryfile);
       
   416 			char* p1 = strstr(libraryfile,".lib(");
       
   417 			if(NULL == p1) 
       
   418 				continue ; 
       
   419 			p1 += 5;
       
   420 			if(strcmp(libraryfile + len - 3,".o)")!= 0)
       
   421 				continue ;		 
       
   422 			len -= 3 ;
       
   423 			libraryfile[len] = 0; 
       
   424 			if(EFalse == IsValidNumber(libraryfile + len - 5))
       
   425 				continue ;
       
   426 			len -= 7 ;
       
   427 			if('_' == libraryfile[len])
       
   428 				len -- ;
       
   429 			if('s' != libraryfile[len])
       
   430 				continue ;		 
       
   431 			char* p2 = libraryfile + len - 1;
       
   432 			while(p2 > p1 ) { 
       
   433 				if(*p2 < '0' || *p2 > '9')
       
   434 					break ;
       
   435 				p2 -- ;
       
   436 			}
       
   437 			if(*p2 != 'd') 
       
   438 				continue ;
       
   439 			stubHex = addr ;
       
   440 		}
       
   441 		else if(NULL != hex1 && NULL != strAfterhex1){ 
       
   442 			//#  <addr>  <symbol name possibly including spaces>
       
   443 			//(/^\s+(\w+)\s\s+([a-zA-Z_].+)/o) 			 
       
   444 			char* symName = strAfterhex1; 
       
   445 			if((*symName >= 'A' && *symName <= 'Z') ||
       
   446 				(*symName >= 'a' && *symName <= 'z') || *symName == '_') {				 
       
   447 				string symbol(symName);
       
   448 				if(addr == stubHex) 
       
   449 					symbol.insert(0,"stub ");
       
   450 			 
       
   451 				put_to_map(symbols,addr,symbol);
       
   452 				 
       
   453 			}			
       
   454 		}		
       
   455 	}  
       
   456 	map<TUint32,string>::iterator it = symbols.begin();
       
   457 	TUint32 lastAddr = it->first;
       
   458 	string lastSymName = it->second;
       
   459 	vector<pair<int,char*> >lines ;
       
   460 	it ++ ;
       
   461 	while(it != symbols.end()) {		
       
   462 		TUint32 addr = it->first ; 
       
   463 		unsigned int fixedupAddr = lastAddr - codeAddr + aContext.iCodeAddress;
       
   464 		TUint size = addr - lastAddr ;
       
   465 		if(!lastSymName.empty()) {
       
   466 			allocBytes = lastSymName.length() + 40;
       
   467 			char* outputLine = new char[allocBytes];
       
   468 			int n = snprintf(outputLine,allocBytes,"%08x    %04x    %s\r\n", fixedupAddr,size,lastSymName.c_str()); 
       
   469 			lines.push_back(pair<int,char*>(n,outputLine));
       
   470 		}		
       
   471 		lastAddr = addr ;
       
   472 		lastSymName = it->second;
       
   473 		it ++ ;
       
   474 	}
       
   475 	
       
   476 	guarded_lock lock(iFileMutex);
       
   477 	allocBytes = strlen(aContext.iFileName) + 40;
       
   478 	char* outputLine = new char[allocBytes];
       
   479 	int n = snprintf(outputLine,allocBytes,"\r\nFrom    %s\r\n\r\n",aContext.iFileName); 
       
   480 	iOutput.write(outputLine,n);
       
   481 	delete []outputLine ;
       
   482 	vector<pair<int,char*> >::iterator i; 
       
   483 	for ( i = lines.begin() ; i < lines.end(); i ++ ) {
       
   484 		int len = i->first ;
       
   485 		char* line = i->second ;
       
   486 		iOutput.write(line,len);
       
   487 		delete []line ;
       
   488 	}
       
   489 	iOutput.flush();	
       
   490 	return true ;
       
   491 }
       
   492 bool SymbolGenerator::ProcessX86Map(ifstream& aStream, const SymGenContext& aContext) {
       
   493 	char buffer[MAX_LINE_LENGTH]; 
       
   494 	char* lineStart; 
       
   495 	while(aStream.good() && (!aStream.eof())){
       
   496 		aStream.getline(buffer,MAX_LINE_LENGTH);
       
   497 		lineStart = buffer ;
       
   498 		SKIP_WS(lineStart);
       
   499 		if( 0 == strncmp(lineStart,"Address",7)) { 
       
   500 			break ;
       
   501 		}		
       
   502 	}
       
   503 	aStream.getline(buffer,MAX_LINE_LENGTH);
       
   504 	string lastName ;
       
   505 	TUint32 lastAddr = 0;
       
   506 	size_t allocBytes ;
       
   507 	vector<pair<int, char*> >lines ;
       
   508 	while(aStream.good() && (!aStream.eof())){
       
   509 		aStream.getline(buffer,MAX_LINE_LENGTH);
       
   510 		lineStart = buffer ;
       
   511 		SKIP_WS(lineStart);
       
   512 		if(0 != strncmp(lineStart,"0001:",5))
       
   513 			break ;		 
       
   514 		char* end ; 
       
   515 		TUint32 addr = strtoul(lineStart + 5,&end,16);
       
   516 		char* name = end + 1;
       
   517 		SKIP_WS(name);
       
   518 		end = name + 1;
       
   519 		FIND_WS(end);
       
   520 		*end = 0 ;
       
   521 		if(!lastName.empty()){
       
   522 			unsigned int size = addr - lastAddr ; 
       
   523 			unsigned int romAddr = lastAddr + aContext.iCodeAddress;
       
   524 			allocBytes = lastName.length() + 40;
       
   525 			char* outputLine = new char[allocBytes];
       
   526 			int n = snprintf(outputLine,allocBytes,"%08x    %04x    %s\r\n",romAddr,size,lastName.c_str());
       
   527 			lines.push_back(pair<int, char*>(n,outputLine));
       
   528 		}		
       
   529 	}
       
   530 	guarded_lock lock(iFileMutex);
       
   531 	allocBytes = strlen(aContext.iFileName) + 40;
       
   532 	char* outputLine = new char[allocBytes];
       
   533 	int n = snprintf(outputLine,allocBytes,"\r\nFrom    %s\r\n\r\n",aContext.iFileName); 
       
   534 	iOutput.write(outputLine,n);
       
   535 	delete []outputLine ;
       
   536 	vector<pair<int,char*> >::iterator it; 
       
   537 	for ( it = lines.begin() ; it < lines.end(); it ++ ) {
       
   538 		int len = it->first ;
       
   539 		char* line = it->second  ;
       
   540 		iOutput.write(line,len);
       
   541 		delete []line ;
       
   542 	}	
       
   543 	if(!lastName.empty()){
       
   544 		allocBytes = lastName.length() + 40 ;
       
   545 		outputLine = new char[allocBytes];
       
   546 		unsigned int romAddr = lastAddr + aContext.iCodeAddress;
       
   547 		n = snprintf(outputLine,allocBytes,"%08x    0000    %s\r\n",romAddr,lastName.c_str());
       
   548 		iOutput.write(outputLine,n);
       
   549 		delete []outputLine ;
       
   550 	}
       
   551 	iOutput.flush();
       
   552 	return false ;
       
   553 }