From: Eric Pouech epouech@codeweavers.com
Required for some Chrome integration.
Wine-Bugs: https://bugs.winehq.org/show_bug.cgi?id=57700
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/kernel32/tests/loader.c | 2 -- dlls/ntdll/loader.c | 69 +++++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 18 deletions(-)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index b839a05325d..8ecc5614148 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -2325,10 +2325,8 @@ static void test_import_resolution(void) { SIZE_T s; /* should be aligned on 1024 bytes, 10 lower bits at 0 */ - todo_wine_if( (DWORD_PTR)str & 0x3ff ) ok( !((DWORD_PTR)str & 0x3ff), "wrong alignment %p\n", str ); s = HeapSize( GetProcessHeap(), 0, ((void **)str)[-1] ); - todo_wine ok( s != (SIZE_T)-1, "Error %Ix\n", s); } ok(ptr->tls_index_hi == 0, "TLS Index written as a short, high half: %d\n", ptr->tls_index_hi); diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 0c25fe14133..bfbe2e63143 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1270,6 +1270,51 @@ static BOOL is_dll_native_subsystem( LDR_DATA_TABLE_ENTRY *mod, const IMAGE_NT_H return TRUE; }
+static void *heap_alloc_aligned( unsigned size, unsigned align ) +{ + char *ptr; + DWORD_PTR mask = ((DWORD_PTR)1 << align) - 1; + + size += sizeof(void *) + mask; + if ((ptr = RtlAllocateHeap( GetProcessHeap(), 0, size ))) + { + void *unaligned_ptr = ptr; + + /* align block and store unaligned pointer just below the returned block */ + ptr = (char *)(((DWORD_PTR)ptr + sizeof(void *) + mask) & ~mask); + ((void **)ptr)[-1] = unaligned_ptr; + } + return ptr; +} + + +static BOOLEAN heap_free_aligned( void *ptr ) +{ + return ptr ? RtlFreeHeap( GetProcessHeap(), 0, ((void **)ptr)[-1] ) : TRUE; +} + + +/* Allocates the slot from a TLS directory (potentially realigning if necessary) + * - must be freed with heap_free_aligned + */ +static void *alloc_thread_tls_slot( const IMAGE_TLS_DIRECTORY *dir ) +{ + UINT size = dir->EndAddressOfRawData - dir->StartAddressOfRawData; + unsigned align; + void *ptr; + + align = (dir->Characteristics & IMAGE_SCN_ALIGN_MASK) >> 20; + if (!align) align = 5; /* default */ + if ((ptr = heap_alloc_aligned( size + dir->SizeOfZeroFill, align ))) + { + memcpy( ptr, (void *)dir->StartAddressOfRawData, size ); + memset( (char *)ptr + size, 0, dir->SizeOfZeroFill ); + } + + return ptr; +} + + /************************************************************************* * alloc_tls_slot * @@ -1348,15 +1393,12 @@ static BOOL alloc_tls_slot( LDR_DATA_TABLE_ENTRY *mod ) /* FIXME: can't free old block here, should be freed at thread exit */ }
- if (!(new_ptr = RtlAllocateHeap( GetProcessHeap(), 0, size + dir->SizeOfZeroFill ))) return -1; - memcpy( new_ptr, (void *)dir->StartAddressOfRawData, size ); - memset( (char *)new_ptr + size, 0, dir->SizeOfZeroFill ); + if (!(new_ptr = alloc_thread_tls_slot( dir ))) return -1;
TRACE( "thread %04lx slot %lu: %lu/%lu bytes at %p\n", HandleToULong(teb->ClientId.UniqueThread), i, size, dir->SizeOfZeroFill, new_ptr );
- RtlFreeHeap( GetProcessHeap(), 0, - InterlockedExchangePointer( (void **)teb->ThreadLocalStoragePointer + i, new_ptr )); + heap_free_aligned( InterlockedExchangePointer( (void **)teb->ThreadLocalStoragePointer + i, new_ptr )); } if (thread) NtClose( thread );
@@ -1569,7 +1611,7 @@ static WINE_MODREF *alloc_module( HMODULE hModule, const UNICODE_STRING *nt_name static NTSTATUS alloc_thread_tls(void) { void **pointers; - UINT i, size; + UINT i;
if (!(pointers = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, tls_module_count * sizeof(*pointers) ))) @@ -1579,20 +1621,15 @@ static NTSTATUS alloc_thread_tls(void) { const IMAGE_TLS_DIRECTORY *dir = &tls_dirs[i];
- if (!dir) continue; - size = dir->EndAddressOfRawData - dir->StartAddressOfRawData; - if (!size && !dir->SizeOfZeroFill) continue; + if (!dir || (dir->EndAddressOfRawData == dir->StartAddressOfRawData && !dir->SizeOfZeroFill)) continue;
- if (!(pointers[i] = RtlAllocateHeap( GetProcessHeap(), 0, size + dir->SizeOfZeroFill ))) + if (!(pointers[i] = alloc_thread_tls_slot( dir ))) { - while (i) RtlFreeHeap( GetProcessHeap(), 0, pointers[--i] ); + while (i) heap_free_aligned( pointers[--i] ); RtlFreeHeap( GetProcessHeap(), 0, pointers ); return STATUS_NO_MEMORY; } - memcpy( pointers[i], (void *)dir->StartAddressOfRawData, size ); - memset( (char *)pointers[i] + size, 0, dir->SizeOfZeroFill ); - - TRACE( "slot %u: %u/%lu bytes at %p\n", i, size, dir->SizeOfZeroFill, pointers[i] ); + TRACE( "slot %u: %u/%lu bytes at %p\n", i, (UINT)(dir->EndAddressOfRawData - dir->StartAddressOfRawData), dir->SizeOfZeroFill, pointers[i] ); } NtCurrentTeb()->ThreadLocalStoragePointer = pointers; #ifdef __x86_64__ /* macOS-specific hack */ @@ -3889,7 +3926,7 @@ void WINAPI LdrShutdownThread(void) if (NtCurrentTeb()->Instrumentation[0]) ((TEB *)NtCurrentTeb()->Instrumentation[0])->ThreadLocalStoragePointer = NULL; #endif - for (i = 0; i < tls_module_count; i++) RtlFreeHeap( GetProcessHeap(), 0, pointers[i] ); + for (i = 0; i < tls_module_count; i++) heap_free_aligned( pointers[i] ); RtlFreeHeap( GetProcessHeap(), 0, pointers ); } RtlProcessFlsData( NtCurrentTeb()->FlsSlots, 2 );