OSDN Git Service

* dcrt0.cc (dll_crt0_0): Check for wincap.wow64_has_secondary_stack
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / dcrt0.cc
1 /* dcrt0.cc -- essentially the main() for the Cygwin dll
2
3    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
4    2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 #include "winsup.h"
13 #include "miscfuncs.h"
14 #include <unistd.h>
15 #include <stdlib.h>
16 #include "glob.h"
17 #include <ctype.h>
18 #include <locale.h>
19 #include "environ.h"
20 #include "sigproc.h"
21 #include "pinfo.h"
22 #include "cygerrno.h"
23 #define NEED_VFORK
24 #include "perprocess.h"
25 #include "path.h"
26 #include "fhandler.h"
27 #include "dtable.h"
28 #include "cygheap.h"
29 #include "child_info_magic.h"
30 #include "cygtls.h"
31 #include "shared_info.h"
32 #include "cygwin_version.h"
33 #include "dll_init.h"
34 #include "heap.h"
35 #include "tls_pbuf.h"
36 #include "exception.h"
37 #include "cygxdr.h"
38 #include "fenv.h"
39 #include "ntdll.h"
40 #include "wow64.h"
41
42 #define MAX_AT_FILE_LEVEL 10
43
44 #define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
45
46 extern "C" void cygwin_exit (int) __attribute__ ((noreturn));
47 extern "C" void __sinit (_reent *);
48
49 static int NO_COPY envc;
50 static char NO_COPY **envp;
51
52 bool NO_COPY jit_debug;
53
54 static void
55 do_global_dtors ()
56 {
57   void (**pfunc) () = user_data->dtors;
58   if (pfunc)
59     {
60       user_data->dtors = NULL;
61       while (*++pfunc)
62         (*pfunc) ();
63     }
64 }
65
66 static void __stdcall
67 do_global_ctors (void (**in_pfunc)(), int force)
68 {
69   if (!force && in_forkee)
70     return;             // inherit constructed stuff from parent pid
71
72   /* Run ctors backwards, so skip the first entry and find how many
73      there are, then run them. */
74
75   void (**pfunc) () = in_pfunc;
76
77   while (*++pfunc)
78     ;
79   while (--pfunc > in_pfunc)
80     (*pfunc) ();
81 }
82
83 /*
84  * Replaces @file in the command line with the contents of the file.
85  * There may be multiple @file's in a single command line
86  * A \@file is replaced with @file so that echo \@foo would print
87  * @foo and not the contents of foo.
88  */
89 static bool __stdcall
90 insert_file (char *name, char *&cmd)
91 {
92   HANDLE f;
93   DWORD size;
94   tmp_pathbuf tp;
95
96   PWCHAR wname = tp.w_get ();
97   sys_mbstowcs (wname, NT_MAX_PATH, name + 1);
98   f = CreateFileW (wname,
99                    GENERIC_READ,                /* open for reading     */
100                    FILE_SHARE_VALID_FLAGS,      /* share for reading    */
101                    &sec_none_nih,               /* default security     */
102                    OPEN_EXISTING,               /* existing file only   */
103                    FILE_ATTRIBUTE_NORMAL,       /* normal file          */
104                    NULL);                       /* no attr. template    */
105
106   if (f == INVALID_HANDLE_VALUE)
107     {
108       debug_printf ("couldn't open file '%s', %E", name);
109       return false;
110     }
111
112   /* This only supports files up to about 4 billion bytes in
113      size.  I am making the bold assumption that this is big
114      enough for this feature */
115   size = GetFileSize (f, NULL);
116   if (size == 0xFFFFFFFF)
117     {
118       debug_printf ("couldn't get file size for '%s', %E", name);
119       return false;
120     }
121
122   int new_size = strlen (cmd) + size + 2;
123   char *tmp = (char *) malloc (new_size);
124   if (!tmp)
125     {
126       debug_printf ("malloc failed, %E");
127       return false;
128     }
129
130   /* realloc passed as it should */
131   DWORD rf_read;
132   BOOL rf_result;
133   rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
134   CloseHandle (f);
135   if (!rf_result || (rf_read != size))
136     {
137       debug_printf ("ReadFile failed, %E");
138       return false;
139     }
140
141   tmp[size++] = ' ';
142   strcpy (tmp + size, cmd);
143   cmd = tmp;
144   return true;
145 }
146
147 static inline int
148 isquote (char c)
149 {
150   char ch = c;
151   return ch == '"' || ch == '\'';
152 }
153
154 /* Step over a run of characters delimited by quotes */
155 static /*__inline*/ char *
156 quoted (char *cmd, int winshell)
157 {
158   char *p;
159   char quote = *cmd;
160
161   if (!winshell)
162     {
163       char *p;
164       strcpy (cmd, cmd + 1);
165       if (*(p = strechr (cmd, quote)))
166         strcpy (p, p + 1);
167       return p;
168     }
169
170   const char *s = quote == '\'' ? "'" : "\\\"";
171   /* This must have been run from a Windows shell, so preserve
172      quotes for globify to play with later. */
173   while (*cmd && *++cmd)
174     if ((p = strpbrk (cmd, s)) == NULL)
175       {
176         cmd = strchr (cmd, '\0');       // no closing quote
177         break;
178       }
179     else if (*p == '\\')
180       cmd = ++p;
181     else if (quote == '"' && p[1] == '"')
182       {
183         *p = '\\';
184         cmd = ++p;                      // a quoted quote
185       }
186     else
187       {
188         cmd = p + 1;            // point to after end
189         break;
190       }
191   return cmd;
192 }
193
194 /* Perform a glob on word if it contains wildcard characters.
195    Also quote every character between quotes to force glob to
196    treat the characters literally. */
197 static int __stdcall
198 globify (char *word, char **&argv, int &argc, int &argvlen)
199 {
200   if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
201     return 0;
202
203   int n = 0;
204   char *p, *s;
205   int dos_spec = isdrive (word);
206   if (!dos_spec && isquote (*word) && word[1] && word[2])
207     dos_spec = isdrive (word + 1);
208
209   /* We'll need more space if there are quoting characters in
210      word.  If that is the case, doubling the size of the
211      string should provide more than enough space. */
212   if (strpbrk (word, "'\""))
213     n = strlen (word);
214   char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
215
216   /* Fill pattern with characters from word, quoting any
217      characters found within quotes. */
218   for (p = pattern, s = word; *s != '\000'; s++, p++)
219     if (!isquote (*s))
220       {
221         if (dos_spec && *s == '\\')
222           *p++ = '\\';
223         *p = *s;
224       }
225     else
226       {
227         char quote = *s;
228         while (*++s && *s != quote)
229           {
230             if (dos_spec || *s != '\\')
231               /* nothing */;
232             else if (s[1] == quote || s[1] == '\\')
233               s++;
234             *p++ = '\\';
235             size_t cnt = isascii (*s) ? 1 : mbtowc (NULL, s, MB_CUR_MAX);
236             if (cnt <= 1 || cnt == (size_t)-1)
237               *p++ = *s;
238             else
239               {
240                 --s;
241                 while (cnt-- > 0)
242                   *p++ = *++s;
243               }
244           }
245         if (*s == quote)
246           p--;
247         if (*s == '\0')
248             break;
249       }
250
251   *p = '\0';
252
253   glob_t gl;
254   gl.gl_offs = 0;
255
256   /* Attempt to match the argument.  Return just word (minus quoting) if no match. */
257   if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
258     return 0;
259
260   /* Allocate enough space in argv for the matched filenames. */
261   n = argc;
262   if ((argc += gl.gl_pathc) > argvlen)
263     {
264       argvlen = argc + 10;
265       argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
266     }
267
268   /* Copy the matched filenames to argv. */
269   char **gv = gl.gl_pathv;
270   char **av = argv + n;
271   while (*gv)
272     {
273       debug_printf ("argv[%d] = '%s'", n++, *gv);
274       *av++ = *gv++;
275     }
276
277   /* Clean up after glob. */
278   free (gl.gl_pathv);
279   return 1;
280 }
281
282 /* Build argv, argc from string passed from Windows.  */
283
284 static void __stdcall
285 build_argv (char *cmd, char **&argv, int &argc, int winshell)
286 {
287   int argvlen = 0;
288   int nesting = 0;              // monitor "nesting" from insert_file
289
290   argc = 0;
291   argvlen = 0;
292   argv = NULL;
293
294   /* Scan command line until there is nothing left. */
295   while (*cmd)
296     {
297       /* Ignore spaces */
298       if (issep (*cmd))
299         {
300           cmd++;
301           continue;
302         }
303
304       /* Found the beginning of an argument. */
305       char *word = cmd;
306       char *sawquote = NULL;
307       while (*cmd)
308         {
309           if (*cmd != '"' && (!winshell || *cmd != '\''))
310             cmd++;              // Skip over this character
311           else
312             /* Skip over characters until the closing quote */
313             {
314               sawquote = cmd;
315               cmd = quoted (cmd, winshell && argc > 0);
316             }
317           if (issep (*cmd))     // End of argument if space
318             break;
319         }
320       if (*cmd)
321         *cmd++ = '\0';          // Terminate `word'
322
323       /* Possibly look for @file construction assuming that this isn't
324          the very first argument and the @ wasn't quoted */
325       if (argc && sawquote != word && *word == '@')
326         {
327           if (++nesting > MAX_AT_FILE_LEVEL)
328             api_fatal ("Too many levels of nesting for %s", word);
329           if (insert_file (word, cmd))
330               continue;                 // There's new stuff in cmd now
331         }
332
333       /* See if we need to allocate more space for argv */
334       if (argc >= argvlen)
335         {
336           argvlen = argc + 10;
337           argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
338         }
339
340       /* Add word to argv file after (optional) wildcard expansion. */
341       if (!winshell || !argc || !globify (word, argv, argc, argvlen))
342         {
343           debug_printf ("argv[%d] = '%s'", argc, word);
344           argv[argc++] = word;
345         }
346     }
347
348   argv[argc] = NULL;
349
350   debug_printf ("argc %d", argc);
351 }
352
353 /* sanity and sync check */
354 void __stdcall
355 check_sanity_and_sync (per_process *p)
356 {
357   /* Sanity check to make sure developers didn't change the per_process    */
358   /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
359   /* about changing it].                                                   */
360   if (sizeof (per_process) != SIZEOF_PER_PROCESS)
361     api_fatal ("per_process sanity check failed");
362
363   /* Make sure that the app and the dll are in sync. */
364
365   /* Complain if older than last incompatible change */
366   if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
367     api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
368                p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
369
370   /* magic_biscuit != 0 if using the old style version numbering scheme.  */
371   if (p->magic_biscuit != SIZEOF_PER_PROCESS)
372     api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
373                p->magic_biscuit, SIZEOF_PER_PROCESS);
374
375   /* Complain if incompatible API changes made */
376   if (p->api_major > cygwin_version.api_major)
377     api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
378                p->api_major, cygwin_version.api_major);
379
380   /* This is a kludge to work around a version of _cygwin_common_crt0
381      which overwrote the cxx_malloc field with the local DLL copy.
382      Hilarity ensues if the DLL is not loaded while the process
383      is forking. */
384   __cygwin_user_data.cxx_malloc = &default_cygwin_cxx_malloc;
385 }
386
387 child_info NO_COPY *child_proc_info = NULL;
388
389 #define CYGWIN_GUARD (PAGE_READWRITE | PAGE_GUARD)
390
391 void
392 child_info_fork::alloc_stack_hard_way (volatile char *b)
393 {
394   void *stack_ptr;
395   DWORD stacksize;
396
397   /* First check if the requested stack area is part of the user heap
398      or part of a mmapped region.  If so, we have been started from a
399      pthread with an application-provided stack, and the stack has just
400      to be used as is. */
401   if ((stacktop >= cygheap->user_heap.base
402       && stackbottom <= cygheap->user_heap.max)
403       || is_mmapped_region ((caddr_t) stacktop, (caddr_t) stackbottom))
404     return;
405
406   /* First, try to reserve the entire stack. */
407   stacksize = (char *) stackbottom - (char *) stackaddr;
408   if (!VirtualAlloc (stackaddr, stacksize, MEM_RESERVE, PAGE_NOACCESS))
409     api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
410                stackaddr, stackbottom);
411   stacksize = (char *) stackbottom - (char *) stacktop;
412   stack_ptr = VirtualAlloc (stacktop, stacksize, MEM_COMMIT, PAGE_READWRITE);
413   if (!stack_ptr)
414     abort ("can't commit memory for stack %p(%d), %E", stacktop, stacksize);
415   if (guardsize != (size_t) -1)
416     {
417       /* Allocate PAGE_GUARD page if it still fits. */
418       if (stack_ptr > stackaddr)
419         {
420           stack_ptr = (void *) ((LPBYTE) stack_ptr
421                                         - wincap.page_size ());
422           if (!VirtualAlloc (stack_ptr, wincap.page_size (), MEM_COMMIT,
423                              CYGWIN_GUARD))
424             api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
425                        stack_ptr);
426         }
427       /* Allocate POSIX guard pages. */
428       if (guardsize > 0)
429         VirtualAlloc (stackaddr, guardsize, MEM_COMMIT, PAGE_NOACCESS);
430     }
431   b[0] = '\0';
432 }
433
434 void *getstack (void *) __attribute__ ((noinline));
435 volatile char *
436 getstack (volatile char * volatile p)
437 {
438   *p ^= 1;
439   *p ^= 1;
440   return p - 4096;
441 }
442
443 /* extend the stack prior to fork longjmp */
444
445 void
446 child_info_fork::alloc_stack ()
447 {
448   volatile char * volatile esp;
449   __asm__ volatile ("movl %%esp,%0": "=r" (esp));
450   /* Make sure not to try a hard allocation if we have been forked off from
451      the main thread of a Cygwin process which has been started from a 64 bit
452      parent.  In that case the _tlsbase of the forked child is not the same
453      as the _tlsbase of the parent (== stackbottom), but only because the
454      stack of the parent has been slightly rearranged.  See comment in
455      wow64_revert_to_original_stack for details. We check here if the
456      parent stack fits into the child stack. */
457   if (_tlsbase != stackbottom
458       && (!wincap.is_wow64 ()
459           || stacktop < (char *) NtCurrentTeb ()->DeallocationStack
460           || stackbottom > _tlsbase))
461     alloc_stack_hard_way (esp);
462   else
463     {
464       char *st = (char *) stacktop - 4096;
465       while (_tlstop >= st)
466         esp = getstack (esp);
467       stackaddr = 0;
468       /* This only affects forked children of a process started from a native
469          64 bit process, but it doesn't hurt to do it unconditionally.  Fix
470          StackBase in the child to be the same as in the parent, so that the
471          computation of _my_tls is correct. */
472       _tlsbase = (char *) stackbottom;
473     }
474 }
475
476 extern "C" void
477 break_here ()
478 {
479   static int NO_COPY sent_break;
480   if (!sent_break++)
481     DebugBreak ();
482   debug_printf ("break here");
483 }
484
485 static void
486 initial_env ()
487 {
488   if (GetEnvironmentVariableA ("CYGWIN_TESTING", NULL, 0))
489     _cygwin_testing = 1;
490
491 #ifdef DEBUGGING
492   DWORD len;
493   char buf[NT_MAX_PATH];
494   if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
495     {
496       char buf1[NT_MAX_PATH];
497       len = GetModuleFileName (NULL, buf1, NT_MAX_PATH);
498       strlwr (buf1);
499       strlwr (buf);
500       char *p = strpbrk (buf, ":=");
501       if (!p)
502         p = (char *) "gdb.exe -nw";
503       else
504         *p++ = '\0';
505       if (strstr (buf1, buf))
506         {
507           error_start_init (p);
508           jit_debug = true;
509           try_to_debug ();
510           console_printf ("*** Sending Break.  gdb may issue spurious SIGTRAP message.\n");
511           break_here ();
512         }
513     }
514 #endif
515 }
516
517 child_info *
518 get_cygwin_startup_info ()
519 {
520   STARTUPINFO si;
521
522   GetStartupInfo (&si);
523   child_info *res = (child_info *) si.lpReserved2;
524
525   if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
526       || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
527     {
528       strace.activate (false);
529       res = NULL;
530     }
531   else
532     {
533       if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
534         multiple_cygwin_problem ("proc intro", res->intro, 0);
535       else if (res->cygheap != (void *) &_cygheap_start)
536         multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
537                                  (DWORD) &_cygheap_start);
538
539       unsigned should_be_cb = 0;
540       switch (res->type)
541         {
542           case _CH_FORK:
543             in_forkee = true;
544             should_be_cb = sizeof (child_info_fork);
545             /* fall through */;
546           case _CH_SPAWN:
547           case _CH_EXEC:
548             if (!should_be_cb)
549               should_be_cb = sizeof (child_info_spawn);
550             if (should_be_cb != res->cb)
551               multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
552             else if (sizeof (fhandler_union) != res->fhandler_union_cb)
553               multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
554             if (res->isstraced ())
555               {
556                 while (!being_debugged ())
557                   yield ();
558                 strace.activate (res->type == _CH_FORK);
559               }
560             break;
561           default:
562             system_printf ("unknown exec type %d", res->type);
563             /* intentionally fall through */
564           case _CH_WHOOPS:
565             res = NULL;
566             break;
567         }
568     }
569
570   return res;
571 }
572
573 #define dll_data_start &_data_start__
574 #define dll_data_end &_data_end__
575 #define dll_bss_start &_bss_start__
576 #define dll_bss_end &_bss_end__
577
578 void
579 child_info_fork::handle_fork ()
580 {
581   cygheap_fixup_in_child (false);
582   memory_init (false);
583   myself.thisproc (NULL);
584   myself->uid = cygheap->user.real_uid;
585   myself->gid = cygheap->user.real_gid;
586
587   child_copy (parent, false,
588               "dll data", dll_data_start, dll_data_end,
589               "dll bss", dll_bss_start, dll_bss_end,
590               "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
591               NULL);
592
593   /* Do the relocations here.  These will actually likely be overwritten by the
594      below child_copy but we do them here in case there is a read-only section
595      which does not get copied by fork. */
596   _pei386_runtime_relocator (user_data);
597
598   /* step 2 now that the dll has its heap filled in, we can fill in the
599      user's data and bss since user_data is now filled out. */
600   child_copy (parent, false,
601               "data", user_data->data_start, user_data->data_end,
602               "bss", user_data->bss_start, user_data->bss_end,
603               NULL);
604
605   if (fixup_mmaps_after_fork (parent))
606     api_fatal ("recreate_mmaps_after_fork_failed");
607 }
608
609 void
610 child_info_spawn::handle_spawn ()
611 {
612   extern void fixup_lockf_after_exec ();
613   HANDLE h;
614   cygheap_fixup_in_child (true);
615   memory_init (false);
616   if (!moreinfo->myself_pinfo ||
617       !DuplicateHandle (GetCurrentProcess (), moreinfo->myself_pinfo,
618                         GetCurrentProcess (), &h, 0,
619                         FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
620     h = NULL;
621   myself.thisproc (h);
622   __argc = moreinfo->argc;
623   __argv = moreinfo->argv;
624   envp = moreinfo->envp;
625   envc = moreinfo->envc;
626   if (!dynamically_loaded)
627     cygheap->fdtab.fixup_after_exec ();
628   if (__stdin >= 0)
629     cygheap->fdtab.move_fd (__stdin, 0);
630   if (__stdout >= 0)
631     cygheap->fdtab.move_fd (__stdout, 1);
632   cygheap->user.groups.clear_supp ();
633
634   /* If we're execing we may have "inherited" a list of children forked by the
635      previous process executing under this pid.  Reattach them here so that we
636      can wait for them.  */
637   if (type == _CH_EXEC)
638     reattach_children ();
639
640   ready (true);
641
642   /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
643      handles might get confused. */
644   CloseHandle (child_proc_info->parent);
645   child_proc_info->parent = NULL;
646
647   signal_fixup_after_exec ();
648   fixup_lockf_after_exec ();
649 }
650
651 /* Retrieve and store system directory for later use.  Note that the
652    directory is stored with a trailing backslash! */
653 static void
654 init_windows_system_directory ()
655 {
656   if (!windows_system_directory_length)
657     {
658       windows_system_directory_length =
659             GetSystemDirectoryW (windows_system_directory, MAX_PATH);
660       if (windows_system_directory_length == 0)
661         api_fatal ("can't find windows system directory");
662       windows_system_directory[windows_system_directory_length++] = L'\\';
663       windows_system_directory[windows_system_directory_length] = L'\0';
664
665       system_wow64_directory_length =
666         GetSystemWow64DirectoryW (system_wow64_directory, MAX_PATH);
667       if (system_wow64_directory_length)
668         {
669           system_wow64_directory[system_wow64_directory_length++] = L'\\';
670           system_wow64_directory[system_wow64_directory_length] = L'\0';
671         }
672     }
673 }
674
675 void
676 dll_crt0_0 ()
677 {
678   child_proc_info = get_cygwin_startup_info ();
679   init_windows_system_directory ();
680   init_global_security ();
681   initial_env ();
682
683   SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
684
685   lock_process::init ();
686   _impure_ptr = _GLOBAL_REENT;
687   _impure_ptr->_stdin = &_impure_ptr->__sf[0];
688   _impure_ptr->_stdout = &_impure_ptr->__sf[1];
689   _impure_ptr->_stderr = &_impure_ptr->__sf[2];
690   _impure_ptr->_current_locale = "C";
691   user_data->impure_ptr = _impure_ptr;
692   user_data->impure_ptr_ptr = &_impure_ptr;
693
694   DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
695                    GetCurrentProcess (), &hMainThread,
696                    0, false, DUPLICATE_SAME_ACCESS);
697
698   NtOpenProcessToken (NtCurrentProcess (), MAXIMUM_ALLOWED, &hProcToken);
699   set_cygwin_privileges (hProcToken);
700
701   device::init ();
702   do_global_ctors (&__CTOR_LIST__, 1);
703   cygthread::init ();
704
705   if (!child_proc_info)
706     {
707       memory_init (true);
708       /* WOW64 process on XP/64 or Server 2003/64?  Check if we have been
709          started from 64 bit process and if our stack is at an unusual
710          address.  Set wow64_needs_stack_adjustment if so.  Problem
711          description in wow64_test_for_64bit_parent. */
712       if (wincap.wow64_has_secondary_stack ())
713         wow64_needs_stack_adjustment = wow64_test_for_64bit_parent ();
714     }
715   else
716     {
717       cygwin_user_h = child_proc_info->user_h;
718       switch (child_proc_info->type)
719         {
720           case _CH_FORK:
721             fork_info->handle_fork ();
722             break;
723           case _CH_SPAWN:
724           case _CH_EXEC:
725             spawn_info->handle_spawn ();
726             break;
727         }
728     }
729
730   user_data->threadinterface->Init ();
731
732   _cygtls::init ();
733
734   /* Initialize events */
735   events_init ();
736   tty_list::init_session ();
737
738   _main_tls = &_my_tls;
739
740   /* Initialize signal processing here, early, in the hopes that the creation
741      of a thread early in the process will cause more predictability in memory
742      layout for the main thread. */
743   if (!dynamically_loaded)
744     sigproc_init ();
745
746   debug_printf ("finished dll_crt0_0 initialization");
747 }
748
749 /* Take over from libc's crt0.o and start the application. Note the
750    various special cases when Cygwin DLL is being runtime loaded (as
751    opposed to being link-time loaded by Cygwin apps) from a non
752    cygwin app via LoadLibrary.  */
753 void
754 dll_crt0_1 (void *)
755 {
756   extern void initial_setlocale ();
757
758   if (dynamically_loaded)
759     sigproc_init ();
760
761   check_sanity_and_sync (user_data);
762
763   /* Initialize malloc and then call user_shared_initialize since it relies
764      on a functioning malloc and it's possible that the user's program may
765      have overridden malloc.  We only know about that at this stage,
766      unfortunately. */
767   malloc_init ();
768   user_shared->initialize ();
769
770 #ifdef CYGHEAP_DEBUG
771   int i = 0;
772   const int n = 2 * 1024 * 1024;
773   while (i--)
774     {
775       void *p = cmalloc (HEAP_STR, n);
776       if (p)
777         small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
778       else
779         {
780           small_printf ("total allocated %p\n", (i - 1) * n);
781           break;
782         }
783     }
784 #endif
785
786   ProtectHandle (hMainThread);
787
788   cygheap->cwd.init ();
789
790   /* Initialize pthread mainthread when not forked and it is safe to call new,
791      otherwise it is reinitalized in fixup_after_fork */
792   if (!in_forkee)
793     {
794       pthread::init_mainthread ();
795       _pei386_runtime_relocator (user_data);
796     }
797
798 #ifdef DEBUGGING
799   strace.microseconds ();
800 #endif
801
802   create_signal_arrived (); /* FIXME: move into wait_sig? */
803
804   /* Initialize debug muto, if DLL is built with --enable-debugging.
805      Need to do this before any helper threads start. */
806   debug_init ();
807
808 #ifdef NEWVFORK
809   cygheap->fdtab.vfork_child_fixup ();
810   main_vfork = vfork_storage.create ();
811 #endif
812
813   cygbench ("pre-forkee");
814   if (in_forkee)
815     {
816       /* If we've played with the stack, stacksize != 0.  That means that
817          fork() was invoked from other than the main thread.  Make sure that
818          frame pointer is referencing the new stack so that the OS knows what
819          to do when it needs to increase the size of the stack.
820
821          NOTE: Don't do anything that involves the stack until you've completed
822          this step. */
823       if (fork_info->stackaddr)
824         {
825           _tlsbase = (char *) fork_info->stackbottom;
826           _tlstop = (char *) fork_info->stacktop;
827         }
828
829       longjmp (fork_info->jmp, true);
830     }
831
832   __sinit (_impure_ptr);
833
834 #ifdef DEBUGGING
835   {
836   extern void fork_init ();
837   fork_init ();
838   }
839 #endif
840   pinfo_init (envp, envc);
841   strace.dll_info ();
842
843   /* Allocate cygheap->fdtab */
844   dtable_init ();
845
846   uinfo_init ();        /* initialize user info */
847
848   /* Connect to tty. */
849   tty::init_session ();
850
851   /* Set internal locale to the environment settings. */
852   initial_setlocale ();
853
854   if (!__argc)
855     {
856       PWCHAR wline = GetCommandLineW ();
857       size_t size = sys_wcstombs (NULL, 0, wline);
858       char *line = (char *) alloca (size);
859       sys_wcstombs (line, size, wline);
860
861       /* Scan the command line and build argv.  Expand wildcards if not
862          called from another cygwin process. */
863       build_argv (line, __argv, __argc,
864                   NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
865
866       /* Convert argv[0] to posix rules if it's currently blatantly
867          win32 style. */
868       if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
869         {
870           char *new_argv0 = (char *) malloc (NT_MAX_PATH);
871           cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
872                             new_argv0, NT_MAX_PATH);
873           __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
874         }
875     }
876
877   __argc_safe = __argc;
878   if (user_data->premain[0])
879     for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
880       user_data->premain[i] (__argc, __argv, user_data);
881
882   /* Set up standard fds in file descriptor table. */
883   cygheap->fdtab.stdio_init ();
884
885   /* Set up __progname for getopt error call. */
886   if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
887     ++__progname;
888   else
889     __progname = __argv[0];
890   program_invocation_name = __argv[0];
891   program_invocation_short_name = __progname;
892   if (__progname)
893     {
894       char *cp = strchr (__progname, '\0') - 4;
895       if (cp > __progname && ascii_strcasematch (cp, ".exe"))
896         *cp = '\0';
897     }
898
899   (void) xdr_set_vprintf (&cygxdr_vwarnx);
900   cygwin_finished_initializing = true;
901   /* Call init of loaded dlls. */
902   dlls.init ();
903
904   /* Execute any specified "premain" functions */
905   if (user_data->premain[PREMAIN_LEN / 2])
906     for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
907       user_data->premain[i] (__argc, __argv, user_data);
908
909   set_errno (0);
910
911   if (dynamically_loaded)
912     {
913       _setlocale_r (_REENT, LC_CTYPE, "C");
914       return;
915     }
916
917   /* Disable case-insensitive globbing */
918   ignore_case_with_glob = false;
919
920   MALLOC_CHECK;
921   cygbench (__progname);
922
923   ld_preload ();
924   /* Per POSIX set the default application locale back to "C". */
925   _setlocale_r (_REENT, LC_CTYPE, "C");
926
927   if (user_data->main)
928     {
929       /* Create a copy of Cygwin's version of __argv so that, if the user makes
930          a change to an element of argv[] it does not affect Cygwin's argv.
931          Changing the the contents of what argv[n] points to will still
932          affect Cygwin.  This is similar (but not exactly like) Linux. */
933       char *newargv[__argc + 1];
934       char **nav = newargv;
935       char **oav = __argv;
936       while ((*nav++ = *oav++) != NULL)
937         continue;
938       cygwin_exit (user_data->main (__argc, newargv, *user_data->envptr));
939     }
940   __asm__ ("                            \n\
941         .global __cygwin_exit_return    \n\
942 __cygwin_exit_return:                   \n\
943 ");
944 }
945
946 extern "C" void __stdcall
947 _dll_crt0 ()
948 {
949   /* Handle WOW64 process on XP/2K3 which has been started from native 64 bit
950      process.  See comment in wow64_test_for_64bit_parent for a full problem
951      description. */
952   if (wow64_needs_stack_adjustment && !dynamically_loaded)
953     {
954       /* Must be static since it's referenced after the stack pointers have
955          been moved. */
956       static PVOID allocationbase = 0;
957
958       /* Check if we just move the stack.  See comment in
959          wow64_revert_to_original_stack for the gory details. */
960       PVOID stackaddr = wow64_revert_to_original_stack (allocationbase);
961       if (stackaddr)
962         {
963           /* 2nd half of the stack move.  Set stack pointers to new address. */
964           __asm__ ("\n\
965                    movl  %[ADDR], %%esp \n\
966                    movl  %%esp, %%ebp   \n"
967                    : : [ADDR] "r" (stackaddr));
968           /* Now we're back on the original stack.  Free up space taken by the
969              former main thread stack and set DeallocationStack correctly. */
970           VirtualFree (NtCurrentTeb ()->DeallocationStack, 0, MEM_RELEASE);
971           NtCurrentTeb ()->DeallocationStack = allocationbase;
972         }
973       else
974         /* Fall back to respawn if wow64_revert_to_original_stack fails. */
975         wow64_respawn_process ();
976     }
977 #ifdef __i386__
978   _feinitialise ();
979 #endif
980   main_environ = user_data->envptr;
981   if (in_forkee)
982     {
983       fork_info->alloc_stack ();
984       _main_tls = &_my_tls;
985     }
986
987   _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
988 }
989
990 void
991 dll_crt0 (per_process *uptr)
992 {
993   /* Set the local copy of the pointer into the user space. */
994   if (!in_forkee && uptr && uptr != user_data)
995     {
996       memcpy (user_data, uptr, per_process_overwrite);
997       *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
998     }
999   _dll_crt0 ();
1000 }
1001
1002 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
1003    You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
1004    calling this function, and that storage must not be overwritten until you
1005    unload cygwin1.dll, as it is used for _my_tls.  It is best to load
1006    cygwin1.dll before spawning any additional threads in your process.
1007
1008    See winsup/testsuite/cygload for an example of how to use cygwin1.dll
1009    from MSVC and non-cygwin MinGW applications.  */
1010 extern "C" void
1011 cygwin_dll_init ()
1012 {
1013   static char **envp;
1014   static int _fmode;
1015
1016   user_data->magic_biscuit = sizeof (per_process);
1017
1018   user_data->envptr = &envp;
1019   user_data->fmode_ptr = &_fmode;
1020
1021   _dll_crt0 ();
1022 }
1023
1024 extern "C" void
1025 __main (void)
1026 {
1027   /* Ordering is critical here.  DLL ctors have already been
1028      run as they were being loaded, so we should stack the
1029      queued call to DLL dtors now.  */
1030   atexit (dll_global_dtors);
1031   do_global_ctors (user_data->ctors, false);
1032   /* Now we have run global ctors, register their dtors.
1033
1034      At exit, global dtors will run first, so the app can still
1035      use shared library functions while terminating; then the
1036      DLLs will be destroyed; finally newlib will shut down stdio
1037      and terminate itself.  */
1038   atexit (do_global_dtors);
1039   sig_dispatch_pending (true);
1040 }
1041
1042 void __stdcall
1043 do_exit (int status)
1044 {
1045   syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1046
1047 #ifdef NEWVFORK
1048   vfork_save *vf = vfork_storage.val ();
1049   if (vf != NULL && vf->pid < 0)
1050     {
1051       exit_state = ES_NOT_EXITING;
1052       vf->restore_exit (status);
1053     }
1054 #endif
1055
1056   lock_process until_exit (true);
1057
1058   if (exit_state < ES_EVENTS_TERMINATE)
1059     {
1060       exit_state = ES_EVENTS_TERMINATE;
1061       events_terminate ();
1062     }
1063
1064   if (exit_state < ES_SIGNAL)
1065     {
1066       exit_state = ES_SIGNAL;
1067       signal (SIGCHLD, SIG_IGN);
1068       signal (SIGHUP, SIG_IGN);
1069       signal (SIGINT, SIG_IGN);
1070       signal (SIGQUIT, SIG_IGN);
1071     }
1072
1073   if (exit_state < ES_CLOSEALL)
1074     {
1075       exit_state = ES_CLOSEALL;
1076       close_all_files ();
1077     }
1078
1079   UINT n = (UINT) status;
1080   if (exit_state < ES_THREADTERM)
1081     {
1082       exit_state = ES_THREADTERM;
1083       cygthread::terminate ();
1084     }
1085
1086   myself->stopsig = 0;
1087
1088   if (exit_state < ES_HUP_PGRP)
1089     {
1090       exit_state = ES_HUP_PGRP;
1091       /* Kill orphaned children on group leader exit */
1092       if (myself->has_pgid_children && myself->pid == myself->pgid)
1093         {
1094           siginfo_t si = {0};
1095           si.si_signo = -SIGHUP;
1096           si.si_code = SI_KERNEL;
1097           sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1098                           myself->pid, myself->pgid);
1099           kill_pgrp (myself->pgid, si);
1100         }
1101     }
1102
1103   if (exit_state < ES_HUP_SID)
1104     {
1105       exit_state = ES_HUP_SID;
1106       /* Kill the foreground process group on session leader exit */
1107       if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1108         {
1109           tty *tp = cygwin_shared->tty[myself->ctty];
1110           sigproc_printf ("%d == sid %d, send SIGHUP to children",
1111                           myself->pid, myself->sid);
1112
1113         /* CGF FIXME: This can't be right. */
1114           if (tp->getsid () == myself->sid)
1115             tp->kill_pgrp (SIGHUP);
1116         }
1117
1118     }
1119
1120   myself.exit (n);
1121 }
1122
1123 extern "C" int
1124 cygwin_atexit (void (*fn) (void))
1125 {
1126   int res;
1127   dll *d = dlls.find ((void *) _my_tls.retaddr ());
1128   res = d ? __cxa_atexit ((void (*) (void *)) fn, NULL, d) : atexit (fn);
1129   return res;
1130 }
1131
1132 extern "C" void
1133 cygwin_exit (int n)
1134 {
1135   exit_state = ES_EXIT_STARTING;
1136   exit (n);
1137 }
1138
1139 extern "C" void
1140 _exit (int n)
1141 {
1142   do_exit (((DWORD) n & 0xff) << 8);
1143 }
1144
1145 extern "C" void cygwin_stackdump ();
1146
1147 extern "C" void
1148 vapi_fatal (const char *fmt, va_list ap)
1149 {
1150   char buf[4096];
1151   int n = __small_sprintf (buf, "%P: *** fatal error %s- ", in_forkee ? "in forked process " : "");
1152   __small_vsprintf (buf + n, fmt, ap);
1153   va_end (ap);
1154   strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1155
1156 #ifdef DEBUGGING
1157   try_to_debug ();
1158 #endif
1159   cygwin_stackdump ();
1160   myself.exit (__api_fatal_exit_val);
1161 }
1162
1163 extern "C" void
1164 api_fatal (const char *fmt, ...)
1165 {
1166   va_list ap;
1167
1168   va_start (ap, fmt);
1169   vapi_fatal (fmt, ap);
1170 }
1171
1172 void
1173 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1174 {
1175   if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1176     {
1177       child_proc_info->type = _CH_WHOOPS;
1178       return;
1179     }
1180
1181   if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
1182     return;
1183
1184   if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1185     system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1186   else
1187     api_fatal ("%s mismatch detected - %p/%p.\n\
1188 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1189 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1190 and delete all but the most recent version.  The most recent version *should*\n\
1191 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1192 installed the cygwin distribution.  Rebooting is also suggested if you\n\
1193 are unable to find another cygwin DLL.",
1194                what, magic_version, version);
1195 }
1196
1197 #ifdef DEBUGGING
1198 void __stdcall
1199 cygbench (const char *s)
1200 {
1201   if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1202     small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());
1203 }
1204 #endif