]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/CCode/Source/GenFvMap/GenFvMap.cpp
Fixed bug of incorrect processing of hexadecimal numbers.
[mirror_edk2.git] / Tools / CCode / Source / GenFvMap / GenFvMap.cpp
1 //****************************************************************************
2 //**
3 //** Copyright (C) 2006 Intel Corporation. All rights reserved.
4 //**
5 //** The information and source code contained herein is the exclusive
6 //** property of Intel Corporation and may not be disclosed, examined
7 //** or reproduced in whole or in part without explicit written authorization
8 //** from the company.
9 //**
10 //****************************************************************************
11 #include <cstdio>
12 #include <iostream>
13 #include <fstream>
14 #include <iomanip>
15 #include <stdexcept>
16 #include <set>
17 #include <string>
18 #include <sstream>
19 #include <vector>
20 #include <map>
21 #include <algorithm>
22 using namespace std;
23
24 #include "ProcessorBind.h"
25
26 class putUINT64
27 {
28 public:
29 putUINT64(UINT64 ullVal) : m_ull(ullVal) {}
30 putUINT64(const putUINT64& r) : m_ull(r.m_ull) {}
31
32 template <class _E, class _Tr>
33 friend basic_ostream<_E, _Tr>& operator << (basic_ostream<_E, _Tr>&, putUINT64);
34
35 private:
36 UINT64 m_ull;
37 };
38
39 template <class _E, class _Tr>
40 basic_ostream<_E, _Tr>& operator << (basic_ostream<_E, _Tr>& os, putUINT64 ull)
41 {
42 static const char cDigits[] = "0123456789abcdef";
43
44 UINT64 base = 10;
45 if (os.flags() & ios_base::hex)
46 base = 16;
47 else if (os.flags() & ios_base::oct)
48 base = 8;
49
50 ostringstream ostr;
51 UINT64 ullVal = ull.m_ull;
52 while (ullVal != 0)
53 {
54 ostr << cDigits[ullVal % base];
55 ullVal /= base;
56 }
57
58 string s1(ostr.str());
59 string s2(s1.rbegin(), s1.rend());
60 return os << s2;
61 }
62
63 class getUINT64
64 {
65 public:
66 getUINT64(UINT64& ullVal) : m_ull(ullVal) {}
67 getUINT64(const getUINT64& r) : m_ull(r.m_ull) {}
68
69 template <class _E, class _Tr>
70 friend basic_istream<_E, _Tr>& operator >> (basic_istream<_E, _Tr>&, getUINT64);
71
72 private:
73 UINT64& m_ull;
74
75 private:
76 getUINT64& operator = (const getUINT64&);
77 };
78
79 template <class _E, class _Tr>
80 basic_istream<_E, _Tr>& operator >> (basic_istream<_E, _Tr>& is, getUINT64 ull)
81 {
82 string strBuf;
83 is >> strBuf;
84
85 UINT64 base = 10;
86 if (is.flags() & ios_base::hex)
87 base = 16;
88 else if (is.flags() & ios_base::oct)
89 base = 8;
90
91 UINT64 ullVal = 0;
92 for (string::iterator i = strBuf.begin(); i != strBuf.end(); i++)
93 {
94 if (*i <= '9' && *i >= '0')
95 *i -= '0';
96 else if (*i <= 'F' && *i >= 'A')
97 *i -= 'A' - '\x0a';
98 else if (*i <= 'f' && *i >= 'a')
99 *i -= 'a' - '\x0a';
100 else throw runtime_error("Invalid number format");
101
102 ullVal = ullVal * base + *i;
103 }
104 ull.m_ull = ullVal;
105 return is;
106 }
107
108 class EMemoryLeak : public logic_error
109 {
110 public:
111 EMemoryLeak() : logic_error("Memory leak detected") {}
112 };
113
114 class EInvalidGuidString : public invalid_argument
115 {
116 public:
117 EInvalidGuidString() : invalid_argument("Unexpected format of GUID string") {}
118 };
119
120 class ELogFileError : public logic_error
121 {
122 public:
123 ELogFileError(const string& strMsg) : logic_error(strMsg) {}
124 };
125
126 class EDuplicatedFfsFile : public ELogFileError
127 {
128 public:
129 EDuplicatedFfsFile() : ELogFileError("Duplicated FFS found in LOG file") {}
130 };
131
132 class EUnexpectedLogFileToken : public ELogFileError
133 {
134 public:
135 EUnexpectedLogFileToken() : ELogFileError("Unexpected LOG file token") {}
136 };
137
138 class EFileNotFound : public invalid_argument
139 {
140 public:
141 EFileNotFound(const string& strFName) : invalid_argument("File not found - " + strFName) {}
142 };
143
144 class EUnexpectedMapFile : public logic_error
145 {
146 public:
147 EUnexpectedMapFile(const string& strKeyWord) : logic_error("Unexpected map file format - " + strKeyWord) {}
148 };
149
150 class EUsage : public invalid_argument
151 {
152 public:
153 EUsage() : invalid_argument("Usage: GenFvMap <FV.LOG> <FV.INF> <FV.MAP>") {}
154 };
155
156 template <class T>
157 class CMemoryLeakChecker : public set<T*>
158 {
159 protected:
160 CMemoryLeakChecker()
161 {
162 }
163
164 public:
165 virtual ~CMemoryLeakChecker();
166 static CMemoryLeakChecker<T>& GetInstance();
167
168 private:
169 CMemoryLeakChecker(const CMemoryLeakChecker<T>&);
170 };
171
172 template <class T>
173 CMemoryLeakChecker<T>::~CMemoryLeakChecker()
174 {
175 if (!CMemoryLeakChecker<T>::empty())
176 throw EMemoryLeak();
177 }
178
179 template <class T>
180 CMemoryLeakChecker<T>& CMemoryLeakChecker<T>::GetInstance()
181 {
182 static CMemoryLeakChecker<T> s_instance;
183 return s_instance;
184 }
185
186 class CObjRoot
187 {
188 protected:
189 CObjRoot()
190 {
191 #ifdef _CHK_MEM_LEAK
192 CMemoryLeakChecker<CObjRoot>::GetInstance().insert(this);
193 #endif
194 }
195
196 public:
197 virtual ~CObjRoot()
198 {
199 #ifdef _CHK_MEM_LEAK
200 CMemoryLeakChecker<CObjRoot>::GetInstance().erase(this);
201 #endif
202 }
203
204 private:
205 CObjRoot(const CObjRoot&);
206 };
207
208 class CIdentity : public CObjRoot
209 {
210 public:
211 CIdentity(const string&);
212 operator string (void) const;
213
214 bool operator < (const CIdentity& id) const
215 {
216 return memcmp(this, &id, sizeof(*this)) < 0;
217 }
218
219 CIdentity() : ulD1(0), wD2(0), wD3(0), wD4(0), ullD5(0)
220 {
221 }
222
223 CIdentity(const CIdentity& r) : ulD1(r.ulD1), wD2(r.wD2), wD3(r.wD3), wD4(r.wD4), ullD5(r.ullD5)
224 {
225 }
226
227 template <class _E, class _Tr>
228 basic_istream<_E, _Tr>& ReadId(basic_istream<_E, _Tr>&);
229 template <class _E, class _Tr>
230 basic_ostream<_E, _Tr>& WriteId(basic_ostream<_E, _Tr>&);
231
232 template <class _E, class _Tr>
233 friend basic_istream<_E, _Tr>& operator >> (basic_istream<_E, _Tr>&, CIdentity&);
234 template <class _E, class _Tr>
235 friend basic_ostream<_E, _Tr>& operator << (basic_ostream<_E, _Tr>&, CIdentity);
236
237 private:
238 UINT32 ulD1;
239 UINT16 wD2, wD3, wD4;
240 UINT64 ullD5;
241 };
242
243 CIdentity::CIdentity(const string& strGuid)
244 {
245 try
246 {
247 string str(strGuid);
248 str.erase(0, str.find_first_not_of(" {"));
249 str.resize(str.find_last_not_of(" }") + 1);
250 str[str.find('-')] = ' ';
251 str[str.find('-')] = ' ';
252 str[str.find('-')] = ' ';
253 str[str.find('-')] = ' ';
254
255 istringstream is(str);
256 is >> hex >> ulD1 >> wD2 >> wD3 >> wD4 >> getUINT64(ullD5);
257 }
258 catch (const exception&)
259 {
260 throw EInvalidGuidString();
261 }
262 }
263
264 CIdentity::operator string(void) const
265 {
266 ostringstream os;
267 os << hex << setfill('0')
268 << setw(8) << ulD1 << '-'
269 << setw(4) << wD2 << '-'
270 << setw(4) << wD3 << '-'
271 << setw(4) << wD4 << '-'
272 << setw(12) << putUINT64(ullD5);
273 return os.str();
274 }
275
276 template <class _E, class _Tr>
277 basic_istream<_E, _Tr>& CIdentity::ReadId(basic_istream<_E, _Tr>& is)
278 {
279 string str;
280 if (!!(is >> str))
281 *this = CIdentity(str);
282 return is;
283 }
284
285 template <class _E, class _Tr>
286 basic_ostream<_E, _Tr>& CIdentity::WriteId(basic_ostream<_E, _Tr>& os)
287 {
288 return os << (string)(*this);
289 }
290
291 template <class _E, class _Tr>
292 basic_istream<_E, _Tr>& operator >> (basic_istream<_E, _Tr>& is, CIdentity& id)
293 {
294 return id.ReadId(is);
295 }
296
297 template <class _E, class _Tr>
298 basic_ostream<_E, _Tr>& operator << (basic_ostream<_E, _Tr>& os, CIdentity id)
299 {
300 return id.WriteId(os);
301 }
302
303 template <class T>
304 class IVectorContainerByReference : virtual public CObjRoot, public vector<T*>
305 {
306 };
307
308 template <class T>
309 class IMapContainer : virtual public CObjRoot, public map<CIdentity, T>
310 {
311 };
312
313 struct ISymbol : virtual public CObjRoot
314 {
315 string strAddress;
316 string strName;
317 string strFrom;
318 UINT64 ullRva;
319 bool bStatic;
320 bool bFunction;
321 virtual void Relocate(UINT64)=0;
322 };
323
324 class IModule : public IVectorContainerByReference<ISymbol>
325 {
326 public:
327 string strName;
328 CIdentity id;
329 virtual UINT64 BaseAddress(void) const=0;
330 virtual UINT64 BaseAddress(UINT64)=0;
331 virtual const ISymbol *EntryPoint(void) const=0;
332 };
333
334 class IFirmwareVolume : public IVectorContainerByReference<IModule>
335 {
336 };
337
338 class IMapFileSet : public IMapContainer<istream*>
339 {
340 };
341
342 class IFfsSet : public IMapContainer<UINT64>
343 {
344 };
345
346 class CFfsSetFromLogFile : public IFfsSet
347 {
348 public:
349 CFfsSetFromLogFile(const string&);
350 };
351
352 CFfsSetFromLogFile::CFfsSetFromLogFile(const string& strFName)
353 {
354 ifstream ifs(strFName.c_str());
355 if (!ifs)
356 throw EFileNotFound(strFName);
357
358 CIdentity ffsId;
359 while (!!ffsId.ReadId(ifs))
360 {
361 UINT64 ullBase;
362 if (!(ifs >> hex >> getUINT64(ullBase)))
363 throw EUnexpectedLogFileToken();
364 if (!insert(value_type(ffsId, ullBase)).second)
365 throw EDuplicatedFfsFile();
366 }
367 }
368
369 class CMapFileSetFromInfFile : public IMapFileSet
370 {
371 public:
372 CMapFileSetFromInfFile(const string&);
373 ~CMapFileSetFromInfFile();
374 };
375
376 CMapFileSetFromInfFile::CMapFileSetFromInfFile(const string& strFName)
377 {
378 static const char cszEfiFileName[] = "EFI_FILE_NAME";
379
380 ifstream ifs(strFName.c_str());
381 if (!ifs)
382 throw EFileNotFound(strFName);
383
384 string strFile;
385 getline(ifs, strFile, ifstream::traits_type::to_char_type(ifstream::traits_type::eof()));
386 strFile.erase(0, strFile.find("[files]"));
387
388 istringstream is(strFile);
389 string strTmp;
390 while (!!getline(is, strTmp))
391 {
392 string::size_type pos = strTmp.find(cszEfiFileName);
393 if (pos == string::npos)
394 continue;
395
396 strTmp.erase(0, strTmp.find_first_not_of(" =", pos + sizeof(cszEfiFileName) - 1));
397 pos = strTmp.find_last_of("\\/");
398 string strId(
399 strTmp.begin() + pos + 1,
400 strTmp.begin() + strTmp.find('-', strTmp.find('-', strTmp.find('-', strTmp.find('-', strTmp.find('-') + 1) + 1) + 1) + 1)
401 );
402 strTmp.erase(pos + 1, strId.length() + 1);
403 strTmp.replace(strTmp.rfind('.'), string::npos, ".map");
404
405 istream *ifmaps = new ifstream(strTmp.c_str());
406 if (ifmaps && !!*ifmaps &&
407 !insert(value_type(CIdentity(strId), ifmaps)).second)
408 throw EDuplicatedFfsFile();
409 }
410 }
411
412 CMapFileSetFromInfFile::~CMapFileSetFromInfFile()
413 {
414 for (iterator i = begin(); i != end(); i++)
415 delete i->second;
416 }
417
418 class CSymbolFromString : public ISymbol
419 {
420 public:
421 CSymbolFromString(const string&, bool = false);
422 void Relocate(UINT64);
423 };
424
425 CSymbolFromString::CSymbolFromString(const string& strSymbol, bool b)
426 {
427 bStatic = b;
428
429 istringstream is(strSymbol);
430 is >> strAddress >> strName >> hex >> getUINT64(ullRva) >> strFrom;
431 if (strFrom == "f")
432 {
433 bFunction = true;
434 is >> strFrom;
435 }
436 else bFunction = false;
437 if (!is)
438 throw EUnexpectedMapFile("Symbol line format");
439 }
440
441 void CSymbolFromString::Relocate(UINT64 ullDelta)
442 {
443 if (ullRva > 0)
444 ullRva += ullDelta;
445 }
446
447 class CModuleFromMap : public IModule
448 {
449 public:
450 CModuleFromMap(istream&);
451 ~CModuleFromMap();
452
453 UINT64 BaseAddress() const;
454 UINT64 BaseAddress(UINT64);
455 const ISymbol *EntryPoint() const;
456
457 private:
458 UINT64 m_ullLoadAddress;
459 iterator m_iEntryPoint;
460
461 static pair<string, string::size_type> FindToken(istream&, const string&);
462 };
463
464 pair<string, string::size_type> CModuleFromMap::FindToken(istream& is, const string& strToken)
465 {
466 for (string strTmp; !!getline(is, strTmp);)
467 {
468 string::size_type pos = strTmp.find(strToken);
469 if (pos != string::npos)
470 return pair<string, string::size_type>(strTmp, pos);
471 }
472 throw EUnexpectedMapFile(strToken);
473 }
474
475 CModuleFromMap::CModuleFromMap(istream& imaps)
476 {
477 static const char cszLoadAddr[] = "Preferred load address is";
478 static const char cszGlobal[] = "Address";
479 static const char cszEntryPoint[] = "entry point at";
480 static const char cszStatic[] = "Static symbols";
481
482 pair<string, string::size_type> pairTmp;
483 istringstream iss;
484
485 getline(imaps, strName);
486 strName.erase(0, strName.find_first_not_of(' '));
487
488 pairTmp = FindToken(imaps, cszLoadAddr);
489 iss.str(pairTmp.first.substr(pairTmp.second + sizeof(cszLoadAddr) - 1));
490 iss >> getUINT64(m_ullLoadAddress);
491
492 pairTmp = FindToken(imaps, cszGlobal);
493 while (!!getline(imaps, pairTmp.first) &&
494 pairTmp.first.find(cszEntryPoint) == string::npos)
495 if (pairTmp.first.find_first_not_of(' ') != string::npos)
496 push_back(new CSymbolFromString(pairTmp.first));
497
498 iss.str(pairTmp.first.substr(pairTmp.first.find(cszEntryPoint) + sizeof(cszEntryPoint) - 1));
499 iss.clear();
500 string strEntryPoint;
501 iss >> strEntryPoint;
502
503 pairTmp = FindToken(imaps, cszStatic);
504 if (pairTmp.second)
505 while (!!getline(imaps, pairTmp.first))
506 if (pairTmp.first.find_first_not_of(' ') != string::npos)
507 push_back(new CSymbolFromString(pairTmp.first, true));
508
509 for (m_iEntryPoint = begin();
510 m_iEntryPoint != end() && (*m_iEntryPoint)->strAddress != strEntryPoint;
511 m_iEntryPoint++);
512 if (m_iEntryPoint == end())
513 throw EUnexpectedMapFile("Entry point not found");
514 }
515
516 CModuleFromMap::~CModuleFromMap()
517 {
518 for (iterator i = begin(); i != end(); i++)
519 delete *i;
520 }
521
522 UINT64 CModuleFromMap::BaseAddress(void) const
523 {
524 return m_ullLoadAddress;
525 }
526
527 UINT64 CModuleFromMap::BaseAddress(UINT64 ullNewBase)
528 {
529 ullNewBase -= m_ullLoadAddress;
530 for (iterator i = begin(); i != end(); i++)
531 (*i)->Relocate(ullNewBase);
532 m_ullLoadAddress += ullNewBase;
533 return m_ullLoadAddress - ullNewBase;
534 }
535
536 const ISymbol *CModuleFromMap::EntryPoint(void) const
537 {
538 return *m_iEntryPoint;
539 }
540
541 class CFvMap : public IFirmwareVolume
542 {
543 public:
544 CFvMap(IFfsSet*, IMapFileSet*);
545 ~CFvMap();
546
547 private:
548 CFvMap(const CFvMap&);
549 };
550
551 CFvMap::CFvMap(IFfsSet *pFfsSet, IMapFileSet *pMapSet)
552 {
553 for (IFfsSet::iterator i = pFfsSet->begin(); i != pFfsSet->end(); i++)
554 {
555 IMapFileSet::iterator j = pMapSet->find(i->first);
556 if (j != pMapSet->end())
557 {
558 IModule *pModule = new CModuleFromMap(*j->second);
559 pModule->id = i->first;
560 pModule->BaseAddress(i->second);
561 push_back(pModule);
562 }
563 }
564 }
565
566 CFvMap::~CFvMap()
567 {
568 for (iterator i = begin(); i != end(); i++)
569 delete *i;
570 }
571
572 class CFvMapGenerator : public CObjRoot
573 {
574 public:
575 CFvMapGenerator(const IFirmwareVolume *pFv) : m_pFv(pFv) {}
576 CFvMapGenerator(const CFvMapGenerator& r) : m_pFv(r.m_pFv) {}
577
578 template <class _E, class _Tr>
579 friend basic_ostream<_E, _Tr>& operator << (basic_ostream<_E, _Tr>&, CFvMapGenerator);
580
581 private:
582 static bool Less(const IModule*, const IModule*);
583
584 private:
585 const IFirmwareVolume *m_pFv;
586 };
587
588 template <class _E, class _Tr>
589 basic_ostream<_E, _Tr>& operator << (basic_ostream<_E, _Tr>& os, CFvMapGenerator fvMapFmt)
590 {
591 vector<IModule*> rgMods(fvMapFmt.m_pFv->begin(), fvMapFmt.m_pFv->end());
592 sort(rgMods.begin(), rgMods.end(), CFvMapGenerator::Less);
593 for (vector<IModule*>::iterator i = rgMods.begin(); i != rgMods.end(); i++)
594 {
595 os << (*i)->strName << hex << " (BaseAddress=" << putUINT64((*i)->BaseAddress());
596 os << ", EntryPoint=" << hex << putUINT64((*i)->EntryPoint()->ullRva);
597 os << ", GUID=";
598 (*i)->id.WriteId(os);
599 os << ")" << endl << endl;
600
601 for (IModule::iterator j = (*i)->begin(); j != (*i)->end(); j++)
602 {
603 os << hex << " " << setw(16) << setfill('0') << putUINT64((*j)->ullRva);
604 os << ((*j)->bFunction ? " F" : " ")
605 << ((*j)->bStatic ? "S " : " ")
606 << (*j)->strName << endl;
607 }
608
609 os << endl << endl;
610 }
611 return os;
612 }
613
614 bool CFvMapGenerator::Less(const IModule *pModL, const IModule *pModR)
615 {
616 return pModL->BaseAddress() < pModR->BaseAddress();
617 }
618
619 class CApplication : public CObjRoot
620 {
621 public:
622 CApplication(int, char**);
623 int Run(void);
624
625 private:
626 char **m_ppszArg;
627 private:
628 CApplication(const CApplication&);
629 };
630
631 CApplication::CApplication(int cArg, char *ppszArg[])
632 : m_ppszArg(ppszArg)
633 {
634 if (cArg != 4)
635 throw EUsage();
636 }
637
638 int CApplication::Run(void)
639 {
640 CFfsSetFromLogFile ffsSet(m_ppszArg[1]);
641 CMapFileSetFromInfFile mapSet(m_ppszArg[2]);
642 ofstream ofs(m_ppszArg[3]);
643 CFvMap fvMap(&ffsSet, &mapSet);
644 ofs << CFvMapGenerator(&fvMap);
645 return 0;
646 }
647
648 int main(int argc, char *argv[])
649 {
650 try
651 {
652 CApplication app(argc, argv);
653 return app.Run();
654 }
655 catch (const exception& e)
656 {
657 cerr << e.what() << endl;
658 return -1;
659 }
660 }
661
662 #ifdef _DDK3790x1830_WORKAROUND
663 extern "C" void __fastcall __security_check_cookie(int)
664 {
665 }
666 #endif