VS Next exe Executable file start code anatomy

Source: Internet
Author: User
Tags exception handling visual studio

When we were learning C + + language programming, the teacher always told us that the program starts with the main function, but when I first used OD to parse a executable exe, it took me a long time to find this main function. Later I know that under Windows different compilers will be in the production of the final executable PE file, before we write the startup function to add some compiler to carry out the boot code, to do some initialization work, such as the initialization of global variables, run the global class object constructor, initialize the C runtime library and so on. To have (know its why) obsessive-compulsive disorder, I climbed a lot of posts on the Internet, but also debug their own analysis for several days vs startup code, so paste out memo.

Before the program enters the Main/winmain function, by debugging in Visual Studio, the _tmaincrtstartup function in crt0.c can be found through stack backtracking, which is responsible for some initialization operations because the C run-Library code has two more versions. If it is statically compiled, the code is in crt0.c, and if it is dynamically compiled, the code is located in Crtexe.c, which can be set through the configuration properties of the project properties--"C + +"--"code generation"-"runtime" of Mt and Md.

Depending on the type of project (WIN32 Engineering and console engineering), and the different engineering codes (Unicode and multibyte), the actual entry function will have four different possibilities, _tmaincrtstartup is set to a red, according to the project settings, Choose one of the actual names:

static
int
__tmaincrtstartup (
         void
         );

#ifdef _winmain_

#ifdef wprflag
int wWinMainCRTStartup (
#else/  * Wprflag */
int WinMainCRTStartup (
#endif/  * Wprflag */

#else/  * _winmain_ */

#ifdef wprflag
int wmainCRTStartup (
#else/  * Wprflag *
/int mainCRTStartup (
#endif/  * Wprflag */

#endif /*  _winmain_
        */void
        )
{/
         * * THE/GS security cookie must be initialized before any except Ion
         * Handling targetting The current image is registered.  No function
         * Using exception handling can be called in the current image until
         * after __security_init_cookie H As been called.
         *
        /__security_init_cookie ();

        return __tmaincrtstartup ();
}


_tmaincrtstartup is actually a wrapper function for __tmaincrtstartup, and before invoking the latter, the cookie is initialized, and if the/GS option is set, a cookie is set when the stack frame is created during the function call. The function returns checks whether the cookie is consistent and simply determines whether a buffer overflow is emitted. Windows under the Program entry function and _security_init_cookie here is a detailed analysis of the cookie

First look at the code when using the static C run-time library (/MT/MTD)

Located in crt0.c

int __tmaincrtstartup (void) {int initret;
        int mainret=0;
int Managedapp;
        #ifdef _winmain_ _tuchar *lpszcommandline;
 
        Startupinfow Startupinfo;
Getstartupinfow (&startupinfo); #endif/* _winmain_ */#ifdef _M_IX86//For 32-bit programs, set to automatically end the process if a heap corruption is detected//64-bit programs set this behavior by default if (!_n oheapenableterminationoncorruption) {heapsetinformation (null, heapenableterminationoncorruption, NULL
        , 0);
        } #endif/* _m_ix86 *//detects the logo in the PE header to determine if the. NET Managed program Managedapp = Check_managed_app (); ======================================================//Heap initialization operation//for 32-bit programs, _heap_init creates a Heap//====================================================== if (!_heap_init ())/* Initia  Lize Heap */Fast_error_exit (_rt_heapinit); /* Write Message and die *///Initialize multithreaded environment, temporarily do not parse if (!_mtinit ())                   /* Initialize Multi-thread */fast_error_exit (_rt_thread);
 
/* Write Message and die */_crtsetcheckcount (TRUE);
#ifdef _RTC _rtc_initialize (); #endif/* _RTC */__try {//I/O initialization, temporarily do not parse if (_ioinit () < 0)/* Initia
            Lize Lowio */_amsg_exit (_rt_lowioinit);
            Get command line Arguments/* Get wide CMD lines info */_tcmdln = (_tschar *) getcommandlinet ();
            Get environment variable parameter _TENVPTR = (_tschar *) getenvironmentstringst ();
            Parse and set command-line arguments if (_tsetargv () < 0) _amsg_exit (_rt_spacearg);
            Parse and SET environment variable parameters if (_TSETENVP () < 0) _amsg_exit (_rt_spaceenv);                  Initialize global data and floating-point registers Initret = _cinit (TRUE);
            /* Do C Data Initialize */if (Initret! = 0) _amsg_exit (initret); Enter (W) WinMain or (W) main function #ifdef _winmain_ lpszcommandline = _twincmdln ();
                                 Mainret = _tWinMain ((hinstance) &__imagebase, NULL,
                                      Lpszcommandline, Startupinfo.dwflags & Startf_useshowwindow ?
StartupInfo.wShowWindow:SW_SHOWDEFAULT);
            #else/* _winmain_ */_tinitenv = _tenviron;
Mainret = _tmain (__ARGC, _TARGV, _tenviron);
 
            #endif/* _winmain_ */if (!managedapp) exit (Mainret);
 
        _cexit (); 
             }//Exception handling __except (_xcptfilter (GetExceptionCode (), GetExceptionInformation ())) {/*
 
            * should never reach here */Mainret = GetExceptionCode ();
 
            if (!managedapp) _exit (Mainret);
 _c_exit ();
        }/* End of Try-except */return mainret; 
 }

First look at _heap_init.

int __cdecl _heap_init (void)
{
        ULONG heaptype = 2;  Initialize the "Big-block" heap first.
        if (_crtheap = heapcreate (0, bytes_per_page, 0)) = = NULL)  _crtheap  Global heap handle  Mallco function use the handle
            return 0;

#ifdef _win64
        //Enable The low fragmentation Heap by default on Windows XP and
        //Windows Server 2003.  It's the 8 byte overhead heap, and have
        //generally better performance charateristics than standard heap,
        //par Ticularly for apps that perform lots of small allocations.

        if (Lobyte (GetVersion ()) < 6)
        {
            heapsetinformation (_crtheap, Heapcompatibilityinformation,
                               & Heaptype, sizeof (Heaptype));
        }
#endif/  * _win64 */
        return 1;
}

This function uses HeapCreate to create a private heap for the standard C function malloc to use to allocate memory, and its third parameter of 0 indicates that the heap can grow automatically. Because the C run-time library is statically linked, the C run-time library code is embedded in the application, so the _crtheap is private to the application, and if the program calls a DLL that also uses the static runtime, the DLL also creates the _ Crtheap and calls HeapCreate to get the handle identity for it.

Come to see the implementation of malloc in the Smallheap.c file

void * __cdecl malloc (
        size_t size
        )
{
        return _nh_malloc (size, _newmode);
}
void __cdecl free (
        void * pblock
        )
{
        if (pblock = = NULL)
            return;

        HeapFree (_crtheap, 0, pblock);
}


_nh_malloc is also located in this file

void * __cdecl _nh_malloc (
        size_t size,
        int nhflag
        )
{
        void * RETP;

        for (;;) {

            RETP = HeapAlloc (_crtheap, 0, size);  Use global handle to request space/
             * * If successful allocation, return pointer to memory
             * If new handling turned off altogether , return NULL
             *

            /if (RETP | | nhflag = = 0)
                return RETP;

            /* Call installed new handler */
            if (!_CALLNEWH (size))
                return NULL;

            /* New Handler is successful--try to allocate again */
        }
}


There is also a function to initialize the heap in this C file

int __cdecl _heap_init (
        void
        )
{
        if ((_crtheap = heapcreate (0, bytes_per_page, 0)) = = NULL)
            return 0;

        return 1;
}

By flipping the code you can find it in dllcrt0.c and CRTLIB.C is called


Dllcrt0.c

BOOL WINAPI _crt_init (       DLL is called when using a static runtime
        HANDLE  hdllhandle,
        DWORD   dwreason,
        lpvoid  Lpreserved
        )
{
         /* * Start-up code only gets executed when the process is initialized
         *

        /if (DW Reason = = Dll_process_attach)
        {
            if (!_heap_init ())/    * Initialize heap */
                return FALSE;  



Crtlib.c

__crtdll_init (               //HANDLE Hdllhandle is called when using dynamic
        runtime  ,
        DWORD   dwreason,
        lpvoid  Lpreserved
        )
{
        if (Dwreason = = Dll_process_attach) {
            if (!_heap_init ())/    * Initialize heap */


It is not difficult to understand that when we invoke a DLL that uses a static C runtime library, or a DLL that uses the dynamic C Runtime Library, it is part of the startup code of the DLL program that uses the static C run-time libraries, and is called when using the dynamic runtime Msvcrxx.dll. They create and use their own private heaps, respectively, and are identified by their respective _CRTHEAP global handles. If the DLL has an exported function, the function uses malloc to request a piece of memory and returns a pointer.

When we write an EXE using the static runtime to call this DLL exported this function, use free to release the requested memory, will cause the program crashes is not difficult to understand, corresponding if EXE with the Dynamic Runtime library to write, then DLL use static library times error, use the dynamic runtime is working properly , because they are called msvcrxx. In the DLL, malloc and free naturally refer to the same _crtheap global handle, which is in Mscrcxx.dll.



It is not difficult to see that when writing a Windows program, if you use a large number of C standard library functions, you should use the dynamic runtime to avoid some unnecessary errors.

Using the New keyword for C + + to allocate space for an object is also the same as using _CRTHEAP to request heap memory for identity using HeapAlloc. Therefore, you should use new and delete in the same module to request and dispose of heap objects

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.