Alexandre Julliard : wow64: Add support for setting up the syscall table.
Alexandre Julliard
julliard at winehq.org
Thu Jul 22 16:28:19 CDT 2021
Module: wine
Branch: master
Commit: 1b63875c66c79a337f65c6c66882c8a55430d2c2
URL: https://source.winehq.org/git/wine.git/?a=commit;h=1b63875c66c79a337f65c6c66882c8a55430d2c2
Author: Alexandre Julliard <julliard at winehq.org>
Date: Thu Jul 22 13:42:56 2021 +0200
wow64: Add support for setting up the syscall table.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/wow64/syscall.c | 126 ++++++++++++++++++++++++++++++++++++++++++++-
dlls/wow64/wow64_private.h | 5 ++
2 files changed, 129 insertions(+), 2 deletions(-)
diff --git a/dlls/wow64/syscall.c b/dlls/wow64/syscall.c
index 504580e8717..12e13b17574 100644
--- a/dlls/wow64/syscall.c
+++ b/dlls/wow64/syscall.c
@@ -35,6 +35,22 @@ WINE_DEFAULT_DEBUG_CHANNEL(wow);
USHORT native_machine = 0;
USHORT current_machine = 0;
+typedef NTSTATUS (WINAPI *syscall_thunk)( UINT *args );
+
+static const syscall_thunk syscall_thunks[] =
+{
+ NULL
+};
+
+static const char *syscall_names[] =
+{
+ ""
+};
+
+static unsigned short syscall_map[1024];
+
+static SYSTEM_DLL_INIT_BLOCK *pLdrSystemDllInitBlock;
+
void *dummy = RtlUnwind;
BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, void *reserved )
@@ -58,6 +74,82 @@ void __cdecl __wine_spec_unimplemented_stub( const char *module, const char *fun
}
+/**********************************************************************
+ * get_syscall_num
+ */
+static DWORD get_syscall_num( const BYTE *syscall )
+{
+ DWORD id = ~0u;
+
+ if (!syscall) return id;
+ switch (current_machine)
+ {
+ case IMAGE_FILE_MACHINE_I386:
+ if (syscall[0] == 0xb8 && syscall[5] == 0xba && syscall[10] == 0xff && syscall[11] == 0xd2)
+ id = *(DWORD *)(syscall + 1);
+ break;
+
+ case IMAGE_FILE_MACHINE_ARM:
+ if (*(WORD *)syscall == 0xb40f)
+ {
+ DWORD inst = *(DWORD *)((WORD *)syscall + 1);
+ id = ((inst << 1) & 0x0800) + ((inst << 12) & 0xf000) +
+ ((inst >> 20) & 0x0700) + ((inst >> 16) & 0x00ff);
+ }
+ break;
+ }
+ return id;
+}
+
+
+/**********************************************************************
+ * init_syscall_table
+ */
+static void init_syscall_table( HMODULE ntdll )
+{
+ const IMAGE_EXPORT_DIRECTORY *exports;
+ const ULONG *functions, *names;
+ const USHORT *ordinals;
+ ULONG id, exp_size, exp_pos, wrap_pos;
+
+ exports = RtlImageDirectoryEntryToData( ntdll, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size );
+ ordinals = get_rva( ntdll, exports->AddressOfNameOrdinals );
+ functions = get_rva( ntdll, exports->AddressOfFunctions );
+ names = get_rva( ntdll, exports->AddressOfNames );
+
+ for (exp_pos = wrap_pos = 0; exp_pos < exports->NumberOfNames; exp_pos++)
+ {
+ char *name = get_rva( ntdll, names[exp_pos] );
+ int res = -1;
+
+ if (strncmp( name, "Nt", 2 ) && strncmp( name, "wine", 4 ) && strncmp( name, "__wine", 6 ))
+ continue; /* not a syscall */
+
+ if ((id = get_syscall_num( get_rva( ntdll, functions[ordinals[exp_pos]] ))) == ~0u)
+ continue; /* not a syscall */
+
+ if (wrap_pos < ARRAY_SIZE(syscall_names))
+ res = strcmp( name, syscall_names[wrap_pos] );
+
+ if (!res) /* got a match */
+ {
+ if (id < ARRAY_SIZE(syscall_map)) syscall_map[id] = wrap_pos++;
+ else ERR( "invalid syscall id %04x for %s\n", id, name );
+ }
+ else if (res > 0)
+ {
+ FIXME( "no ntdll export for syscall %s\n", syscall_names[wrap_pos] );
+ wrap_pos++;
+ exp_pos--; /* try again */
+ }
+ else FIXME( "missing wrapper for syscall %04x %s\n", id, name );
+ }
+
+ for ( ; wrap_pos < ARRAY_SIZE(syscall_thunks); wrap_pos++)
+ FIXME( "no ntdll export for syscall %s\n", syscall_names[wrap_pos] );
+}
+
+
/**********************************************************************
* load_cpu_dll
*/
@@ -100,10 +192,24 @@ static HMODULE load_cpu_dll(void)
*/
static void process_init(void)
{
+ HMODULE module;
+ UNICODE_STRING str;
+
RtlWow64GetProcessMachines( GetCurrentProcess(), ¤t_machine, &native_machine );
if (!current_machine) current_machine = native_machine;
+#define GET_PTR(name) p ## name = RtlFindExportedRoutineByName( module, #name )
+
+ RtlInitUnicodeString( &str, L"ntdll.dll" );
+ LdrGetDllHandle( NULL, 0, &str, &module );
+ GET_PTR( LdrSystemDllInitBlock );
+
+ module = (HMODULE)(ULONG_PTR)pLdrSystemDllInitBlock->ntdll_handle;
+ init_syscall_table( module );
+
load_cpu_dll();
+
+#undef GET_PTR
}
@@ -112,8 +218,24 @@ static void process_init(void)
*/
NTSTATUS WINAPI Wow64SystemServiceEx( UINT num, UINT *args )
{
- FIXME( "stub\n" );
- return STATUS_INVALID_SYSTEM_SERVICE;
+ NTSTATUS status;
+
+ if (num >= ARRAY_SIZE( syscall_map ) || !syscall_map[num])
+ {
+ ERR( "unsupported syscall %04x\n", num );
+ return STATUS_INVALID_SYSTEM_SERVICE;
+ }
+ __TRY
+ {
+ syscall_thunk thunk = syscall_thunks[syscall_map[num]];
+ status = thunk( args );
+ }
+ __EXCEPT_ALL
+ {
+ status = GetExceptionCode();
+ }
+ __ENDTRY;
+ return status;
}
diff --git a/dlls/wow64/wow64_private.h b/dlls/wow64/wow64_private.h
index 52cc40566b1..2c8f6f313fc 100644
--- a/dlls/wow64/wow64_private.h
+++ b/dlls/wow64/wow64_private.h
@@ -24,6 +24,11 @@
extern USHORT native_machine DECLSPEC_HIDDEN;
extern USHORT current_machine DECLSPEC_HIDDEN;
+static inline void *get_rva( HMODULE module, DWORD va )
+{
+ return (void *)((char *)module + va);
+}
+
/* cf. GetSystemWow64Directory2 */
static inline const WCHAR *get_machine_wow64_dir( USHORT machine )
{
More information about the wine-cvs
mailing list