Monday, July 15, 2013

Microsoft Visual C memory segments

If you look in a file called Microsoft Visual Studio\VC\crt\src\sect_attribs.h you'll see a list of #pragma's for section attributes.  This is here to define memory segments in your compiled software.   After a little searching on the internet I wasn't able to find a list of what each of this segments were for.  Poking around the rest of the CRT source was able to give me some clues.


#pragma section(".CRTMP$XCA",long,read)
#pragma section(".CRTMP$XCZ",long,read)
#pragma section(".CRTMP$XIA",long,read)
#pragma section(".CRTMP$XIZ",long,read)

#pragma section(".CRTMA$XCA",long,read)
#pragma section(".CRTMA$XCZ",long,read)
#pragma section(".CRTMA$XIA",long,read)
#pragma section(".CRTMA$XIZ",long,read)

#pragma section(".CRTVT$XCA",long,read)
#pragma section(".CRTVT$XCZ",long,read)

These sections are used for initializers of globals when you are building a managed binary.  The $XI are C initializes while the $XC are C++ initializers.   The MP means managed per process, while the MA means managed per app domain.  The VT stands for VTABLE, in other words your virtual method initializers.  I found this all in crt\src\mstartup.cpp.   Something interesting is the C initializers are never called.

#pragma section(".CRT$XCA",long,read)
#pragma section(".CRT$XCC",long,read)
#pragma section(".CRT$XCZ",long,read)
#pragma section(".CRT$XIA",long,read)
#pragma section(".CRT$XIC",long,read)
#pragma section(".CRT$XID",long,read)
#pragma section(".CRT$XIY",long,read)
#pragma section(".CRT$XIZ",long,read)

These sections are used for native initializers. Like before $XI are C while $XC are C++ initializers.  The XCC section is the list of C++ initializers and the XIC are the C initializers.  The XID and XIY seems to be a special sections of C initializers that are to be run after all the C initializers

#pragma section(".CRT$XCAA",long,read)
#pragma section(".CRT$XIAA",long,read)

These sections are for native PRE-initializers.  That is, they are run before the above initializers.

#pragma section(".CRT$XPA",long,read)
#pragma section(".CRT$XPB",long,read)
#pragma section(".CRT$XPX",long,read)
#pragma section(".CRT$XPXA",long,read)
#pragma section(".CRT$XPZ",long,read)
#pragma section(".CRT$XTA",long,read)
#pragma section(".CRT$XTB",long,read)
#pragma section(".CRT$XTX",long,read)
#pragma section(".CRT$XTZ",long,read)

These are C terminators (read destructors), that get called on exit.  $XP are pre-terminators, and $XT are normal terminators.

#pragma section(".CRT$XDA",long,read)
#pragma section(".CRT$XDC",long,read)
#pragma section(".CRT$XDL",long,read)
#pragma section(".CRT$XDU",long,read)
#pragma section(".CRT$XDZ",long,read)

These are used for Thread Local Storage dynamic initializers.  You can find a detailed explanation in crt\src\tlsdyn.c.

#pragma section(".CRT$XLA",long,read)
#pragma section(".CRT$XLC",long,read)
#pragma section(".CRT$XLD",long,read)
#pragma section(".CRT$XLZ",long,read)

These seem to be for bootstrapping for Thread Local Storage.  From a comment in src\crt\tlssup.c
/* Start section for TLS callback array examined by the OS loader code.
 * If dynamic TLS initialization is used, then a pointer to __dyn_tls_init
 * will be placed in .CRT$XLC by inclusion of tlsdyn.obj.  This will cause
 * the .CRT$XD? array of individual TLS variable initialization callbacks
 * to be walked.
 */
If I understand this correctly, it means that if you have Thread Local Storage enabled, a pointer to __dyn_tls_init will be placed in .CRT$XLC, which should cause it to be called and your TLS to be initialized as needed.  The XLD points to _dyn_tls_dtor, which calls the destructors for Thread Local Storage.

For an explanation on what these sections are used for read this blog

1 comment: