编译器链接启动代码crtexe.c

来源:互联网 发布:mac怎么压缩文件夹 编辑:程序博客网 时间:2024/06/05 18:19

你是否想过为什么有时候main()函数是入口地址,在win32中winmain()函数又是入口地址,其实是编译器在动态链接到crt[C runtime library(part of the C standard library)]时候设置的

程序设置断点,我们来看crtexe.c代码

第一个static int __cdecl pre_c_init(void)

*       The code in mainCRTStartup that was executed before executing C   initializers was shifted in this function. Also this funciton is the   first thing that is executed in c init section.

什么意思不用详细说,老外的注释很给力

[cpp] view plaincopyprint?
  1. static int __cdecl pre_c_init(void)  
  2. {  
  3.     /* 
  4.      * Determine if this is a managed application 
  5.      */  
  6.     managedapp = check_managed_app();  
  7.   
  8.     /* 
  9.      * Set __app_type properly 
  10.      */  
  11. #ifdef _WINMAIN_    //根据WINMAIN宏来设置应用程序是GUI程序还是控制台程序  
  12.     __set_app_type(_GUI_APP);  
  13. #else  /* _WINMAIN_ */  
  14.     __set_app_type(_CONSOLE_APP);  
  15. #endif  /* _WINMAIN_ */  
  16.   
  17.     /* 
  18.      * Mark this module as an EXE file so that atexit/_onexit 
  19.      * will do the right thing when called, including for C++ 
  20.      * d-tors. 
  21.      */  
  22.     __onexitbegin = __onexitend = (_PVFV *)_encode_pointer((_PVFV *)(-1));  
  23.   
  24.     /* 
  25.      * Propogate the _fmode and _commode variables to the DLL 
  26.      */  
  27.     *_IMP___FMODE = _fmode;  
  28.     *_IMP___COMMODE = _commode;  
  29.   
  30. #ifdef _M_IX86  
  31.     /* 
  32.      * Set the local copy of the Pentium FDIV adjustment flag 
  33.      */  
  34.   
  35.     _adjust_fdiv = * _imp___adjust_fdiv;  
  36. #endif  /* _M_IX86 */  
  37.   
  38.     /* 
  39.      * Run the RTC initialization code for this DLL 
  40.      */  
  41. #ifdef _RTC  
  42.     _RTC_Initialize();  
  43. #endif  /* _RTC */  
  44.   
  45.     /* 
  46.      * Call _setargv(), which will trigger a call to __setargv() if 
  47.      * SETARGV.OBJ is linked with the EXE.  If SETARGV.OBJ is not 
  48.      * linked with the EXE, a dummy _setargv() will be called. 
  49.      */  
  50. #ifdef WPRFLAG  
  51.     _wsetargv();  
  52. #else  /* WPRFLAG */  
  53.     _setargv();  
  54. #endif  /* WPRFLAG */  
  55.   
  56.     /* 
  57.      * If the user has supplied a _matherr routine then set 
  58.      * __pusermatherr to point to it. 
  59.      */  
  60.     if ( !__defaultmatherr )  
  61.         __setusermatherr(_matherr);  
  62.   
  63. #ifdef _M_IX86  
  64.     _setdefaultprecision();  
  65. #endif  /* _M_IX86 */  
  66.   
  67.     /* Enable per-thread locale if user asked for it */  
  68.     if(__globallocalestatus == -1)  
  69.     {  
  70.         _configthreadlocale(-1);  
  71.     }  
  72.   
  73.     return 0;  
  74. }  
这个函数在crt0dat.c中被调用,详细介绍,略去

第二个函数

[cpp] view plaincopyprint?
  1. static void __cdecl pre_cpp_init(void)  
[cpp] view plaincopyprint?
  1. static void __cdecl pre_cpp_init(void)  
  2. {  
  3. #ifdef _RTC  
  4.     atexit(_RTC_Terminate);  //注册程序退出时的清理工  
  5. #endif  /* _RTC */  
  6.   
  7.     /* 
  8.      * Get the arguments for the call to main. Note this must be 
  9.      * done explicitly, rather than as part of the dll's 
  10.      * initialization, to implement optional expansion of wild 
  11.      * card chars in filename args 
  12.      */  
  13.   
  14.     startinfo.newmode = _newmode;  
  15.   
  16.   
  17. #ifdef WPRFLAG  
  18.     argret = __wgetmainargs(&argc, &argv, &envp,  
  19.                             _dowildcard, &startinfo);  
  20. #else  /* WPRFLAG */  
  21.     argret = __getmainargs(&argc, &argv, &envp,  
  22.                            _dowildcard, &startinfo);  
  23. #endif  /* WPRFLAG */  
  24.   
  25. #ifndef _SYSCRT  
  26.     if (argret < 0)  
  27.         _amsg_exit(_RT_SPACEARG);  
  28. #endif  /* _SYSCRT */  
  29. }  


下面是程序的第一个入口处

[cpp] view plaincopyprint?
  1. static  
  2. int  
  3. __tmainCRTStartup(  
  4.          void  
  5.          );  
  6.   
  7. #ifdef _WINMAIN_  
  8.   
  9. #ifdef WPRFLAG  
  10. int wWinMainCRTStartup(  
  11. #else  /* WPRFLAG */  
  12. int WinMainCRTStartup(  
  13. #endif  /* WPRFLAG */  
  14.   
  15. #else  /* _WINMAIN_ */  
  16.   
  17. #ifdef WPRFLAG  
  18. int wmainCRTStartup(  
  19. #else  /* WPRFLAG */  
  20. int mainCRTStartup(  
  21. #endif  /* WPRFLAG */  
  22.   
  23. #endif  /* _WINMAIN_ */  
  24.         void  
  25.         )  
  26. {  
  27.         /* 
  28.          * The /GS security cookie must be initialized before any exception 
  29.          * handling targetting the current image is registered.  No function 
  30.          * using exception handling can be called in the current image until 
  31.          * after __security_init_cookie has been called. 
  32.          */  
  33.         __security_init_cookie();  
  34.   
  35.         return __tmainCRTStartup();  
  36. }  


/***
*mainCRTStartup(void)
*wmainCRTStartup(void)
*WinMainCRTStartup(void)
*wWinMainCRTStartup(void)
*
*Purpose:
*       These routines do the C runtime initialization, call the appropriate
*       user entry function, and handle termination cleanup.  For a managed
*       app, they then return the exit code back to the calling routine, which
*       is the managed startup code.  For an unmanaged app, they call exit and
*       never return.
*
*       Function:               User entry called:
*       mainCRTStartup          main
*       wmainCRTStartup         wmain
*       WinMainCRTStartup       WinMain
*       wWinMainCRTStartup      wWinMain

就是为程序找到入口地址,具体的判断是在函数__tmainCRTStartup()中

关键代码:

[cpp] view plaincopyprint?
  1. #ifdef WPRFLAG  
  2.             mainret = wWinMain(  
  3. #else  /* WPRFLAG */  
  4.             mainret = WinMain(  
  5. #endif  /* WPRFLAG */  
  6.                        (HINSTANCE)&__ImageBase,  
  7.                        NULL,  
  8.                        lpszCommandLine,  
  9.                        StartupInfo.dwFlags & STARTF_USESHOWWINDOW  
  10.                         ? StartupInfo.wShowWindow  
  11.                         : SW_SHOWDEFAULT  
  12.                       );  
  13. #else  /* _WINMAIN_ */  
  14.   
  15. #ifdef WPRFLAG  
  16.             __winitenv = envp;  
  17.             mainret = wmain(argc, argv, envp);  
  18. #else  /* WPRFLAG */  
  19.             __initenv = envp;  
  20.             mainret = main(argc, argv, envp);  
  21. #endif  /* WPRFLAG */  
  22.   
  23. #endif  /* _WINMAIN_ */  

我们看到,根据宏WPRFLAG来判断是wWinmain()还是WinMain(),根据_WINMAIN_来判断入口函数是main(),wmain()还是WinMain(),wWinMain()

wmain()和wWinMain()是unicode版的,main()和WinMain()是ANSI版的 不过在程序中始终没有找到宏WPRFLAG是在哪里定义的,有空了再详细研究

然后就找到对应的入口程序执行。

原创粉丝点击