4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-01-16 19:40:07 +08:00
Corinna Vinschen d03f429727 Fix crash at process init on 64 bit XP/2003 under WOW64
* init.cc (munge_threadfunc): Don't call NtQueryInformationThread with
	ThreadQuerySetWin32StartAddress info class on XP 64 and Server 2003 64.
	It crashes.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-11-12 11:48:30 +01:00

114 lines
2.6 KiB
C++

/* init.cc
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2013, 2015 Red Hat, Inc.
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)
{
#ifndef __x86_64__
(void)__builtin_return_address(1);
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 **) _tlsbase;
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;
if (wincap.wow64_has_secondary_stack ())
threadfunc = ebp[threadfunc_ix[0]];
else
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 ();
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);
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;
}