Skip to content

Commit

Permalink
.map ファイルがあればそれを読むことでリンク高速化
Browse files Browse the repository at this point in the history
  • Loading branch information
i-saint committed Sep 1, 2013
1 parent 5556243 commit 104802d
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 16 deletions.
11 changes: 6 additions & 5 deletions DynamicPatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,12 @@ dpAPI bool dpFinalize()


dpAPI size_t dpLoad(const char *path) { return dpGetCurrentContext()->load(path); }
dpAPI bool dpLoadObj(const char *path) { return dpGetCurrentContext()->loadObj(path)!=nullptr; }
dpAPI bool dpLoadLib(const char *path) { return dpGetCurrentContext()->loadLib(path)!=nullptr; }
dpAPI bool dpLoadDll(const char *path) { return dpGetCurrentContext()->loadDll(path)!=nullptr; }
dpAPI bool dpUnload(const char *path) { return dpGetCurrentContext()->unload(path); };
dpAPI bool dpLink() { return dpGetCurrentContext()->link(); }
dpAPI bool dpLoadObj(const char *path) { return dpGetCurrentContext()->getLoader()->loadObj(path)!=nullptr; }
dpAPI bool dpLoadLib(const char *path) { return dpGetCurrentContext()->getLoader()->loadLib(path)!=nullptr; }
dpAPI bool dpLoadDll(const char *path) { return dpGetCurrentContext()->getLoader()->loadDll(path)!=nullptr; }
dpAPI size_t dpLoadMapFiles() { return dpGetCurrentContext()->getLoader()->loadMapFiles(); };
dpAPI bool dpUnload(const char *path) { return dpGetCurrentContext()->getLoader()->unload(path); };
dpAPI bool dpLink() { return dpGetCurrentContext()->getLoader()->link(); }

dpAPI size_t dpPatchByFile(const char *filename, const char *filter_regex)
{
Expand Down
2 changes: 2 additions & 0 deletions DynamicPatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ dpAPI size_t dpLoad(const char *path); // path to .obj .lib .dll .exe. accepts w
dpAPI bool dpLoadObj(const char *path); // load as .obj regardless file extension
dpAPI bool dpLoadLib(const char *path); // load as .lib regardless file extension
dpAPI bool dpLoadDll(const char *path); // load as .dll regardless file extension
dpAPI size_t dpLoadMapFiles(); // load symbol info from .map files.
dpAPI bool dpUnload(const char *path);
dpAPI bool dpLink(); // must be called after dpLoad*()s & dpUnload()s. onload handler is called in this.

Expand Down Expand Up @@ -177,6 +178,7 @@ dpAPI const char* dpGetVCVarsPath();
#define dpLoadObj(...)
#define dpLoadLib(...)
#define dpLoadDll(...)
#define dpLoadMapFiles(...)
#define dpUnload(...)
#define dpLink(...)
#define dpPatchByFile(...)
Expand Down
3 changes: 3 additions & 0 deletions Test/Test_UseLibDll.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>false</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<GenerateMapFile>true</GenerateMapFile>
</Link>
<PostBuildEvent>
<Command>
Expand All @@ -134,6 +135,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>false</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<GenerateMapFile>true</GenerateMapFile>
</Link>
<PostBuildEvent>
<Command>
Expand Down Expand Up @@ -174,6 +176,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>false</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<GenerateMapFile>true</GenerateMapFile>
</Link>
<PostBuildEvent>
<Command>
Expand Down
5 changes: 0 additions & 5 deletions dpContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@ size_t dpContext::load(const char *path)
});
return ret;
}
dpObjFile* dpContext::loadObj(const char *path) { return m_loader->loadObj(path); }
dpLibFile* dpContext::loadLib(const char *path) { return m_loader->loadLib(path); }
dpDllFile* dpContext::loadDll(const char *path) { return m_loader->loadDll(path); }
bool dpContext::unload( const char *path ) { return m_loader->unload(path); }
bool dpContext::link() { return m_loader->link(); }

size_t dpContext::patchByFile(const char *filename, const char *filter_regex)
{
Expand Down
12 changes: 6 additions & 6 deletions dpInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -416,11 +416,16 @@ class dpLoader
void addForceHostSymbolPattern(const char *pattern);
bool doesForceHostSymbol(const char *name);

bool loadMapFile(const char *path, void *imagebase);
size_t loadMapFiles();

private:
typedef std::vector<dpBinary*> binary_cont;
typedef std::vector<dpBinary*> binary_cont;
typedef std::vector<std::regex> pattern_cont;
typedef std::set<std::string> string_set;

dpContext *m_context;
string_set m_mapfiles_read;
pattern_cont m_force_host_symbol_patterns;
binary_cont m_binaries;
binary_cont m_onload_queue;
Expand Down Expand Up @@ -527,11 +532,6 @@ class dpContext
dpLoader* getLoader();

size_t load(const char *path);
dpObjFile* loadObj(const char *path);
dpLibFile* loadLib(const char *path);
dpDllFile* loadDll(const char *path);
bool unload(const char *path);
bool link();

size_t patchByFile(const char *filename, const char *filter_regex);
size_t patchByFile(const char *filename, const std::function<bool (const dpSymbolS&)> &condition);
Expand Down
75 changes: 75 additions & 0 deletions dpLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include "DynamicPatcher.h"
#include "dpInternal.h"
#include <psapi.h>
#pragma comment(lib, "psapi.lib")


static const int g_host_symbol_flags = dpE_Code|dpE_Read|dpE_Execute|dpE_HostSymbol|dpE_NameNeedsDelete;
Expand Down Expand Up @@ -53,6 +55,7 @@ dpSymbol* dpLoader::findHostSymbolByAddress(void *addr)
dpLoader::dpLoader(dpContext *ctx)
: m_context(ctx)
{
loadMapFiles();
}

dpLoader::~dpLoader()
Expand All @@ -62,6 +65,78 @@ dpLoader::~dpLoader()
m_hostsymbols.clear();
}

bool dpLoader::loadMapFile(const char *path, void *imagebase)
{
if(m_mapfiles_read.find(path)!=m_mapfiles_read.end()) {
return true;
}

FILE *file = fopen(path, "rb");
if(!file) { return false; }

char line[1024*5]; // VisualC++2013 で symbol 名は最大 4KB

// C99 から size_t 用の scanf フォーマット %zx が加わったらしいが、VisualC++ は未対応な様子
#ifdef _WIN64
# define ZX "%llx"
#else
# define ZX "%x"
#endif

size_t preferred_addr = 0;
size_t gap = 0;
{
while(fgets(line, _countof(line), file)) {
if(sscanf(line, " Preferred load address is " ZX, &preferred_addr)==1) {
gap = (size_t)imagebase - preferred_addr;
break;
}
}
}
{
std::regex reg("^ [0-9a-f]{4}:[0-9a-f]{8} ([^ ]+) +([0-9a-f]+) ");
std::cmatch m;
while(fgets(line, _countof(line), file)) {
if(std::regex_search(line, m, reg)) {
char *name_src = line+m.position(1);
size_t rva_plus_base = 0;
sscanf(line+m.position(2), ZX, &rva_plus_base);
if(rva_plus_base <= preferred_addr) { continue; }

void *addr = (void*)(rva_plus_base + gap);
char *name = new char[m.length(1)+1];
strncpy(name, name_src, m.length(1));
name[m.length(1)] = '\0';
m_hostsymbols.addSymbol(newSymbol(name, addr, g_host_symbol_flags, 0, nullptr));
}
}
}
m_hostsymbols.sort();
fclose(file);
m_mapfiles_read.insert(path);
return true;
}

size_t dpLoader::loadMapFiles()
{
std::vector<HMODULE> modules;
DWORD num_modules;
::EnumProcessModules(::GetCurrentProcess(), nullptr, 0, &num_modules);
modules.resize(num_modules/sizeof(HMODULE));
::EnumProcessModules(::GetCurrentProcess(), &modules[0], num_modules, &num_modules);
size_t ret = 0;
for(size_t i=0; i<modules.size(); ++i) {
char path[MAX_PATH];
HMODULE mod = modules[i];
::GetModuleFileNameA(mod, path, _countof(path));
std::string mappath = std::regex_replace(std::string(path), std::regex("\\.[^.]+$"), std::string(".map"));
if(loadMapFile(mappath.c_str(), mod)) {
++ret;
}
}
return ret;
}

void dpLoader::unloadImpl( dpBinary *bin )
{
m_binaries.erase(std::find(m_binaries.begin(), m_binaries.end(), bin));
Expand Down

0 comments on commit 104802d

Please sign in to comment.