If supported by the linker, prevent the ELF loader from calling the
dll constructors at load time and call them from the dll entry point instead.
This commit is contained in:
parent
925a2f936e
commit
3604824262
|
@ -13649,6 +13649,72 @@ echo "${ECHO_T}$ac_cv_c_dll_zdefs" >&6
|
|||
LDDLL="$LDDLL,-z,defs"
|
||||
fi
|
||||
|
||||
echo "$as_me:$LINENO: checking whether the linker accepts -init and -fini" >&5
|
||||
echo $ECHO_N "checking whether the linker accepts -init and -fini... $ECHO_C" >&6
|
||||
if test "${ac_cv_c_dll_init_fini+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
ac_wine_try_cflags_saved=$CFLAGS
|
||||
CFLAGS="$CFLAGS -fPIC -shared -Wl,-Bsymbolic,-init,__wine_spec_init,-fini,__wine_spec_fini"
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
|
||||
(eval $ac_link) 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest$ac_exeext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
ac_cv_c_dll_init_fini="yes"
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_cv_c_dll_init_fini="no"
|
||||
fi
|
||||
rm -f conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
CFLAGS=$ac_wine_try_cflags_saved
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: $ac_cv_c_dll_init_fini" >&5
|
||||
echo "${ECHO_T}$ac_cv_c_dll_init_fini" >&6
|
||||
if test "$ac_cv_c_dll_init_fini" = "yes"
|
||||
then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_LINKER_INIT_FINI 1
|
||||
_ACEOF
|
||||
|
||||
LDDLL="$LDDLL,-init,__wine_spec_init,-fini,__wine_spec_fini"
|
||||
fi
|
||||
|
||||
echo "$as_me:$LINENO: checking whether the linker accepts --export-dynamic" >&5
|
||||
echo $ECHO_N "checking whether the linker accepts --export-dynamic... $ECHO_C" >&6
|
||||
if test "${ac_cv_c_export_dynamic+set}" = set; then
|
||||
|
|
|
@ -880,6 +880,15 @@ case $host_os in
|
|||
LDDLL="$LDDLL,-z,defs"
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([whether the linker accepts -init and -fini], ac_cv_c_dll_init_fini,
|
||||
[WINE_TRY_CFLAGS([-fPIC -shared -Wl,-Bsymbolic,-init,__wine_spec_init,-fini,__wine_spec_fini],
|
||||
ac_cv_c_dll_init_fini="yes",ac_cv_c_dll_init_fini="no")])
|
||||
if test "$ac_cv_c_dll_init_fini" = "yes"
|
||||
then
|
||||
AC_DEFINE(HAVE_LINKER_INIT_FINI,1,[Define if the linker supports renaming the init and fini functions])
|
||||
LDDLL="$LDDLL,-init,__wine_spec_init,-fini,__wine_spec_fini"
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([whether the linker accepts --export-dynamic], ac_cv_c_export_dynamic,
|
||||
[WINE_TRY_CFLAGS([-fPIC -Wl,--export-dynamic],
|
||||
ac_cv_c_export_dynamic="yes",ac_cv_c_export_dynamic="no")])
|
||||
|
|
|
@ -618,9 +618,12 @@ static BOOL process_init( char *argv[], char **environ )
|
|||
RTL_USER_PROCESS_PARAMETERS *params;
|
||||
PEB *peb = NtCurrentTeb()->Peb;
|
||||
HANDLE hstdin, hstdout, hstderr;
|
||||
extern void __wine_dbg_kernel32_init(void);
|
||||
|
||||
PTHREAD_Init();
|
||||
|
||||
__wine_dbg_kernel32_init(); /* hack: register debug channels early */
|
||||
|
||||
setbuf(stdout,NULL);
|
||||
setbuf(stderr,NULL);
|
||||
setlocale(LC_CTYPE,"");
|
||||
|
|
|
@ -1956,8 +1956,10 @@ void __wine_process_init( int argc, char *argv[] )
|
|||
NTSTATUS status;
|
||||
ANSI_STRING func_name;
|
||||
void (* DECLSPEC_NORETURN init_func)();
|
||||
extern void __wine_dbg_ntdll_init(void);
|
||||
|
||||
thread_init();
|
||||
__wine_dbg_ntdll_init(); /* hack: register debug channels early */
|
||||
|
||||
/* setup the load callback and create ntdll modref */
|
||||
wine_dll_set_callback( load_builtin_callback );
|
||||
|
|
|
@ -461,6 +461,11 @@
|
|||
*/
|
||||
#undef HAVE_LIBXXSHM
|
||||
|
||||
/*
|
||||
Define if the linker supports renaming the init
|
||||
and fini functions */
|
||||
#undef HAVE_LINKER_INIT_FINI
|
||||
|
||||
/*
|
||||
Define to 1 if you have the <link.h>
|
||||
header file. */
|
||||
|
|
|
@ -491,7 +491,6 @@ void BuildSpec32File( FILE *outfile )
|
|||
int nr_exports, nr_imports, nr_resources;
|
||||
int characteristics, subsystem;
|
||||
DWORD page_size;
|
||||
char constructor[100];
|
||||
|
||||
#ifdef HAVE_GETPAGESIZE
|
||||
page_size = getpagesize();
|
||||
|
@ -569,30 +568,53 @@ void BuildSpec32File( FILE *outfile )
|
|||
|
||||
nr_resources = output_resources( outfile );
|
||||
|
||||
/* Output LibMain function */
|
||||
/* Output the entry point function */
|
||||
|
||||
fprintf( outfile, "extern int __wine_main_argc;\n" );
|
||||
fprintf( outfile, "extern char **__wine_main_argv;\n" );
|
||||
fprintf( outfile, "extern char **__wine_main_environ;\n" );
|
||||
fprintf( outfile, "extern unsigned short **__wine_main_wargv;\n" );
|
||||
fprintf( outfile, "extern void _init(int, char**, char**);\n" );
|
||||
fprintf( outfile, "extern void _fini();\n" );
|
||||
|
||||
characteristics = subsystem = 0;
|
||||
switch(SpecMode)
|
||||
{
|
||||
case SPEC_MODE_DLL:
|
||||
if (init_func) fprintf( outfile, "extern void %s();\n", init_func );
|
||||
if (init_func)
|
||||
fprintf( outfile, "extern int __stdcall %s( void*, unsigned int, void* );\n\n", init_func );
|
||||
else
|
||||
{
|
||||
fprintf( outfile, "#ifdef __GNUC__\n" );
|
||||
fprintf( outfile, "# ifdef __APPLE__\n" );
|
||||
fprintf( outfile, "extern void DllMain() __attribute__((weak_import));\n" );
|
||||
fprintf( outfile, "extern int __stdcall DllMain( void*, unsigned int, void* ) __attribute__((weak_import));\n" );
|
||||
fprintf( outfile, "# else\n" );
|
||||
fprintf( outfile, "extern void DllMain() __attribute__((weak));\n" );
|
||||
fprintf( outfile, "extern int __stdcall DllMain( void*, unsigned int, void* ) __attribute__((weak));\n" );
|
||||
fprintf( outfile, "# endif\n" );
|
||||
fprintf( outfile, "#else\n" );
|
||||
fprintf( outfile, "extern void DllMain();\n" );
|
||||
fprintf( outfile, "extern int __stdcall DllMain( void*, unsigned int, void* );\n" );
|
||||
fprintf( outfile, "static void __asm__dummy_dllmain(void)" );
|
||||
fprintf( outfile, " { asm(\".weak " __ASM_NAME("DllMain") "\"); }\n" );
|
||||
fprintf( outfile, "#endif\n" );
|
||||
fprintf( outfile, "#endif\n\n" );
|
||||
init_func = "DllMain";
|
||||
}
|
||||
#ifdef HAVE_LINKER_INIT_FINI
|
||||
fprintf( outfile,
|
||||
"static int __stdcall __wine_dll_main( void *inst, unsigned int reason, void *reserved )\n"
|
||||
"{\n"
|
||||
" int ret;\n"
|
||||
" if (reason == %d) _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n"
|
||||
" ret = %s ? %s( inst, reason, reserved ) : 1;\n"
|
||||
" if (reason == %d) _fini();\n"
|
||||
" return ret;\n"
|
||||
"}\n",
|
||||
DLL_PROCESS_ATTACH, init_func, init_func, DLL_PROCESS_DETACH );
|
||||
init_func = "__wine_dll_main";
|
||||
#endif
|
||||
characteristics = IMAGE_FILE_DLL;
|
||||
break;
|
||||
case SPEC_MODE_GUIEXE:
|
||||
case SPEC_MODE_GUIEXE_UNICODE:
|
||||
if (!init_func) init_func = "WinMain";
|
||||
fprintf( outfile,
|
||||
"\ntypedef struct {\n"
|
||||
|
@ -604,8 +626,6 @@ void BuildSpec32File( FILE *outfile )
|
|||
" char *lpReserved2;\n"
|
||||
" void *hStdInput, *hStdOutput, *hStdError;\n"
|
||||
"} STARTUPINFOA;\n"
|
||||
"int _ARGC;\n"
|
||||
"char **_ARGV;\n"
|
||||
"extern int __stdcall %s(void *,void *,char *,int);\n"
|
||||
"extern char * __stdcall GetCommandLineA(void);\n"
|
||||
"extern void * __stdcall GetModuleHandleA(char *);\n"
|
||||
|
@ -613,11 +633,9 @@ void BuildSpec32File( FILE *outfile )
|
|||
"extern void __stdcall ExitProcess(unsigned int);\n"
|
||||
"static void __wine_exe_main(void)\n"
|
||||
"{\n"
|
||||
" extern int __wine_main_argc;\n"
|
||||
" extern char **__wine_main_argv;\n"
|
||||
" STARTUPINFOA info;\n"
|
||||
" char *cmdline = GetCommandLineA();\n"
|
||||
" int bcount=0, in_quotes=0;\n"
|
||||
" int ret, bcount=0, in_quotes=0;\n"
|
||||
" while (*cmdline) {\n"
|
||||
" if ((*cmdline=='\\t' || *cmdline==' ') && !in_quotes) break;\n"
|
||||
" else if (*cmdline=='\\\\') bcount++;\n"
|
||||
|
@ -631,56 +649,14 @@ void BuildSpec32File( FILE *outfile )
|
|||
" while (*cmdline=='\\t' || *cmdline==' ') cmdline++;\n"
|
||||
" GetStartupInfoA( &info );\n"
|
||||
" if (!(info.dwFlags & 1)) info.wShowWindow = 1;\n"
|
||||
" _ARGC = __wine_main_argc;\n"
|
||||
" _ARGV = __wine_main_argv;\n"
|
||||
" ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n"
|
||||
"}\n\n", init_func, init_func );
|
||||
init_func = "__wine_exe_main";
|
||||
subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
|
||||
break;
|
||||
case SPEC_MODE_GUIEXE_UNICODE:
|
||||
if (!init_func) init_func = "WinMain";
|
||||
fprintf( outfile,
|
||||
"\ntypedef unsigned short WCHAR;\n"
|
||||
"typedef struct {\n"
|
||||
" unsigned int cb;\n"
|
||||
" char *lpReserved, *lpDesktop, *lpTitle;\n"
|
||||
" unsigned int dwX, dwY, dwXSize, dwYSize;\n"
|
||||
" unsigned int dwXCountChars, dwYCountChars, dwFillAttribute, dwFlags;\n"
|
||||
" unsigned short wShowWindow, cbReserved2;\n"
|
||||
" char *lpReserved2;\n"
|
||||
" void *hStdInput, *hStdOutput, *hStdError;\n"
|
||||
"} STARTUPINFOA;\n"
|
||||
"int _ARGC;\n"
|
||||
"WCHAR **_ARGV;\n"
|
||||
"extern int __stdcall %s(void *,void *,char *,int);\n"
|
||||
"extern char * __stdcall GetCommandLineA(void);\n"
|
||||
"extern void * __stdcall GetModuleHandleA(char *);\n"
|
||||
"extern void __stdcall GetStartupInfoA(STARTUPINFOA *);\n"
|
||||
"extern void __stdcall ExitProcess(unsigned int);\n"
|
||||
"static void __wine_exe_main(void)\n"
|
||||
"{\n"
|
||||
" extern int __wine_main_argc;\n"
|
||||
" extern WCHAR **__wine_main_wargv;\n"
|
||||
" STARTUPINFOA info;\n"
|
||||
" char *cmdline = GetCommandLineA();\n"
|
||||
" int bcount=0, in_quotes=0;\n"
|
||||
" while (*cmdline) {\n"
|
||||
" if ((*cmdline=='\\t' || *cmdline==' ') && !in_quotes) break;\n"
|
||||
" else if (*cmdline=='\\\\') bcount++;\n"
|
||||
" else if (*cmdline=='\\\"') {\n"
|
||||
" if ((bcount & 1)==0) in_quotes=!in_quotes;\n"
|
||||
" bcount=0;\n"
|
||||
" }\n"
|
||||
" else bcount=0;\n"
|
||||
" cmdline++;\n"
|
||||
" }\n"
|
||||
" while (*cmdline=='\\t' || *cmdline==' ') cmdline++;\n"
|
||||
" GetStartupInfoA( &info );\n"
|
||||
" if (!(info.dwFlags & 1)) info.wShowWindow = 1;\n"
|
||||
" _ARGC = __wine_main_argc;\n"
|
||||
" _ARGV = __wine_main_wargv;\n"
|
||||
" ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n"
|
||||
#ifdef HAVE_LINKER_INIT_FINI
|
||||
" _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n"
|
||||
" ret = %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow );\n"
|
||||
" _fini();\n"
|
||||
#else
|
||||
" ret = %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow );\n"
|
||||
#endif
|
||||
" ExitProcess( ret );\n"
|
||||
"}\n\n", init_func, init_func );
|
||||
init_func = "__wine_exe_main";
|
||||
subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
|
||||
|
@ -688,17 +664,19 @@ void BuildSpec32File( FILE *outfile )
|
|||
case SPEC_MODE_CUIEXE:
|
||||
if (!init_func) init_func = "main";
|
||||
fprintf( outfile,
|
||||
"\nint _ARGC;\n"
|
||||
"char **_ARGV;\n"
|
||||
"extern void __stdcall ExitProcess(int);\n"
|
||||
"\nextern void __stdcall ExitProcess(int);\n"
|
||||
"static void __wine_exe_main(void)\n"
|
||||
"{\n"
|
||||
" int ret;\n"
|
||||
" extern int %s( int argc, char *argv[] );\n"
|
||||
" extern int __wine_main_argc;\n"
|
||||
" extern char **__wine_main_argv;\n"
|
||||
" _ARGC = __wine_main_argc;\n"
|
||||
" _ARGV = __wine_main_argv;\n"
|
||||
" ExitProcess( %s( _ARGC, _ARGV ) );\n"
|
||||
#ifdef HAVE_LINKER_INIT_FINI
|
||||
" _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n"
|
||||
" ret = %s( __wine_main_argc, __wine_main_argv );\n"
|
||||
" _fini();\n"
|
||||
#else
|
||||
" ret = %s( __wine_main_argc, __wine_main_argv );\n"
|
||||
#endif
|
||||
" ExitProcess( ret );\n"
|
||||
"}\n\n", init_func, init_func );
|
||||
init_func = "__wine_exe_main";
|
||||
subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
|
||||
|
@ -706,18 +684,19 @@ void BuildSpec32File( FILE *outfile )
|
|||
case SPEC_MODE_CUIEXE_UNICODE:
|
||||
if (!init_func) init_func = "wmain";
|
||||
fprintf( outfile,
|
||||
"\ntypedef unsigned short WCHAR;\n"
|
||||
"int _ARGC;\n"
|
||||
"WCHAR **_ARGV;\n"
|
||||
"extern void __stdcall ExitProcess(int);\n"
|
||||
"\nextern void __stdcall ExitProcess(int);\n"
|
||||
"static void __wine_exe_main(void)\n"
|
||||
"{\n"
|
||||
" extern int %s( int argc, WCHAR *argv[] );\n"
|
||||
" extern int __wine_main_argc;\n"
|
||||
" extern WCHAR **__wine_main_wargv;\n"
|
||||
" _ARGC = __wine_main_argc;\n"
|
||||
" _ARGV = __wine_main_wargv;\n"
|
||||
" ExitProcess( %s( _ARGC, _ARGV ) );\n"
|
||||
" int ret;\n"
|
||||
" extern int %s( int argc, unsigned short *argv[] );\n"
|
||||
#ifdef HAVE_LINKER_INIT_FINI
|
||||
" _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n"
|
||||
" ret = %s( __wine_main_argc, __wine_main_wargv );\n"
|
||||
" _fini();\n"
|
||||
#else
|
||||
" ret = %s( __wine_main_argc, __wine_main_wargv );\n"
|
||||
#endif
|
||||
" ExitProcess( ret );\n"
|
||||
"}\n\n", init_func, init_func );
|
||||
init_func = "__wine_exe_main";
|
||||
subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
|
||||
|
@ -787,7 +766,7 @@ void BuildSpec32File( FILE *outfile )
|
|||
fprintf( outfile, " { 0x%04x,\n", IMAGE_NT_OPTIONAL_HDR_MAGIC ); /* Magic */
|
||||
fprintf( outfile, " 0, 0,\n" ); /* Major/MinorLinkerVersion */
|
||||
fprintf( outfile, " 0, 0, 0,\n" ); /* SizeOfCode/Data */
|
||||
fprintf( outfile, " %s,\n", init_func ? init_func : "DllMain" ); /* AddressOfEntryPoint */
|
||||
fprintf( outfile, " %s,\n", init_func ); /* AddressOfEntryPoint */
|
||||
fprintf( outfile, " 0, __wine_spec_data_start,\n" ); /* BaseOfCode/Data */
|
||||
fprintf( outfile, " __wine_spec_pe_header,\n" ); /* ImageBase */
|
||||
fprintf( outfile, " %ld,\n", page_size ); /* SectionAlignment */
|
||||
|
@ -818,17 +797,16 @@ void BuildSpec32File( FILE *outfile )
|
|||
|
||||
/* Output the DLL constructor */
|
||||
|
||||
sprintf( constructor, "__wine_spec_%s_init", make_c_identifier(dll_file_name) );
|
||||
output_dll_init( outfile, constructor, NULL );
|
||||
|
||||
#ifndef HAVE_LINKER_INIT_FINI
|
||||
output_dll_init( outfile, "__wine_spec_init", NULL );
|
||||
#endif
|
||||
fprintf( outfile,
|
||||
"void %s(void)\n"
|
||||
"void __wine_spec_init(void)\n"
|
||||
"{\n"
|
||||
" extern void __wine_dll_register( const struct image_nt_headers *, const char * );\n"
|
||||
" extern void *__wine_dbg_register( char * const *, int );\n"
|
||||
" __wine_dll_register( &nt_header, \"%s\" );\n"
|
||||
"}\n",
|
||||
constructor, dll_file_name );
|
||||
dll_file_name );
|
||||
}
|
||||
|
||||
|
||||
|
@ -942,8 +920,8 @@ void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv )
|
|||
|
||||
fprintf( outfile,
|
||||
"#ifdef __GNUC__\n"
|
||||
"static void __wine_dbg_%s_init(void) __attribute__((constructor));\n"
|
||||
"static void __wine_dbg_%s_fini(void) __attribute__((destructor));\n"
|
||||
"void __wine_dbg_%s_init(void) __attribute__((constructor));\n"
|
||||
"void __wine_dbg_%s_fini(void) __attribute__((destructor));\n"
|
||||
"#else\n"
|
||||
"static void __asm__dummy_dll_init(void) {\n",
|
||||
prefix, prefix );
|
||||
|
@ -971,21 +949,15 @@ void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv )
|
|||
#else
|
||||
#error You need to define the DLL constructor for your architecture
|
||||
#endif
|
||||
fprintf( outfile, "}\n#endif /* defined(__GNUC__) */\n" );
|
||||
fprintf( outfile, "}\n#endif /* defined(__GNUC__) */\n\n" );
|
||||
|
||||
fprintf( outfile,
|
||||
"\n#ifdef __GNUC__\n"
|
||||
"static\n"
|
||||
"#endif\n"
|
||||
"void __wine_dbg_%s_init(void)\n"
|
||||
"{\n"
|
||||
" extern void *__wine_dbg_register( char * const *, int );\n"
|
||||
" debug_registration = __wine_dbg_register( debug_channels, %d );\n"
|
||||
"}\n", prefix, nr_debug );
|
||||
" if (!debug_registration) debug_registration = __wine_dbg_register( debug_channels, %d );\n"
|
||||
"}\n\n", prefix, nr_debug );
|
||||
fprintf( outfile,
|
||||
"\n#ifdef __GNUC__\n"
|
||||
"static\n"
|
||||
"#endif\n"
|
||||
"void __wine_dbg_%s_fini(void)\n"
|
||||
"{\n"
|
||||
" extern void __wine_dbg_unregister( void* );\n"
|
||||
|
|
Loading…
Reference in New Issue