|
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 } |