2001-09-12 04:01:02 +08:00
|
|
|
/* init.cc
|
2000-02-18 03: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-29 04:55:59 +08:00
|
|
|
#include "cygtls.h"
|
2005-08-15 03:48:07 +08:00
|
|
|
#include "ntdll.h"
|
2008-07-27 22:52:46 +08:00
|
|
|
#include "shared_info.h"
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2006-05-16 11:14:24 +08:00
|
|
|
static DWORD _my_oldfunc;
|
|
|
|
|
2012-02-15 03:08:20 +08:00
|
|
|
static char *search_for = (char *) cygthread::stub;
|
|
|
|
unsigned threadfunc_ix[8];
|
2004-01-14 23:45:37 +08:00
|
|
|
|
2010-09-02 02:24:11 +08:00
|
|
|
static bool dll_finished_loading;
|
2004-01-14 23:45:37 +08:00
|
|
|
#define OLDFUNC_OFFSET -1
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2003-12-14 15:09:22 +08:00
|
|
|
static void WINAPI
|
|
|
|
threadfunc_fe (VOID *arg)
|
|
|
|
{
|
2017-10-10 00:08:10 +08:00
|
|
|
#ifdef __i386__
|
|
|
|
#if __GNUC_PREREQ(6,0)
|
2017-09-13 03:30:34 +08:00
|
|
|
#pragma GCC diagnostic ignored "-Wframe-address"
|
2017-10-10 00:08:10 +08:00
|
|
|
#endif
|
2004-04-30 21:27:27 +08:00
|
|
|
(void)__builtin_return_address(1);
|
2017-10-10 00:08:10 +08:00
|
|
|
#if __GNUC_PREREQ(6,0)
|
2017-09-13 03:30:34 +08:00
|
|
|
#pragma GCC diagnostic pop
|
2017-10-10 00:08:10 +08:00
|
|
|
#endif
|
2004-04-30 21:27:27 +08:00
|
|
|
asm volatile ("andl $-16,%%esp" ::: "%esp");
|
2015-07-29 19:32:29 +08:00
|
|
|
#endif
|
2006-05-16 11:14:24 +08:00
|
|
|
_cygtls::call ((DWORD (*) (void *, void *)) TlsGetValue (_my_oldfunc), arg);
|
2004-01-14 23:45:37 +08:00
|
|
|
}
|
|
|
|
|
2004-01-20 07:03:43 +08:00
|
|
|
/* If possible, redirect the thread entry point to a cygwin routine which
|
|
|
|
adds tls stuff to the stack. */
|
2003-12-14 15:09:22 +08:00
|
|
|
static void
|
2004-02-14 03:34:32 +08:00
|
|
|
munge_threadfunc ()
|
2003-12-14 15:09:22 +08:00
|
|
|
{
|
2004-03-23 02:30:38 +08:00
|
|
|
int i;
|
2004-01-14 23:45:37 +08:00
|
|
|
char **ebp = (char **) __builtin_frame_address (0);
|
2004-03-23 02:30:38 +08:00
|
|
|
if (!threadfunc_ix[0])
|
2003-12-14 15:09:22 +08:00
|
|
|
{
|
2004-03-23 02:30:38 +08:00
|
|
|
char **peb;
|
2015-12-02 19:11:06 +08:00
|
|
|
char **top = (char **) NtCurrentTeb()->Tib.StackBase;
|
2004-03-23 02:30:38 +08:00
|
|
|
for (peb = ebp, i = 0; peb < top && i < 7; peb++)
|
2004-01-14 23:45:37 +08:00
|
|
|
if (*peb == search_for)
|
2004-03-23 02:30:38 +08:00
|
|
|
threadfunc_ix[i++] = peb - ebp;
|
2005-12-30 04:46:34 +08:00
|
|
|
if (0 && !threadfunc_ix[0])
|
2004-03-23 02:30:38 +08:00
|
|
|
{
|
|
|
|
try_to_debug ();
|
|
|
|
return;
|
|
|
|
}
|
2003-12-14 15:09:22 +08:00
|
|
|
}
|
|
|
|
|
2006-03-13 07:57:05 +08:00
|
|
|
if (threadfunc_ix[0])
|
2004-01-14 23:45:37 +08:00
|
|
|
{
|
2015-10-29 16:17:46 +08:00
|
|
|
char *threadfunc = NULL;
|
|
|
|
|
2015-12-15 22:48:44 +08:00
|
|
|
NtQueryInformationThread (NtCurrentThread (),
|
|
|
|
ThreadQuerySetWin32StartAddress,
|
|
|
|
&threadfunc, sizeof threadfunc, NULL);
|
2006-03-13 07:57:05 +08:00
|
|
|
if (!search_for || threadfunc == search_for)
|
|
|
|
{
|
|
|
|
search_for = NULL;
|
|
|
|
for (i = 0; threadfunc_ix[i]; i++)
|
2015-10-29 16:17:46 +08:00
|
|
|
if (!threadfunc || ebp[threadfunc_ix[i]] == threadfunc)
|
|
|
|
ebp[threadfunc_ix[i]] = (char *) threadfunc_fe;
|
2006-05-16 11:14:24 +08:00
|
|
|
TlsSetValue (_my_oldfunc, threadfunc);
|
2006-03-13 07:57:05 +08:00
|
|
|
}
|
2004-01-14 23:45:37 +08:00
|
|
|
}
|
2003-12-14 15:09:22 +08:00
|
|
|
}
|
|
|
|
|
2011-08-18 23:59:16 +08:00
|
|
|
void dll_crt0_0 ();
|
2004-01-14 23:45:37 +08:00
|
|
|
|
2016-07-27 19:52:10 +08:00
|
|
|
/* Non-static fake variable so GCC doesn't second-guess if we *really*
|
|
|
|
need the alloca'd space in the DLL_PROCESS_ATTACH case below... */
|
|
|
|
void *alloca_dummy;
|
|
|
|
|
2005-09-28 10:43:29 +08:00
|
|
|
extern "C" BOOL WINAPI
|
2003-12-14 15:09:22 +08:00
|
|
|
dll_entry (HANDLE h, DWORD reason, void *static_load)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2011-12-12 18:16:53 +08:00
|
|
|
BOOL test_stack_marker;
|
2006-02-24 03:21:21 +08:00
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
switch (reason)
|
|
|
|
{
|
|
|
|
case DLL_PROCESS_ATTACH:
|
2006-03-19 03:17:21 +08:00
|
|
|
init_console_handler (false);
|
|
|
|
|
2005-03-23 03:00:31 +08:00
|
|
|
cygwin_hmodule = (HMODULE) h;
|
2005-05-17 09:21:06 +08:00
|
|
|
dynamically_loaded = (static_load == NULL);
|
2005-08-15 03:48:07 +08:00
|
|
|
|
2016-07-21 04:05:59 +08:00
|
|
|
/* Starting with adding the POSIX-1.2008 per-thread locale functionality,
|
|
|
|
we need an initalized _REENT area even for the functions called from
|
2016-07-27 19:52:10 +08:00
|
|
|
dll_crt0_0. Most importantly, we need the _REENT->_locale pointer
|
2016-07-21 04:05:59 +08:00
|
|
|
initialized to NULL, so subsequent calls to locale-specific functions
|
|
|
|
will always fall back to __global_locale, rather then crash due to
|
|
|
|
_REENT->_locale having an arbitrary value. */
|
2016-07-27 19:52:10 +08:00
|
|
|
alloca_dummy = alloca (CYGTLS_PADSIZE);
|
|
|
|
memcpy (_REENT, _GLOBAL_REENT, sizeof (struct _reent));
|
2016-07-21 04:05:59 +08:00
|
|
|
|
2004-01-14 23:45:37 +08:00
|
|
|
dll_crt0_0 ();
|
2006-05-16 11:14:24 +08:00
|
|
|
_my_oldfunc = TlsAlloc ();
|
2010-09-02 02:24:11 +08:00
|
|
|
dll_finished_loading = true;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
2002-10-07 12:12:54 +08:00
|
|
|
case DLL_PROCESS_DETACH:
|
2008-07-27 22:52:46 +08:00
|
|
|
if (dynamically_loaded)
|
|
|
|
shared_destroy ();
|
2002-10-07 12:12:54 +08:00
|
|
|
break;
|
2000-02-18 03:38:33 +08:00
|
|
|
case DLL_THREAD_ATTACH:
|
2010-09-02 02:24:11 +08:00
|
|
|
if (dll_finished_loading)
|
2005-12-30 04:46:34 +08:00
|
|
|
munge_threadfunc ();
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
2003-12-26 12:40:52 +08:00
|
|
|
case DLL_THREAD_DETACH:
|
2011-05-16 02:49:40 +08:00
|
|
|
if (dll_finished_loading
|
2011-12-12 18:16:53 +08:00
|
|
|
&& (PVOID) &_my_tls > (PVOID) &test_stack_marker
|
2006-05-17 11:36:14 +08:00
|
|
|
&& _my_tls.isinitialized ())
|
2014-11-22 05:41:37 +08:00
|
|
|
_my_tls.remove (0);
|
2003-12-26 12:40:52 +08:00
|
|
|
break;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
2005-09-28 10:43:29 +08:00
|
|
|
|
|
|
|
return TRUE;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|