forked from Mirrors/wine-wine
ntdll: Dynamically load callback functions from the Unix library.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>feature/deterministic
parent
0b48050da5
commit
c1dc5021ac
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue