169d65a577
- Support pseudo console in PTY. Pseudo console is a new feature in Windows 10 1809, which provides console APIs on virtual terminal. With this patch, native console applications can work in PTYs such as mintty, ssh, gnu screen or tmux.
128 lines
3.2 KiB
C++
128 lines
3.2 KiB
C++
/* init.cc
|
|
|
|
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"
|
|
#include "cygtls.h"
|
|
#include "ntdll.h"
|
|
#include "shared_info.h"
|
|
|
|
static DWORD _my_oldfunc;
|
|
|
|
static char *search_for = (char *) cygthread::stub;
|
|
unsigned threadfunc_ix[8];
|
|
|
|
static bool dll_finished_loading;
|
|
#define OLDFUNC_OFFSET -1
|
|
|
|
static void WINAPI
|
|
threadfunc_fe (VOID *arg)
|
|
{
|
|
#ifdef __i386__
|
|
#if __GNUC_PREREQ(6,0)
|
|
#pragma GCC diagnostic ignored "-Wframe-address"
|
|
#endif
|
|
(void)__builtin_return_address(1);
|
|
#if __GNUC_PREREQ(6,0)
|
|
#pragma GCC diagnostic pop
|
|
#endif
|
|
asm volatile ("andl $-16,%%esp" ::: "%esp");
|
|
#endif
|
|
_cygtls::call ((DWORD (*) (void *, void *)) TlsGetValue (_my_oldfunc), arg);
|
|
}
|
|
|
|
/* If possible, redirect the thread entry point to a cygwin routine which
|
|
adds tls stuff to the stack. */
|
|
static void
|
|
munge_threadfunc ()
|
|
{
|
|
int i;
|
|
char **ebp = (char **) __builtin_frame_address (0);
|
|
if (!threadfunc_ix[0])
|
|
{
|
|
char **peb;
|
|
char **top = (char **) NtCurrentTeb()->Tib.StackBase;
|
|
for (peb = ebp, i = 0; peb < top && i < 7; peb++)
|
|
if (*peb == search_for)
|
|
threadfunc_ix[i++] = peb - ebp;
|
|
if (0 && !threadfunc_ix[0])
|
|
{
|
|
try_to_debug ();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (threadfunc_ix[0])
|
|
{
|
|
char *threadfunc = NULL;
|
|
|
|
NtQueryInformationThread (NtCurrentThread (),
|
|
ThreadQuerySetWin32StartAddress,
|
|
&threadfunc, sizeof threadfunc, NULL);
|
|
if (!search_for || threadfunc == search_for)
|
|
{
|
|
search_for = NULL;
|
|
for (i = 0; threadfunc_ix[i]; i++)
|
|
if (!threadfunc || ebp[threadfunc_ix[i]] == threadfunc)
|
|
ebp[threadfunc_ix[i]] = (char *) threadfunc_fe;
|
|
TlsSetValue (_my_oldfunc, threadfunc);
|
|
}
|
|
}
|
|
}
|
|
|
|
void dll_crt0_0 ();
|
|
|
|
/* 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;
|
|
|
|
extern "C" BOOL WINAPI
|
|
dll_entry (HANDLE h, DWORD reason, void *static_load)
|
|
{
|
|
BOOL test_stack_marker;
|
|
|
|
switch (reason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
init_console_handler (false);
|
|
|
|
cygwin_hmodule = (HMODULE) h;
|
|
dynamically_loaded = (static_load == NULL);
|
|
|
|
/* Starting with adding the POSIX-1.2008 per-thread locale functionality,
|
|
we need an initalized _REENT area even for the functions called from
|
|
dll_crt0_0. Most importantly, we need the _REENT->_locale pointer
|
|
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. */
|
|
alloca_dummy = alloca (CYGTLS_PADSIZE);
|
|
ZeroMemory (alloca_dummy, CYGTLS_PADSIZE);
|
|
memcpy (_REENT, _GLOBAL_REENT, sizeof (struct _reent));
|
|
|
|
dll_crt0_0 ();
|
|
_my_oldfunc = TlsAlloc ();
|
|
dll_finished_loading = true;
|
|
break;
|
|
case DLL_PROCESS_DETACH:
|
|
if (dynamically_loaded)
|
|
shared_destroy ();
|
|
break;
|
|
case DLL_THREAD_ATTACH:
|
|
if (dll_finished_loading)
|
|
munge_threadfunc ();
|
|
break;
|
|
case DLL_THREAD_DETACH:
|
|
if (dll_finished_loading
|
|
&& (PVOID) &_my_tls > (PVOID) &test_stack_marker
|
|
&& _my_tls.isinitialized ())
|
|
_my_tls.remove (0);
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|