Rewrote module TLS support and moved it to ntdll.
This commit is contained in:
parent
0b34697abb
commit
adb532903c
|
@ -63,6 +63,10 @@ static const char * const reason_names[] =
|
||||||
"THREAD_DETACH"
|
"THREAD_DETACH"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static UINT tls_module_count; /* number of modules with TLS directory */
|
||||||
|
static UINT tls_total_size; /* total size of TLS storage */
|
||||||
|
static const IMAGE_TLS_DIRECTORY **tls_dirs; /* array of TLS directories */
|
||||||
|
|
||||||
static CRITICAL_SECTION loader_section = CRITICAL_SECTION_INIT( "loader_section" );
|
static CRITICAL_SECTION loader_section = CRITICAL_SECTION_INIT( "loader_section" );
|
||||||
static WINE_MODREF *cached_modref;
|
static WINE_MODREF *cached_modref;
|
||||||
static WINE_MODREF *current_modref;
|
static WINE_MODREF *current_modref;
|
||||||
|
@ -398,6 +402,92 @@ WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* alloc_process_tls
|
||||||
|
*
|
||||||
|
* Allocate the process-wide structure for module TLS storage.
|
||||||
|
*/
|
||||||
|
static NTSTATUS alloc_process_tls(void)
|
||||||
|
{
|
||||||
|
WINE_MODREF *wm;
|
||||||
|
IMAGE_TLS_DIRECTORY *dir;
|
||||||
|
ULONG size, i;
|
||||||
|
|
||||||
|
for (wm = MODULE_modref_list; wm; wm = wm->next)
|
||||||
|
{
|
||||||
|
if (!(dir = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
|
||||||
|
IMAGE_DIRECTORY_ENTRY_TLS, &size )))
|
||||||
|
continue;
|
||||||
|
size = (dir->EndAddressOfRawData - dir->StartAddressOfRawData) + dir->SizeOfZeroFill;
|
||||||
|
if (!size) continue;
|
||||||
|
tls_total_size += size;
|
||||||
|
tls_module_count++;
|
||||||
|
}
|
||||||
|
if (!tls_module_count) return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
TRACE( "count %u size %u\n", tls_module_count, tls_total_size );
|
||||||
|
|
||||||
|
tls_dirs = RtlAllocateHeap( ntdll_get_process_heap(), 0, tls_module_count * sizeof(*tls_dirs) );
|
||||||
|
if (!tls_dirs) return STATUS_NO_MEMORY;
|
||||||
|
|
||||||
|
for (i = 0, wm = MODULE_modref_list; wm; wm = wm->next)
|
||||||
|
{
|
||||||
|
if (!(dir = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
|
||||||
|
IMAGE_DIRECTORY_ENTRY_TLS, &size )))
|
||||||
|
continue;
|
||||||
|
tls_dirs[i] = dir;
|
||||||
|
*dir->AddressOfIndex = i;
|
||||||
|
wm->ldr.TlsIndex = i;
|
||||||
|
wm->ldr.LoadCount = -1; /* can't unload it */
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* alloc_thread_tls
|
||||||
|
*
|
||||||
|
* Allocate the per-thread structure for module TLS storage.
|
||||||
|
*/
|
||||||
|
static NTSTATUS alloc_thread_tls(void)
|
||||||
|
{
|
||||||
|
void **pointers;
|
||||||
|
char *data;
|
||||||
|
UINT i;
|
||||||
|
|
||||||
|
if (!tls_module_count) return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (!(pointers = RtlAllocateHeap( ntdll_get_process_heap(), 0,
|
||||||
|
tls_module_count * sizeof(*pointers) )))
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
|
||||||
|
if (!(data = RtlAllocateHeap( ntdll_get_process_heap(), 0, tls_total_size )))
|
||||||
|
{
|
||||||
|
RtlFreeHeap( ntdll_get_process_heap(), 0, pointers );
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < tls_module_count; i++)
|
||||||
|
{
|
||||||
|
const IMAGE_TLS_DIRECTORY *dir = tls_dirs[i];
|
||||||
|
ULONG size = dir->EndAddressOfRawData - dir->StartAddressOfRawData;
|
||||||
|
|
||||||
|
TRACE( "thread %04lx idx %d: %ld/%ld bytes from %p to %p\n",
|
||||||
|
GetCurrentThreadId(), i, size, dir->SizeOfZeroFill,
|
||||||
|
(void *)dir->StartAddressOfRawData, data );
|
||||||
|
|
||||||
|
pointers[i] = data;
|
||||||
|
memcpy( data, (void *)dir->StartAddressOfRawData, size );
|
||||||
|
data += size;
|
||||||
|
memset( data, 0, dir->SizeOfZeroFill );
|
||||||
|
data += dir->SizeOfZeroFill;
|
||||||
|
}
|
||||||
|
NtCurrentTeb()->tls_ptr = pointers;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* call_tls_callbacks
|
* call_tls_callbacks
|
||||||
*/
|
*/
|
||||||
|
@ -492,9 +582,9 @@ static BOOL MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved )
|
||||||
* detach notifications are called in the reverse of the sequence the attach
|
* detach notifications are called in the reverse of the sequence the attach
|
||||||
* notifications *returned*.
|
* notifications *returned*.
|
||||||
*/
|
*/
|
||||||
BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved )
|
NTSTATUS MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved )
|
||||||
{
|
{
|
||||||
BOOL retv = TRUE;
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
RtlEnterCriticalSection( &loader_section );
|
RtlEnterCriticalSection( &loader_section );
|
||||||
|
@ -502,7 +592,9 @@ BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved )
|
||||||
if (!wm)
|
if (!wm)
|
||||||
{
|
{
|
||||||
wm = exe_modref;
|
wm = exe_modref;
|
||||||
PE_InitTls();
|
wm->ldr.LoadCount = -1; /* can't unload main exe */
|
||||||
|
if ((status = alloc_process_tls()) != STATUS_SUCCESS) goto done;
|
||||||
|
if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto done;
|
||||||
}
|
}
|
||||||
assert( wm );
|
assert( wm );
|
||||||
|
|
||||||
|
@ -517,22 +609,26 @@ BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved )
|
||||||
wm->ldr.Flags |= LDR_LOAD_IN_PROGRESS;
|
wm->ldr.Flags |= LDR_LOAD_IN_PROGRESS;
|
||||||
|
|
||||||
/* Recursively attach all DLLs this one depends on */
|
/* Recursively attach all DLLs this one depends on */
|
||||||
for ( i = 0; retv && i < wm->nDeps; i++ )
|
for ( i = 0; i < wm->nDeps; i++ )
|
||||||
if ( wm->deps[i] )
|
{
|
||||||
retv = MODULE_DllProcessAttach( wm->deps[i], lpReserved );
|
if (!wm->deps[i]) continue;
|
||||||
|
if ((status = MODULE_DllProcessAttach( wm->deps[i], lpReserved )) != STATUS_SUCCESS) break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Call DLL entry point */
|
/* Call DLL entry point */
|
||||||
if ( retv )
|
if (status == STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
WINE_MODREF *prev = current_modref;
|
WINE_MODREF *prev = current_modref;
|
||||||
current_modref = wm;
|
current_modref = wm;
|
||||||
retv = MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved );
|
if (MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved ))
|
||||||
if (retv) wm->ldr.Flags |= LDR_PROCESS_ATTACHED;
|
wm->ldr.Flags |= LDR_PROCESS_ATTACHED;
|
||||||
|
else
|
||||||
|
status = STATUS_DLL_INIT_FAILED;
|
||||||
current_modref = prev;
|
current_modref = prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Re-insert MODREF at head of list */
|
/* Re-insert MODREF at head of list */
|
||||||
if ( retv && wm->prev )
|
if (status == STATUS_SUCCESS && wm->prev )
|
||||||
{
|
{
|
||||||
wm->prev->next = wm->next;
|
wm->prev->next = wm->next;
|
||||||
if ( wm->next ) wm->next->prev = wm->prev;
|
if ( wm->next ) wm->next->prev = wm->prev;
|
||||||
|
@ -547,10 +643,9 @@ BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved )
|
||||||
|
|
||||||
TRACE("(%s,%p) - END\n", wm->modname, lpReserved );
|
TRACE("(%s,%p) - END\n", wm->modname, lpReserved );
|
||||||
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
RtlLeaveCriticalSection( &loader_section );
|
RtlLeaveCriticalSection( &loader_section );
|
||||||
return retv;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
@ -573,7 +668,7 @@ static void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved )
|
||||||
/* Check whether to detach this DLL */
|
/* Check whether to detach this DLL */
|
||||||
if ( !(wm->ldr.Flags & LDR_PROCESS_ATTACHED) )
|
if ( !(wm->ldr.Flags & LDR_PROCESS_ATTACHED) )
|
||||||
continue;
|
continue;
|
||||||
if ( wm->ldr.LoadCount > 0 && !bForceDetach )
|
if ( wm->ldr.LoadCount && !bForceDetach )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Call detach notification */
|
/* Call detach notification */
|
||||||
|
@ -596,17 +691,18 @@ static void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved )
|
||||||
* reverse sequence of process detach notification.
|
* reverse sequence of process detach notification.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void MODULE_DllThreadAttach( LPVOID lpReserved )
|
NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved )
|
||||||
{
|
{
|
||||||
WINE_MODREF *wm;
|
WINE_MODREF *wm;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
/* don't do any attach calls if process is exiting */
|
/* don't do any attach calls if process is exiting */
|
||||||
if (process_detaching) return;
|
if (process_detaching) return STATUS_SUCCESS;
|
||||||
/* FIXME: there is still a race here */
|
/* FIXME: there is still a race here */
|
||||||
|
|
||||||
RtlEnterCriticalSection( &loader_section );
|
RtlEnterCriticalSection( &loader_section );
|
||||||
|
|
||||||
PE_InitTls();
|
if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto done;
|
||||||
|
|
||||||
for ( wm = MODULE_modref_list; wm; wm = wm->next )
|
for ( wm = MODULE_modref_list; wm; wm = wm->next )
|
||||||
if ( !wm->next )
|
if ( !wm->next )
|
||||||
|
@ -622,7 +718,9 @@ void MODULE_DllThreadAttach( LPVOID lpReserved )
|
||||||
MODULE_InitDLL( wm, DLL_THREAD_ATTACH, lpReserved );
|
MODULE_InitDLL( wm, DLL_THREAD_ATTACH, lpReserved );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
RtlLeaveCriticalSection( &loader_section );
|
RtlLeaveCriticalSection( &loader_section );
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
|
@ -922,8 +1020,8 @@ static NTSTATUS load_dll( LPCSTR libname, DWORD flags, WINE_MODREF** pwm )
|
||||||
}
|
}
|
||||||
if (*pwm)
|
if (*pwm)
|
||||||
{
|
{
|
||||||
(*pwm)->ldr.LoadCount++;
|
if ((*pwm)->ldr.LoadCount != -1) (*pwm)->ldr.LoadCount++;
|
||||||
|
|
||||||
if (((*pwm)->ldr.Flags & LDR_DONT_RESOLVE_REFS) &&
|
if (((*pwm)->ldr.Flags & LDR_DONT_RESOLVE_REFS) &&
|
||||||
!(flags & DONT_RESOLVE_DLL_REFERENCES))
|
!(flags & DONT_RESOLVE_DLL_REFERENCES))
|
||||||
{
|
{
|
||||||
|
@ -1022,11 +1120,11 @@ NTSTATUS WINAPI LdrLoadDll(LPCWSTR path_name, DWORD flags, PUNICODE_STRING libna
|
||||||
switch (nts = load_dll( str.Buffer, flags, &wm ))
|
switch (nts = load_dll( str.Buffer, flags, &wm ))
|
||||||
{
|
{
|
||||||
case STATUS_SUCCESS:
|
case STATUS_SUCCESS:
|
||||||
if ( !MODULE_DllProcessAttach( wm, NULL ) )
|
nts = MODULE_DllProcessAttach( wm, NULL );
|
||||||
|
if (nts != STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
WARN("Attach failed for module '%s'.\n", str.Buffer);
|
WARN("Attach failed for module '%s'.\n", str.Buffer);
|
||||||
LdrUnloadDll(wm->ldr.BaseAddress);
|
LdrUnloadDll(wm->ldr.BaseAddress);
|
||||||
nts = STATUS_DLL_INIT_FAILED;
|
|
||||||
wm = NULL;
|
wm = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -181,8 +181,8 @@ enum binary_type
|
||||||
};
|
};
|
||||||
|
|
||||||
/* module.c */
|
/* module.c */
|
||||||
extern BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved );
|
extern NTSTATUS MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved );
|
||||||
extern void MODULE_DllThreadAttach( LPVOID lpReserved );
|
extern NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved );
|
||||||
extern WINE_MODREF *MODULE_FindModule( LPCSTR path );
|
extern WINE_MODREF *MODULE_FindModule( LPCSTR path );
|
||||||
extern HMODULE16 MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 );
|
extern HMODULE16 MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 );
|
||||||
extern enum binary_type MODULE_GetBinaryType( HANDLE hfile );
|
extern enum binary_type MODULE_GetBinaryType( HANDLE hfile );
|
||||||
|
@ -224,7 +224,6 @@ extern NTSTATUS PE_LoadLibraryExA(LPCSTR, DWORD, WINE_MODREF**);
|
||||||
extern HMODULE PE_LoadImage( HANDLE hFile, LPCSTR filename, DWORD flags );
|
extern HMODULE PE_LoadImage( HANDLE hFile, LPCSTR filename, DWORD flags );
|
||||||
extern WINE_MODREF *PE_CreateModule( HMODULE hModule, LPCSTR filename,
|
extern WINE_MODREF *PE_CreateModule( HMODULE hModule, LPCSTR filename,
|
||||||
DWORD flags, HANDLE hFile, BOOL builtin );
|
DWORD flags, HANDLE hFile, BOOL builtin );
|
||||||
extern void PE_InitTls(void);
|
|
||||||
extern DWORD PE_fixup_imports(WINE_MODREF *wm);
|
extern DWORD PE_fixup_imports(WINE_MODREF *wm);
|
||||||
|
|
||||||
/* loader/loadorder.c */
|
/* loader/loadorder.c */
|
||||||
|
|
|
@ -371,56 +371,3 @@ NTSTATUS PE_LoadLibraryExA (LPCSTR name, DWORD flags, WINE_MODREF** pwm)
|
||||||
CloseHandle( hFile );
|
CloseHandle( hFile );
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
* PE_InitTls (internal)
|
|
||||||
*
|
|
||||||
* If included, initialises the thread local storages of modules.
|
|
||||||
* Pointers in those structs are not RVAs but real pointers which have been
|
|
||||||
* relocated by do_relocations() already.
|
|
||||||
*/
|
|
||||||
static LPVOID
|
|
||||||
_fixup_address(PIMAGE_OPTIONAL_HEADER opt,int delta,LPVOID addr) {
|
|
||||||
if ( ((DWORD)addr>opt->ImageBase) &&
|
|
||||||
((DWORD)addr<opt->ImageBase+opt->SizeOfImage)
|
|
||||||
)
|
|
||||||
/* the address has not been relocated! */
|
|
||||||
return (LPVOID)(((DWORD)addr)+delta);
|
|
||||||
else
|
|
||||||
/* the address has been relocated already */
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PE_InitTls( void )
|
|
||||||
{
|
|
||||||
WINE_MODREF *wm;
|
|
||||||
IMAGE_NT_HEADERS *peh;
|
|
||||||
DWORD size,datasize,dirsize;
|
|
||||||
LPVOID mem;
|
|
||||||
PIMAGE_TLS_DIRECTORY pdir;
|
|
||||||
int delta;
|
|
||||||
|
|
||||||
for (wm = MODULE_modref_list;wm;wm=wm->next) {
|
|
||||||
peh = RtlImageNtHeader(wm->ldr.BaseAddress);
|
|
||||||
pdir = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
|
|
||||||
IMAGE_DIRECTORY_ENTRY_TLS, &dirsize );
|
|
||||||
if (!pdir) continue;
|
|
||||||
delta = (char *)wm->ldr.BaseAddress - (char *)peh->OptionalHeader.ImageBase;
|
|
||||||
|
|
||||||
if ( wm->ldr.TlsIndex == -1 ) {
|
|
||||||
LPDWORD xaddr;
|
|
||||||
wm->ldr.TlsIndex = TlsAlloc();
|
|
||||||
xaddr = _fixup_address(&(peh->OptionalHeader),delta,
|
|
||||||
pdir->AddressOfIndex
|
|
||||||
);
|
|
||||||
*xaddr=wm->ldr.TlsIndex;
|
|
||||||
}
|
|
||||||
datasize= pdir->EndAddressOfRawData-pdir->StartAddressOfRawData;
|
|
||||||
size = datasize + pdir->SizeOfZeroFill;
|
|
||||||
NtAllocateVirtualMemory( GetCurrentProcess(), &mem, NULL, &size,
|
|
||||||
MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
|
|
||||||
memcpy(mem,_fixup_address(&(peh->OptionalHeader),delta,(LPVOID)pdir->StartAddressOfRawData),datasize);
|
|
||||||
TlsSetValue( wm->ldr.TlsIndex, mem );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -539,7 +539,6 @@ static void start_process(void)
|
||||||
/* create the main modref and load dependencies */
|
/* create the main modref and load dependencies */
|
||||||
if (!(wm = PE_CreateModule( current_process.module, main_exe_name, 0, 0, FALSE )))
|
if (!(wm = PE_CreateModule( current_process.module, main_exe_name, 0, 0, FALSE )))
|
||||||
goto error;
|
goto error;
|
||||||
wm->ldr.LoadCount++;
|
|
||||||
|
|
||||||
if (main_exe_file) CloseHandle( main_exe_file ); /* we no longer need it */
|
if (main_exe_file) CloseHandle( main_exe_file ); /* we no longer need it */
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,6 @@ static BOOL THREAD_InitTEB( TEB *teb )
|
||||||
teb->except = (void *)~0UL;
|
teb->except = (void *)~0UL;
|
||||||
teb->self = teb;
|
teb->self = teb;
|
||||||
teb->tibflags = TEBF_WIN32;
|
teb->tibflags = TEBF_WIN32;
|
||||||
teb->tls_ptr = teb->tls_array;
|
|
||||||
teb->exit_code = STILL_ACTIVE;
|
teb->exit_code = STILL_ACTIVE;
|
||||||
teb->request_fd = -1;
|
teb->request_fd = -1;
|
||||||
teb->reply_fd = -1;
|
teb->reply_fd = -1;
|
||||||
|
|
Loading…
Reference in New Issue