diff options
Diffstat (limited to 'Tools/CCode/Source/GenFvMap')
-rw-r--r-- | Tools/CCode/Source/GenFvMap/GenFvMap.cpp | 507 | ||||
-rw-r--r-- | Tools/CCode/Source/GenFvMap/build.xml | 72 |
2 files changed, 579 insertions, 0 deletions
diff --git a/Tools/CCode/Source/GenFvMap/GenFvMap.cpp b/Tools/CCode/Source/GenFvMap/GenFvMap.cpp new file mode 100644 index 0000000000..4a8c726785 --- /dev/null +++ b/Tools/CCode/Source/GenFvMap/GenFvMap.cpp @@ -0,0 +1,507 @@ +//****************************************************************************
+//**
+//** 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 <stdexcept>
+#include <list>
+#include <map>
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <algorithm>
+#include <functional>
+using namespace std;
+
+typedef unsigned __int64 ulonglong_t;
+
+template <class T>
+class CMemoryLeakChecker : public list<T*>
+{
+public:
+ static CMemoryLeakChecker<T>& GetInstance(void);
+
+private:
+ CMemoryLeakChecker(void)
+ {
+ }
+
+ ~CMemoryLeakChecker(void);
+};
+
+template <class T>
+CMemoryLeakChecker<T>& CMemoryLeakChecker<T>::GetInstance(void)
+{
+ static CMemoryLeakChecker<T> s_memLeakChecker;
+ return s_memLeakChecker;
+}
+
+template <class T>
+CMemoryLeakChecker<T>::~CMemoryLeakChecker(void)
+{
+ if (!list<T*>::empty())
+ throw logic_error(__FUNCTION__ ": Memory leak detected!");
+}
+
+class CObjRoot
+{
+protected:
+ CObjRoot(void);
+ virtual ~CObjRoot(void);
+};
+
+CObjRoot::CObjRoot(void)
+{
+ CMemoryLeakChecker<CObjRoot>::GetInstance().push_back(this);
+}
+
+CObjRoot::~CObjRoot(void)
+{
+ CMemoryLeakChecker<CObjRoot>::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&);
+
+ 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;
+}
+
+class CInputFile : public CObjRoot
+{
+protected:
+ CInputFile(const string&);
+ CInputFile(istream&);
+ istream& GetLine(string&);
+
+private:
+ CInputFile(const CInputFile&);
+ CInputFile& operator = (const CInputFile&);
+
+private:
+ auto_ptr<istream> 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 CIdAddressMap : public CInputFile, public map<CIdentity, ulonglong_t>
+{
+public:
+ CIdAddressMap(istream&);
+};
+
+CIdAddressMap::CIdAddressMap(istream& is)
+: CInputFile(is)
+{
+ CIdentity id;
+ ulonglong_t ullBase;
+
+ while (!!(m_is >> hex >> id >> ullBase))
+ if (!insert(value_type(id, ullBase)).second)
+ throw runtime_error(__FUNCTION__ ": Duplicated files");
+}
+
+class CIdPathMap : public CInputFile, public map<CIdentity, string>
+{
+public:
+ CIdPathMap(istream&);
+};
+
+CIdPathMap::CIdPathMap(istream& is)
+: CInputFile(is)
+{
+ static const char cszFileSec[] = "[files]";
+ static const char cszFfsFile[] = "EFI_FILE_NAME";
+
+ string strALine;
+
+ // Find the [files] section
+ while (!!GetLine(strALine) && strALine.compare(0, sizeof(cszFileSec) - 1, cszFileSec));
+
+ // m_is error means no FFS files listed in this INF file
+ if (!m_is)
+ return;
+
+ // Parse FFS files one by one
+ while (!!GetLine(strALine))
+ {
+ // Test if this begins a new section
+ if (strALine[0] == '[')
+ break;
+
+ // Is it a line of FFS file?
+ if (strALine.compare(0, sizeof(cszFfsFile) - 1, cszFfsFile))
+ continue;
+
+ string::size_type pos = strALine.find_first_not_of(' ', sizeof(cszFfsFile) - 1);
+ if (pos == string::npos || strALine[pos] != '=')
+ throw runtime_error(__FUNCTION__ ": Invalid FV INF format");
+ pos = strALine.find_first_not_of(' ', pos + 1);
+ if (pos == string::npos)
+ throw runtime_error(__FUNCTION__ ": Incomplete line");
+
+ strALine.erase(0, pos);
+ pos = strALine.rfind('\\');
+ if (pos == string::npos)
+ pos = 0;
+ else pos++;
+
+ CIdentity id(strALine.substr(pos, CIdentity::s_nIdStrLen));
+ if (!insert(value_type(id, strALine)).second)
+ throw runtime_error(__FUNCTION__ ": Duplicated FFS 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 << endl;
+}
+
+class CMapFile : public CInputFile, public list<CSymbol>
+{
+public:
+ CMapFile(const string&);
+
+ void SetLoadAddress(ulonglong_t);
+ friend ostream& operator << (ostream&, const CMapFile&);
+
+ 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 != 0)
+ i->m_ullRva += ullLoadAddr - m_ullLoadAddr;
+ m_ullLoadAddr = ullLoadAddr;
+}
+
+ostream& operator << (ostream& os, const CMapFile& mapFile)
+{
+ CMapFile::const_iterator i = mapFile.begin();
+ while (i != mapFile.end() && i->m_strAddress != mapFile.m_strEntryPoint)
+ i++;
+ if (i == mapFile.end())
+ throw runtime_error(
+ __FUNCTION__ ": Entry point not found for module " +
+ mapFile.m_strModuleName);
+
+ os << endl << hex
+ << mapFile.m_strModuleName << " (EP=" << i->m_ullRva
+ << ", BA=" << mapFile.m_ullLoadAddr << ')' << endl
+ << endl;
+
+ for (i = mapFile.begin(); i != mapFile.end(); i++)
+ os << " " << *i;
+
+ return os << endl;
+}
+
+class COutputFile : public CObjRoot
+{
+protected:
+ COutputFile(ostream&);
+ ostream& m_os;
+
+private:
+ COutputFile(const COutputFile&);
+ COutputFile& operator = (const COutputFile&);
+};
+
+class CFvMapFile : public CObjRoot, public map<CIdentity, CMapFile*>
+{
+public:
+ CFvMapFile(const CIdAddressMap&, const CIdPathMap&);
+ ~CFvMapFile(void);
+
+ friend ostream& operator << (ostream&, const CFvMapFile&);
+
+private:
+ void Cleanup(void);
+};
+
+CFvMapFile::CFvMapFile(const CIdAddressMap& idAddr, const CIdPathMap& idPath)
+{
+ for (CIdAddressMap::const_iterator i = idAddr.begin(); i != idAddr.end(); i++)
+ {
+ CIdPathMap::const_iterator j = idPath.find(i->first);
+ if (j == idPath.end())
+ throw runtime_error(__FUNCTION__ ": Map file not found");
+
+ try
+ {
+ pair<iterator, bool> k = insert(value_type(i->first,
+ new CMapFile(j->second.substr(0, j->second.rfind('.')) + ".map")));
+ if (!k.second)
+ throw logic_error(__FUNCTION__ ": Duplicated file found in rebase log");
+
+ k.first->second->SetLoadAddress(i->second);
+ }
+ catch (const runtime_error& e)
+ {
+ cerr << e.what() << endl;
+ }
+ }
+}
+
+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++)
+ os << *i->second;
+ 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 <LOG> <INF> <MAP>";
+
+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 != 4)
+ throw CGenFvMapUsage();
+}
+
+CGenFvMapApp::~CGenFvMapApp(void)
+{
+}
+
+int CGenFvMapApp::Run(void)
+{
+ ifstream isLog(m_ppszArgv[1]);
+ ifstream isInf(m_ppszArgv[2]);
+
+ CIdAddressMap idAddress(isLog);
+ CIdPathMap idPath(isInf);
+
+ CFvMapFile fvMap(idAddress, idPath);
+
+ ofstream osMap(m_ppszArgv[3], 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;
+ }
+}
diff --git a/Tools/CCode/Source/GenFvMap/build.xml b/Tools/CCode/Source/GenFvMap/build.xml new file mode 100644 index 0000000000..6c236bf979 --- /dev/null +++ b/Tools/CCode/Source/GenFvMap/build.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK GenTEImage Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="GenFvMap"/>
+ <property name="FileSet" value="*.cpp"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+ <compilerarg value="/EHsc" unless="GCC"/>
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>
|