//**************************************************************************** //** //** Copyright (C) 2006 Intel Corporation. All rights reserved. //** //** The information and source code contained herein is the exclusive //** property of Intel Corporation and may not be disclosed, examined //** or reproduced in whole or in part without explicit written authorization //** from the company. //** //**************************************************************************** #include #include #include #include #include #include #include #include #include #include #include using namespace std; typedef unsigned __int64 ulonglong_t; template class CMemoryLeakChecker : public list { public: static CMemoryLeakChecker& GetInstance(void); private: CMemoryLeakChecker(void) { } ~CMemoryLeakChecker(void); }; template CMemoryLeakChecker& CMemoryLeakChecker::GetInstance(void) { static CMemoryLeakChecker s_memLeakChecker; return s_memLeakChecker; } template CMemoryLeakChecker::~CMemoryLeakChecker(void) { if (!list::empty()) throw logic_error(__FUNCTION__ ": Memory leak detected!"); } class CObjRoot { protected: CObjRoot(void); virtual ~CObjRoot(void); }; CObjRoot::CObjRoot(void) { CMemoryLeakChecker::GetInstance().push_back(this); } CObjRoot::~CObjRoot(void) { CMemoryLeakChecker::GetInstance().remove(this); } class CIdentity : public CObjRoot { public: CIdentity(void); CIdentity(const string&); CIdentity(const CIdentity&); bool operator < (const CIdentity&) const; friend istream& operator >> (istream&, CIdentity&); friend ostream& operator << (ostream&, const CIdentity&); static const string::size_type s_nIdStrLen; protected: ulonglong_t m_ullId[2]; }; const string::size_type CIdentity::s_nIdStrLen = 36; CIdentity::CIdentity(void) { memset(m_ullId, 0, sizeof(m_ullId)); } CIdentity::CIdentity(const string& strId) { if (strId.length() != CIdentity::s_nIdStrLen || strId[8] != '-' || strId[13] != '-' || strId[18] != '-' || strId[23] != '-') throw runtime_error( __FUNCTION__ ": Error GUID format " + strId); string strIdCopy(strId); strIdCopy.erase(23, 1); strIdCopy[18] = ' '; strIdCopy.erase(13, 1); strIdCopy.erase(8, 1); istringstream is(strIdCopy); is >> hex >> m_ullId[0] >> m_ullId[1]; if (!is) throw runtime_error( __FUNCTION__ ": GUID contains invalid characters" + strId); } CIdentity::CIdentity(const CIdentity& idRight) { memmove(m_ullId, idRight.m_ullId, sizeof(m_ullId)); } bool CIdentity::operator < (const CIdentity& idRight) const { return memcmp(m_ullId, idRight.m_ullId, sizeof(m_ullId)) < 0; } istream& operator >> (istream& is, CIdentity& idRight) { string strId; is >> strId; if (!!is) idRight = CIdentity(strId); return is; } ostream& operator << (ostream& os, const CIdentity& idRight) { return os << hex << setfill('0') << setw(8) << (unsigned long)(idRight.m_ullId[0] >> 32) << '-' << setw(4) << (unsigned short)(idRight.m_ullId[0] >> 16) << '-' << setw(4) << (unsigned short)idRight.m_ullId[0] << '-' << setw(4) << (unsigned short)(idRight.m_ullId[1] >> 48) << '-' << setw(12) << (idRight.m_ullId[1] & 0xffffffffffff); } class CInputFile : public CObjRoot { protected: CInputFile(const string&); CInputFile(istream&); istream& GetLine(string&); private: CInputFile(const CInputFile&); CInputFile& operator = (const CInputFile&); private: auto_ptr m_pIs; protected: istream& m_is; }; CInputFile::CInputFile(const string& strFName) : m_pIs(new ifstream(strFName.c_str())) , m_is(*m_pIs) { if (!m_is) throw runtime_error(__FUNCTION__ ": Error opening input file " + strFName); } CInputFile::CInputFile(istream& is) : m_is(is) { if (!m_is) throw runtime_error(__FUNCTION__ ": Error opening input stream"); } istream& CInputFile::GetLine(string& strALine) { if (!!m_is) while (!!getline(m_is, strALine)) { string::size_type pos = strALine.find_last_not_of(' '); if (pos != string::npos) { strALine.erase(pos + 1); strALine.erase(0, strALine.find_first_not_of(' ')); break; } } return m_is; } class CIdAddressPathMap : public CInputFile, public map > { public: CIdAddressPathMap(istream&); }; CIdAddressPathMap::CIdAddressPathMap(istream& is) : CInputFile(is) { key_type k; mapped_type m; while (!!(m_is >> hex >> k >> m.first) && !!GetLine(m.second)) if (!insert(value_type(k, m)).second) throw runtime_error(__FUNCTION__ ": Duplicated files"); } class CSymbol : public CObjRoot { public: string m_strAddress; string m_strName; ulonglong_t m_ullRva; string m_strFrom; bool m_bStatic; bool m_bFunction; CSymbol() { } CSymbol(const string&, bool = false); friend ostream& operator << (ostream&, const CSymbol&); }; CSymbol::CSymbol(const string& strALine, bool bStatic) : m_bStatic(bStatic) { istringstream is(strALine); is >> m_strAddress >> m_strName >> hex >> m_ullRva >> m_strFrom; if (m_strFrom == "F" || m_strFrom == "f") { m_bFunction = true; is >> m_strFrom; } else m_bFunction = false; } ostream& operator << (ostream& os, const CSymbol& symbol) { os << hex << setw(16) << setfill('0') << symbol.m_ullRva << setw(0); os << ' ' << (symbol.m_bFunction ? 'F' : ' ') << (symbol.m_bStatic ? 'S' : ' ') << ' '; return os << symbol.m_strName; } class CMapFile : public CInputFile, public list { public: CMapFile(const string&); void SetLoadAddress(ulonglong_t); string m_strModuleName; ulonglong_t m_ullLoadAddr; string m_strEntryPoint; }; CMapFile::CMapFile(const string& strFName) : CInputFile(strFName) { static const char cszLoadAddr[] = "Preferred load address is"; static const char cszGlobal[] = "Address"; static const char cszEntryPoint[] = "entry point at"; static const char cszStatic[] = "Static symbols"; string strALine; GetLine(m_strModuleName); while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszLoadAddr) - 1, cszLoadAddr)); if (!m_is) throw runtime_error(__FUNCTION__ ": Load Address not listed in map file"); istringstream is(strALine.substr(sizeof(cszLoadAddr) - 1)); if (!(is >> hex >> m_ullLoadAddr)) throw runtime_error(__FUNCTION__ ": Unexpected Load Address format"); while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszGlobal) - 1, cszGlobal)); if (!m_is) throw runtime_error(__FUNCTION__ ": Global symbols not found in map file"); while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszEntryPoint) - 1, cszEntryPoint)) push_back(CSymbol(strALine)); if (!m_is) throw runtime_error(__FUNCTION__ ": Entry Point not listed in map file"); is.str(strALine.substr(strALine.find_first_not_of(' ', sizeof(cszEntryPoint) - 1))); is.clear(); if (!getline(is, m_strEntryPoint)) throw runtime_error(__FUNCTION__ ": Unexpected Entry Point format"); while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszStatic) - 1, cszStatic)); while (!!GetLine(strALine)) push_back(CSymbol(strALine, true)); } void CMapFile::SetLoadAddress(ulonglong_t ullLoadAddr) { for (iterator i = begin(); i != end(); i++) if (i->m_ullRva >= m_ullLoadAddr) i->m_ullRva += ullLoadAddr - m_ullLoadAddr; m_ullLoadAddr = ullLoadAddr; } class COutputFile : public CObjRoot { protected: COutputFile(ostream&); ostream& m_os; private: COutputFile(const COutputFile&); COutputFile& operator = (const COutputFile&); }; class CFvMapFile : public CObjRoot, public map { public: CFvMapFile(const CIdAddressPathMap&); ~CFvMapFile(void); friend ostream& operator << (ostream&, const CFvMapFile&); private: void Cleanup(void); }; CFvMapFile::CFvMapFile(const CIdAddressPathMap& idAddrPath) { for (CIdAddressPathMap::const_iterator i = idAddrPath.begin(); i != idAddrPath.end(); i++) { if (i->second.second == "*") continue; pair r = insert(value_type(i->first, new CMapFile(i->second.second.substr(0, i->second.second.rfind('.')) + ".map"))); r.first->second->SetLoadAddress(i->second.first); } } void CFvMapFile::Cleanup(void) { for (iterator i = begin(); i != end(); i++) delete i->second; } ostream& operator << (ostream& os, const CFvMapFile& fvMap) { for (CFvMapFile::const_iterator i = fvMap.begin(); !!os && i != fvMap.end(); i++) { CMapFile::const_iterator j = i->second->begin(); while (j != i->second->end() && j->m_strAddress != i->second->m_strEntryPoint) j++; if (j == i->second->end()) throw runtime_error( __FUNCTION__ ":Entry point not found for module " + i->second->m_strModuleName); os << hex << i->second->m_strModuleName << " (EP=" << j->m_ullRva << ", BA=" << i->second->m_ullLoadAddr << ", GUID=" << i->first << ")" << endl << endl; for (j = i->second->begin(); j != i->second->end(); j++) os << " " << *j << endl; os << endl << endl; } return os; } CFvMapFile::~CFvMapFile(void) { Cleanup(); } class CGenFvMapUsage : public invalid_argument { public: CGenFvMapUsage(void) : invalid_argument(s_szUsage) { } private: static const char s_szUsage[]; }; const char CGenFvMapUsage::s_szUsage[] = "Usage: GenFvMap "; class CGenFvMapApp : public CObjRoot { public: CGenFvMapApp(int, char *[]); ~CGenFvMapApp(void); int Run(void); private: int m_cArgc; char **m_ppszArgv; }; CGenFvMapApp::CGenFvMapApp(int cArgc, char *ppszArgv[]) : m_cArgc(cArgc) , m_ppszArgv(ppszArgv) { if (cArgc != 3) throw CGenFvMapUsage(); } CGenFvMapApp::~CGenFvMapApp(void) { } int CGenFvMapApp::Run(void) { ifstream isLog(m_ppszArgv[1]); CIdAddressPathMap idAddrPath(isLog); CFvMapFile fvMap(idAddrPath); ofstream osMap(m_ppszArgv[2], ios_base::out | ios_base::trunc); osMap << fvMap; if (!osMap) throw runtime_error(__FUNCTION__ ": Error writing output file"); return 0; } int main(int argc, char *argv[]) { try { CGenFvMapApp app(argc, argv); return app.Run(); } catch (const exception& e) { cerr << e.what() << endl; return -1; } }