1 //****************************************************************************
3 //** Copyright (C) 2006 Intel Corporation. All rights reserved.
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
10 //****************************************************************************
11 #include "ProcessorBind.h"
26 typedef UINT64 ulonglong_t
;
29 #if __STDC_VERSION__ < 199901L
30 #define __FUNCTION__ __FILE__
35 class CMemoryLeakChecker
: public list
<T
*>
38 static CMemoryLeakChecker
<T
>& GetInstance(void);
41 CMemoryLeakChecker(void)
45 ~CMemoryLeakChecker(void);
49 CMemoryLeakChecker
<T
>& CMemoryLeakChecker
<T
>::GetInstance(void)
51 static CMemoryLeakChecker
<T
> s_memLeakChecker
;
52 return s_memLeakChecker
;
56 CMemoryLeakChecker
<T
>::~CMemoryLeakChecker(void)
58 if (!list
<T
*>::empty())
59 throw logic_error(__FUNCTION__
": Memory leak detected!");
66 virtual ~CObjRoot(void);
69 CObjRoot::CObjRoot(void)
71 CMemoryLeakChecker
<CObjRoot
>::GetInstance().push_back(this);
74 CObjRoot::~CObjRoot(void)
76 CMemoryLeakChecker
<CObjRoot
>::GetInstance().remove(this);
79 class CIdentity
: public CObjRoot
83 CIdentity(const string
&);
84 CIdentity(const CIdentity
&);
86 bool operator < (const CIdentity
&) const;
87 friend istream
& operator >> (istream
&, CIdentity
&);
88 friend ostream
& operator << (ostream
&, const CIdentity
&);
90 static const string::size_type s_nIdStrLen
;
93 ulonglong_t m_ullId
[2];
96 const string::size_type
CIdentity::s_nIdStrLen
= 36;
98 CIdentity::CIdentity(void)
100 memset(m_ullId
, 0, sizeof(m_ullId
));
103 CIdentity::CIdentity(const string
& strId
)
105 if (strId
.length() != CIdentity::s_nIdStrLen
||
111 __FUNCTION__
": Error GUID format " + strId
);
113 string
strIdCopy(strId
);
114 strIdCopy
.erase(23, 1);
116 strIdCopy
.erase(13, 1);
117 strIdCopy
.erase(8, 1);
119 istringstream
is(strIdCopy
);
120 is
>> hex
>> m_ullId
[0] >> m_ullId
[1];
123 __FUNCTION__
": GUID contains invalid characters" + strId
);
126 CIdentity::CIdentity(const CIdentity
& idRight
)
128 memmove(m_ullId
, idRight
.m_ullId
, sizeof(m_ullId
));
131 bool CIdentity::operator < (const CIdentity
& idRight
) const
133 return memcmp(m_ullId
, idRight
.m_ullId
, sizeof(m_ullId
)) < 0;
136 istream
& operator >> (istream
& is
, CIdentity
& idRight
)
141 idRight
= CIdentity(strId
);
145 ostream
& operator << (ostream
& os
, const CIdentity
& idRight
)
147 return os
<< hex
<< setfill('0')
148 << setw(8) << (unsigned long)(idRight
.m_ullId
[0] >> 32) << '-'
149 << setw(4) << (unsigned short)(idRight
.m_ullId
[0] >> 16) << '-'
150 << setw(4) << (unsigned short)idRight
.m_ullId
[0] << '-'
151 << setw(4) << (unsigned short)(idRight
.m_ullId
[1] >> 48) << '-'
152 << setw(12) << (idRight
.m_ullId
[1] & 0xffffffffffffULL
);
155 class CInputFile
: public CObjRoot
158 CInputFile(const string
&);
159 CInputFile(istream
&);
160 istream
& GetLine(string
&);
163 CInputFile(const CInputFile
&);
164 CInputFile
& operator = (const CInputFile
&);
167 auto_ptr
<istream
> m_pIs
;
173 CInputFile::CInputFile(const string
& strFName
)
174 : m_pIs(new ifstream(strFName
.c_str()))
178 throw runtime_error(__FUNCTION__
": Error opening input file " + strFName
);
181 CInputFile::CInputFile(istream
& is
)
185 throw runtime_error(__FUNCTION__
": Error opening input stream");
188 istream
& CInputFile::GetLine(string
& strALine
)
191 while (!!getline(m_is
, strALine
))
193 string::size_type pos
= strALine
.find_last_not_of(' ');
194 if (pos
!= string::npos
)
196 strALine
.erase(pos
+ 1);
197 strALine
.erase(0, strALine
.find_first_not_of(' '));
204 class CIdAddressPathMap
: public CInputFile
, public map
<CIdentity
, pair
<ulonglong_t
, string
> >
207 CIdAddressPathMap(istream
&);
210 CIdAddressPathMap::CIdAddressPathMap(istream
& is
)
215 while (!!(m_is
>> hex
>> k
>> m
.first
) && !!GetLine(m
.second
))
216 if (!insert(value_type(k
, m
)).second
)
217 throw runtime_error(__FUNCTION__
": Duplicated files");
220 class CSymbol
: public CObjRoot
225 ulonglong_t m_ullRva
;
233 CSymbol(const string
&, bool = false);
234 friend ostream
& operator << (ostream
&, const CSymbol
&);
237 CSymbol::CSymbol(const string
& strALine
, bool bStatic
)
240 istringstream
is(strALine
);
242 is
>> m_strAddress
>> m_strName
>> hex
>> m_ullRva
>> m_strFrom
;
243 if (m_strFrom
== "F" || m_strFrom
== "f")
247 } else m_bFunction
= false;
250 ostream
& operator << (ostream
& os
, const CSymbol
& symbol
)
252 os
<< hex
<< setw(16) << setfill('0') << symbol
.m_ullRva
<< setw(0);
253 os
<< ' ' << (symbol
.m_bFunction
? 'F' : ' ')
254 << (symbol
.m_bStatic
? 'S' : ' ') << ' ';
255 return os
<< symbol
.m_strName
;
258 class CMapFile
: public CInputFile
, public list
<CSymbol
>
261 CMapFile(const string
&);
263 void SetLoadAddress(ulonglong_t
);
265 string m_strModuleName
;
266 ulonglong_t m_ullLoadAddr
;
267 string m_strEntryPoint
;
270 CMapFile::CMapFile(const string
& strFName
)
271 : CInputFile(strFName
)
273 static const char cszLoadAddr
[] = "Preferred load address is";
274 static const char cszGlobal
[] = "Address";
275 static const char cszEntryPoint
[] = "entry point at";
276 static const char cszStatic
[] = "Static symbols";
280 GetLine(m_strModuleName
);
282 while (!!GetLine(strALine
) && strALine
.compare(0, sizeof(cszLoadAddr
) - 1, cszLoadAddr
));
284 throw runtime_error(__FUNCTION__
": Load Address not listed in map file");
286 istringstream
is(strALine
.substr(sizeof(cszLoadAddr
) - 1));
287 if (!(is
>> hex
>> m_ullLoadAddr
))
288 throw runtime_error(__FUNCTION__
": Unexpected Load Address format");
290 while (!!GetLine(strALine
) && strALine
.compare(0, sizeof(cszGlobal
) - 1, cszGlobal
));
292 throw runtime_error(__FUNCTION__
": Global symbols not found in map file");
294 while (!!GetLine(strALine
) && strALine
.compare(0, sizeof(cszEntryPoint
) - 1, cszEntryPoint
))
295 push_back(CSymbol(strALine
));
297 throw runtime_error(__FUNCTION__
": Entry Point not listed in map file");
299 is
.str(strALine
.substr(strALine
.find_first_not_of(' ', sizeof(cszEntryPoint
) - 1)));
301 if (!getline(is
, m_strEntryPoint
))
302 throw runtime_error(__FUNCTION__
": Unexpected Entry Point format");
304 while (!!GetLine(strALine
) && strALine
.compare(0, sizeof(cszStatic
) - 1, cszStatic
));
305 while (!!GetLine(strALine
))
306 push_back(CSymbol(strALine
, true));
309 void CMapFile::SetLoadAddress(ulonglong_t ullLoadAddr
)
311 for (iterator i
= begin(); i
!= end(); i
++)
312 if (i
->m_ullRva
>= m_ullLoadAddr
)
313 i
->m_ullRva
+= ullLoadAddr
- m_ullLoadAddr
;
314 m_ullLoadAddr
= ullLoadAddr
;
317 class COutputFile
: public CObjRoot
320 COutputFile(ostream
&);
324 COutputFile(const COutputFile
&);
325 COutputFile
& operator = (const COutputFile
&);
328 class CFvMapFile
: public CObjRoot
, public map
<CIdentity
, CMapFile
*>
331 CFvMapFile(const CIdAddressPathMap
&);
334 friend ostream
& operator << (ostream
&, const CFvMapFile
&);
340 CFvMapFile::CFvMapFile(const CIdAddressPathMap
& idAddrPath
)
342 for (CIdAddressPathMap::const_iterator i
= idAddrPath
.begin(); i
!= idAddrPath
.end(); i
++)
344 if (i
->second
.second
== "*")
349 pair
<iterator
, bool> r
= insert(value_type(i
->first
,
350 new CMapFile(i
->second
.second
.substr(0, i
->second
.second
.rfind('.')) + ".map")));
351 r
.first
->second
->SetLoadAddress(i
->second
.first
);
353 catch (const runtime_error
& e
)
359 CFvMapFile::~CFvMapFile(void)
364 void CFvMapFile::Cleanup(void)
366 for (iterator i
= begin(); i
!= end(); i
++)
370 static bool map_less(const CFvMapFile::const_iterator
& l
, const CFvMapFile::const_iterator
& r
)
372 return l
->second
->m_ullLoadAddr
< r
->second
->m_ullLoadAddr
;
375 ostream
& operator << (ostream
& os
, const CFvMapFile
& fvMap
)
377 vector
<CFvMapFile::const_iterator
> rgIter
;
378 rgIter
.reserve(fvMap
.size());
379 for (CFvMapFile::const_iterator i
= fvMap
.begin(); i
!= fvMap
.end(); i
++)
381 sort(rgIter
.begin(), rgIter
.end(), map_less
);
383 for (vector
<CFvMapFile::const_iterator
>::const_iterator i
= rgIter
.begin(); i
!= rgIter
.end(); i
++)
385 CMapFile::const_iterator j
= (*i
)->second
->begin();
386 while (j
!= (*i
)->second
->end() && j
->m_strAddress
!= (*i
)->second
->m_strEntryPoint
) j
++;
387 if (j
== (*i
)->second
->end())
389 __FUNCTION__
":Entry point not found for module " +
390 (*i
)->second
->m_strModuleName
);
393 << (*i
)->second
->m_strModuleName
394 << " (EntryPoint=" << j
->m_ullRva
395 << ", BaseAddress=" << (*i
)->second
->m_ullLoadAddr
396 << ", GUID=" << (*i
)->first
397 << ")" << endl
<< endl
;
399 for (j
= (*i
)->second
->begin(); j
!= (*i
)->second
->end(); j
++)
400 os
<< " " << *j
<< endl
;
408 class CGenFvMapUsage
: public invalid_argument
411 CGenFvMapUsage(void) : invalid_argument(s_szUsage
)
416 static const char s_szUsage
[];
419 const char CGenFvMapUsage::s_szUsage
[] = "Usage: GenFvMap <LOG> <MAP>";
421 class CGenFvMapApp
: public CObjRoot
424 CGenFvMapApp(int, char *[]);
434 CGenFvMapApp::CGenFvMapApp(int cArgc
, char *ppszArgv
[])
436 , m_ppszArgv(ppszArgv
)
439 throw CGenFvMapUsage();
442 CGenFvMapApp::~CGenFvMapApp(void)
446 int CGenFvMapApp::Run(void)
448 ifstream
isLog(m_ppszArgv
[1]);
449 CIdAddressPathMap
idAddrPath(isLog
);
450 CFvMapFile
fvMap(idAddrPath
);
452 ofstream
osMap(m_ppszArgv
[2], ios_base::out
| ios_base::trunc
);
456 throw runtime_error(__FUNCTION__
": Error writing output file");
461 int main(int argc
, char *argv
[])
465 CGenFvMapApp
app(argc
, argv
);
468 catch (const exception
& e
)
470 cerr
<< e
.what() << endl
;