mirror of
https://github.com/reactos/wine.git
synced 2024-11-26 05:00:30 +00:00
PE_FindExportedFunction: use a binary search for function names.
This commit is contained in:
parent
8a3edf9b5a
commit
bbeaeebb2d
@ -71,7 +71,7 @@ DECLARE_DEBUG_CHANNEL(segment)
|
|||||||
|
|
||||||
|
|
||||||
/* convert PE image VirtualAddress to Real Address */
|
/* convert PE image VirtualAddress to Real Address */
|
||||||
#define RVA(x) ((unsigned int)load_addr+(unsigned int)(x))
|
#define RVA(x) ((void *)((char *)load_addr+(unsigned int)(x)))
|
||||||
|
|
||||||
#define AdjustPtr(ptr,delta) ((char *)(ptr) + (delta))
|
#define AdjustPtr(ptr,delta) ((char *)(ptr) + (delta))
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ void dump_exports( HMODULE hModule )
|
|||||||
if (!*function) continue; /* No such function */
|
if (!*function) continue; /* No such function */
|
||||||
if (TRACE_ON(win32))
|
if (TRACE_ON(win32))
|
||||||
{
|
{
|
||||||
DPRINTF( "%4ld %08lx %08x", i + pe_exports->Base, *function, RVA(*function) );
|
DPRINTF( "%4ld %08lx %p", i + pe_exports->Base, *function, RVA(*function) );
|
||||||
/* Check if we have a name for it */
|
/* Check if we have a name for it */
|
||||||
for (j = 0; j < pe_exports->NumberOfNames; j++)
|
for (j = 0; j < pe_exports->NumberOfNames; j++)
|
||||||
if (ordinal[j] == i)
|
if (ordinal[j] == i)
|
||||||
@ -133,10 +133,10 @@ FARPROC PE_FindExportedFunction(
|
|||||||
LPCSTR funcName, /* [in] function name */
|
LPCSTR funcName, /* [in] function name */
|
||||||
BOOL snoop )
|
BOOL snoop )
|
||||||
{
|
{
|
||||||
u_short * ordinal;
|
u_short * ordinals;
|
||||||
u_long * function;
|
u_long * function;
|
||||||
u_char ** name, *ename;
|
u_char ** name, *ename = NULL;
|
||||||
int i;
|
int i, ordinal;
|
||||||
PE_MODREF *pem = &(wm->binfmt.pe);
|
PE_MODREF *pem = &(wm->binfmt.pe);
|
||||||
IMAGE_EXPORT_DIRECTORY *exports = pem->pe_export;
|
IMAGE_EXPORT_DIRECTORY *exports = pem->pe_export;
|
||||||
unsigned int load_addr = wm->module;
|
unsigned int load_addr = wm->module;
|
||||||
@ -155,7 +155,7 @@ FARPROC PE_FindExportedFunction(
|
|||||||
WARN("Module %08x(%s)/MODREF %p doesn't have a exports table.\n",wm->module,wm->modname,pem);
|
WARN("Module %08x(%s)/MODREF %p doesn't have a exports table.\n",wm->module,wm->modname,pem);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ordinal = (u_short*) RVA(exports->AddressOfNameOrdinals);
|
ordinals= (u_short*) RVA(exports->AddressOfNameOrdinals);
|
||||||
function= (u_long*) RVA(exports->AddressOfFunctions);
|
function= (u_long*) RVA(exports->AddressOfFunctions);
|
||||||
name = (u_char **) RVA(exports->AddressOfNames);
|
name = (u_char **) RVA(exports->AddressOfNames);
|
||||||
forward = NULL;
|
forward = NULL;
|
||||||
@ -164,56 +164,77 @@ FARPROC PE_FindExportedFunction(
|
|||||||
rva_end = rva_start + PE_HEADER(wm->module)->OptionalHeader
|
rva_end = rva_start + PE_HEADER(wm->module)->OptionalHeader
|
||||||
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
|
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
|
||||||
|
|
||||||
if (HIWORD(funcName)) {
|
if (HIWORD(funcName))
|
||||||
for(i=0; i<exports->NumberOfNames; i++) {
|
{
|
||||||
ename=(char*)RVA(*name);
|
/* first try a binary search */
|
||||||
if(!strcmp(ename,funcName))
|
int min = 0, max = exports->NumberOfNames - 1;
|
||||||
{
|
while (min <= max)
|
||||||
addr = function[*ordinal];
|
{
|
||||||
if (!addr) return NULL;
|
int res, pos = (min + max) / 2;
|
||||||
if ((addr < rva_start) || (addr >= rva_end))
|
ename = RVA(name[pos]);
|
||||||
return snoop? SNOOP_GetProcAddress(wm->module,ename,*ordinal,(FARPROC)RVA(addr))
|
if (!(res = strcmp( ename, funcName )))
|
||||||
: (FARPROC)RVA(addr);
|
{
|
||||||
forward = (char *)RVA(addr);
|
ordinal = ordinals[pos];
|
||||||
break;
|
goto found;
|
||||||
}
|
}
|
||||||
ordinal++;
|
if (res > 0) max = pos - 1;
|
||||||
name++;
|
else min = pos + 1;
|
||||||
}
|
}
|
||||||
} else {
|
/* now try a linear search in case the names aren't sorted properly */
|
||||||
int i;
|
for (i = 0; i < exports->NumberOfNames; i++)
|
||||||
if (LOWORD(funcName)-exports->Base > exports->NumberOfFunctions) {
|
{
|
||||||
TRACE(" ordinal %d out of range!\n", LOWORD(funcName));
|
ename = RVA(name[i]);
|
||||||
return NULL;
|
if (!strcmp( ename, funcName ))
|
||||||
}
|
{
|
||||||
addr = function[(int)funcName-exports->Base];
|
ERR( "%s.%s required a linear search\n", wm->modname, funcName );
|
||||||
if (!addr) return NULL;
|
ordinal = ordinals[i];
|
||||||
ename = "";
|
goto found;
|
||||||
if (name) {
|
}
|
||||||
for (i=0;i<exports->NumberOfNames;i++) {
|
}
|
||||||
ename = (char*)RVA(*name);
|
return NULL;
|
||||||
if (*ordinal == LOWORD(funcName)-exports->Base)
|
|
||||||
break;
|
|
||||||
ordinal++;
|
|
||||||
name++;
|
|
||||||
}
|
|
||||||
if (i==exports->NumberOfNames)
|
|
||||||
ename = "";
|
|
||||||
}
|
|
||||||
if ((addr < rva_start) || (addr >= rva_end))
|
|
||||||
return snoop? SNOOP_GetProcAddress(wm->module,ename,(DWORD)funcName-exports->Base,(FARPROC)RVA(addr))
|
|
||||||
: (FARPROC)RVA(addr);
|
|
||||||
forward = (char *)RVA(addr);
|
|
||||||
}
|
}
|
||||||
if (forward)
|
else /* find by ordinal */
|
||||||
|
{
|
||||||
|
ordinal = LOWORD(funcName) - exports->Base;
|
||||||
|
if (snoop && name) /* need to find a name for it */
|
||||||
|
{
|
||||||
|
for (i = 0; i < exports->NumberOfNames; i++)
|
||||||
|
if (ordinals[i] == ordinal)
|
||||||
|
{
|
||||||
|
ename = RVA(name[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
found:
|
||||||
|
if (ordinal >= exports->NumberOfFunctions)
|
||||||
|
{
|
||||||
|
TRACE(" ordinal %ld out of range!\n", ordinal + exports->Base );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
addr = function[ordinal];
|
||||||
|
if (!addr) return NULL;
|
||||||
|
if ((addr < rva_start) || (addr >= rva_end))
|
||||||
|
{
|
||||||
|
FARPROC proc = RVA(addr);
|
||||||
|
if (snoop)
|
||||||
|
{
|
||||||
|
if (!ename) ename = "@";
|
||||||
|
proc = SNOOP_GetProcAddress(wm->module,ename,ordinal,proc);
|
||||||
|
}
|
||||||
|
return proc;
|
||||||
|
}
|
||||||
|
else /* forward entry point */
|
||||||
{
|
{
|
||||||
WINE_MODREF *wm;
|
WINE_MODREF *wm;
|
||||||
|
char *forward = RVA(addr);
|
||||||
char module[256];
|
char module[256];
|
||||||
char *end = strchr(forward, '.');
|
char *end = strchr(forward, '.');
|
||||||
|
|
||||||
if (!end) return NULL;
|
if (!end) return NULL;
|
||||||
assert(end-forward<256);
|
if (end - forward >= sizeof(module)) return NULL;
|
||||||
strncpy(module, forward, (end - forward));
|
memcpy( module, forward, end - forward );
|
||||||
module[end-forward] = 0;
|
module[end-forward] = 0;
|
||||||
if (!(wm = MODULE_FindModule( module )))
|
if (!(wm = MODULE_FindModule( module )))
|
||||||
{
|
{
|
||||||
@ -222,7 +243,6 @@ FARPROC PE_FindExportedFunction(
|
|||||||
}
|
}
|
||||||
return MODULE_GetProcAddress( wm->module, end + 1, snoop );
|
return MODULE_GetProcAddress( wm->module, end + 1, snoop );
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD fixup_imports( WINE_MODREF *wm )
|
DWORD fixup_imports( WINE_MODREF *wm )
|
||||||
|
Loading…
Reference in New Issue
Block a user