OSDN Git Service

* fhandler_console.cc (fhandler_console::read): Revert change from
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / init.cc
1 /* init.cc
2
3    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4    2006, 2007, 2008, 2009 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 "cygtls.h"
14 #include "ntdll.h"
15 #include "shared_info.h"
16
17 static DWORD _my_oldfunc;
18
19 static char NO_COPY *search_for = (char *) cygthread::stub;
20 unsigned threadfunc_ix[8] __attribute__((section (".cygwin_dll_common"), shared));
21 extern cygthread *hwait_sig;
22
23 #define OLDFUNC_OFFSET -1
24
25 static void WINAPI
26 threadfunc_fe (VOID *arg)
27 {
28   (void)__builtin_return_address(1);
29   asm volatile ("andl $-16,%%esp" ::: "%esp");
30   _cygtls::call ((DWORD (*)  (void *, void *)) TlsGetValue (_my_oldfunc), arg);
31 }
32
33 /* If possible, redirect the thread entry point to a cygwin routine which
34    adds tls stuff to the stack. */
35 static void
36 munge_threadfunc ()
37 {
38   int i;
39   char **ebp = (char **) __builtin_frame_address (0);
40   if (!threadfunc_ix[0])
41     {
42       char **peb;
43       char **top = (char **) _tlsbase;
44       for (peb = ebp, i = 0; peb < top && i < 7; peb++)
45         if (*peb == search_for)
46           threadfunc_ix[i++] = peb - ebp;
47       if (0 && !threadfunc_ix[0])
48         {
49           try_to_debug ();
50           return;
51         }
52     }
53
54   if (threadfunc_ix[0])
55     {
56       char *threadfunc = ebp[threadfunc_ix[0]];
57       if (!search_for || threadfunc == search_for)
58         {
59           search_for = NULL;
60           for (i = 0; threadfunc_ix[i]; i++)
61             ebp[threadfunc_ix[i]] = (char *) threadfunc_fe;
62           TlsSetValue (_my_oldfunc, threadfunc);
63         }
64     }
65 }
66
67 inline static void
68 respawn_wow64_process ()
69 {
70   NTSTATUS ret;
71   PROCESS_BASIC_INFORMATION pbi;
72   HANDLE parent;
73
74   ULONG wow64 = TRUE;   /* Opt on the safe side. */
75
76   /* Unfortunately there's no simpler way to retrieve the
77      parent process in NT, as far as I know.  Hints welcome. */
78   ret = NtQueryInformationProcess (GetCurrentProcess (),
79                                    ProcessBasicInformation,
80                                    &pbi, sizeof pbi, NULL);
81   if (NT_SUCCESS (ret)
82       && (parent = OpenProcess (PROCESS_QUERY_INFORMATION,
83                                 FALSE,
84                                 pbi.InheritedFromUniqueProcessId)))
85     {
86       NtQueryInformationProcess (parent, ProcessWow64Information,
87                                  &wow64, sizeof wow64, NULL);
88       CloseHandle (parent);
89     }
90
91   /* The parent is a real 64 bit process?  Respawn! */
92   if (!wow64)
93     {
94       PROCESS_INFORMATION pi;
95       STARTUPINFOW si;
96       DWORD ret = 0;
97
98       GetStartupInfoW (&si);
99       if (!CreateProcessW (NULL, GetCommandLineW (), NULL, NULL, TRUE,
100                            CREATE_DEFAULT_ERROR_MODE
101                            | GetPriorityClass (GetCurrentProcess ()),
102                            NULL, NULL, &si, &pi))
103         api_fatal ("Failed to create process <%s>, %E", GetCommandLineA ());
104       CloseHandle (pi.hThread);
105       if (WaitForSingleObject (pi.hProcess, INFINITE) == WAIT_FAILED)
106         api_fatal ("Waiting for process %d failed, %E", pi.dwProcessId);
107       GetExitCodeProcess (pi.hProcess, &ret);
108       CloseHandle (pi.hProcess);
109       ExitProcess (ret);
110     }
111 }
112
113 extern void __stdcall dll_crt0_0 ();
114
115 extern "C" BOOL WINAPI
116 dll_entry (HANDLE h, DWORD reason, void *static_load)
117 {
118   BOOL wow64_test_stack_marker;
119
120   switch (reason)
121     {
122     case DLL_PROCESS_ATTACH:
123       wincap.init ();
124       init_console_handler (false);
125
126       cygwin_hmodule = (HMODULE) h;
127       dynamically_loaded = (static_load == NULL);
128
129       /* Is the stack at an unusual address?  This is, an address which
130          is in the usual space occupied by the process image, but below
131          the auto load address of DLLs?
132          Check if we're running in WOW64 on a 64 bit machine *and* are
133          spawned by a genuine 64 bit process.  If so, respawn. */
134       if (wincap.is_wow64 ()
135           && &wow64_test_stack_marker >= (PBOOL) 0x400000
136           && &wow64_test_stack_marker <= (PBOOL) 0x10000000)
137         respawn_wow64_process ();
138
139       dll_crt0_0 ();
140       _my_oldfunc = TlsAlloc ();
141       break;
142     case DLL_PROCESS_DETACH:
143       if (dynamically_loaded)
144         shared_destroy ();
145       break;
146     case DLL_THREAD_ATTACH:
147       if (hwait_sig)
148         munge_threadfunc ();
149       break;
150     case DLL_THREAD_DETACH:
151       if (hwait_sig && (void *) &_my_tls > (void *) &wow64_test_stack_marker
152           && _my_tls.isinitialized ())
153         _my_tls.remove (0);
154       break;
155     }
156
157   return TRUE;
158 }