]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/CCode/Source/GenFvMap/GenFvMap.cpp
- Fixed EDKT513 by adding existing section files into the dependency check of genffsf...
[mirror_edk2.git] / Tools / CCode / Source / GenFvMap / GenFvMap.cpp
CommitLineData
8733430b 1//****************************************************************************\r
2//**\r
a3ab2a47 3//** Copyright (C) 2006 Intel Corporation. All rights reserved.\r
8733430b 4//**\r
a3ab2a47 5//** The information and source code contained herein is the exclusive\r
8733430b 6//** property of Intel Corporation and may not be disclosed, examined\r
a3ab2a47 7//** or reproduced in whole or in part without explicit written authorization\r
8733430b 8//** from the company.\r
9//**\r
10//****************************************************************************\r
327bd141 11#include "ProcessorBind.h"\r
12#include <iostream>\r
8733430b 13#include <stdexcept>\r
14#include <list>\r
15#include <map>\r
93d16c69 16#include <vector>\r
8733430b 17#include <iomanip>\r
18#include <fstream>\r
19#include <sstream>\r
20#include <string>\r
21#include <utility>\r
22#include <algorithm>\r
23#include <functional>\r
24using namespace std;\r
25\r
327bd141 26typedef UINT64 ulonglong_t;\r
8733430b 27\r
1b266b0c 28#ifdef __GNUC__\r
29#if __STDC_VERSION__ < 199901L\r
30#define __FUNCTION__ __FILE__\r
31#endif\r
32#endif\r
33\r
8733430b 34template <class T>\r
35class CMemoryLeakChecker : public list<T*>\r
36{\r
37public:\r
38 static CMemoryLeakChecker<T>& GetInstance(void);\r
39\r
40private:\r
41 CMemoryLeakChecker(void)\r
42 {\r
43 }\r
44\r
45 ~CMemoryLeakChecker(void);\r
46};\r
47\r
48template <class T>\r
49CMemoryLeakChecker<T>& CMemoryLeakChecker<T>::GetInstance(void)\r
50{\r
51 static CMemoryLeakChecker<T> s_memLeakChecker;\r
52 return s_memLeakChecker;\r
53}\r
54\r
55template <class T>\r
56CMemoryLeakChecker<T>::~CMemoryLeakChecker(void)\r
57{\r
58 if (!list<T*>::empty())\r
59 throw logic_error(__FUNCTION__ ": Memory leak detected!");\r
60}\r
61\r
62class CObjRoot\r
63{\r
64protected:\r
65 CObjRoot(void);\r
66 virtual ~CObjRoot(void);\r
67};\r
68\r
69CObjRoot::CObjRoot(void)\r
70{\r
71 CMemoryLeakChecker<CObjRoot>::GetInstance().push_back(this);\r
72}\r
73\r
74CObjRoot::~CObjRoot(void)\r
75{\r
76 CMemoryLeakChecker<CObjRoot>::GetInstance().remove(this);\r
77}\r
78\r
79class CIdentity : public CObjRoot\r
80{\r
81public:\r
82 CIdentity(void);\r
83 CIdentity(const string&);\r
84 CIdentity(const CIdentity&);\r
85\r
86 bool operator < (const CIdentity&) const;\r
87 friend istream& operator >> (istream&, CIdentity&);\r
a3ab2a47 88 friend ostream& operator << (ostream&, const CIdentity&);\r
8733430b 89\r
90 static const string::size_type s_nIdStrLen;\r
91\r
92protected:\r
93 ulonglong_t m_ullId[2];\r
94};\r
95\r
96const string::size_type CIdentity::s_nIdStrLen = 36;\r
97\r
98CIdentity::CIdentity(void)\r
99{\r
100 memset(m_ullId, 0, sizeof(m_ullId));\r
101}\r
102\r
103CIdentity::CIdentity(const string& strId)\r
104{\r
105 if (strId.length() != CIdentity::s_nIdStrLen ||\r
106 strId[8] != '-' ||\r
107 strId[13] != '-' ||\r
108 strId[18] != '-' ||\r
109 strId[23] != '-')\r
110 throw runtime_error(\r
111 __FUNCTION__ ": Error GUID format " + strId);\r
112\r
113 string strIdCopy(strId);\r
114 strIdCopy.erase(23, 1);\r
115 strIdCopy[18] = ' ';\r
116 strIdCopy.erase(13, 1);\r
117 strIdCopy.erase(8, 1);\r
118\r
119 istringstream is(strIdCopy);\r
120 is >> hex >> m_ullId[0] >> m_ullId[1];\r
121 if (!is)\r
122 throw runtime_error(\r
123 __FUNCTION__ ": GUID contains invalid characters" + strId);\r
124}\r
125\r
126CIdentity::CIdentity(const CIdentity& idRight)\r
127{\r
128 memmove(m_ullId, idRight.m_ullId, sizeof(m_ullId));\r
129}\r
130\r
131bool CIdentity::operator < (const CIdentity& idRight) const\r
132{\r
133 return memcmp(m_ullId, idRight.m_ullId, sizeof(m_ullId)) < 0;\r
134}\r
135\r
136istream& operator >> (istream& is, CIdentity& idRight)\r
137{\r
138 string strId;\r
139 is >> strId;\r
140 if (!!is)\r
141 idRight = CIdentity(strId);\r
142 return is;\r
143}\r
144\r
a3ab2a47 145ostream& operator << (ostream& os, const CIdentity& idRight)\r
146{\r
147 return os << hex << setfill('0')\r
148 << setw(8) << (unsigned long)(idRight.m_ullId[0] >> 32) << '-'\r
149 << setw(4) << (unsigned short)(idRight.m_ullId[0] >> 16) << '-'\r
150 << setw(4) << (unsigned short)idRight.m_ullId[0] << '-'\r
151 << setw(4) << (unsigned short)(idRight.m_ullId[1] >> 48) << '-'\r
327bd141 152 << setw(12) << (idRight.m_ullId[1] & 0xffffffffffffULL);\r
a3ab2a47 153}\r
154\r
8733430b 155class CInputFile : public CObjRoot\r
156{\r
157protected:\r
158 CInputFile(const string&);\r
159 CInputFile(istream&);\r
160 istream& GetLine(string&);\r
161\r
162private:\r
163 CInputFile(const CInputFile&);\r
164 CInputFile& operator = (const CInputFile&);\r
165\r
166private:\r
167 auto_ptr<istream> m_pIs;\r
168\r
169protected:\r
170 istream& m_is;\r
171};\r
172\r
173CInputFile::CInputFile(const string& strFName)\r
174: m_pIs(new ifstream(strFName.c_str()))\r
175, m_is(*m_pIs)\r
176{\r
177 if (!m_is)\r
178 throw runtime_error(__FUNCTION__ ": Error opening input file " + strFName);\r
179}\r
180\r
181CInputFile::CInputFile(istream& is)\r
182: m_is(is)\r
183{\r
184 if (!m_is)\r
185 throw runtime_error(__FUNCTION__ ": Error opening input stream");\r
186}\r
187\r
188istream& CInputFile::GetLine(string& strALine)\r
189{\r
190 if (!!m_is)\r
191 while (!!getline(m_is, strALine))\r
192 {\r
193 string::size_type pos = strALine.find_last_not_of(' ');\r
194 if (pos != string::npos)\r
195 {\r
196 strALine.erase(pos + 1);\r
197 strALine.erase(0, strALine.find_first_not_of(' '));\r
198 break;\r
199 }\r
200 }\r
201 return m_is;\r
202}\r
203\r
a3ab2a47 204class CIdAddressPathMap : public CInputFile, public map<CIdentity, pair<ulonglong_t, string> >\r
8733430b 205{\r
206public:\r
a3ab2a47 207 CIdAddressPathMap(istream&);\r
8733430b 208};\r
209\r
a3ab2a47 210CIdAddressPathMap::CIdAddressPathMap(istream& is)\r
8733430b 211: CInputFile(is)\r
212{\r
a3ab2a47 213 key_type k;\r
214 mapped_type m;\r
215 while (!!(m_is >> hex >> k >> m.first) && !!GetLine(m.second))\r
216 if (!insert(value_type(k, m)).second)\r
8733430b 217 throw runtime_error(__FUNCTION__ ": Duplicated files");\r
218}\r
219\r
8733430b 220class CSymbol : public CObjRoot\r
221{\r
222public:\r
223 string m_strAddress;\r
224 string m_strName;\r
225 ulonglong_t m_ullRva;\r
226 string m_strFrom;\r
227 bool m_bStatic;\r
228 bool m_bFunction;\r
229\r
230 CSymbol()\r
231 {\r
232 }\r
233 CSymbol(const string&, bool = false);\r
234 friend ostream& operator << (ostream&, const CSymbol&);\r
235};\r
236\r
237CSymbol::CSymbol(const string& strALine, bool bStatic)\r
238: m_bStatic(bStatic)\r
239{\r
240 istringstream is(strALine);\r
241\r
242 is >> m_strAddress >> m_strName >> hex >> m_ullRva >> m_strFrom;\r
243 if (m_strFrom == "F" || m_strFrom == "f")\r
244 {\r
245 m_bFunction = true;\r
246 is >> m_strFrom;\r
247 } else m_bFunction = false;\r
248}\r
249\r
250ostream& operator << (ostream& os, const CSymbol& symbol)\r
251{\r
252 os << hex << setw(16) << setfill('0') << symbol.m_ullRva << setw(0);\r
253 os << ' ' << (symbol.m_bFunction ? 'F' : ' ')\r
254 << (symbol.m_bStatic ? 'S' : ' ') << ' ';\r
a3ab2a47 255 return os << symbol.m_strName;\r
8733430b 256}\r
257\r
258class CMapFile : public CInputFile, public list<CSymbol>\r
259{\r
260public:\r
261 CMapFile(const string&);\r
262\r
263 void SetLoadAddress(ulonglong_t);\r
8733430b 264\r
265 string m_strModuleName;\r
266 ulonglong_t m_ullLoadAddr;\r
267 string m_strEntryPoint;\r
268};\r
269\r
270CMapFile::CMapFile(const string& strFName)\r
271: CInputFile(strFName)\r
272{\r
273 static const char cszLoadAddr[] = "Preferred load address is";\r
274 static const char cszGlobal[] = "Address";\r
275 static const char cszEntryPoint[] = "entry point at";\r
276 static const char cszStatic[] = "Static symbols";\r
277\r
278 string strALine;\r
279\r
280 GetLine(m_strModuleName);\r
281\r
282 while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszLoadAddr) - 1, cszLoadAddr));\r
283 if (!m_is)\r
284 throw runtime_error(__FUNCTION__ ": Load Address not listed in map file");\r
285\r
286 istringstream is(strALine.substr(sizeof(cszLoadAddr) - 1));\r
287 if (!(is >> hex >> m_ullLoadAddr))\r
288 throw runtime_error(__FUNCTION__ ": Unexpected Load Address format");\r
289\r
290 while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszGlobal) - 1, cszGlobal));\r
291 if (!m_is)\r
292 throw runtime_error(__FUNCTION__ ": Global symbols not found in map file");\r
293\r
294 while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszEntryPoint) - 1, cszEntryPoint))\r
295 push_back(CSymbol(strALine));\r
296 if (!m_is)\r
297 throw runtime_error(__FUNCTION__ ": Entry Point not listed in map file");\r
298\r
299 is.str(strALine.substr(strALine.find_first_not_of(' ', sizeof(cszEntryPoint) - 1)));\r
300 is.clear();\r
301 if (!getline(is, m_strEntryPoint))\r
302 throw runtime_error(__FUNCTION__ ": Unexpected Entry Point format");\r
303\r
304 while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszStatic) - 1, cszStatic));\r
305 while (!!GetLine(strALine))\r
306 push_back(CSymbol(strALine, true));\r
307}\r
308\r
309void CMapFile::SetLoadAddress(ulonglong_t ullLoadAddr)\r
310{\r
311 for (iterator i = begin(); i != end(); i++)\r
a3ab2a47 312 if (i->m_ullRva >= m_ullLoadAddr)\r
8733430b 313 i->m_ullRva += ullLoadAddr - m_ullLoadAddr;\r
314 m_ullLoadAddr = ullLoadAddr;\r
315}\r
316\r
8733430b 317class COutputFile : public CObjRoot\r
318{\r
319protected:\r
320 COutputFile(ostream&);\r
321 ostream& m_os;\r
322\r
323private:\r
324 COutputFile(const COutputFile&);\r
325 COutputFile& operator = (const COutputFile&);\r
326};\r
327\r
328class CFvMapFile : public CObjRoot, public map<CIdentity, CMapFile*>\r
329{\r
330public:\r
a3ab2a47 331 CFvMapFile(const CIdAddressPathMap&);\r
8733430b 332 ~CFvMapFile(void);\r
333\r
334 friend ostream& operator << (ostream&, const CFvMapFile&);\r
335\r
336private:\r
337 void Cleanup(void);\r
338};\r
339\r
a3ab2a47 340CFvMapFile::CFvMapFile(const CIdAddressPathMap& idAddrPath)\r
8733430b 341{\r
a3ab2a47 342 for (CIdAddressPathMap::const_iterator i = idAddrPath.begin(); i != idAddrPath.end(); i++)\r
8733430b 343 {\r
a3ab2a47 344 if (i->second.second == "*")\r
345 continue;\r
8733430b 346\r
a3ab2a47 347 pair<iterator, bool> r = insert(value_type(i->first,\r
348 new CMapFile(i->second.second.substr(0, i->second.second.rfind('.')) + ".map")));\r
349 r.first->second->SetLoadAddress(i->second.first);\r
8733430b 350 }\r
351}\r
352\r
93d16c69 353CFvMapFile::~CFvMapFile(void)\r
354{\r
355 Cleanup();\r
356}\r
357\r
8733430b 358void CFvMapFile::Cleanup(void)\r
359{\r
360 for (iterator i = begin(); i != end(); i++)\r
361 delete i->second;\r
362}\r
363\r
93d16c69 364static bool map_less(const CFvMapFile::const_iterator& l, const CFvMapFile::const_iterator& r)\r
365{\r
366 return l->second->m_ullLoadAddr < r->second->m_ullLoadAddr;\r
367}\r
368\r
8733430b 369ostream& operator << (ostream& os, const CFvMapFile& fvMap)\r
370{\r
93d16c69 371 vector<CFvMapFile::const_iterator> rgIter;\r
372 rgIter.reserve(fvMap.size());\r
373 for (CFvMapFile::const_iterator i = fvMap.begin(); i != fvMap.end(); i++)\r
374 rgIter.push_back(i);\r
375 sort(rgIter.begin(), rgIter.end(), map_less);\r
376\r
377 for (vector<CFvMapFile::const_iterator>::const_iterator i = rgIter.begin(); i != rgIter.end(); i++)\r
a3ab2a47 378 {\r
93d16c69 379 CMapFile::const_iterator j = (*i)->second->begin();\r
380 while (j != (*i)->second->end() && j->m_strAddress != (*i)->second->m_strEntryPoint) j++;\r
381 if (j == (*i)->second->end())\r
a3ab2a47 382 throw runtime_error(\r
383 __FUNCTION__ ":Entry point not found for module " +\r
93d16c69 384 (*i)->second->m_strModuleName);\r
a3ab2a47 385\r
386 os << hex\r
93d16c69 387 << (*i)->second->m_strModuleName\r
388 << " (EntryPoint=" << j->m_ullRva\r
389 << ", BaseAddress=" << (*i)->second->m_ullLoadAddr\r
390 << ", GUID=" << (*i)->first\r
a3ab2a47 391 << ")" << endl << endl;\r
392\r
93d16c69 393 for (j = (*i)->second->begin(); j != (*i)->second->end(); j++)\r
a3ab2a47 394 os << " " << *j << endl;\r
395\r
396 os << endl << endl;\r
397 }\r
398\r
8733430b 399 return os;\r
400}\r
401\r
8733430b 402class CGenFvMapUsage : public invalid_argument\r
403{\r
404public:\r
405 CGenFvMapUsage(void) : invalid_argument(s_szUsage)\r
406 {\r
407 }\r
408\r
409private:\r
410 static const char s_szUsage[];\r
411};\r
412\r
a3ab2a47 413const char CGenFvMapUsage::s_szUsage[] = "Usage: GenFvMap <LOG> <MAP>";\r
8733430b 414\r
415class CGenFvMapApp : public CObjRoot\r
416{\r
417public:\r
418 CGenFvMapApp(int, char *[]);\r
419 ~CGenFvMapApp(void);\r
420\r
421 int Run(void);\r
422\r
423private:\r
424 int m_cArgc;\r
425 char **m_ppszArgv;\r
426};\r
427\r
428CGenFvMapApp::CGenFvMapApp(int cArgc, char *ppszArgv[])\r
429: m_cArgc(cArgc)\r
430, m_ppszArgv(ppszArgv)\r
431{\r
a3ab2a47 432 if (cArgc != 3)\r
8733430b 433 throw CGenFvMapUsage();\r
434}\r
435\r
436CGenFvMapApp::~CGenFvMapApp(void)\r
437{\r
438}\r
439\r
440int CGenFvMapApp::Run(void)\r
441{\r
442 ifstream isLog(m_ppszArgv[1]);\r
a3ab2a47 443 CIdAddressPathMap idAddrPath(isLog);\r
444 CFvMapFile fvMap(idAddrPath);\r
8733430b 445\r
a3ab2a47 446 ofstream osMap(m_ppszArgv[2], ios_base::out | ios_base::trunc);\r
8733430b 447 osMap << fvMap;\r
448\r
449 if (!osMap)\r
450 throw runtime_error(__FUNCTION__ ": Error writing output file");\r
451\r
452 return 0;\r
453}\r
454\r
455int main(int argc, char *argv[])\r
456{\r
457 try\r
458 {\r
459 CGenFvMapApp app(argc, argv);\r
460 return app.Run();\r
461 }\r
462 catch (const exception& e)\r
463 {\r
464 cerr << e.what() << endl;\r
465 return -1;\r
466 }\r
467}\r