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"