ntdll: Dynamically load callback functions from the Unix library.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Alexandre Julliard 2020-06-17 11:57:32 +02:00
parent 0b48050da5
commit c1dc5021ac
8 changed files with 79 additions and 58 deletions

View File

@ -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 );
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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");

View File

@ -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;