Skip to content

Implement Binary Search from py2exe. #74

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions MemoryModule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <windows.h>
Expand Down Expand Up @@ -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);

Expand All @@ -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;
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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;
Expand All @@ -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; i<exports->NumberOfNames; 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) {
Expand All @@ -728,6 +801,7 @@ FARPROC MemoryGetProcAddress(HMEMORYMODULE module, LPCSTR name)
break;
}
}
#endif

if (!found) {
// exported symbol not found
Expand Down Expand Up @@ -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;
Expand Down