From 013cd1e5f754c12a7edab14495ea533beab3840b Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Tue, 20 Mar 2018 23:33:12 +0100 Subject: [PATCH] DBG: dont copy MODINFO and MODIMPORT/MODEXPORT structures --- src/dbg/module.cpp | 102 +++++++++++++++++++-------------------------- src/dbg/module.h | 15 ++++++- 2 files changed, 57 insertions(+), 60 deletions(-) diff --git a/src/dbg/module.cpp b/src/dbg/module.cpp index a51647ca..277b7407 100644 --- a/src/dbg/module.cpp +++ b/src/dbg/module.cpp @@ -10,8 +10,9 @@ #include #include "console.h" #include "debugger.h" +#include -std::map modinfo; +std::map, RangeCompare> modinfo; std::unordered_map hashNameMap; static void ReadExportDirectory(MODINFO & Info, ULONG_PTR FileMapVA) @@ -53,7 +54,8 @@ static void ReadExportDirectory(MODINFO & Info, ULONG_PTR FileMapVA) for(DWORD i = 0; i < exportDir->NumberOfFunctions; i++) { - MODEXPORT entry; + Info.exports.emplace_back(); + auto & entry = Info.exports.back(); entry.ordinal = i + exportDir->Base; entry.rva = addressOfFunctions[i]; if(entry.forwarded = entry.rva >= exportDirRva && entry.rva < exportDirRva + exportDirSize) @@ -62,7 +64,6 @@ static void ReadExportDirectory(MODINFO & Info, ULONG_PTR FileMapVA) if(forwardNameOffset) // TODO: what does the Windows loader do if this fails? entry.forwardName = String((const char*)(forwardNameOffset + FileMapVA)); } - Info.exports.push_back(entry); } for(DWORD i = 0; i < exportDir->NumberOfNames; i++) @@ -121,8 +122,7 @@ static void ReadImportDirectory(MODINFO & Info, ULONG_PTR FileMapVA) if(!moduleNameOffset) // TODO: what does the Windows loader do if this fails? continue; - auto moduleName = String((const char*)(moduleNameOffset + FileMapVA)); - Info.importModules.push_back(moduleName); + Info.importModules.emplace_back((const char*)(moduleNameOffset + FileMapVA)); auto firstThunkOffset = rva2offset(importDescriptor->FirstThunk); if(!firstThunkOffset) // TODO: what does the Windows loader do if this fails? @@ -131,7 +131,8 @@ static void ReadImportDirectory(MODINFO & Info, ULONG_PTR FileMapVA) auto thunkData = PIMAGE_THUNK_DATA(firstThunkOffset + FileMapVA); for(auto iatRva = importDescriptor->FirstThunk; thunkData->u1.AddressOfData; thunkData++, iatRva += sizeof(duint)) { - MODIMPORT entry; + Info.imports.emplace_back(); + auto & entry = Info.imports.back(); entry.iatRva = iatRva; entry.moduleIndex = moduleIndex; if((thunkData->u1.Ordinal & IMAGE_ORDINAL_FLAG) == IMAGE_ORDINAL_FLAG) @@ -148,7 +149,6 @@ static void ReadImportDirectory(MODINFO & Info, ULONG_PTR FileMapVA) entry.name = String((const char*)importByName->Name); entry.ordinal = -1; } - Info.imports.push_back(entry); } } @@ -476,6 +476,7 @@ void GetModuleInfo(MODINFO & Info, ULONG_PTR FileMapVA) ReadExportDirectory(Info, FileMapVA); ReadImportDirectory(Info, FileMapVA); + dprintf("[%s%s] read %d imports and %d exports\n", Info.name, Info.extension, Info.imports.size(), Info.exports.size()); ReadTlsCallbacks(Info, FileMapVA); ReadBaseRelocationTable(Info, FileMapVA); ReadDebugDirectory(Info, FileMapVA); @@ -487,8 +488,10 @@ bool ModLoad(duint Base, duint Size, const char* FullPath) if(!Base || !Size || !FullPath) return false; + auto infoPtr = std::make_unique(); + auto & info = *infoPtr; + // Copy the module path in the struct - MODINFO info; strcpy_s(info.path, FullPath); // Break the module path into a directory and file name @@ -589,7 +592,7 @@ bool ModLoad(duint Base, duint Size, const char* FullPath) // Add module to list EXCLUSIVE_ACQUIRE(LockModules); - modinfo.insert(std::make_pair(Range(Base, Base + Size - 1), info)); + modinfo.insert(std::make_pair(Range(Base, Base + Size - 1), std::move(infoPtr))); EXCLUSIVE_RELEASE(); // Put labels for virtual module exports @@ -618,14 +621,6 @@ bool ModUnload(duint Base) if(found == modinfo.end()) return false; - // Unload the mapped file from memory - auto & info = found->second; - if(info.fileMapVA) - StaticFileUnloadW(StringUtils::Utf8ToUtf16(info.path).c_str(), false, info.fileHandle, info.loadedSize, info.fileMap, info.fileMapVA); - - // Unload symbols from the module - info.unloadSymbols(); - // Remove it from the list modinfo.erase(found); EXCLUSIVE_RELEASE(); @@ -640,26 +635,6 @@ void ModClear() { // Clean up all the modules EXCLUSIVE_ACQUIRE(LockModules); - - for(const auto & mod : modinfo) - { - // Unload the mapped file from memory - const auto & info = mod.second; - if(info.fileMapVA) - StaticFileUnloadW(StringUtils::Utf8ToUtf16(info.path).c_str(), false, info.fileHandle, info.loadedSize, info.fileMap, info.fileMapVA); - - if(info.symbols != nullptr && - info.symbols != &EmptySymbolSource) - { - if(info.symbols->isLoading()) - { - info.symbols->cancelLoading(); - } - - delete info.symbols; - } - } - modinfo.clear(); } @@ -684,7 +659,7 @@ MODINFO* ModInfoFromAddr(duint Address) if(found == modinfo.end()) return nullptr; - return &found->second; + return found->second.get(); } bool ModNameFromAddr(duint Address, char* Name, bool Extension) @@ -787,16 +762,16 @@ duint ModBaseFromName(const char* Module) { const auto & currentModule = i.second; char currentModuleName[MAX_MODULE_SIZE]; - strcpy_s(currentModuleName, currentModule.name); - strcat_s(currentModuleName, currentModule.extension); + strcpy_s(currentModuleName, currentModule->name); + strcat_s(currentModuleName, currentModule->extension); // Compare with extension (perfect match) if(!_stricmp(currentModuleName, Module)) - return currentModule.base; + return currentModule->base; // Compare without extension, possible candidate (thanks to chessgod101 for finding this) - if(!candidate && !_stricmp(currentModule.name, Module)) - candidate = currentModule.base; + if(!candidate && !_stricmp(currentModule->name, Module)) + candidate = currentModule->base; } return candidate; @@ -867,20 +842,11 @@ int ModPathFromName(const char* Module, char* Path, int Size) return ModPathFromAddr(ModBaseFromName(Module), Path, Size); } -void ModGetList(std::vector & list) -{ - SHARED_ACQUIRE(LockModules); - list.clear(); - list.reserve(modinfo.size()); - for(const auto & mod : modinfo) - list.push_back(mod.second); -} - void ModEnum(const std::function & cbEnum) { SHARED_ACQUIRE(LockModules); for(const auto & mod : modinfo) - cbEnum(mod.second); + cbEnum(*mod.second); } int ModGetParty(duint Address) @@ -1042,12 +1008,32 @@ void MODINFO::unloadSymbols() { if(symbols != nullptr && symbols != &EmptySymbolSource) { - if(symbols->isLoading()) - { - symbols->cancelLoading(); - } - delete symbols; symbols = &EmptySymbolSource; } } + +void MODINFO::unmapFile() +{ + // Unload the mapped file from memory + if(fileMapVA) + StaticFileUnloadW(StringUtils::Utf8ToUtf16(path).c_str(), false, fileHandle, loadedSize, fileMap, fileMapVA); +} + +void MODIMPORT::convertToGuiSymbol(duint base, SYMBOLINFO* info) const +{ + info->addr = base + iatRva; + info->type = sym_import; + info->decoratedSymbol = (char*)name.c_str(); + info->undecoratedSymbol = ""; + info->freeDecorated = info->freeUndecorated = false; +} + +void MODEXPORT::convertToGuiSymbol(duint base, SYMBOLINFO* info) const +{ + info->addr = base + rva; + info->type = sym_export; + info->decoratedSymbol = (char*)name.c_str(); + info->undecoratedSymbol = ""; + info->freeDecorated = info->freeUndecorated = false; +} diff --git a/src/dbg/module.h b/src/dbg/module.h index 2f16df9a..1c21fec8 100644 --- a/src/dbg/module.h +++ b/src/dbg/module.h @@ -37,21 +37,25 @@ struct PdbValidationData } }; -struct MODEXPORT +struct MODEXPORT : SymbolInfoGui { DWORD ordinal = 0; DWORD rva = 0; bool forwarded = false; String forwardName; String name; + + virtual void convertToGuiSymbol(duint base, SYMBOLINFO* info) const override; }; -struct MODIMPORT +struct MODIMPORT : SymbolInfoGui { size_t moduleIndex; //index in MODINFO.importModules DWORD iatRva; duint ordinal; //equal to -1 if imported by name String name; + + virtual void convertToGuiSymbol(duint base, SYMBOLINFO* info) const override; }; struct MODINFO @@ -98,8 +102,15 @@ struct MODINFO memset(path, 0, sizeof(path)); } + ~MODINFO() + { + unmapFile(); + unloadSymbols(); + } + bool loadSymbols(); void unloadSymbols(); + void unmapFile(); }; bool ModLoad(duint Base, duint Size, const char* FullPath);