wow64: Add support for multiple syscall tables.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
18c512089e
commit
0afbbabcd9
|
@ -53,7 +53,14 @@ static const char *syscall_names[] =
|
||||||
#undef SYSCALL_ENTRY
|
#undef SYSCALL_ENTRY
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned short syscall_map[1024];
|
static const SYSTEM_SERVICE_TABLE ntdll_syscall_table =
|
||||||
|
{
|
||||||
|
(ULONG_PTR *)syscall_thunks,
|
||||||
|
(ULONG_PTR *)syscall_names,
|
||||||
|
ARRAY_SIZE(syscall_thunks)
|
||||||
|
};
|
||||||
|
|
||||||
|
static SYSTEM_SERVICE_TABLE syscall_tables[4];
|
||||||
|
|
||||||
/* header for Wow64AllocTemp blocks; probably not the right layout */
|
/* header for Wow64AllocTemp blocks; probably not the right layout */
|
||||||
struct mem_header
|
struct mem_header
|
||||||
|
@ -330,50 +337,64 @@ static DWORD get_syscall_num( const BYTE *syscall )
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* init_syscall_table
|
* init_syscall_table
|
||||||
*/
|
*/
|
||||||
static void init_syscall_table( HMODULE ntdll )
|
static void init_syscall_table( HMODULE module, ULONG idx, const SYSTEM_SERVICE_TABLE *orig_table )
|
||||||
{
|
{
|
||||||
|
static syscall_thunk thunks[2048];
|
||||||
|
static ULONG start_pos;
|
||||||
|
|
||||||
const IMAGE_EXPORT_DIRECTORY *exports;
|
const IMAGE_EXPORT_DIRECTORY *exports;
|
||||||
const ULONG *functions, *names;
|
const ULONG *functions, *names;
|
||||||
const USHORT *ordinals;
|
const USHORT *ordinals;
|
||||||
ULONG id, exp_size, exp_pos, wrap_pos;
|
ULONG id, exp_size, exp_pos, wrap_pos, max_pos = 0;
|
||||||
|
const char **syscall_names = (const char **)orig_table->CounterTable;
|
||||||
|
|
||||||
args_alignment = (current_machine == IMAGE_FILE_MACHINE_I386) ? sizeof(ULONG) : sizeof(ULONG64);
|
exports = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size );
|
||||||
|
ordinals = get_rva( module, exports->AddressOfNameOrdinals );
|
||||||
exports = RtlImageDirectoryEntryToData( ntdll, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size );
|
functions = get_rva( module, exports->AddressOfFunctions );
|
||||||
ordinals = get_rva( ntdll, exports->AddressOfNameOrdinals );
|
names = get_rva( module, exports->AddressOfNames );
|
||||||
functions = get_rva( ntdll, exports->AddressOfFunctions );
|
|
||||||
names = get_rva( ntdll, exports->AddressOfNames );
|
|
||||||
|
|
||||||
for (exp_pos = wrap_pos = 0; exp_pos < exports->NumberOfNames; exp_pos++)
|
for (exp_pos = wrap_pos = 0; exp_pos < exports->NumberOfNames; exp_pos++)
|
||||||
{
|
{
|
||||||
char *name = get_rva( ntdll, names[exp_pos] );
|
char *name = get_rva( module, names[exp_pos] );
|
||||||
int res = -1;
|
int res = -1;
|
||||||
|
|
||||||
if (strncmp( name, "Nt", 2 ) && strncmp( name, "wine", 4 ) && strncmp( name, "__wine", 6 ))
|
if (strncmp( name, "Nt", 2 ) && strncmp( name, "wine", 4 ) && strncmp( name, "__wine", 6 ))
|
||||||
continue; /* not a syscall */
|
continue; /* not a syscall */
|
||||||
|
|
||||||
if ((id = get_syscall_num( get_rva( ntdll, functions[ordinals[exp_pos]] ))) == ~0u)
|
if ((id = get_syscall_num( get_rva( module, functions[ordinals[exp_pos]] ))) == ~0u)
|
||||||
continue; /* not a syscall */
|
continue; /* not a syscall */
|
||||||
|
|
||||||
if (wrap_pos < ARRAY_SIZE(syscall_names))
|
if (wrap_pos < orig_table->ServiceLimit) res = strcmp( name, syscall_names[wrap_pos] );
|
||||||
res = strcmp( name, syscall_names[wrap_pos] );
|
|
||||||
|
|
||||||
if (!res) /* got a match */
|
if (!res) /* got a match */
|
||||||
{
|
{
|
||||||
if (id < ARRAY_SIZE(syscall_map)) syscall_map[id] = wrap_pos++;
|
ULONG table_idx = (id >> 12) & 3, table_pos = id & 0xfff;
|
||||||
else ERR( "invalid syscall id %04x for %s\n", id, name );
|
if (table_idx == idx)
|
||||||
|
{
|
||||||
|
if (start_pos + table_pos < ARRAY_SIZE(thunks))
|
||||||
|
{
|
||||||
|
thunks[start_pos + table_pos] = (syscall_thunk)orig_table->ServiceTable[wrap_pos++];
|
||||||
|
max_pos = max( table_pos, max_pos );
|
||||||
|
}
|
||||||
|
else ERR( "invalid syscall id %04x for %s\n", id, name );
|
||||||
|
}
|
||||||
|
else ERR( "wrong syscall table id %04x for %s\n", id, name );
|
||||||
}
|
}
|
||||||
else if (res > 0)
|
else if (res > 0)
|
||||||
{
|
{
|
||||||
FIXME( "no ntdll export for syscall %s\n", syscall_names[wrap_pos] );
|
FIXME( "no export for syscall %s\n", syscall_names[wrap_pos] );
|
||||||
wrap_pos++;
|
wrap_pos++;
|
||||||
exp_pos--; /* try again */
|
exp_pos--; /* try again */
|
||||||
}
|
}
|
||||||
else FIXME( "missing wrapper for syscall %04x %s\n", id, name );
|
else FIXME( "missing wrapper for syscall %04x %s\n", id, name );
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( ; wrap_pos < ARRAY_SIZE(syscall_thunks); wrap_pos++)
|
for ( ; wrap_pos < orig_table->ServiceLimit; wrap_pos++)
|
||||||
FIXME( "no ntdll export for syscall %s\n", syscall_names[wrap_pos] );
|
FIXME( "no export for syscall %s\n", syscall_names[wrap_pos] );
|
||||||
|
|
||||||
|
syscall_tables[idx].ServiceTable = (ULONG_PTR *)(thunks + start_pos);
|
||||||
|
syscall_tables[idx].ServiceLimit = max_pos + 1;
|
||||||
|
start_pos += max_pos + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -425,6 +446,7 @@ static DWORD WINAPI process_init( RTL_RUN_ONCE *once, void *param, void **contex
|
||||||
|
|
||||||
RtlWow64GetProcessMachines( GetCurrentProcess(), ¤t_machine, &native_machine );
|
RtlWow64GetProcessMachines( GetCurrentProcess(), ¤t_machine, &native_machine );
|
||||||
if (!current_machine) current_machine = native_machine;
|
if (!current_machine) current_machine = native_machine;
|
||||||
|
args_alignment = (current_machine == IMAGE_FILE_MACHINE_I386) ? sizeof(ULONG) : sizeof(ULONG64);
|
||||||
|
|
||||||
#define GET_PTR(name) p ## name = RtlFindExportedRoutineByName( module, #name )
|
#define GET_PTR(name) p ## name = RtlFindExportedRoutineByName( module, #name )
|
||||||
|
|
||||||
|
@ -435,7 +457,7 @@ static DWORD WINAPI process_init( RTL_RUN_ONCE *once, void *param, void **contex
|
||||||
module = (HMODULE)(ULONG_PTR)pLdrSystemDllInitBlock->ntdll_handle;
|
module = (HMODULE)(ULONG_PTR)pLdrSystemDllInitBlock->ntdll_handle;
|
||||||
GET_PTR( Wow64Transition );
|
GET_PTR( Wow64Transition );
|
||||||
GET_PTR( __wine_syscall_dispatcher );
|
GET_PTR( __wine_syscall_dispatcher );
|
||||||
init_syscall_table( module );
|
init_syscall_table( module, 0, &ntdll_syscall_table );
|
||||||
|
|
||||||
module = load_cpu_dll();
|
module = load_cpu_dll();
|
||||||
GET_PTR( BTCpuGetBopCode );
|
GET_PTR( BTCpuGetBopCode );
|
||||||
|
@ -540,15 +562,17 @@ static LONG CALLBACK syscall_filter( EXCEPTION_POINTERS *ptrs )
|
||||||
NTSTATUS WINAPI Wow64SystemServiceEx( UINT num, UINT *args )
|
NTSTATUS WINAPI Wow64SystemServiceEx( UINT num, UINT *args )
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
UINT id = num & 0xfff;
|
||||||
|
const SYSTEM_SERVICE_TABLE *table = &syscall_tables[(num >> 12) & 3];
|
||||||
|
|
||||||
if (num >= ARRAY_SIZE( syscall_map ) || !syscall_map[num])
|
if (id >= table->ServiceLimit || !table->ServiceTable[id])
|
||||||
{
|
{
|
||||||
ERR( "unsupported syscall %04x\n", num );
|
ERR( "unsupported syscall %04x\n", num );
|
||||||
return STATUS_INVALID_SYSTEM_SERVICE;
|
return STATUS_INVALID_SYSTEM_SERVICE;
|
||||||
}
|
}
|
||||||
__TRY
|
__TRY
|
||||||
{
|
{
|
||||||
syscall_thunk thunk = syscall_thunks[syscall_map[num]];
|
syscall_thunk thunk = (syscall_thunk)table->ServiceTable[id];
|
||||||
status = thunk( args );
|
status = thunk( args );
|
||||||
}
|
}
|
||||||
__EXCEPT( syscall_filter )
|
__EXCEPT( syscall_filter )
|
||||||
|
|
Loading…
Reference in New Issue