]> git.proxmox.com Git - mirror_edk2.git/blobdiff - Tools/CCode/Source/GenFvMap/GenFvMap.cpp
1. Updated LOG file format generated by PeiRebase.
[mirror_edk2.git] / Tools / CCode / Source / GenFvMap / GenFvMap.cpp
index 9934d3cb5580ab80954d5c39a9dcbef59bc338e6..8c8910cc820767a6b10a25101c46d6c3589f0d8b 100644 (file)
 //** from the company.\r
 //**\r
 //****************************************************************************\r
-#include "ProcessorBind.h"\r
+#include <cstdio>\r
 #include <iostream>\r
-#include <stdexcept>\r
-#include <list>\r
-#include <map>\r
-#include <vector>\r
-#include <iomanip>\r
 #include <fstream>\r
-#include <sstream>\r
+#include <iomanip>\r
+#include <stdexcept>\r
+#include <set>\r
 #include <string>\r
-#include <utility>\r
+#include <sstream>\r
+#include <vector>\r
+#include <map>\r
 #include <algorithm>\r
-#include <functional>\r
 using namespace std;\r
 \r
-typedef UINT64 ulonglong_t;\r
-\r
-#ifdef __GNUC__\r
-#if __STDC_VERSION__ < 199901L\r
-#define __FUNCTION__ __FILE__\r
-#endif\r
-#endif\r
+#include "ProcessorBind.h"\r
 \r
-template <class T>\r
-class CMemoryLeakChecker : public list<T*>\r
+class putUINT64\r
 {\r
 public:\r
-    static CMemoryLeakChecker<T>& GetInstance(void);\r
+    putUINT64(UINT64 ullVal) : m_ull(ullVal) {}\r
+    putUINT64(const putUINT64& r) : m_ull(r.m_ull) {}\r
+\r
+    template <class _E, class _Tr>\r
+    friend basic_ostream<_E, _Tr>& operator << (basic_ostream<_E, _Tr>&, putUINT64);\r
 \r
 private:\r
-    CMemoryLeakChecker(void)\r
+    UINT64 m_ull;\r
+};\r
+\r
+template <class _E, class _Tr>\r
+basic_ostream<_E, _Tr>& operator << (basic_ostream<_E, _Tr>& os, putUINT64 ull)\r
+{\r
+    static const char cDigits[] = "0123456789abcdef";\r
+\r
+    UINT64 base = 10;\r
+    if (os.flags() & ios_base::hex)\r
+        base = 16;\r
+    else if (os.flags() & ios_base::oct)\r
+        base = 8;\r
+\r
+    ostringstream ostr;\r
+    UINT64 ullVal = ull.m_ull;\r
+    while (ullVal != 0)\r
     {\r
+        ostr << cDigits[ullVal % base];\r
+        ullVal /= base;\r
     }\r
 \r
-    ~CMemoryLeakChecker(void);\r
+    string s1(ostr.str());\r
+    string s2(s1.rbegin(), s1.rend());\r
+    return os << s2;\r
+}\r
+\r
+class getUINT64\r
+{\r
+public:\r
+    getUINT64(UINT64& ullVal) : m_ull(ullVal) {}\r
+    getUINT64(const getUINT64& r) : m_ull(r.m_ull) {}\r
+\r
+    template <class _E, class _Tr>\r
+    friend basic_istream<_E, _Tr>& operator >> (basic_istream<_E, _Tr>&, getUINT64);\r
+\r
+private:\r
+    UINT64& m_ull;\r
+\r
+private:\r
+    getUINT64& operator = (const getUINT64&);\r
 };\r
 \r
-template <class T>\r
-CMemoryLeakChecker<T>& CMemoryLeakChecker<T>::GetInstance(void)\r
+template <class _E, class _Tr>\r
+basic_istream<_E, _Tr>& operator >> (basic_istream<_E, _Tr>& is, getUINT64 ull)\r
 {\r
-    static CMemoryLeakChecker<T> s_memLeakChecker;\r
-    return s_memLeakChecker;\r
+    string strBuf;\r
+    is >> strBuf;\r
+\r
+    UINT64 base = 10;\r
+    if (is.flags() & ios_base::hex)\r
+        base = 16;\r
+    else if (is.flags() & ios_base::oct)\r
+        base = 8;\r
+\r
+    UINT64 ullVal = 0;\r
+    for (string::iterator i = strBuf.begin(); i != strBuf.end(); i++)\r
+    {\r
+        if (*i <= '9' && *i >= '0')\r
+            *i -= '0';\r
+        else if (*i <= 'F' && *i >= 'A')\r
+            *i -= 'A' - '\x0a';\r
+        else if (*i <= 'f' && *i >= 'a')\r
+            *i -= 'a' - '\x0a';\r
+        else throw runtime_error("Invalid number format");\r
+\r
+        ullVal = ullVal * base + *i;\r
+    }\r
+    ull.m_ull = ullVal;\r
+    return is;\r
 }\r
 \r
-template <class T>\r
-CMemoryLeakChecker<T>::~CMemoryLeakChecker(void)\r
+class EMemoryLeak : public logic_error\r
 {\r
-    if (!list<T*>::empty())\r
-        throw logic_error(__FUNCTION__ ": Memory leak detected!");\r
-}\r
+public:\r
+    EMemoryLeak() : logic_error("Memory leak detected") {}\r
+};\r
 \r
-class CObjRoot\r
+class EInvalidGuidString : public invalid_argument\r
+{\r
+public:\r
+    EInvalidGuidString() : invalid_argument("Unexpected format of GUID string") {}\r
+};\r
+\r
+class ELogFileError : public logic_error\r
+{\r
+public:\r
+    ELogFileError(const string& strMsg) : logic_error(strMsg) {}\r
+};\r
+\r
+class EDuplicatedFfsFile : public ELogFileError\r
+{\r
+public:\r
+    EDuplicatedFfsFile() : ELogFileError("Duplicated FFS found in LOG file") {}\r
+};\r
+\r
+class EUnexpectedLogFileToken : public ELogFileError\r
+{\r
+public:\r
+    EUnexpectedLogFileToken() : ELogFileError("Unexpected LOG file token") {}\r
+};\r
+\r
+class EFileNotFound : public invalid_argument\r
+{\r
+public:\r
+    EFileNotFound(const string& strFName) : invalid_argument("File not found - " + strFName) {}\r
+};\r
+\r
+class EUnexpectedMapFile : public logic_error\r
+{\r
+public:\r
+    EUnexpectedMapFile(const string& strKeyWord) : logic_error("Unexpected map file format - " + strKeyWord) {}\r
+};\r
+\r
+class EUsage : public invalid_argument\r
+{\r
+public:\r
+    EUsage() : invalid_argument("Usage: GenFvMap <FV.LOG> <FV.INF> <FV.MAP>") {}\r
+};\r
+\r
+template <class T>\r
+class CMemoryLeakChecker : public set<T*>\r
 {\r
 protected:\r
-    CObjRoot(void);\r
-    virtual ~CObjRoot(void);\r
+    CMemoryLeakChecker()\r
+    {\r
+    }\r
+\r
+public:\r
+    virtual ~CMemoryLeakChecker();\r
+    static CMemoryLeakChecker<T>& GetInstance();\r
+\r
+private:\r
+    CMemoryLeakChecker(const CMemoryLeakChecker<T>&);\r
 };\r
 \r
-CObjRoot::CObjRoot(void)\r
+template <class T>\r
+CMemoryLeakChecker<T>::~CMemoryLeakChecker()\r
 {\r
-    CMemoryLeakChecker<CObjRoot>::GetInstance().push_back(this);\r
+    if (!CMemoryLeakChecker<T>::empty())\r
+        throw EMemoryLeak();\r
 }\r
 \r
-CObjRoot::~CObjRoot(void)\r
+template <class T>\r
+CMemoryLeakChecker<T>& CMemoryLeakChecker<T>::GetInstance()\r
 {\r
-    CMemoryLeakChecker<CObjRoot>::GetInstance().remove(this);\r
+    static CMemoryLeakChecker<T> s_instance;\r
+    return s_instance;\r
 }\r
 \r
+class CObjRoot\r
+{\r
+protected:\r
+    CObjRoot()\r
+    {\r
+#ifdef _CHK_MEM_LEAK\r
+        CMemoryLeakChecker<CObjRoot>::GetInstance().insert(this);\r
+#endif\r
+    }\r
+\r
+public:\r
+    virtual ~CObjRoot()\r
+    {\r
+#ifdef _CHK_MEM_LEAK\r
+        CMemoryLeakChecker<CObjRoot>::GetInstance().erase(this);\r
+#endif\r
+    }\r
+\r
+private:\r
+    CObjRoot(const CObjRoot&);\r
+};\r
+\r
 class CIdentity : public CObjRoot\r
 {\r
 public:\r
-    CIdentity(void);\r
     CIdentity(const string&);\r
-    CIdentity(const CIdentity&);\r
+    operator string (void) const;\r
+\r
+    bool operator < (const CIdentity& id) const\r
+    {\r
+        return memcmp(this, &id, sizeof(*this)) < 0;\r
+    }\r
+\r
+    CIdentity() : ulD1(0), wD2(0), wD3(0), wD4(0), ullD5(0)\r
+    {\r
+    }\r
 \r
-    bool operator < (const CIdentity&) const;\r
-    friend istream& operator >> (istream&, CIdentity&);\r
-    friend ostream& operator << (ostream&, const CIdentity&);\r
+    CIdentity(const CIdentity& r) : ulD1(r.ulD1), wD2(r.wD2), wD3(r.wD3), wD4(r.wD4), ullD5(r.ullD5)\r
+    {\r
+    }\r
 \r
-    static const string::size_type s_nIdStrLen;\r
+    template <class _E, class _Tr>\r
+    basic_istream<_E, _Tr>& ReadId(basic_istream<_E, _Tr>&);\r
+    template <class _E, class _Tr>\r
+    basic_ostream<_E, _Tr>& WriteId(basic_ostream<_E, _Tr>&);\r
 \r
-protected:\r
-    ulonglong_t m_ullId[2];\r
-};\r
+    template <class _E, class _Tr>\r
+    friend basic_istream<_E, _Tr>& operator >> (basic_istream<_E, _Tr>&, CIdentity&);\r
+    template <class _E, class _Tr>\r
+    friend basic_ostream<_E, _Tr>& operator << (basic_ostream<_E, _Tr>&, CIdentity);\r
 \r
-const string::size_type CIdentity::s_nIdStrLen = 36;\r
+private:\r
+    UINT32 ulD1;\r
+    UINT16 wD2, wD3, wD4;\r
+    UINT64 ullD5;\r
+};\r
 \r
-CIdentity::CIdentity(void)\r
+CIdentity::CIdentity(const string& strGuid)\r
 {\r
-    memset(m_ullId, 0, sizeof(m_ullId));\r
+    try\r
+    {\r
+        string str(strGuid);\r
+        str.erase(0, str.find_first_not_of(" {"));\r
+        str.resize(str.find_last_not_of(" }") + 1);\r
+        str[str.find('-')] = ' ';\r
+        str[str.find('-')] = ' ';\r
+        str[str.find('-')] = ' ';\r
+        str[str.find('-')] = ' ';\r
+\r
+        istringstream is(str);\r
+        is >> hex >> ulD1 >> wD2 >> wD3 >> wD4 >> getUINT64(ullD5);\r
+    }\r
+    catch (const exception&)\r
+    {\r
+        throw EInvalidGuidString();\r
+    }\r
 }\r
 \r
-CIdentity::CIdentity(const string& strId)\r
+CIdentity::operator string(void) const\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
+    ostringstream os;\r
+    os << hex << setfill('0')\r
+        << setw(8) << ulD1 << '-'\r
+        << setw(4) << wD2 << '-'\r
+        << setw(4) << wD3 << '-'\r
+        << setw(4) << wD4 << '-'\r
+        << setw(12) << putUINT64(ullD5);\r
+    return os.str();\r
 }\r
 \r
-CIdentity::CIdentity(const CIdentity& idRight)\r
+template <class _E, class _Tr>\r
+basic_istream<_E, _Tr>& CIdentity::ReadId(basic_istream<_E, _Tr>& is)\r
 {\r
-    memmove(m_ullId, idRight.m_ullId, sizeof(m_ullId));\r
+    string str;\r
+    if (!!(is >> str))\r
+        *this = CIdentity(str);\r
+    return is;\r
 }\r
 \r
-bool CIdentity::operator < (const CIdentity& idRight) const\r
+template <class _E, class _Tr>\r
+basic_ostream<_E, _Tr>& CIdentity::WriteId(basic_ostream<_E, _Tr>& os)\r
 {\r
-    return memcmp(m_ullId, idRight.m_ullId, sizeof(m_ullId)) < 0;\r
+    return os << (string)(*this);\r
 }\r
 \r
-istream& operator >> (istream& is, CIdentity& idRight)\r
+template <class _E, class _Tr>\r
+basic_istream<_E, _Tr>& operator >> (basic_istream<_E, _Tr>& is, CIdentity& id)\r
 {\r
-    string strId;\r
-    is >> strId;\r
-    if (!!is)\r
-        idRight = CIdentity(strId);\r
-    return is;\r
+    return id.ReadId(is);\r
 }\r
 \r
-ostream& operator << (ostream& os, const CIdentity& idRight)\r
+template <class _E, class _Tr>\r
+basic_ostream<_E, _Tr>& operator << (basic_ostream<_E, _Tr>& os, CIdentity id)\r
 {\r
-    return os << hex << setfill('0')\r
-        << setw(8) << (unsigned long)(idRight.m_ullId[0] >> 32) << '-'\r
-        << setw(4) << (unsigned short)(idRight.m_ullId[0] >> 16) << '-'\r
-        << setw(4) << (unsigned short)idRight.m_ullId[0] << '-'\r
-        << setw(4) << (unsigned short)(idRight.m_ullId[1] >> 48) << '-'\r
-        << setw(12) <<  (idRight.m_ullId[1] & 0xffffffffffffULL);\r
+    return id.WriteId(os);\r
 }\r
 \r
-class CInputFile : public CObjRoot\r
+template <class T>\r
+class IVectorContainerByReference : virtual public CObjRoot, public vector<T*>\r
 {\r
-protected:\r
-    CInputFile(const string&);\r
-    CInputFile(istream&);\r
-    istream& GetLine(string&);\r
+};\r
 \r
-private:\r
-    CInputFile(const CInputFile&);\r
-    CInputFile& operator = (const CInputFile&);\r
+template <class T>\r
+class IMapContainer : virtual public CObjRoot, public map<CIdentity, T>\r
+{\r
+};\r
 \r
-private:\r
-    auto_ptr<istream> m_pIs;\r
+struct ISymbol : virtual public CObjRoot\r
+{\r
+    string strAddress;\r
+    string strName;\r
+    string strFrom;\r
+    UINT64 ullRva;\r
+    bool bStatic;\r
+    bool bFunction;\r
+    virtual void Relocate(UINT64)=0;\r
+};\r
 \r
-protected:\r
-    istream& m_is;\r
+class IModule : public IVectorContainerByReference<ISymbol>\r
+{\r
+public:\r
+    string strName;\r
+    CIdentity id;\r
+    virtual UINT64 BaseAddress(void) const=0;\r
+    virtual UINT64 BaseAddress(UINT64)=0;\r
+    virtual const ISymbol *EntryPoint(void) const=0;\r
 };\r
 \r
-CInputFile::CInputFile(const string& strFName)\r
-: m_pIs(new ifstream(strFName.c_str()))\r
-, m_is(*m_pIs)\r
+class IFirmwareVolume : public IVectorContainerByReference<IModule>\r
 {\r
-    if (!m_is)\r
-        throw runtime_error(__FUNCTION__ ": Error opening input file " + strFName);\r
-}\r
+};\r
 \r
-CInputFile::CInputFile(istream& is)\r
-: m_is(is)\r
+class IMapFileSet : public IMapContainer<istream*>\r
 {\r
-    if (!m_is)\r
-        throw runtime_error(__FUNCTION__ ": Error opening input stream");\r
-}\r
+};\r
 \r
-istream& CInputFile::GetLine(string& strALine)\r
+class IFfsSet : public IMapContainer<UINT64>\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
 \r
-class CIdAddressPathMap : public CInputFile, public map<CIdentity, pair<ulonglong_t, string> >\r
+class CFfsSetFromLogFile : public IFfsSet\r
 {\r
 public:\r
-    CIdAddressPathMap(istream&);\r
+    CFfsSetFromLogFile(const string&);\r
 };\r
 \r
-CIdAddressPathMap::CIdAddressPathMap(istream& is)\r
-: CInputFile(is)\r
+CFfsSetFromLogFile::CFfsSetFromLogFile(const string& strFName)\r
 {\r
-    key_type k;\r
-    mapped_type m;\r
-    while (!!(m_is >> hex >> k >> m.first) && !!GetLine(m.second))\r
-        if (!insert(value_type(k, m)).second)\r
-            throw runtime_error(__FUNCTION__ ": Duplicated files");\r
+    ifstream ifs(strFName.c_str());\r
+    if (!ifs)\r
+        throw EFileNotFound(strFName);\r
+\r
+    CIdentity ffsId;\r
+    while (!!ffsId.ReadId(ifs))\r
+    {\r
+        UINT64 ullBase;\r
+        if (!(ifs >> hex >> getUINT64(ullBase)))\r
+            throw EUnexpectedLogFileToken();\r
+        if (!insert(value_type(ffsId, ullBase)).second)\r
+            throw EDuplicatedFfsFile();\r
+    }\r
 }\r
 \r
-class CSymbol : public CObjRoot\r
+class CMapFileSetFromInfFile : public IMapFileSet\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
+    CMapFileSetFromInfFile(const string&);\r
+    ~CMapFileSetFromInfFile();\r
+};\r
+\r
+CMapFileSetFromInfFile::CMapFileSetFromInfFile(const string& strFName)\r
+{\r
+    static const char cszEfiFileName[] = "EFI_FILE_NAME";\r
+\r
+    ifstream ifs(strFName.c_str());\r
+    if (!ifs)\r
+        throw EFileNotFound(strFName);\r
+\r
+    string strFile;\r
+    getline(ifs, strFile, ifstream::traits_type::to_char_type(ifstream::traits_type::eof()));\r
+    strFile.erase(0, strFile.find("[files]"));\r
+\r
+    istringstream is(strFile);\r
+    string strTmp;\r
+    while (!!getline(is, strTmp))\r
     {\r
+        string::size_type pos = strTmp.find(cszEfiFileName);\r
+        if (pos == string::npos)\r
+            continue;\r
+\r
+        strTmp.erase(0, strTmp.find_first_not_of(" =", pos + sizeof(cszEfiFileName) - 1));\r
+        pos = strTmp.find_last_of("\\/");\r
+        string strId(\r
+            strTmp.begin() + pos + 1,\r
+            strTmp.begin() + strTmp.find('-', strTmp.find('-', strTmp.find('-', strTmp.find('-', strTmp.find('-') + 1) + 1) + 1) + 1)\r
+            );\r
+        strTmp.erase(pos + 1, strId.length() + 1);\r
+        strTmp.replace(strTmp.rfind('.'), string::npos, ".map");\r
+\r
+        istream *ifmaps = new ifstream(strTmp.c_str());\r
+        if (ifmaps && !!*ifmaps &&\r
+            !insert(value_type(CIdentity(strId), ifmaps)).second)\r
+                throw EDuplicatedFfsFile();\r
     }\r
-    CSymbol(const string&, bool = false);\r
-    friend ostream& operator << (ostream&, const CSymbol&);\r
+}\r
+\r
+CMapFileSetFromInfFile::~CMapFileSetFromInfFile()\r
+{\r
+    for (iterator i = begin(); i != end(); i++)\r
+        delete i->second;\r
+}\r
+\r
+class CSymbolFromString : public ISymbol\r
+{\r
+public:\r
+    CSymbolFromString(const string&, bool = false);\r
+    void Relocate(UINT64);\r
 };\r
 \r
-CSymbol::CSymbol(const string& strALine, bool bStatic)\r
-: m_bStatic(bStatic)\r
+CSymbolFromString::CSymbolFromString(const string& strSymbol, bool b)\r
 {\r
-    istringstream is(strALine);\r
+    bStatic = b;\r
 \r
-    is >> m_strAddress >> m_strName >> hex >> m_ullRva >> m_strFrom;\r
-    if (m_strFrom == "F" || m_strFrom == "f")\r
+    istringstream is(strSymbol);\r
+    is >> strAddress >> strName >> getUINT64(ullRva) >> strFrom;\r
+    if (strFrom == "f")\r
     {\r
-        m_bFunction = true;\r
-        is >> m_strFrom;\r
-    } else m_bFunction = false;\r
+        bFunction = true;\r
+        is >> strFrom;\r
+    }\r
+    else bFunction = false;\r
+    if (!is)\r
+        throw EUnexpectedMapFile("Symbol line format");\r
 }\r
 \r
-ostream& operator << (ostream& os, const CSymbol& symbol)\r
+void CSymbolFromString::Relocate(UINT64 ullDelta)\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;\r
+    if (ullRva > 0)\r
+        ullRva += ullDelta;\r
 }\r
 \r
-class CMapFile : public CInputFile, public list<CSymbol>\r
+class CModuleFromMap : public IModule\r
 {\r
 public:\r
-    CMapFile(const string&);\r
+    CModuleFromMap(istream&);\r
+    ~CModuleFromMap();\r
+\r
+    UINT64 BaseAddress() const;\r
+    UINT64 BaseAddress(UINT64);\r
+    const ISymbol *EntryPoint() const;\r
 \r
-    void SetLoadAddress(ulonglong_t);\r
+private:\r
+    UINT64 m_ullLoadAddress;\r
+    iterator m_iEntryPoint;\r
 \r
-    string m_strModuleName;\r
-    ulonglong_t m_ullLoadAddr;\r
-    string m_strEntryPoint;\r
+    static pair<string, string::size_type> FindToken(istream&, const string&);\r
 };\r
 \r
-CMapFile::CMapFile(const string& strFName)\r
-: CInputFile(strFName)\r
+pair<string, string::size_type> CModuleFromMap::FindToken(istream& is, const string& strToken)\r
+{\r
+    for (string strTmp; !!getline(is, strTmp);)\r
+    {\r
+        string::size_type pos = strTmp.find(strToken);\r
+        if (pos != string::npos)\r
+            return pair<string, string::size_type>(strTmp, pos);\r
+    }\r
+    throw EUnexpectedMapFile(strToken);\r
+}\r
+\r
+CModuleFromMap::CModuleFromMap(istream& imaps)\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
+    pair<string, string::size_type> pairTmp;\r
+    istringstream iss;\r
+\r
+    getline(imaps, strName);\r
+    strName.erase(0, strName.find_first_not_of(' '));\r
+\r
+    pairTmp = FindToken(imaps, cszLoadAddr);\r
+    iss.str(pairTmp.first.substr(pairTmp.second + sizeof(cszLoadAddr) - 1));\r
+    iss >> getUINT64(m_ullLoadAddress);\r
+\r
+    pairTmp = FindToken(imaps, cszGlobal);\r
+    while (!!getline(imaps, pairTmp.first) &&\r
+            pairTmp.first.find(cszEntryPoint) == string::npos)\r
+        if (pairTmp.first.find_first_not_of(' ') != string::npos)\r
+            push_back(new CSymbolFromString(pairTmp.first));\r
+\r
+    iss.str(pairTmp.first.substr(pairTmp.first.find(cszEntryPoint) + sizeof(cszEntryPoint) - 1));\r
+    iss.clear();\r
+    string strEntryPoint;\r
+    iss >> strEntryPoint;\r
+\r
+    pairTmp = FindToken(imaps, cszStatic);\r
+    if (pairTmp.second)\r
+        while (!!getline(imaps, pairTmp.first))\r
+            if (pairTmp.first.find_first_not_of(' ') != string::npos)\r
+                push_back(new CSymbolFromString(pairTmp.first, true));\r
+\r
+    for (m_iEntryPoint = begin();\r
+         m_iEntryPoint != end() && (*m_iEntryPoint)->strAddress != strEntryPoint;\r
+         m_iEntryPoint++);\r
+    if (m_iEntryPoint == end())\r
+        throw EUnexpectedMapFile("Entry point not found");\r
+}\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
+CModuleFromMap::~CModuleFromMap()\r
+{\r
+    for (iterator i = begin(); i != end(); i++)\r
+        delete *i;\r
+}\r
 \r
-    while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszStatic) - 1, cszStatic));\r
-    while (!!GetLine(strALine))\r
-        push_back(CSymbol(strALine, true));\r
+UINT64 CModuleFromMap::BaseAddress(void) const\r
+{\r
+    return m_ullLoadAddress;\r
 }\r
 \r
-void CMapFile::SetLoadAddress(ulonglong_t ullLoadAddr)\r
+UINT64 CModuleFromMap::BaseAddress(UINT64 ullNewBase)\r
 {\r
+    ullNewBase -= m_ullLoadAddress;\r
     for (iterator i = begin(); i != end(); i++)\r
-        if (i->m_ullRva >= m_ullLoadAddr)\r
-            i->m_ullRva += ullLoadAddr - m_ullLoadAddr;\r
-    m_ullLoadAddr = ullLoadAddr;\r
+        (*i)->Relocate(ullNewBase);\r
+    m_ullLoadAddress += ullNewBase;\r
+    return m_ullLoadAddress - ullNewBase;\r
 }\r
 \r
-class COutputFile : public CObjRoot\r
+const ISymbol *CModuleFromMap::EntryPoint(void) const\r
 {\r
-protected:\r
-    COutputFile(ostream&);\r
-    ostream& m_os;\r
-\r
-private:\r
-    COutputFile(const COutputFile&);\r
-    COutputFile& operator = (const COutputFile&);\r
-};\r
+    return *m_iEntryPoint;\r
+}\r
 \r
-class CFvMapFile : public CObjRoot, public map<CIdentity, CMapFile*>\r
+class CFvMap : public IFirmwareVolume\r
 {\r
 public:\r
-    CFvMapFile(const CIdAddressPathMap&);\r
-    ~CFvMapFile(void);\r
-\r
-    friend ostream& operator << (ostream&, const CFvMapFile&);\r
+    CFvMap(IFfsSet*, IMapFileSet*);\r
+    ~CFvMap();\r
 \r
 private:\r
-    void Cleanup(void);\r
+    CFvMap(const CFvMap&);\r
 };\r
 \r
-CFvMapFile::CFvMapFile(const CIdAddressPathMap& idAddrPath)\r
+CFvMap::CFvMap(IFfsSet *pFfsSet, IMapFileSet *pMapSet)\r
 {\r
-    for (CIdAddressPathMap::const_iterator i = idAddrPath.begin(); i != idAddrPath.end(); i++)\r
+    for (IFfsSet::iterator i = pFfsSet->begin(); i != pFfsSet->end(); i++)\r
     {\r
-        if (i->second.second == "*")\r
-            continue;\r
-\r
-        try\r
-        {\r
-            pair<iterator, bool> r = insert(value_type(i->first,\r
-              new CMapFile(i->second.second.substr(0, i->second.second.rfind('.')) + ".map")));\r
-            r.first->second->SetLoadAddress(i->second.first);\r
-        }\r
-        catch (const runtime_error& e)\r
+        IMapFileSet::iterator j = pMapSet->find(i->first);\r
+        if (j != pMapSet->end())\r
         {\r
+            IModule *pModule = new CModuleFromMap(*j->second);\r
+            pModule->id = i->first;\r
+            pModule->BaseAddress(i->second);\r
+            push_back(pModule);\r
         }\r
     }\r
 }\r
 \r
-CFvMapFile::~CFvMapFile(void)\r
-{\r
-    Cleanup();\r
-}\r
-\r
-void CFvMapFile::Cleanup(void)\r
+CFvMap::~CFvMap()\r
 {\r
     for (iterator i = begin(); i != end(); i++)\r
-        delete i->second;\r
+        delete *i;\r
 }\r
 \r
-static bool map_less(const CFvMapFile::const_iterator& l, const CFvMapFile::const_iterator& r)\r
+class CFvMapFormatter : public CObjRoot\r
 {\r
-    return l->second->m_ullLoadAddr < r->second->m_ullLoadAddr;\r
-}\r
+public:\r
+    CFvMapFormatter(const IFirmwareVolume *pFv) : m_pFv(pFv) {}\r
+    CFvMapFormatter(const CFvMapFormatter& r) : m_pFv(r.m_pFv) {}\r
 \r
-ostream& operator << (ostream& os, const CFvMapFile& fvMap)\r
-{\r
-    vector<CFvMapFile::const_iterator> rgIter;\r
-    rgIter.reserve(fvMap.size());\r
-    for (CFvMapFile::const_iterator i = fvMap.begin(); i != fvMap.end(); i++)\r
-        rgIter.push_back(i);\r
-    sort(rgIter.begin(), rgIter.end(), map_less);\r
+    template <class _E, class _Tr>\r
+    friend basic_ostream<_E, _Tr>& operator << (basic_ostream<_E, _Tr>&, CFvMapFormatter);\r
 \r
-    for (vector<CFvMapFile::const_iterator>::const_iterator i = rgIter.begin(); i != rgIter.end(); i++)\r
+private:\r
+    static bool Less(const IModule*, const IModule*);\r
+\r
+private:\r
+    const IFirmwareVolume *m_pFv;\r
+};\r
+\r
+template <class _E, class _Tr>\r
+basic_ostream<_E, _Tr>& operator << (basic_ostream<_E, _Tr>& os, CFvMapFormatter fvMapFmt)\r
+{\r
+    vector<IModule*> rgMods(fvMapFmt.m_pFv->begin(), fvMapFmt.m_pFv->end());\r
+    sort(rgMods.begin(), rgMods.end(), CFvMapFormatter::Less);\r
+    for (vector<IModule*>::iterator i = rgMods.begin(); i != rgMods.end(); i++)\r
     {\r
-        CMapFile::const_iterator j = (*i)->second->begin();\r
-        while (j != (*i)->second->end() && j->m_strAddress != (*i)->second->m_strEntryPoint) j++;\r
-        if (j == (*i)->second->end())\r
-            throw runtime_error(\r
-                __FUNCTION__ ":Entry point not found for module " +\r
-                (*i)->second->m_strModuleName);\r
-\r
-        os << hex\r
-            << (*i)->second->m_strModuleName\r
-            << " (EntryPoint=" << j->m_ullRva\r
-            << ", BaseAddress=" << (*i)->second->m_ullLoadAddr\r
-            << ", GUID=" << (*i)->first\r
-            << ")" << endl << endl;\r
-\r
-        for (j = (*i)->second->begin(); j != (*i)->second->end(); j++)\r
-            os << "  " << *j << endl;\r
+        os << (*i)->strName << hex << " (BaseAddress=" << putUINT64((*i)->BaseAddress());\r
+        os << ", EntryPoint=" << hex << putUINT64((*i)->EntryPoint()->ullRva);\r
+        os << ", GUID=";\r
+        (*i)->id.WriteId(os);\r
+        os << ")" << endl << endl;\r
+\r
+        for (IModule::iterator j = (*i)->begin(); j != (*i)->end(); j++)\r
+        {\r
+            os << hex << "  " << setw(16) << setfill('0') << putUINT64((*j)->ullRva);\r
+            os << ((*j)->bFunction ? " F" : "  ")\r
+                << ((*j)->bStatic ? "S " : "  ")\r
+                << (*j)->strName << endl;\r
+        }\r
 \r
         os << endl << endl;\r
     }\r
-\r
     return os;\r
 }\r
 \r
-class CGenFvMapUsage : public invalid_argument\r
+bool CFvMapFormatter::Less(const IModule *pModL, const IModule *pModR)\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> <MAP>";\r
+    return pModL->BaseAddress() < pModR->BaseAddress();\r
+}\r
 \r
-class CGenFvMapApp : public CObjRoot\r
+class CApplication : public CObjRoot\r
 {\r
 public:\r
-    CGenFvMapApp(int, char *[]);\r
-    ~CGenFvMapApp(void);\r
-\r
+    CApplication(int, char**);\r
     int Run(void);\r
 \r
 private:\r
-    int m_cArgc;\r
-    char **m_ppszArgv;\r
+    char **m_ppszArg;\r
+private:\r
+    CApplication(const CApplication&);\r
 };\r
 \r
-CGenFvMapApp::CGenFvMapApp(int cArgc, char *ppszArgv[])\r
-: m_cArgc(cArgc)\r
-, m_ppszArgv(ppszArgv)\r
+CApplication::CApplication(int cArg, char *ppszArg[])\r
+: m_ppszArg(ppszArg)\r
 {\r
-    if (cArgc != 3)\r
-        throw CGenFvMapUsage();\r
+    if (cArg != 4)\r
+        throw EUsage();\r
 }\r
 \r
-CGenFvMapApp::~CGenFvMapApp(void)\r
+int CApplication::Run(void)\r
 {\r
-}\r
-\r
-int CGenFvMapApp::Run(void)\r
-{\r
-    ifstream isLog(m_ppszArgv[1]);\r
-    CIdAddressPathMap idAddrPath(isLog);\r
-    CFvMapFile fvMap(idAddrPath);\r
-\r
-    ofstream osMap(m_ppszArgv[2], ios_base::out | ios_base::trunc);\r
-    osMap << fvMap;\r
-\r
-    if (!osMap)\r
-        throw runtime_error(__FUNCTION__ ": Error writing output file");\r
-\r
+    CFfsSetFromLogFile ffsSet(m_ppszArg[1]);\r
+    CMapFileSetFromInfFile mapSet(m_ppszArg[2]);\r
+    ofstream ofs(m_ppszArg[3]);\r
+    CFvMap fvMap(&ffsSet, &mapSet);\r
+    ofs << CFvMapFormatter(&fvMap);\r
     return 0;\r
 }\r
 \r
@@ -462,7 +649,7 @@ int main(int argc, char *argv[])
 {\r
     try\r
     {\r
-        CGenFvMapApp app(argc, argv);\r
+        CApplication app(argc, argv);\r
         return app.Run();\r
     }\r
     catch (const exception& e)\r
@@ -471,3 +658,9 @@ int main(int argc, char *argv[])
         return -1;\r
     }\r
 }\r
+\r
+#ifdef _DDK3790x1830_WORKAROUND\r
+extern "C" void __fastcall __security_check_cookie(int)\r
+{\r
+}\r
+#endif\r