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