тащемта не могу вкурить как колбэк подключить. в х86 работало так: #pragma comment (linker, "/INCLUDE:__tls_used") //IMAGE_TLS_DIRECTORY64 _tls_used #pragma comment (linker, "/INCLUDE:__xl_b") #pragma data_seg (".CRT$XLB") EXTERN_C PIMAGE_TLS_CALLBACK _xl_b = CallbackRoutine; #pragma data_seg() всё работало. и судя по комментам в vcruntime - XL* -это массив поинтеров, ограничевается через __xl_a и __xl_z . но нихрена не работает в х64. но что интересно: делая такое: #pragma comment (linker, "/INCLUDE:_tls_used") extern "C" const IMAGE_TLS_DIRECTORY64 _tls_used{0x666,0,0,(ULONGLONG)0x666,0}; на выходе получаю у бинаря диркторию с указанными значениями. т.е. вроде как определение, но динкер не ругается на редеф. а вот когда запиливаю #pragma comment (linker, "/INCLUDE:__xl_a") #pragma data_seg(".CRT$XLA") extern "C" const PIMAGE_TLS_CALLBACK __xl_a = cb0; #pragma data_seg() то тут сразу ругается на редеф, и так и должно быть по идее вопроса 2: 1) что я делаю не так чтобы воткнуть колбак 2) что за фигня с линкером, или это какоето ключевой символ который он позволяет редефайнить --- Сообщение объединено, 23 окт 2018 --- _CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0; /* NULL terminator for TLS callback array. This symbol, __xl_z, is never * actually referenced anywhere, but it must remain. The OS loader code * walks the TLS callback array until it finds a NULL pointer, so this makes * sure the array is properly terminated. */ _CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0; то есть пытаюсь вклиниться data_seg (".CRT$XLB") __xl_b = lalala но получаю .rdata:00000001400B3160 ; _IMAGE_TLS_DIRECTORY64 tls_used .rdata:00000001400B3160 _tls_used dq offset _tls_start .rdata:00000001400B3168 TlsEnd_ptr dq offset _tls_end .rdata:00000001400B3170 TlsIndex_ptr dq offset _tls_index .rdata:00000001400B3178 TlsCallbacks_ptr dq offset __xl_z .rdata:00000001400B3180 TlsSizeOfZeroFill db 0 .rdata:00000001400B3181 db 0 .rdata:00000001400B3182 db 0 .rdata:00000001400B3183 db 0 .rdata:00000001400B3184 TlsCharacteristics db 0 .rdata:00000001400B3185 db 0 .rdata:00000001400B3186 db 10h .rdata:00000001400B3187 db 0 впрочем __xl_z там и должно быть ибо: _CRTALLOC(".rdata$T") extern const IMAGE_TLS_DIRECTORY64 _tls_used = { (ULONGLONG) &_tls_start, // start of tls data (ULONGLONG) &_tls_end, // end of tls data (ULONGLONG) &_tls_index, // address of tls_index (ULONGLONG) (&__xl_a+1), // pointer to call back array (ULONG) 0, // size of tls zero fill (ULONG) 0 // characteristics }; но ведь поинтеры должны идти в таком порядке: data_seg (".CRT$XLA") data_seg (".CRT$XLB") data_seg (".CRT$XLZ") а у меня выходит: .rdata:0000000140094360 __xl_a dq 0 ; __xl_a .rdata:0000000140094368 ; void (__fastcall *_xl_z)(void *, unsigned int, void *) .rdata:0000000140094368 __xl_z dq 0 ; DATA XREF: .rdata:TlsCallbacks_ptr↓o ;сюда поинтит TlsCallbacks .rdata:0000000140094370 ; void (__fastcall *_xp_a[1])() .rdata:0000000140094370 __xp_a dq 0 ; DATA XREF: _lambda_6e4b09c48022b2350581041d5f6b0c4c___operator__+B8↑o .rdata:0000000140094378 ; void (__fastcall *const _acrt_locale_terminator)() .rdata:0000000140094378 __acrt_locale_terminator dq offset __acrt_uninitialize_locale .rdata:0000000140094380 ; void (__fastcall *const _dcrt_console_output_terminator)() .rdata:0000000140094380 __dcrt_console_output_terminator dq offset __dcrt_terminate_console_output .rdata:0000000140094388 ; void (__fastcall *const _acrt_stdio_terminator)() .rdata:0000000140094388 __acrt_stdio_terminator dq offset __acrt_uninitialize_stdio .rdata:0000000140094390 ; void (__fastcall *_xp_z[1])() .rdata:0000000140094390 __xp_z dq 0 ; DATA XREF: _lambda_6e4b09c48022b2350581041d5f6b0c4c___operator__+B1↑o .rdata:0000000140094398 ; void (__fastcall *_xt_a[1])() .rdata:0000000140094398 __xt_a dq 0 ; DATA XREF: _lambda_6e4b09c48022b2350581041d5f6b0c4c___operator__+CB↑o .rdata:00000001400943A0 ; void (__fastcall *_xt_z[1])() .rdata:00000001400943A0 __xt_z dq 0 ; DATA XREF: _lambda_6e4b09c48022b2350581041d5f6b0c4c___operator__:loc_14001E764↑o .rdata:00000001400943A8 align 10h .rdata:00000001400943B0 ; void (__fastcall *const _xl_b)(void *, unsigned int, void *) .rdata:00000001400943B0 __xl_b dq offset ?cb0@@YAXPEAXK0@Z ; cb0(void *,ulong,void *) ; <------- а это должно быть после .rdata:0000000140094360 __xl_a dq 0 ; --- Сообщение объединено, 23 окт 2018 --- короче разобрался, почемуто поинтер не влезает между __xl_a и __xl_z а впиливается уже позже. коме того линкер пишет TlsCallbacks на __xl_z. если запилить типа #pragma data_seg (".CRT$XLB") EXTERN_C const PIMAGE_TLS_CALLBACK __xl_b = cb0; EXTERN_C const PIMAGE_TLS_CALLBACK __xl_b0 = (PIMAGE_TLS_CALLBACK)0; #pragma data_seg() и руками костыльнуть TlsCallbacks на __xl_b - то всё работает. странно с этим ордерингом - почему криво располагает? да и еще почему позволяет запись в __tls_used не считая это редефайном --- Сообщение объединено, 23 окт 2018 --- короче ясно, надо было const_seg вместо data_seg, хотя в 86 то работало и упорядочивалось нормально, независимо от cv, с конст всё на свои места встало, рабочий вариант: void __stdcall cb0(PVOID, DWORD, PVOID) { MessageBox(0, L"WWW", 0, 0); } #pragma comment (linker, "/INCLUDE:_tls_used") //EXTERN_C const IMAGE_TLS_DIRECTORY64 _tls_used{ 0,0,0 }; // AV in ntdll!LdrpAllocateTlsEntry+0xc8: #pragma const_seg (".CRT$XLB") EXTERN_C const PIMAGE_TLS_CALLBACK __xl_b = cb0; #pragma const_seg()