diff --git a/MemoryModule.c b/MemoryModule.c index cf38388..de5e08b 100644 --- a/MemoryModule.c +++ b/MemoryModule.c @@ -22,6 +22,12 @@ * Portions created by Joachim Bauch are Copyright (C) 2004-2015 * Joachim Bauch. All Rights Reserved. * + * + * THeller: Added binary search in MemoryGetProcAddress function + * (#define USE_BINARY_SEARCH to enable it). This gives a very large + * speedup for libraries that exports lots of functions. + * + * These portions are Copyright (C) 2013 Thomas Heller. */ #include @@ -56,6 +62,15 @@ #include "MemoryModule.h" +#ifdef USE_BINARY_SEARCH + +struct NAME_TABLE { + LPCSTR name; + WORD idx; +}; + +#endif + typedef BOOL (WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved); typedef int (WINAPI *ExeEntryProc)(void); @@ -72,6 +87,10 @@ typedef struct { CustomLoadLibraryFunc loadLibrary; CustomGetProcAddressFunc getProcAddress; CustomFreeLibraryFunc freeLibrary; +#ifdef USE_BINARY_SEARCH + struct NAME_TABLE *name_table; + int numEntries; +#endif void *userdata; ExeEntryProc exeEntry; DWORD pageSize; @@ -613,6 +632,9 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size, result->getProcAddress = getProcAddress; result->freeLibrary = freeLibrary; result->userdata = userdata; +#ifdef USE_BINARY_SEARCH + result->name_table = NULL; +#endif result->pageSize = sysInfo.dwPageSize; if (!CheckSize(size, old_header->OptionalHeader.SizeOfHeaders)) { @@ -688,6 +710,18 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size, return NULL; } +#ifdef USE_BINARY_SEARCH +int _compare(const struct NAME_TABLE *p1, const struct NAME_TABLE *p2) +{ + return _stricmp(p1->name, p2->name); +} + +int _find(LPCSTR *name, const struct NAME_TABLE *p) +{ + return _stricmp(*name, p->name); +} +#endif + FARPROC MemoryGetProcAddress(HMEMORYMODULE module, LPCSTR name) { unsigned char *codeBase = ((PMEMORYMODULE)module)->codeBase; @@ -707,6 +741,45 @@ FARPROC MemoryGetProcAddress(HMEMORYMODULE module, LPCSTR name) return NULL; } +#ifdef USE_BINARY_SEARCH + + // build name table and sort it by names + if (((PMEMORYMODULE)module)->name_table == NULL) { + struct NAME_TABLE *entry = (struct NAME_TABLE*)malloc(exports->NumberOfNames + * sizeof(struct NAME_TABLE)); + ((PMEMORYMODULE)module)->name_table = entry; + if (entry == NULL) { + ((PMEMORYMODULE)module)->numEntries = 0; + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } + ((PMEMORYMODULE)module)->numEntries = exports->NumberOfNames; + + nameRef = (DWORD *) (codeBase + exports->AddressOfNames); + ordinal = (WORD *) (codeBase + exports->AddressOfNameOrdinals); + for (i=0; iNumberOfNames; i++, nameRef++, ordinal++) { + entry->name = (const char *) (codeBase + (*nameRef)); + entry->idx = *ordinal; + entry++; + } + entry = ((PMEMORYMODULE)module)->name_table; + qsort(entry, exports->NumberOfNames, sizeof(struct NAME_TABLE), _compare); + } + + if (!IS_INTRESOURCE(name)) { + // search function name in list of exported names with binary search + if (((PMEMORYMODULE)module)->name_table) { + struct NAME_TABLE *found; + found = bsearch(&name, + ((PMEMORYMODULE)module)->name_table, + exports->NumberOfNames, + sizeof(struct NAME_TABLE), _find); + if (found) + idx = found->idx; + } + } else + idx = (int)name; +#else if (HIWORD(name) == 0) { // load function by ordinal value if (LOWORD(name) < exports->Base) { @@ -728,6 +801,7 @@ FARPROC MemoryGetProcAddress(HMEMORYMODULE module, LPCSTR name) break; } } +#endif if (!found) { // exported symbol not found @@ -759,6 +833,12 @@ void MemoryFreeLibrary(HMEMORYMODULE mod) (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0); } +#ifdef USE_BINARY_SEARCH + if (module->name_table != NULL) { + free(module->name_table); + } +#endif + if (module->modules != NULL) { // free previously opened libraries int i;