2001-09-11 13:01:02 -07:00
|
|
|
/* init.cc
|
2000-02-17 11:38:33 -08:00
|
|
|
|
2006-01-12 07:53:51 -08:00
|
|
|
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
2009-01-02 21:12:22 -08:00
|
|
|
2006, 2007, 2008, 2009 Red Hat, Inc.
|
2000-02-17 11:38:33 -08:00
|
|
|
|
|
|
|
This file is part of Cygwin.
|
|
|
|
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
|
|
details. */
|
|
|
|
|
|
|
|
#include "winsup.h"
|
2003-11-28 12:55:59 -08:00
|
|
|
#include "cygtls.h"
|
2005-08-14 12:48:07 -07:00
|
|
|
#include "ntdll.h"
|
2008-07-27 07:52:46 -07:00
|
|
|
#include "shared_info.h"
|
2000-02-17 11:38:33 -08:00
|
|
|
|
2006-05-15 20:14:24 -07:00
|
|
|
static DWORD _my_oldfunc;
|
|
|
|
|
2006-03-12 15:57:05 -08:00
|
|
|
static char NO_COPY *search_for = (char *) cygthread::stub;
|
2005-06-09 12:29:27 -07:00
|
|
|
unsigned threadfunc_ix[8] __attribute__((section (".cygwin_dll_common"), shared));
|
2006-03-12 15:57:05 -08:00
|
|
|
extern cygthread *hwait_sig;
|
2004-01-14 07:45:37 -08:00
|
|
|
|
|
|
|
#define OLDFUNC_OFFSET -1
|
2000-02-17 11:38:33 -08:00
|
|
|
|
2003-12-13 23:09:22 -08:00
|
|
|
static void WINAPI
|
|
|
|
threadfunc_fe (VOID *arg)
|
|
|
|
{
|
2004-04-30 06:27:27 -07:00
|
|
|
(void)__builtin_return_address(1);
|
|
|
|
asm volatile ("andl $-16,%%esp" ::: "%esp");
|
2006-05-15 20:14:24 -07:00
|
|
|
_cygtls::call ((DWORD (*) (void *, void *)) TlsGetValue (_my_oldfunc), arg);
|
2004-01-14 07:45:37 -08:00
|
|
|
}
|
|
|
|
|
2004-01-19 15:03:43 -08:00
|
|
|
/* If possible, redirect the thread entry point to a cygwin routine which
|
|
|
|
adds tls stuff to the stack. */
|
2003-12-13 23:09:22 -08:00
|
|
|
static void
|
2004-02-13 11:34:32 -08:00
|
|
|
munge_threadfunc ()
|
2003-12-13 23:09:22 -08:00
|
|
|
{
|
2004-03-22 10:30:38 -08:00
|
|
|
int i;
|
2004-01-14 07:45:37 -08:00
|
|
|
char **ebp = (char **) __builtin_frame_address (0);
|
2004-03-22 10:30:38 -08:00
|
|
|
if (!threadfunc_ix[0])
|
2003-12-13 23:09:22 -08:00
|
|
|
{
|
2004-03-22 10:30:38 -08:00
|
|
|
char **peb;
|
|
|
|
char **top = (char **) _tlsbase;
|
|
|
|
for (peb = ebp, i = 0; peb < top && i < 7; peb++)
|
2004-01-14 07:45:37 -08:00
|
|
|
if (*peb == search_for)
|
2004-03-22 10:30:38 -08:00
|
|
|
threadfunc_ix[i++] = peb - ebp;
|
2005-12-29 12:46:34 -08:00
|
|
|
if (0 && !threadfunc_ix[0])
|
2004-03-22 10:30:38 -08:00
|
|
|
{
|
|
|
|
try_to_debug ();
|
|
|
|
return;
|
|
|
|
}
|
2003-12-13 23:09:22 -08:00
|
|
|
}
|
|
|
|
|
2006-03-12 15:57:05 -08:00
|
|
|
if (threadfunc_ix[0])
|
2004-01-14 07:45:37 -08:00
|
|
|
{
|
2006-03-12 15:57:05 -08:00
|
|
|
char *threadfunc = ebp[threadfunc_ix[0]];
|
|
|
|
if (!search_for || threadfunc == search_for)
|
|
|
|
{
|
|
|
|
search_for = NULL;
|
|
|
|
for (i = 0; threadfunc_ix[i]; i++)
|
|
|
|
ebp[threadfunc_ix[i]] = (char *) threadfunc_fe;
|
2006-05-15 20:14:24 -07:00
|
|
|
TlsSetValue (_my_oldfunc, threadfunc);
|
2006-03-12 15:57:05 -08:00
|
|
|
}
|
2004-01-14 07:45:37 -08:00
|
|
|
}
|
2003-12-13 23:09:22 -08:00
|
|
|
}
|
|
|
|
|
2005-08-14 12:48:07 -07:00
|
|
|
inline static void
|
2004-07-24 02:41:34 -07:00
|
|
|
respawn_wow64_process ()
|
|
|
|
{
|
2005-08-14 12:48:07 -07:00
|
|
|
NTSTATUS ret;
|
|
|
|
PROCESS_BASIC_INFORMATION pbi;
|
|
|
|
HANDLE parent;
|
|
|
|
|
2008-04-28 01:47:06 -07:00
|
|
|
ULONG wow64 = TRUE; /* Opt on the safe side. */
|
2005-08-14 12:48:07 -07:00
|
|
|
|
|
|
|
/* Unfortunately there's no simpler way to retrieve the
|
|
|
|
parent process in NT, as far as I know. Hints welcome. */
|
|
|
|
ret = NtQueryInformationProcess (GetCurrentProcess (),
|
|
|
|
ProcessBasicInformation,
|
2008-04-28 01:47:06 -07:00
|
|
|
&pbi, sizeof pbi, NULL);
|
|
|
|
if (NT_SUCCESS (ret)
|
2005-08-14 12:48:07 -07:00
|
|
|
&& (parent = OpenProcess (PROCESS_QUERY_INFORMATION,
|
|
|
|
FALSE,
|
|
|
|
pbi.InheritedFromUniqueProcessId)))
|
|
|
|
{
|
2008-04-28 01:47:06 -07:00
|
|
|
NtQueryInformationProcess (parent, ProcessWow64Information,
|
|
|
|
&wow64, sizeof wow64, NULL);
|
2005-08-14 12:48:07 -07:00
|
|
|
CloseHandle (parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The parent is a real 64 bit process? Respawn! */
|
2008-04-28 01:47:06 -07:00
|
|
|
if (!wow64)
|
2005-08-14 12:48:07 -07:00
|
|
|
{
|
|
|
|
PROCESS_INFORMATION pi;
|
2008-04-03 08:28:03 -07:00
|
|
|
STARTUPINFOW si;
|
2006-02-07 01:57:43 -08:00
|
|
|
DWORD ret = 0;
|
|
|
|
|
2008-04-03 08:28:03 -07:00
|
|
|
GetStartupInfoW (&si);
|
|
|
|
if (!CreateProcessW (NULL, GetCommandLineW (), NULL, NULL, TRUE,
|
2005-08-14 12:48:07 -07:00
|
|
|
CREATE_DEFAULT_ERROR_MODE
|
|
|
|
| GetPriorityClass (GetCurrentProcess ()),
|
|
|
|
NULL, NULL, &si, &pi))
|
|
|
|
api_fatal ("Failed to create process <%s>, %E", GetCommandLineA ());
|
|
|
|
CloseHandle (pi.hThread);
|
|
|
|
if (WaitForSingleObject (pi.hProcess, INFINITE) == WAIT_FAILED)
|
|
|
|
api_fatal ("Waiting for process %d failed, %E", pi.dwProcessId);
|
2006-02-07 01:57:43 -08:00
|
|
|
GetExitCodeProcess (pi.hProcess, &ret);
|
2005-08-14 12:48:07 -07:00
|
|
|
CloseHandle (pi.hProcess);
|
2006-02-07 01:57:43 -08:00
|
|
|
ExitProcess (ret);
|
2005-08-14 12:48:07 -07:00
|
|
|
}
|
2004-07-24 02:41:34 -07:00
|
|
|
}
|
|
|
|
|
2004-01-14 07:45:37 -08:00
|
|
|
extern void __stdcall dll_crt0_0 ();
|
|
|
|
|
2005-09-27 19:43:29 -07:00
|
|
|
extern "C" BOOL WINAPI
|
2003-12-13 23:09:22 -08:00
|
|
|
dll_entry (HANDLE h, DWORD reason, void *static_load)
|
2000-02-17 11:38:33 -08:00
|
|
|
{
|
2006-01-10 10:11:32 -08:00
|
|
|
BOOL wow64_test_stack_marker;
|
2006-02-23 11:21:21 -08:00
|
|
|
|
2000-02-17 11:38:33 -08:00
|
|
|
switch (reason)
|
|
|
|
{
|
|
|
|
case DLL_PROCESS_ATTACH:
|
2006-03-18 11:17:21 -08:00
|
|
|
wincap.init ();
|
|
|
|
init_console_handler (false);
|
|
|
|
|
2005-03-22 11:00:31 -08:00
|
|
|
cygwin_hmodule = (HMODULE) h;
|
2005-05-16 18:21:06 -07:00
|
|
|
dynamically_loaded = (static_load == NULL);
|
2005-08-14 12:48:07 -07:00
|
|
|
|
|
|
|
/* Is the stack at an unusual address? This is, an address which
|
2005-12-21 21:57:54 -08:00
|
|
|
is in the usual space occupied by the process image, but below
|
2005-08-14 12:48:07 -07:00
|
|
|
the auto load address of DLLs?
|
|
|
|
Check if we're running in WOW64 on a 64 bit machine *and* are
|
|
|
|
spawned by a genuine 64 bit process. If so, respawn. */
|
2006-01-10 10:11:32 -08:00
|
|
|
if (wincap.is_wow64 ()
|
|
|
|
&& &wow64_test_stack_marker >= (PBOOL) 0x400000
|
|
|
|
&& &wow64_test_stack_marker <= (PBOOL) 0x10000000)
|
2004-07-24 02:41:34 -07:00
|
|
|
respawn_wow64_process ();
|
|
|
|
|
2004-01-14 07:45:37 -08:00
|
|
|
dll_crt0_0 ();
|
2006-05-15 20:14:24 -07:00
|
|
|
_my_oldfunc = TlsAlloc ();
|
2000-02-17 11:38:33 -08:00
|
|
|
break;
|
2002-10-06 21:12:54 -07:00
|
|
|
case DLL_PROCESS_DETACH:
|
2008-07-27 07:52:46 -07:00
|
|
|
if (dynamically_loaded)
|
|
|
|
shared_destroy ();
|
2002-10-06 21:12:54 -07:00
|
|
|
break;
|
2000-02-17 11:38:33 -08:00
|
|
|
case DLL_THREAD_ATTACH:
|
2006-03-12 15:57:05 -08:00
|
|
|
if (hwait_sig)
|
2005-12-29 12:46:34 -08:00
|
|
|
munge_threadfunc ();
|
2000-02-17 11:38:33 -08:00
|
|
|
break;
|
2003-12-25 20:40:52 -08:00
|
|
|
case DLL_THREAD_DETACH:
|
2006-05-16 20:36:14 -07:00
|
|
|
if (hwait_sig && (void *) &_my_tls > (void *) &wow64_test_stack_marker
|
|
|
|
&& _my_tls.isinitialized ())
|
2005-12-29 12:46:34 -08:00
|
|
|
_my_tls.remove (0);
|
2003-12-25 20:40:52 -08:00
|
|
|
break;
|
2000-02-17 11:38:33 -08:00
|
|
|
}
|
2005-09-27 19:43:29 -07:00
|
|
|
|
|
|
|
return TRUE;
|
2000-02-17 11:38:33 -08:00
|
|
|
}
|