Commit a7b49b0e authored by Evan Tang's avatar Evan Tang Committed by Alexandre Julliard

kernel32/tests: Fix tls callback tests on Windows 7.

Also add a few more so the full set of callbacks is tested. Fixes: 2203a856 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54657
parent 67f992c8
...@@ -2144,6 +2144,19 @@ static void check_tls_index(HANDLE dll, BOOL tls_initialized) ...@@ -2144,6 +2144,19 @@ static void check_tls_index(HANDLE dll, BOOL tls_initialized)
ok(found_dll, "Couldn't find dll %p in module list\n", dll); ok(found_dll, "Couldn't find dll %p in module list\n", dll);
} }
static int tls_init_fn_output;
static DWORD WINAPI tls_thread_fn(void* tlsidx_v)
{
int tls_index = (int)(DWORD_PTR)(tlsidx_v);
const char* str = ((char **)NtCurrentTeb()->ThreadLocalStoragePointer)[tls_index];
ok( !strcmp( str, "hello world" ), "wrong tls data '%s' at %p\n", str, str );
ok( tls_init_fn_output == DLL_THREAD_ATTACH,
"tls init function didn't run or got wrong reason: %d instead of %d\n", tls_init_fn_output, DLL_THREAD_ATTACH );
tls_init_fn_output = 9999;
return 0;
}
static void test_import_resolution(void) static void test_import_resolution(void)
{ {
char temp_path[MAX_PATH]; char temp_path[MAX_PATH];
...@@ -2165,31 +2178,41 @@ static void test_import_resolution(void) ...@@ -2165,31 +2178,41 @@ static void test_import_resolution(void)
char tls_data[16]; char tls_data[16];
SHORT tls_index; SHORT tls_index;
SHORT tls_index_hi; SHORT tls_index_hi;
UCHAR tls_init_fn[64]; /* Note: Uses rip-relative address of tls_index, don't separate */ int* tls_init_fn_output;
UCHAR tls_init_fn[64]; /* Note: Uses rip-relative address of tls_init_fn_output, don't separate */
UCHAR entry_point_fn[16];
} data, *ptr; } data, *ptr;
IMAGE_NT_HEADERS nt; IMAGE_NT_HEADERS nt;
IMAGE_SECTION_HEADER section; IMAGE_SECTION_HEADER section;
int test; int test, tls_index_save;
#if defined(__i386__) #if defined(__i386__)
static const UCHAR tls_init_code[] = { static const UCHAR tls_init_code[] = {
0xE8, 0x00, 0x00, 0x00, 0x00, /* call 1f */ 0xE8, 0x00, 0x00, 0x00, 0x00, /* call 1f */
0x59, /* 1: pop ecx */ 0x59, /* 1: pop ecx */
0x8B, 0x49, 0xF7, /* mov ecx, [ecx - 9] ; mov ecx, [tls_index] */ 0x8B, 0x49, 0xF7, /* mov ecx, [ecx - 9] ; mov ecx, [tls_init_fn_output] */
0x64, 0x8B, 0x15, 0x2C, 0x00, 0x00, 0x00, /* mov edx, fs:0x2c */ 0x8B, 0x54, 0x24, 0x08, /* mov edx, [esp + 8] */
0x8B, 0x14, 0x8A, /* mov edx, [edx + edx * 4] */ 0x89, 0x11, /* mov [ecx], edx */
0xC6, 0x42, 0x05, 0x21, /* mov byte [edx + 5], 0x21 */ 0xB8, 0x01, 0x00, 0x00, 0x00, /* mov eax, 1 */
0xC2, 0x0C, 0x00, /* ret 12 */ 0xC2, 0x0C, 0x00, /* ret 12 */
};
static const UCHAR entry_point_code[] = {
0xB8, 0x01, 0x00, 0x00, 0x00, /* mov eax, 1 */
0xC2, 0x0C, 0x00, /* ret 12 */
}; };
#elif defined(__x86_64__) #elif defined(__x86_64__)
static const UCHAR tls_init_code[] = { static const UCHAR tls_init_code[] = {
0x8B, 0x0D, 0xF6, 0xFF, 0xFF, 0xFF, /* mov ecx, [rip + tls_index] */ 0x48, 0x8B, 0x0D, 0xF1, 0xFF, 0xFF, 0xFF, /* mov rcx, [rip + tls_init_fn_output] */
0x65, 0x48, 0x8B, 0x14, 0x25, 0x58, 0x00, 0x00, 0x00, /* mov rdx, gs:0x58 */ 0x89, 0x11, /* mov [rcx], edx */
0x48, 0x8B, 0x14, 0xCA, /* mov rdx, [rdx + rcx * 8] */ 0xB8, 0x01, 0x00, 0x00, 0x00, /* mov eax, 1 */
0xC6, 0x42, 0x05, 0x21, /* mov byte [rdx + 5], 0x21 */ 0xC3, /* ret */
0xC3, /* ret */ };
static const UCHAR entry_point_code[] = {
0xB8, 0x01, 0x00, 0x00, 0x00, /* mov eax, 1 */
0xC3, /* ret */
}; };
#else #else
static const UCHAR tls_init_code[] = { 0x00 }; static const UCHAR tls_init_code[] = { 0x00 };
static const UCHAR entry_point_code[] = { 0x00 };
#endif #endif
for (test = 0; test < 4; test++) for (test = 0; test < 4; test++)
...@@ -2230,10 +2253,16 @@ static void test_import_resolution(void) ...@@ -2230,10 +2253,16 @@ static void test_import_resolution(void)
if (test == 3 && sizeof(tls_init_code) > 1) if (test == 3 && sizeof(tls_init_code) > 1)
{ {
/* Windows doesn't consistently call tls init functions on dlls without entry points */
assert(sizeof(tls_init_code) <= sizeof(data.tls_init_fn)); assert(sizeof(tls_init_code) <= sizeof(data.tls_init_fn));
assert(sizeof(entry_point_code) <= sizeof(data.entry_point_fn));
memcpy(data.tls_init_fn, tls_init_code, sizeof(tls_init_code)); memcpy(data.tls_init_fn, tls_init_code, sizeof(tls_init_code));
memcpy(data.entry_point_fn, entry_point_code, sizeof(entry_point_code));
tls_init_fn_output = 9999;
data.tls_init_fn_output = &tls_init_fn_output;
data.tls_init_fn_list[0] = nt.OptionalHeader.ImageBase + DATA_RVA(&data.tls_init_fn); data.tls_init_fn_list[0] = nt.OptionalHeader.ImageBase + DATA_RVA(&data.tls_init_fn);
data.tls.AddressOfCallBacks = nt.OptionalHeader.ImageBase + DATA_RVA(&data.tls_init_fn_list); data.tls.AddressOfCallBacks = nt.OptionalHeader.ImageBase + DATA_RVA(&data.tls_init_fn_list);
nt.OptionalHeader.AddressOfEntryPoint = DATA_RVA(&data.entry_point_fn);
} }
GetTempPathA(MAX_PATH, temp_path); GetTempPathA(MAX_PATH, temp_path);
...@@ -2315,16 +2344,27 @@ static void test_import_resolution(void) ...@@ -2315,16 +2344,27 @@ static void test_import_resolution(void)
ok( mod != NULL, "failed to load err %lu\n", GetLastError() ); ok( mod != NULL, "failed to load err %lu\n", GetLastError() );
if (!mod) break; if (!mod) break;
ptr = (struct imports *)((char *)mod + page_size); ptr = (struct imports *)((char *)mod + page_size);
tls_index_save = ptr->tls_index;
ok( ptr->tls_index < 32 || broken(ptr->tls_index == 9999), /* before vista */ ok( ptr->tls_index < 32 || broken(ptr->tls_index == 9999), /* before vista */
"wrong tls index %d\n", ptr->tls_index ); "wrong tls index %d\n", ptr->tls_index );
if (ptr->tls_index != 9999 && sizeof(tls_init_code) > 1) if (ptr->tls_index != 9999 && sizeof(tls_init_code) > 1)
{ {
/* tls init function will write an '!' over the space in "hello world" */
str = ((char **)NtCurrentTeb()->ThreadLocalStoragePointer)[ptr->tls_index]; str = ((char **)NtCurrentTeb()->ThreadLocalStoragePointer)[ptr->tls_index];
ok( !strcmp( str, "hello!world" ), "wrong tls data '%s' at %p\n", str, str ); ok( !strcmp( str, "hello world" ), "wrong tls data '%s' at %p\n", str, str );
/* tls init function will write the reason to *tls_init_fn_output */
ok( tls_init_fn_output == DLL_PROCESS_ATTACH,
"tls init function didn't run or got wrong reason: %d instead of %d\n", tls_init_fn_output, DLL_PROCESS_ATTACH );
tls_init_fn_output = 9999;
WaitForSingleObject(CreateThread(NULL, 0, tls_thread_fn, (void*)(DWORD_PTR)ptr->tls_index, 0, NULL), INFINITE);
ok( tls_init_fn_output == DLL_THREAD_DETACH,
"tls init function didn't run or got wrong reason: %d instead of %d\n", tls_init_fn_output, DLL_THREAD_DETACH );
} }
check_tls_index(mod, ptr->tls_index != 9999); check_tls_index(mod, ptr->tls_index != 9999);
tls_init_fn_output = 9999;
FreeLibrary( mod ); FreeLibrary( mod );
if (tls_index_save != 9999 && sizeof(tls_init_code) > 1)
ok( tls_init_fn_output == DLL_PROCESS_DETACH,
"tls init function didn't run or got wrong reason: %d instead of %d\n", tls_init_fn_output, DLL_PROCESS_DETACH );
} }
DeleteFileA( dll_name ); DeleteFileA( dll_name );
#undef DATA_RVA #undef DATA_RVA
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment