From c1dc5021ac2534ea7bf52246f13c19941b791efa Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 17 Jun 2020 11:57:32 +0200 Subject: [PATCH] ntdll: Dynamically load callback functions from the Unix library. Signed-off-by: Alexandre Julliard --- dlls/ntdll/unix/loader.c | 110 +++++++++++++++++++------------- dlls/ntdll/unix/server.c | 2 +- dlls/ntdll/unix/signal_arm.c | 2 +- dlls/ntdll/unix/signal_arm64.c | 4 +- dlls/ntdll/unix/signal_i386.c | 4 +- dlls/ntdll/unix/signal_x86_64.c | 4 +- dlls/ntdll/unix/thread.c | 4 +- dlls/ntdll/unix/unix_private.h | 7 +- 8 files changed, 79 insertions(+), 58 deletions(-) diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 2bf54e5a4fb..cbed3753ceb 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -77,7 +77,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntdll); extern IMAGE_NT_HEADERS __wine_spec_nt_header; -extern void CDECL __wine_set_unix_funcs( int version, const struct unix_funcs *funcs ); + +void (WINAPI *pDbgUiRemoteBreakin)( void *arg ) = NULL; +NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*) = NULL; +void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PTR) = NULL; +void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) = NULL; + +static void (CDECL *p__wine_set_unix_funcs)( int version, const struct unix_funcs *funcs ); #ifdef __GNUC__ static void fatal_error( const char *err, ... ) __attribute__((noreturn, format(printf,1,2))); @@ -713,31 +719,36 @@ static ULONG_PTR find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTO } static ULONG_PTR find_named_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports, - const IMAGE_IMPORT_BY_NAME *name ) + const char *name ) { const WORD *ordinals = (const WORD *)((BYTE *)module + exports->AddressOfNameOrdinals); const DWORD *names = (const DWORD *)((BYTE *)module + exports->AddressOfNames); int min = 0, max = exports->NumberOfNames - 1; - /* first check the hint */ - if (name->Hint <= max) + while (min <= max) + { + int res, pos = (min + max) / 2; + char *ename = (char *)module + names[pos]; + if (!(res = strcmp( ename, name ))) return find_ordinal_export( module, exports, ordinals[pos] ); + if (res > 0) max = pos - 1; + else min = pos + 1; + } + return 0; +} + +static ULONG_PTR find_pe_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports, + const IMAGE_IMPORT_BY_NAME *name ) +{ + const WORD *ordinals = (const WORD *)((BYTE *)module + exports->AddressOfNameOrdinals); + const DWORD *names = (const DWORD *)((BYTE *)module + exports->AddressOfNames); + + if (name->Hint < exports->NumberOfNames) { char *ename = (char *)module + names[name->Hint]; if (!strcmp( ename, (char *)name->Name )) return find_ordinal_export( module, exports, ordinals[name->Hint] ); } - - /* then do a binary search */ - while (min <= max) - { - int res, pos = (min + max) / 2; - char *ename = (char *)module + names[pos]; - if (!(res = strcmp( ename, (char *)name->Name ))) - return find_ordinal_export( module, exports, ordinals[pos] ); - if (res > 0) max = pos - 1; - else min = pos + 1; - } - return 0; + return find_named_export( module, exports, (char *)name->Name ); } static void fixup_ntdll_imports( const IMAGE_NT_HEADERS *nt, HMODULE ntdll_module ) @@ -750,38 +761,45 @@ static void fixup_ntdll_imports( const IMAGE_NT_HEADERS *nt, HMODULE ntdll_modul assert( ntdll_exports ); descr = get_rva( nt, nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY].VirtualAddress ); - while (descr->Name) + + /* ntdll must be the only import */ + assert( !strcmp( get_rva( nt, descr->Name ), "ntdll.dll" )); + assert( !descr[1].Name ); + + thunk_list = get_rva( nt, (DWORD)descr->FirstThunk ); + if (descr->u.OriginalFirstThunk) + import_list = get_rva( nt, (DWORD)descr->u.OriginalFirstThunk ); + else + import_list = thunk_list; + + while (import_list->u1.Ordinal) { - /* ntdll must be the only import */ - assert( !strcmp( get_rva( nt, descr->Name ), "ntdll.dll" )); - - thunk_list = get_rva( nt, (DWORD)descr->FirstThunk ); - if (descr->u.OriginalFirstThunk) - import_list = get_rva( nt, (DWORD)descr->u.OriginalFirstThunk ); - else - import_list = thunk_list; - - - while (import_list->u1.Ordinal) + if (IMAGE_SNAP_BY_ORDINAL( import_list->u1.Ordinal )) { - if (IMAGE_SNAP_BY_ORDINAL( import_list->u1.Ordinal )) - { - int ordinal = IMAGE_ORDINAL( import_list->u1.Ordinal ) - ntdll_exports->Base; - thunk_list->u1.Function = find_ordinal_export( ntdll_module, ntdll_exports, ordinal ); - if (!thunk_list->u1.Function) ERR( "ordinal %u not found\n", ordinal ); - } - else /* import by name */ - { - IMAGE_IMPORT_BY_NAME *pe_name = get_rva( nt, import_list->u1.AddressOfData ); - thunk_list->u1.Function = find_named_export( ntdll_module, ntdll_exports, pe_name ); - if (!thunk_list->u1.Function) ERR( "%s not found\n", pe_name->Name ); - } - import_list++; - thunk_list++; + int ordinal = IMAGE_ORDINAL( import_list->u1.Ordinal ) - ntdll_exports->Base; + thunk_list->u1.Function = find_ordinal_export( ntdll_module, ntdll_exports, ordinal ); + if (!thunk_list->u1.Function) ERR( "ordinal %u not found\n", ordinal ); } - - descr++; + else /* import by name */ + { + IMAGE_IMPORT_BY_NAME *pe_name = get_rva( nt, import_list->u1.AddressOfData ); + thunk_list->u1.Function = find_pe_export( ntdll_module, ntdll_exports, pe_name ); + if (!thunk_list->u1.Function) ERR( "%s not found\n", pe_name->Name ); + } + import_list++; + thunk_list++; } + +#define GET_FUNC(name) \ + if (!(p##name = (void *)find_named_export( ntdll_module, ntdll_exports, #name ))) \ + ERR( "%s not found\n", #name ) + + GET_FUNC( DbgUiRemoteBreakin ); + GET_FUNC( KiUserExceptionDispatcher ); + GET_FUNC( LdrInitializeThunk ); + GET_FUNC( RtlUserThreadStart ); + GET_FUNC( __wine_set_unix_funcs ); +#undef GET_FUNC } /*********************************************************************** @@ -979,7 +997,7 @@ struct apple_stack_info static void *apple_wine_thread( void *arg ) { - __wine_set_unix_funcs( NTDLL_UNIXLIB_VERSION, &unix_funcs ); + p__wine_set_unix_funcs( NTDLL_UNIXLIB_VERSION, &unix_funcs ); return NULL; } @@ -1234,7 +1252,7 @@ void __wine_main( int argc, char *argv[], char *envp[] ) #ifdef __APPLE__ apple_main_thread(); #endif - __wine_set_unix_funcs( NTDLL_UNIXLIB_VERSION, &unix_funcs ); + p__wine_set_unix_funcs( NTDLL_UNIXLIB_VERSION, &unix_funcs ); } diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index cf6f6c3832c..61658a6fb8c 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -587,7 +587,7 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result ) result->type = APC_BREAK_PROCESS; result->break_process.status = NtCreateThreadEx( &handle, THREAD_ALL_ACCESS, NULL, - NtCurrentProcess(), DbgUiRemoteBreakin, NULL, + NtCurrentProcess(), pDbgUiRemoteBreakin, NULL, 0, 0, 0, 0, NULL ); if (!result->break_process.status) NtClose( handle ); break; diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index 1ef3ff6618b..faa2952a483 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -906,7 +906,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, } pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL ); ctx->ContextFlags = CONTEXT_FULL; - LdrInitializeThunk( ctx, (void **)&ctx->R0, 0, 0 ); + pLdrInitializeThunk( ctx, (void **)&ctx->R0, 0, 0 ); return ctx; } diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index 6c9083664e0..e2c52a1a4f6 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -483,7 +483,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout * PC_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline; /* raise_generic_exception; */ REGn_sig(0, sigcontext) = (ULONG_PTR)&stack->rec; /* first arg for raise_generic_exception */ REGn_sig(1, sigcontext) = (ULONG_PTR)&stack->context; /* second arg for raise_generic_exception */ - REGn_sig(2, sigcontext) = (ULONG_PTR)KiUserExceptionDispatcher; /* third arg for raise_func_trampoline */ + REGn_sig(2, sigcontext) = (ULONG_PTR)pKiUserExceptionDispatcher; /* third arg for raise_func_trampoline */ REGn_sig(18, sigcontext) = (ULONG_PTR)NtCurrentTeb(); } @@ -828,7 +828,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, } pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL ); ctx->ContextFlags = CONTEXT_FULL; - LdrInitializeThunk( ctx, (void **)&ctx->u.s.X0, 0, 0 ); + pLdrInitializeThunk( ctx, (void **)&ctx->u.s.X0, 0, 0 ); return ctx; } diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 7ae4cda33a6..adf622ca673 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -1565,7 +1565,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout * return; } ESP_sig(sigcontext) = (DWORD)stack; - EIP_sig(sigcontext) = (DWORD)KiUserExceptionDispatcher; + EIP_sig(sigcontext) = (DWORD)pKiUserExceptionDispatcher; /* clear single-step, direction, and align check flag */ EFL_sig(sigcontext) &= ~(0x100|0x400|0x40000); CS_sig(sigcontext) = get_cs(); @@ -2290,7 +2290,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, } pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL ); ctx->ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS; - LdrInitializeThunk( ctx, (void **)&ctx->Eax, 0, 0 ); + pLdrInitializeThunk( ctx, (void **)&ctx->Eax, 0, 0 ); return ctx; } diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index d4a6e821a4c..1bf8f5e8b8e 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -893,7 +893,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout * RIP_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline; RCX_sig(sigcontext) = (ULONG_PTR)&stack->rec; RDX_sig(sigcontext) = (ULONG_PTR)&stack->context; - R8_sig(sigcontext) = (ULONG_PTR)KiUserExceptionDispatcher; + R8_sig(sigcontext) = (ULONG_PTR)pKiUserExceptionDispatcher; RBP_sig(sigcontext) = (ULONG_PTR)rsp_ptr; RSP_sig(sigcontext) = (ULONG_PTR)stack; /* clear single-step, direction, and align check flag */ @@ -1458,7 +1458,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, } pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL ); ctx->ContextFlags = CONTEXT_FULL; - LdrInitializeThunk( ctx, (void **)&ctx->Rcx, 0, 0 ); + pLdrInitializeThunk( ctx, (void **)&ctx->Rcx, 0, 0 ); return ctx; } diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index d6fb12d7f47..c6ca9af56ac 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -152,7 +152,7 @@ static void start_thread( TEB *teb ) RtlActivateActivationContext( 0, info->actctx, &cookie ); RtlReleaseActivationContext( info->actctx ); } - signal_start_thread( info->entry, info->arg, suspend, RtlUserThreadStart, teb ); + signal_start_thread( info->entry, info->arg, suspend, pRtlUserThreadStart, teb ); } @@ -456,7 +456,7 @@ NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED) NtSetContextThread( GetCurrentThread(), context ); - if (first_chance) KiUserExceptionDispatcher( rec, context ); + if (first_chance) pKiUserExceptionDispatcher( rec, context ); if (rec->ExceptionFlags & EH_STACK_INVALID) ERR("Exception frame is not in stack limits => unable to dispatch exception.\n"); diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 83d4cb0e1c0..d8390b2f345 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -56,8 +56,11 @@ static inline struct ntdll_thread_data *ntdll_get_thread_data(void) static const UINT_PTR page_size = 0x1000; -NTSTATUS WINAPI KiUserExceptionDispatcher(EXCEPTION_RECORD*,CONTEXT*); -void WINAPI LdrInitializeThunk(CONTEXT*,void**,ULONG_PTR,ULONG_PTR); +/* callbacks to PE ntdll from the Unix side */ +extern void (WINAPI *pDbgUiRemoteBreakin)( void *arg ) DECLSPEC_HIDDEN; +extern NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*) DECLSPEC_HIDDEN; +extern void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PTR) DECLSPEC_HIDDEN; +extern void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit ) DECLSPEC_HIDDEN;