]>
Commit | Line | Data |
---|---|---|
1 | //****************************************************************************\r | |
2 | //**\r | |
3 | //** Copyright (C) 2006 Intel Corporation. All rights reserved.\r | |
4 | //**\r | |
5 | //** The information and source code contained herein is the exclusive\r | |
6 | //** property of Intel Corporation and may not be disclosed, examined\r | |
7 | //** or reproduced in whole or in part without explicit written authorization\r | |
8 | //** from the company.\r | |
9 | //**\r | |
10 | //****************************************************************************\r | |
11 | #include "ProcessorBind.h"\r | |
12 | #include <iostream>\r | |
13 | #include <stdexcept>\r | |
14 | #include <list>\r | |
15 | #include <map>\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 | |
23 | using namespace std;\r | |
24 | \r | |
25 | typedef UINT64 ulonglong_t;\r | |
26 | \r | |
27 | #ifdef __GNUC__\r | |
28 | #if __STDC_VERSION__ < 199901L\r | |
29 | #define __FUNCTION__ __FILE__\r | |
30 | #endif\r | |
31 | #endif\r | |
32 | \r | |
33 | template <class T>\r | |
34 | class CMemoryLeakChecker : public list<T*>\r | |
35 | {\r | |
36 | public:\r | |
37 | static CMemoryLeakChecker<T>& GetInstance(void);\r | |
38 | \r | |
39 | private:\r | |
40 | CMemoryLeakChecker(void)\r | |
41 | {\r | |
42 | }\r | |
43 | \r | |
44 | ~CMemoryLeakChecker(void);\r | |
45 | };\r | |
46 | \r | |
47 | template <class T>\r | |
48 | CMemoryLeakChecker<T>& CMemoryLeakChecker<T>::GetInstance(void)\r | |
49 | {\r | |
50 | static CMemoryLeakChecker<T> s_memLeakChecker;\r | |
51 | return s_memLeakChecker;\r | |
52 | }\r | |
53 | \r | |
54 | template <class T>\r | |
55 | CMemoryLeakChecker<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 | |
61 | class CObjRoot\r | |
62 | {\r | |
63 | protected:\r | |
64 | CObjRoot(void);\r | |
65 | virtual ~CObjRoot(void);\r | |
66 | };\r | |
67 | \r | |
68 | CObjRoot::CObjRoot(void)\r | |
69 | {\r | |
70 | CMemoryLeakChecker<CObjRoot>::GetInstance().push_back(this);\r | |
71 | }\r | |
72 | \r | |
73 | CObjRoot::~CObjRoot(void)\r | |
74 | {\r | |
75 | CMemoryLeakChecker<CObjRoot>::GetInstance().remove(this);\r | |
76 | }\r | |
77 | \r | |
78 | class CIdentity : public CObjRoot\r | |
79 | {\r | |
80 | public:\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 | |
87 | friend ostream& operator << (ostream&, const CIdentity&);\r | |
88 | \r | |
89 | static const string::size_type s_nIdStrLen;\r | |
90 | \r | |
91 | protected:\r | |
92 | ulonglong_t m_ullId[2];\r | |
93 | };\r | |
94 | \r | |
95 | const string::size_type CIdentity::s_nIdStrLen = 36;\r | |
96 | \r | |
97 | CIdentity::CIdentity(void)\r | |
98 | {\r | |
99 | memset(m_ullId, 0, sizeof(m_ullId));\r | |
100 | }\r | |
101 | \r | |
102 | CIdentity::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 | |
125 | CIdentity::CIdentity(const CIdentity& idRight)\r | |
126 | {\r | |
127 | memmove(m_ullId, idRight.m_ullId, sizeof(m_ullId));\r | |
128 | }\r | |
129 | \r | |
130 | bool 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 | |
135 | istream& 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 | |
144 | ostream& 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 | |
151 | << setw(12) << (idRight.m_ullId[1] & 0xffffffffffffULL);\r | |
152 | }\r | |
153 | \r | |
154 | class CInputFile : public CObjRoot\r | |
155 | {\r | |
156 | protected:\r | |
157 | CInputFile(const string&);\r | |
158 | CInputFile(istream&);\r | |
159 | istream& GetLine(string&);\r | |
160 | \r | |
161 | private:\r | |
162 | CInputFile(const CInputFile&);\r | |
163 | CInputFile& operator = (const CInputFile&);\r | |
164 | \r | |
165 | private:\r | |
166 | auto_ptr<istream> m_pIs;\r | |
167 | \r | |
168 | protected:\r | |
169 | istream& m_is;\r | |
170 | };\r | |
171 | \r | |
172 | CInputFile::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 | |
180 | CInputFile::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 | |
187 | istream& 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 | |
203 | class CIdAddressPathMap : public CInputFile, public map<CIdentity, pair<ulonglong_t, string> >\r | |
204 | {\r | |
205 | public:\r | |
206 | CIdAddressPathMap(istream&);\r | |
207 | };\r | |
208 | \r | |
209 | CIdAddressPathMap::CIdAddressPathMap(istream& is)\r | |
210 | : CInputFile(is)\r | |
211 | {\r | |
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 | |
216 | throw runtime_error(__FUNCTION__ ": Duplicated files");\r | |
217 | }\r | |
218 | \r | |
219 | class CSymbol : public CObjRoot\r | |
220 | {\r | |
221 | public:\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 | |
236 | CSymbol::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 | |
249 | ostream& 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 | |
254 | return os << symbol.m_strName;\r | |
255 | }\r | |
256 | \r | |
257 | class CMapFile : public CInputFile, public list<CSymbol>\r | |
258 | {\r | |
259 | public:\r | |
260 | CMapFile(const string&);\r | |
261 | \r | |
262 | void SetLoadAddress(ulonglong_t);\r | |
263 | \r | |
264 | string m_strModuleName;\r | |
265 | ulonglong_t m_ullLoadAddr;\r | |
266 | string m_strEntryPoint;\r | |
267 | };\r | |
268 | \r | |
269 | CMapFile::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 | |
308 | void CMapFile::SetLoadAddress(ulonglong_t ullLoadAddr)\r | |
309 | {\r | |
310 | for (iterator i = begin(); i != end(); i++)\r | |
311 | if (i->m_ullRva >= m_ullLoadAddr)\r | |
312 | i->m_ullRva += ullLoadAddr - m_ullLoadAddr;\r | |
313 | m_ullLoadAddr = ullLoadAddr;\r | |
314 | }\r | |
315 | \r | |
316 | class COutputFile : public CObjRoot\r | |
317 | {\r | |
318 | protected:\r | |
319 | COutputFile(ostream&);\r | |
320 | ostream& m_os;\r | |
321 | \r | |
322 | private:\r | |
323 | COutputFile(const COutputFile&);\r | |
324 | COutputFile& operator = (const COutputFile&);\r | |
325 | };\r | |
326 | \r | |
327 | class CFvMapFile : public CObjRoot, public map<CIdentity, CMapFile*>\r | |
328 | {\r | |
329 | public:\r | |
330 | CFvMapFile(const CIdAddressPathMap&);\r | |
331 | ~CFvMapFile(void);\r | |
332 | \r | |
333 | friend ostream& operator << (ostream&, const CFvMapFile&);\r | |
334 | \r | |
335 | private:\r | |
336 | void Cleanup(void);\r | |
337 | };\r | |
338 | \r | |
339 | CFvMapFile::CFvMapFile(const CIdAddressPathMap& idAddrPath)\r | |
340 | {\r | |
341 | for (CIdAddressPathMap::const_iterator i = idAddrPath.begin(); i != idAddrPath.end(); i++)\r | |
342 | {\r | |
343 | if (i->second.second == "*")\r | |
344 | continue;\r | |
345 | \r | |
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 | |
349 | }\r | |
350 | }\r | |
351 | \r | |
352 | void CFvMapFile::Cleanup(void)\r | |
353 | {\r | |
354 | for (iterator i = begin(); i != end(); i++)\r | |
355 | delete i->second;\r | |
356 | }\r | |
357 | \r | |
358 | ostream& operator << (ostream& os, const CFvMapFile& fvMap)\r | |
359 | {\r | |
360 | for (CFvMapFile::const_iterator i = fvMap.begin(); !!os && i != fvMap.end(); i++)\r | |
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 | |
382 | return os;\r | |
383 | }\r | |
384 | \r | |
385 | CFvMapFile::~CFvMapFile(void)\r | |
386 | {\r | |
387 | Cleanup();\r | |
388 | }\r | |
389 | \r | |
390 | class CGenFvMapUsage : public invalid_argument\r | |
391 | {\r | |
392 | public:\r | |
393 | CGenFvMapUsage(void) : invalid_argument(s_szUsage)\r | |
394 | {\r | |
395 | }\r | |
396 | \r | |
397 | private:\r | |
398 | static const char s_szUsage[];\r | |
399 | };\r | |
400 | \r | |
401 | const char CGenFvMapUsage::s_szUsage[] = "Usage: GenFvMap <LOG> <MAP>";\r | |
402 | \r | |
403 | class CGenFvMapApp : public CObjRoot\r | |
404 | {\r | |
405 | public:\r | |
406 | CGenFvMapApp(int, char *[]);\r | |
407 | ~CGenFvMapApp(void);\r | |
408 | \r | |
409 | int Run(void);\r | |
410 | \r | |
411 | private:\r | |
412 | int m_cArgc;\r | |
413 | char **m_ppszArgv;\r | |
414 | };\r | |
415 | \r | |
416 | CGenFvMapApp::CGenFvMapApp(int cArgc, char *ppszArgv[])\r | |
417 | : m_cArgc(cArgc)\r | |
418 | , m_ppszArgv(ppszArgv)\r | |
419 | {\r | |
420 | if (cArgc != 3)\r | |
421 | throw CGenFvMapUsage();\r | |
422 | }\r | |
423 | \r | |
424 | CGenFvMapApp::~CGenFvMapApp(void)\r | |
425 | {\r | |
426 | }\r | |
427 | \r | |
428 | int CGenFvMapApp::Run(void)\r | |
429 | {\r | |
430 | ifstream isLog(m_ppszArgv[1]);\r | |
431 | CIdAddressPathMap idAddrPath(isLog);\r | |
432 | CFvMapFile fvMap(idAddrPath);\r | |
433 | \r | |
434 | ofstream osMap(m_ppszArgv[2], ios_base::out | ios_base::trunc);\r | |
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 | |
443 | int 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 |