Commit c1dc5021 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Dynamically load callback functions from the Unix library.

parent 0b48050d
...@@ -77,7 +77,13 @@ ...@@ -77,7 +77,13 @@
WINE_DEFAULT_DEBUG_CHANNEL(ntdll); WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
extern IMAGE_NT_HEADERS __wine_spec_nt_header; 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__ #ifdef __GNUC__
static void fatal_error( const char *err, ... ) __attribute__((noreturn, format(printf,1,2))); static void fatal_error( const char *err, ... ) __attribute__((noreturn, format(printf,1,2)));
...@@ -713,33 +719,38 @@ static ULONG_PTR find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTO ...@@ -713,33 +719,38 @@ 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, 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 WORD *ordinals = (const WORD *)((BYTE *)module + exports->AddressOfNameOrdinals);
const DWORD *names = (const DWORD *)((BYTE *)module + exports->AddressOfNames); const DWORD *names = (const DWORD *)((BYTE *)module + exports->AddressOfNames);
int min = 0, max = exports->NumberOfNames - 1; int min = 0, max = exports->NumberOfNames - 1;
/* first check the hint */
if (name->Hint <= max)
{
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) while (min <= max)
{ {
int res, pos = (min + max) / 2; int res, pos = (min + max) / 2;
char *ename = (char *)module + names[pos]; char *ename = (char *)module + names[pos];
if (!(res = strcmp( ename, (char *)name->Name ))) if (!(res = strcmp( ename, name ))) return find_ordinal_export( module, exports, ordinals[pos] );
return find_ordinal_export( module, exports, ordinals[pos] );
if (res > 0) max = pos - 1; if (res > 0) max = pos - 1;
else min = pos + 1; else min = pos + 1;
} }
return 0; 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] );
}
return find_named_export( module, exports, (char *)name->Name );
}
static void fixup_ntdll_imports( const IMAGE_NT_HEADERS *nt, HMODULE ntdll_module ) static void fixup_ntdll_imports( const IMAGE_NT_HEADERS *nt, HMODULE ntdll_module )
{ {
const IMAGE_EXPORT_DIRECTORY *ntdll_exports = get_export_dir( ntdll_module ); const IMAGE_EXPORT_DIRECTORY *ntdll_exports = get_export_dir( ntdll_module );
...@@ -750,38 +761,45 @@ static void fixup_ntdll_imports( const IMAGE_NT_HEADERS *nt, HMODULE ntdll_modul ...@@ -750,38 +761,45 @@ static void fixup_ntdll_imports( const IMAGE_NT_HEADERS *nt, HMODULE ntdll_modul
assert( ntdll_exports ); assert( ntdll_exports );
descr = get_rva( nt, nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY].VirtualAddress ); 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" ));
thunk_list = get_rva( nt, (DWORD)descr->FirstThunk ); /* ntdll must be the only import */
if (descr->u.OriginalFirstThunk) assert( !strcmp( get_rva( nt, descr->Name ), "ntdll.dll" ));
import_list = get_rva( nt, (DWORD)descr->u.OriginalFirstThunk ); assert( !descr[1].Name );
else
import_list = thunk_list;
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) 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 );
int ordinal = IMAGE_ORDINAL( import_list->u1.Ordinal ) - ntdll_exports->Base; if (!thunk_list->u1.Function) ERR( "ordinal %u not found\n", ordinal );
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++;
} }
else /* import by name */
descr++; {
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 ...@@ -979,7 +997,7 @@ struct apple_stack_info
static void *apple_wine_thread( void *arg ) 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; return NULL;
} }
...@@ -1234,7 +1252,7 @@ void __wine_main( int argc, char *argv[], char *envp[] ) ...@@ -1234,7 +1252,7 @@ void __wine_main( int argc, char *argv[], char *envp[] )
#ifdef __APPLE__ #ifdef __APPLE__
apple_main_thread(); apple_main_thread();
#endif #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 ) ...@@ -587,7 +587,7 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result )
result->type = APC_BREAK_PROCESS; result->type = APC_BREAK_PROCESS;
result->break_process.status = NtCreateThreadEx( &handle, THREAD_ALL_ACCESS, NULL, result->break_process.status = NtCreateThreadEx( &handle, THREAD_ALL_ACCESS, NULL,
NtCurrentProcess(), DbgUiRemoteBreakin, NULL, NtCurrentProcess(), pDbgUiRemoteBreakin, NULL,
0, 0, 0, 0, NULL ); 0, 0, 0, 0, NULL );
if (!result->break_process.status) NtClose( handle ); if (!result->break_process.status) NtClose( handle );
break; break;
......
...@@ -906,7 +906,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, ...@@ -906,7 +906,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg,
} }
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL ); pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
ctx->ContextFlags = CONTEXT_FULL; ctx->ContextFlags = CONTEXT_FULL;
LdrInitializeThunk( ctx, (void **)&ctx->R0, 0, 0 ); pLdrInitializeThunk( ctx, (void **)&ctx->R0, 0, 0 );
return ctx; return ctx;
} }
......
...@@ -483,7 +483,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout * ...@@ -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; */ 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(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(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(); REGn_sig(18, sigcontext) = (ULONG_PTR)NtCurrentTeb();
} }
...@@ -828,7 +828,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, ...@@ -828,7 +828,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg,
} }
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL ); pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
ctx->ContextFlags = CONTEXT_FULL; ctx->ContextFlags = CONTEXT_FULL;
LdrInitializeThunk( ctx, (void **)&ctx->u.s.X0, 0, 0 ); pLdrInitializeThunk( ctx, (void **)&ctx->u.s.X0, 0, 0 );
return ctx; return ctx;
} }
......
...@@ -1565,7 +1565,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout * ...@@ -1565,7 +1565,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *
return; return;
} }
ESP_sig(sigcontext) = (DWORD)stack; ESP_sig(sigcontext) = (DWORD)stack;
EIP_sig(sigcontext) = (DWORD)KiUserExceptionDispatcher; EIP_sig(sigcontext) = (DWORD)pKiUserExceptionDispatcher;
/* clear single-step, direction, and align check flag */ /* clear single-step, direction, and align check flag */
EFL_sig(sigcontext) &= ~(0x100|0x400|0x40000); EFL_sig(sigcontext) &= ~(0x100|0x400|0x40000);
CS_sig(sigcontext) = get_cs(); CS_sig(sigcontext) = get_cs();
...@@ -2290,7 +2290,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, ...@@ -2290,7 +2290,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg,
} }
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL ); pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
ctx->ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS; 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; return ctx;
} }
......
...@@ -893,7 +893,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout * ...@@ -893,7 +893,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *
RIP_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline; RIP_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline;
RCX_sig(sigcontext) = (ULONG_PTR)&stack->rec; RCX_sig(sigcontext) = (ULONG_PTR)&stack->rec;
RDX_sig(sigcontext) = (ULONG_PTR)&stack->context; 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; RBP_sig(sigcontext) = (ULONG_PTR)rsp_ptr;
RSP_sig(sigcontext) = (ULONG_PTR)stack; RSP_sig(sigcontext) = (ULONG_PTR)stack;
/* clear single-step, direction, and align check flag */ /* clear single-step, direction, and align check flag */
...@@ -1458,7 +1458,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, ...@@ -1458,7 +1458,7 @@ PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg,
} }
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL ); pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
ctx->ContextFlags = CONTEXT_FULL; ctx->ContextFlags = CONTEXT_FULL;
LdrInitializeThunk( ctx, (void **)&ctx->Rcx, 0, 0 ); pLdrInitializeThunk( ctx, (void **)&ctx->Rcx, 0, 0 );
return ctx; return ctx;
} }
......
...@@ -152,7 +152,7 @@ static void start_thread( TEB *teb ) ...@@ -152,7 +152,7 @@ static void start_thread( TEB *teb )
RtlActivateActivationContext( 0, info->actctx, &cookie ); RtlActivateActivationContext( 0, info->actctx, &cookie );
RtlReleaseActivationContext( info->actctx ); 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 ...@@ -456,7 +456,7 @@ NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED) if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
NtSetContextThread( GetCurrentThread(), context ); NtSetContextThread( GetCurrentThread(), context );
if (first_chance) KiUserExceptionDispatcher( rec, context ); if (first_chance) pKiUserExceptionDispatcher( rec, context );
if (rec->ExceptionFlags & EH_STACK_INVALID) if (rec->ExceptionFlags & EH_STACK_INVALID)
ERR("Exception frame is not in stack limits => unable to dispatch exception.\n"); 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) ...@@ -56,8 +56,11 @@ static inline struct ntdll_thread_data *ntdll_get_thread_data(void)
static const UINT_PTR page_size = 0x1000; static const UINT_PTR page_size = 0x1000;
NTSTATUS WINAPI KiUserExceptionDispatcher(EXCEPTION_RECORD*,CONTEXT*); /* callbacks to PE ntdll from the Unix side */
void WINAPI LdrInitializeThunk(CONTEXT*,void**,ULONG_PTR,ULONG_PTR); 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_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit ) DECLSPEC_HIDDEN;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment