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