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.
diff --git a/configure b/configure
index b95800e..7ad9bc2 100755
--- a/configure
+++ b/configure
@@ -13649,6 +13649,72 @@
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
diff --git a/configure.ac b/configure.ac
index 161211e..5ea663f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -880,6 +880,15 @@
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")])
diff --git a/dlls/kernel/process.c b/dlls/kernel/process.c
index 2011162..da84b88 100644
--- a/dlls/kernel/process.c
+++ b/dlls/kernel/process.c
@@ -618,9 +618,12 @@
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,"");
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index e3afb10..94fb681 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -1956,8 +1956,10 @@
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 );
diff --git a/include/config.h.in b/include/config.h.in
index be8b724..1ce5de7 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -462,6 +462,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. */
#undef HAVE_LINK_H
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index 02567c3..dc19d00 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -491,7 +491,6 @@
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 @@
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 @@
" 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 @@
"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 @@
" 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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
#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"