tools/elf4rom/src/processoptions.cpp
changeset 34 92d87f2e53c2
equal deleted inserted replaced
33:1af5c1be89f8 34:92d87f2e53c2
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 *
       
     5 * This program is free software: you can redistribute it and/or modify
       
     6 * it under the terms of the GNU Lesser General Public License as published by
       
     7 * the Free Software Foundation, either version 3 of the License, or
       
     8 * (at your option) any later version.
       
     9 *
       
    10 * This program is distributed in the hope that it will be useful,
       
    11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    13 * GNU Lesser General Public License for more details.
       
    14 * 
       
    15 * You should have received a copy of the GNU Lesser General Public License
       
    16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
       
    17 */
       
    18 
       
    19 #include <boost/program_options.hpp>
       
    20 namespace po = boost::program_options;
       
    21 #include <boost/regex.hpp>
       
    22 #include <boost/filesystem.hpp>
       
    23 namespace fs = boost::filesystem;
       
    24 
       
    25 #include <iostream>
       
    26 
       
    27 #include <iterator>
       
    28 #include <string>
       
    29 #include <map>
       
    30 #include <set>
       
    31 
       
    32 #include <ctype.h>
       
    33 #include <cstdlib>
       
    34 
       
    35 using namespace std;
       
    36 
       
    37 #include "defs.h"
       
    38 #include "romdetails.h"
       
    39 #include "inputfile.h"
       
    40 #include "elfromerror.h"
       
    41 
       
    42 static inline void downcase(std::string & s){
       
    43 	for (std::string::iterator i = s.begin(); i != s.end(); i++)
       
    44 		*i = tolower(*i);
       
    45 }
       
    46 
       
    47 static int required_option(const po::variables_map& vm, const char* option){
       
    48 	if (vm.count(option) == 0 || vm[option].defaulted()) {
       
    49 		cerr << "Error: option \'" << option << "\' required.\n";
       
    50 		return 1;
       
    51 	} 
       
    52 	return 0;
       
    53 }
       
    54 
       
    55 static int either_or_required(const po::variables_map& vm, const char* option1, const char* option2){
       
    56 	if ((vm.count(option1) == 0 || vm[option1].defaulted()) &&
       
    57 		(vm.count(option2) == 0 || vm[option2].defaulted())) {
       
    58 		cerr << "Error: either option \'" << option1 << "\' or option \'" << option2 <<"\' required.\n";
       
    59 		return 1;
       
    60 	} 
       
    61 	return 0;
       
    62 }
       
    63 
       
    64 RomDetails * ProcessOptions(int ac, char* av[]) {
       
    65 	RomDetails * details = new RomDetails;
       
    66 	int errors = 0;
       
    67 	
       
    68     try {
       
    69 
       
    70     	string phys_addr;
       
    71         po::options_description desc("  Command Line Only");
       
    72         desc.add_options()
       
    73             ("help,h", "produce help message")
       
    74             ("config-file,c", po::value<string>(), 	"pathname of config file "
       
    75             													  	"(overrides default of elf4rom.cfg and value "
       
    76             														"of ELF4ROM_CFG_FILE environment variable)")
       
    77         ;
       
    78 
       
    79         po::options_description config("  Command Line and Configuration File");
       
    80         config.add_options()
       
    81             ("board-name,b", po::value<string>(&details->iBoardName), 	"name of board targeted e.g. versatilepb")
       
    82             ("debug,d", po::value< vector<string> >(&details->iTargetFiles)->multitoken()->composing(), 
       
    83 																		"collect ELF and DWARF data from the listed files")
       
    84 			("drive,D", po::value<string>(&details->iDrive), 			"drive on which to find ELF files")
       
    85 			("exclude,e", po::value< vector<string> >(&details->iExcludeFiles)->multitoken()->composing(), 
       
    86 																		"exclude collection of ELF and DWARF data from the listed files")
       
    87             ("input,i", po::value<string>(&details->iRomFile), 			"pathname of ROM image")
       
    88             ("logfile,l", po::value<string>(&details->iLogFile), 		"pathname of ROMBUILD log file")
       
    89             ("no-dwarf,n", po::bool_switch(&details->iNoDwarf), 		"suppress generatation of DWARF in output"
       
    90 																		" (prevents source level debugging but saves time and space)")
       
    91             ("output,o", po::value<string>(&details->iElfRomFile), 		"pathname of output file")
       
    92             // lexical_cast doesn't understand <LinearAddress> even though its just a typedef
       
    93             // for unsigned int
       
    94             ("physical-address,p", po::value<string>(&phys_addr), 		"physical address of ROM on device. Overrides board-name")
       
    95             ("search,s", po::bool_switch(&details->iSearch), 			"search for ELF files in build directory if .sym file not "
       
    96             															"found in release directory")
       
    97             ("strip,S", po::bool_switch(&details->iStrip), 				"suppress generation of symbol table and DWARF in output"
       
    98 																		" (useful to produce a 'loadable' ELF image for e.g. a simulator)")
       
    99 			("trace,t", po::bool_switch(&details->iTrace), 				"switch on trace")
       
   100 			;
       
   101             
       
   102         po::options_description cmdline_options;
       
   103         cmdline_options.add(desc).add(config);
       
   104 
       
   105         po::options_description config_file_options;
       
   106         config_file_options.add(config);
       
   107         
       
   108         po::variables_map vm; 
       
   109         //po::store(po::parse_command_line(ac, av, desc), vm);
       
   110         po::store(po::command_line_parser(ac, av).options(cmdline_options).run(), vm);
       
   111         
       
   112         char * cfgFile = "elf4rom.cfg";
       
   113         if (vm.count("config-file")) {
       
   114         	char * xcfgFile = (char *)(vm["config-file"].as<string>().c_str());
       
   115         	fs::path cfgpath(xcfgFile);
       
   116 
       
   117         	if (fs::exists(cfgpath)) {
       
   118         		cfgFile = xcfgFile;
       
   119         	} else {
       
   120         		cerr << "Warning: specified config file " << xcfgFile << " not found: will not attempt to use default.\n";
       
   121         	}
       
   122         } else {
       
   123         	char * envCfgFile = getenv("ELF4ROM_CFG_FILE");
       
   124         	if (envCfgFile != NULL) 
       
   125         		cfgFile = envCfgFile;
       
   126         }
       
   127         
       
   128         ifstream ifs(cfgFile);
       
   129         store(parse_config_file(ifs, config_file_options), vm);
       
   130 
       
   131        	po::notify(vm); 
       
   132  
       
   133         if (vm.count("help")) {
       
   134         	cout << "elf4rom [option]";
       
   135             cout << cmdline_options << "\n";
       
   136             delete details;
       
   137             exit(EXIT_SUCCESS) ;
       
   138         }
       
   139 
       
   140         
       
   141         errors += required_option(vm, "input");
       
   142         errors += required_option(vm, "logfile");
       
   143         errors += required_option(vm, "output");
       
   144         
       
   145         errors += either_or_required(vm, "board-name", "physical-address");
       
   146 
       
   147         if (vm.count("physical-address")){
       
   148         	char *f;
       
   149         	const char * p = phys_addr.c_str();
       
   150         	details->iRomPhysAddr = strtoul(p ,&f , 16);
       
   151         	if (f == p){
       
   152         		cerr << "Error: invalid arg to --physical-address: " << phys_addr.c_str() << "\n";
       
   153         		exit(EXIT_FAILURE);
       
   154         	}
       
   155         } else if (vm.count("board-name")){
       
   156         	// TODO: figure out address frmo board name
       
   157         	cerr << "Error: --board-name option not implemented yet\n";
       
   158             exit(EXIT_FAILURE) ;
       
   159         }
       
   160         
       
   161         if (errors) {
       
   162         	cerr << "elf4rom [option]";
       
   163             cerr << cmdline_options << "\n";
       
   164             delete details;
       
   165             exit(EXIT_FAILURE) ;
       
   166         }
       
   167     }
       
   168     catch(exception& e) {
       
   169         cerr << "error: " << e.what() << "\n";
       
   170         exit(EXIT_FAILURE) ;
       
   171     }
       
   172     catch(...) {
       
   173         cerr << "Exception of unknown type!\n";
       
   174         exit(EXIT_FAILURE) ;
       
   175     }
       
   176 
       
   177     return details;
       
   178 }
       
   179 
       
   180 
       
   181 static bool VerifyLogFile(string::const_iterator & start, string::const_iterator & end, string::const_iterator & rest){
       
   182 #if 0 
       
   183 // Look for somthing like the following
       
   184 ROMBUILD - Rom builder V2.08 (Build 593)
       
   185 Copyright (c) 1996-2007 Symbian Software Ltd.
       
   186 or
       
   187 ROMBUILD - Rom builder V2.08 (Build 596)
       
   188 Copyright (c) 1996-2009 Nokia Corporation.
       
   189 #endif	
       
   190 
       
   191 	const char * banner  = "ROMBUILD.*Rom builder.*Copyright.*";
       
   192 	boost::regex e(banner);
       
   193 	boost::match_results<string::const_iterator> what;
       
   194 	if (boost::regex_search(start, end, what, e)){ 
       
   195 		rest = what[0].second;
       
   196 		return true;
       
   197 	}
       
   198 	return false;
       
   199 }
       
   200 
       
   201 static void OffenceWarning (string & offender){
       
   202 	cerr << "Warning: The following section of the ROM Log appears corrupt:\n" << offender << "\n";	
       
   203 }
       
   204 
       
   205 static inline unsigned int ConvertToUnsignedLong(string & s, string & offender){
       
   206 	char * endp;
       
   207 	const char * ss = s.c_str();
       
   208 	unsigned int res = strtoul(ss, &endp,16);
       
   209 	if (endp == ss)
       
   210 		OffenceWarning(offender);
       
   211 	return res;
       
   212 }
       
   213 
       
   214 static bool ProcessXIPFile(string::const_iterator & start, string::const_iterator & end, 
       
   215 		string::const_iterator & rest, RomDetails * details){
       
   216 	const char * f  = 
       
   217 		"Processing file (\\S+)\\s*" 		// 1
       
   218 		"(\\[Primary\\]\\s*)?"				// 2
       
   219 		"(\\[Secondary\\]\\s*)?"			// 3		
       
   220 		"(ELF File:\\s*\\S+\\s*)?" 			// 4
       
   221 		"(ELF MD5:\\s*\\S+\\s*)?"			// 5
       
   222 		"Load Address:\\s+(\\S+)\\s*"		// 6
       
   223 		"Size:\\s+\\S+\\s*"
       
   224 		"Uids:\\s+\\S+\\s+\\S+\\s+\\S+\\s+\\S+\\s*"
       
   225 		"Entry point:\\s+\\S+\\s*"
       
   226 		"Code start addr:\\s+(\\S+)\\s*"	// 7
       
   227 		"Data start addr:\\s+(\\S+)\\s*"	// 8
       
   228 		"DataBssLinearBase:\\s+(\\S+)\\s*"	// 9
       
   229 		"Text size:\\s+\\S+\\s*"
       
   230 		"Code size:\\s+(\\S+)\\s*"			// 10
       
   231 		"Data size:\\s+(\\S+)\\s*"			// 11
       
   232 		"BssSize:\\s+(\\S+)\\s*"			// 12
       
   233 		;
       
   234 	boost::regex e(f);
       
   235 	boost::match_results<string::const_iterator> what;
       
   236 	if (boost::regex_search(start, end, what, e)){
       
   237 		string filename(what[1].first, what[1].second);
       
   238 		string offender(what[0].first, what[0].second);
       
   239 		if (filename.size() == 0)
       
   240 			OffenceWarning(offender);
       
   241 		bool primary = what[2].matched;
       
   242 		if (what[2].matched){
       
   243 			primary = true;
       
   244 		}
       
   245 		
       
   246 		const int kla = 6;
       
   247 		string ls(what[kla].first, what[kla].second);
       
   248 		LinearAddr load = ConvertToUnsignedLong(ls, offender);
       
   249 
       
   250 		const int kta = kla + 1;
       
   251 		string ts(what[kta].first, what[kta].second);
       
   252 		LinearAddr text = ConvertToUnsignedLong(ts, offender);
       
   253 
       
   254 		const int kda = kta + 1;
       
   255 		string ds(what[kda].first, what[kda].second);
       
   256 		LinearAddr data = ConvertToUnsignedLong(ds, offender);
       
   257 
       
   258 		const int kva = kda + 1;
       
   259 		string vds(what[kva].first, what[kva].second);
       
   260 		VirtualAddr vdata = ConvertToUnsignedLong(vds, offender);
       
   261 
       
   262 		const int kts = kva + 1;
       
   263 		string tss(what[kts].first, what[kts].second);
       
   264 		size_t textSize = ConvertToUnsignedLong(tss, offender);		
       
   265 
       
   266 		const int kds = kts + 1;
       
   267 		string dss(what[kds].first, what[kds].second);
       
   268 		size_t fileDataSize = ConvertToUnsignedLong(dss, offender);
       
   269 
       
   270 		const int kbs = kds + 1;
       
   271 		string bsss(what[kbs].first, what[kbs].second);
       
   272 		size_t bssSize = ConvertToUnsignedLong(bsss, offender);		
       
   273 		VirtualAddr bss = vdata + fileDataSize;
       
   274 		size_t memDataSize = fileDataSize + bssSize;
       
   275 		
       
   276 		string elffile("");
       
   277 		details->iXIPFiles.push_back(XIPFileDetails(filename, 
       
   278 													elffile, 
       
   279 													load, 
       
   280 													text, 
       
   281 													textSize,
       
   282 													vdata, 
       
   283 													fileDataSize, 
       
   284 													data, 
       
   285 													bss, 
       
   286 													memDataSize));
       
   287 		if (primary)
       
   288 			new(&details->iPrimary)XIPFileDetails(filename, 
       
   289 												  elffile, 
       
   290 												  load, 
       
   291 												  text, 
       
   292 												  textSize,
       
   293 												  vdata, 
       
   294 												  fileDataSize, 
       
   295 												  data, 
       
   296 												  bss, 
       
   297 												  memDataSize);
       
   298 		
       
   299 		rest = what[0].second;
       
   300 		return true;
       
   301 	}
       
   302 	rest = start;
       
   303 	return false;
       
   304 
       
   305 }
       
   306 
       
   307 static void CheckXIPFiles(RomDetails * details, std::vector<string> & list){
       
   308 	for (std::vector<string>::iterator i = list.begin(); i != list.end(); i++) {
       
   309 		bool found = false;
       
   310 		for (RomDetails::XIPFileList::iterator j = details->iXIPFiles.begin(); j != details->iXIPFiles.end(); j++){
       
   311 			fs::path e32filePath(j->iE32File);
       
   312 			String e32FileName(e32filePath.leaf());
       
   313 			if ((*i) == e32FileName){
       
   314 				found = true;
       
   315 				break;
       
   316 			}
       
   317 
       
   318 		}
       
   319 		if (!found){
       
   320 			cerr << "WARNING: " << (*i) << " not found in ROM\n";
       
   321 		}
       
   322 	}
       
   323 }
       
   324 
       
   325 static void CheckDebugXIPFiles(RomDetails * details){
       
   326 	CheckXIPFiles(details, details->iTargetFiles);
       
   327 }
       
   328 
       
   329 static void CheckExcludeXIPFile(RomDetails * details){
       
   330 	CheckXIPFiles(details, details->iExcludeFiles);
       
   331 }
       
   332 
       
   333 static void ProcessXIPFiles(string::const_iterator & start, string::const_iterator & end, 
       
   334 		string::const_iterator & rest, RomDetails * details){
       
   335 	while (ProcessXIPFile(start,end,rest,details)){
       
   336 		start = rest;
       
   337 	}
       
   338 	CheckDebugXIPFiles(details);
       
   339 	CheckExcludeXIPFile(details);
       
   340 }
       
   341 
       
   342 
       
   343 static void ProcessRomDetails(string::const_iterator & start, string::const_iterator & end, 
       
   344 								string::const_iterator & rest, RomDetails * details){
       
   345 	const char * align  = "Linear base address:\\s*([\\S]+)$";
       
   346 	boost::regex e(align);
       
   347 	boost::match_results<string::const_iterator> what;
       
   348 	if (boost::regex_search(start, end, what, e)){ 
       
   349 		string offender(what[0].first, what[0].second);
       
   350 		string lbas(what[1].first, what[1].second);
       
   351 		details->iRomBaseLinearAddr = ConvertToUnsignedLong(lbas, offender);
       
   352 	} else {
       
   353         cerr << "Error: " << details->iLogFile << " not a valid ROM log file. Could not find Linear base address." << "\n";
       
   354         exit(EXIT_FAILURE) ;		
       
   355 	}
       
   356 }
       
   357 
       
   358 static fs::path FindBuildPath(RomDetails * details){
       
   359 	const string epoc32("epoc32");
       
   360 	const string builddir("build");
       
   361 	const string epocRoot(getenv("EPOCROOT"));
       
   362 	if (details->iDrive.size() > 0) {
       
   363 		string drive(details->iDrive);
       
   364 		if (drive.size() == 1){
       
   365 			drive += ":";
       
   366 		} else if (((drive.size() == 2) && (drive[drive.size()-1] != ':')) || (drive.size() > 2)){
       
   367 	        cerr << "Error: Invalid drive specification: " << drive << "\n";
       
   368 	        exit(EXIT_FAILURE) ;			
       
   369 		}
       
   370 		fs::path buildpath(drive);
       
   371 
       
   372 		buildpath /= epocRoot;
       
   373 		buildpath /= epoc32;
       
   374 		buildpath /= builddir;
       
   375 		return buildpath;
       
   376 	}
       
   377 	fs::path primary_path(details->iPrimary.iE32File);
       
   378 	fs::path buildpath;
       
   379 	for (fs::path::iterator i = primary_path.begin(); i != primary_path.end(); i++){
       
   380 		string item(*i);
       
   381 		downcase(item);
       
   382 		buildpath /= item;
       
   383 		if (item == epoc32) {
       
   384 			buildpath /= builddir;
       
   385 			break;
       
   386 		}
       
   387 	}
       
   388 	return buildpath;
       
   389 }
       
   390 
       
   391 class PathCache {
       
   392 public:
       
   393 	typedef std::map<string, string> PathMap;
       
   394 
       
   395 	PathCache(fs::path & apath):
       
   396 		iBuildPath(apath)
       
   397 		{
       
   398 			if (fs::exists(apath)){
       
   399 				fs::recursive_directory_iterator i(apath);
       
   400 				iCurrent = i;
       
   401 			}
       
   402 		}
       
   403 	bool FindPath(string & pattern, string & result);
       
   404 	fs::path & GetBuildPath() { return iBuildPath; }
       
   405 	
       
   406 private:
       
   407 	bool GetNextPath(string & path);
       
   408 	bool Filtered(fs::path & path);
       
   409 
       
   410 private:
       
   411 	
       
   412 	fs::path iBuildPath;
       
   413 	fs::recursive_directory_iterator iCurrent;
       
   414 	fs::recursive_directory_iterator iEnd;
       
   415 	PathMap iPathMap;
       
   416 	static const std::string filters;
       
   417 };
       
   418 
       
   419 
       
   420 
       
   421 bool PathCache::Filtered(fs::path & apath){
       
   422 	std::string ext(fs::extension(apath));
       
   423 	downcase(ext);
       
   424 	if (ext.size() > 0){
       
   425 		if (filters.find(ext) != std::string::npos)
       
   426 			return true;
       
   427 	} 
       
   428 	return false;
       
   429 }
       
   430 
       
   431 bool PathCache::GetNextPath(string & path){
       
   432 	 for (; iCurrent != iEnd; ++iCurrent ){
       
   433 		 if (fs::is_directory(iCurrent->status()))
       
   434 			 continue;
       
   435 		 fs::path candidate(iCurrent->path());
       
   436 		 if (!Filtered(candidate)) {
       
   437 			 path = candidate.string();
       
   438 			 ++iCurrent;
       
   439 			 return true;
       
   440 		 }
       
   441 	 }
       
   442 	 return false;
       
   443 }
       
   444 
       
   445 static void GetTarget(string & source, string & target){
       
   446 	fs::path t1(source);
       
   447 	fs::path::iterator s = t1.begin();
       
   448 	fs::path::iterator start = t1.end();
       
   449 	int n = 0;
       
   450 	for (; n < 3 && s != start; n++, start--){}
       
   451 	if (n < 3) {
       
   452 		warnx(0, "%s does not have 3 elements\n", source.c_str());
       
   453 	}
       
   454 
       
   455 	fs::path q;
       
   456 	for (; start != t1.end(); start++){
       
   457 		q /= fs::path(*start);
       
   458 	}
       
   459 	target = q.string();
       
   460 	downcase(target);
       
   461 }
       
   462 
       
   463 bool PathCache::FindPath(string & source, string & result){
       
   464 	string ss;
       
   465 	if (source.size() == 0) return false;
       
   466 	GetTarget(source, ss);
       
   467 	
       
   468 	// now check the cache
       
   469 	PathMap::iterator res = iPathMap.find(ss);
       
   470 	if (res != iPathMap.end()){
       
   471 		result = res->second;
       
   472 		return true;
       
   473 	}
       
   474 	
       
   475 	// otherwise iterate until we find a match
       
   476 	string candidate;
       
   477 	while (GetNextPath(candidate)){
       
   478 		downcase(candidate);
       
   479 		size_t n = candidate.rfind(ss);
       
   480 		if (n != string::npos){
       
   481 			size_t csize = candidate.size();
       
   482 			size_t sssize = ss.size();
       
   483 			if ((csize - sssize) == n){
       
   484 				// put it in cache anyway just in case its the primary
       
   485 				iPathMap[ss] = candidate;
       
   486 				result = candidate;
       
   487 				return true;
       
   488 			}
       
   489 		}
       
   490 		string x;
       
   491 		GetTarget(candidate, x);
       
   492 		iPathMap[x] = candidate;
       
   493 	}
       
   494 	return false;
       
   495 }
       
   496 
       
   497 const std::string PathCache::filters(
       
   498 		".cpp"
       
   499 		".h"
       
   500 		".mk"
       
   501 		".o"
       
   502 		".in"
       
   503 		".via"
       
   504 		".mbg"
       
   505 		".rsg"
       
   506 		".bat"
       
   507 		".make"
       
   508 		".def"
       
   509 		".armv5"
       
   510 	);
       
   511 
       
   512 static bool FindSymFile(XIPFileDetails & detail, string & rootname){
       
   513 	fs::path buildpath(rootname);
       
   514 	fs::path e32path(detail.iE32File);
       
   515 	buildpath /= e32path;
       
   516 	// check for pre-RAPTOR .sym file
       
   517 	fs::path elfpath = fs::change_extension(buildpath, ".sym");
       
   518 	if (fs::exists(elfpath)) {
       
   519 		detail.iElfFile = elfpath.string();
       
   520 		return true;
       
   521 	}
       
   522 	// check for RAPTOR .sym file
       
   523 	fs::path symPath(buildpath.string() + ".sym");
       
   524 	if (fs::exists(symPath)) {
       
   525 		detail.iElfFile = symPath.string();
       
   526 		return true;
       
   527 	}	
       
   528 	return false;
       
   529 }
       
   530 
       
   531 static void FindElfFile(XIPFileDetails & detail, PathCache & cache, bool search){
       
   532 	// see if there's a .sym file
       
   533 	string root(cache.GetBuildPath().root_name());
       
   534 	if (FindSymFile(detail, root)) return;
       
   535 	if (!search) {
       
   536 		cerr << "Warning: could not find ELF file for " << detail.iE32File << ".\n";
       
   537 		return;
       
   538 	}
       
   539 	string s(detail.iE32File);
       
   540 	string res;
       
   541 	if (s.size() == 0) return;
       
   542 	if (cache.GetBuildPath().string().empty()) return;
       
   543 	
       
   544 	if (cache.FindPath(s, res)){
       
   545 		detail.iElfFile = res;
       
   546 	} else
       
   547 		cerr << "Warning: could not find ELF file for " << detail.iE32File << ".\n";
       
   548 }
       
   549 
       
   550 
       
   551 static void FindElfFiles(RomDetails * details){
       
   552 	fs::path buildroot = FindBuildPath(details);
       
   553 	PathCache cache(buildroot);
       
   554 	bool search = details->iSearch;
       
   555 	FindElfFile(details->iPrimary, cache, search);
       
   556 	for(RomDetails::XIPFileList::iterator i = details->iXIPFiles.begin(); i != details->iXIPFiles.end(); i++){
       
   557 		fs::path e32filePath(i->iE32File);
       
   558 		String e32FileName(e32filePath.leaf());
       
   559 		if (details->iTargetFiles.empty()) {
       
   560 			bool find = true;
       
   561 			for (std::vector<String>::iterator ef = details->iExcludeFiles.begin(); ef != details->iExcludeFiles.end(); ef++) {
       
   562 				fs::path excludePath(*ef);
       
   563 				String excludeFile(excludePath.leaf());
       
   564 				if (e32FileName == excludeFile) {
       
   565 					find = false;
       
   566 					break;
       
   567 				}
       
   568 			}
       
   569 			if (find)
       
   570 				FindElfFile(*i, cache, search);
       
   571 		} else {
       
   572 			for (std::vector<String>::iterator tf = details->iTargetFiles.begin(); tf != details->iTargetFiles.end(); tf++) {
       
   573 				fs::path targetPath(*tf);
       
   574 				String targetFile(targetPath.leaf());				
       
   575 				if (e32FileName == targetFile) {
       
   576 					FindElfFile(*i, cache, search);
       
   577 					break;
       
   578 				}
       
   579 			}
       
   580 		}
       
   581 	}
       
   582 	
       
   583 }
       
   584 
       
   585 RomDetails * ProcessRomDetails(RomDetails * details){
       
   586 	InputFile in(details->iLogFile);
       
   587 	char * data = in.GetData();
       
   588 	string logfile(data);
       
   589 	string::const_iterator  start = logfile.begin();
       
   590 	string::const_iterator  end = logfile.end();
       
   591 	string::const_iterator  rest;
       
   592 
       
   593 	if (!VerifyLogFile(start, end , rest)) {
       
   594         cerr << "error: " << details->iLogFile << " not a valid ROM log file." << "\n";
       
   595         exit(EXIT_FAILURE) ;
       
   596 	}
       
   597 	
       
   598 	ProcessXIPFiles(start,end,rest,details);
       
   599 	
       
   600 	ProcessRomDetails(rest, end, rest, details);
       
   601 	
       
   602 	FindElfFiles(details);
       
   603 	
       
   604 	// TODO: make sure functions that return data allocated with new [] 
       
   605 	// have an appropriate return value so that delete [] can be used
       
   606 	delete [] data;
       
   607 	
       
   608 	return details;
       
   609 }