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