OSDN Git Service

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