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