VC TLS

Тема в разделе "WASM.X64", создана пользователем sn0w, 23 окт 2018.

  1. sn0w

    sn0w Active Member

    Публикаций:
    0
    Регистрация:
    27 фев 2010
    Сообщения:
    956
    тащемта не могу вкурить как колбэк подключить. в х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()