编译器链接启动代码crtexe.c
来源:互联网 发布:炫踪网络发行的游戏 编辑:程序博客网 时间:2024/05/17 07:55
你是否想过为什么有时候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.
什么意思不用详细说,老外的注释很给力
static int __cdecl pre_c_init(void){ /* * Determine if this is a managed application */ managedapp = check_managed_app(); /* * Set __app_type properly */#ifdef _WINMAIN_ //根据WINMAIN宏来设置应用程序是GUI程序还是控制台程序 __set_app_type(_GUI_APP);#else /* _WINMAIN_ */ __set_app_type(_CONSOLE_APP);#endif /* _WINMAIN_ */ /* * Mark this module as an EXE file so that atexit/_onexit * will do the right thing when called, including for C++ * d-tors. */ __onexitbegin = __onexitend = (_PVFV *)_encode_pointer((_PVFV *)(-1)); /* * Propogate the _fmode and _commode variables to the DLL */ *_IMP___FMODE = _fmode; *_IMP___COMMODE = _commode;#ifdef _M_IX86 /* * Set the local copy of the Pentium FDIV adjustment flag */ _adjust_fdiv = * _imp___adjust_fdiv;#endif /* _M_IX86 */ /* * Run the RTC initialization code for this DLL */#ifdef _RTC _RTC_Initialize();#endif /* _RTC */ /* * Call _setargv(), which will trigger a call to __setargv() if * SETARGV.OBJ is linked with the EXE. If SETARGV.OBJ is not * linked with the EXE, a dummy _setargv() will be called. */#ifdef WPRFLAG _wsetargv();#else /* WPRFLAG */ _setargv();#endif /* WPRFLAG */ /* * If the user has supplied a _matherr routine then set * __pusermatherr to point to it. */ if ( !__defaultmatherr ) __setusermatherr(_matherr);#ifdef _M_IX86 _setdefaultprecision();#endif /* _M_IX86 */ /* Enable per-thread locale if user asked for it */ if(__globallocalestatus == -1) { _configthreadlocale(-1); } return 0;}这个函数在crt0dat.c中被调用,详细介绍,略去
第二个函数
static void __cdecl pre_cpp_init(void)
static void __cdecl pre_cpp_init(void){#ifdef _RTC atexit(_RTC_Terminate); //注册程序退出时的清理工#endif /* _RTC */ /* * Get the arguments for the call to main. Note this must be * done explicitly, rather than as part of the dll's * initialization, to implement optional expansion of wild * card chars in filename args */ startinfo.newmode = _newmode;#ifdef WPRFLAG argret = __wgetmainargs(&argc, &argv, &envp, _dowildcard, &startinfo);#else /* WPRFLAG */ argret = __getmainargs(&argc, &argv, &envp, _dowildcard, &startinfo);#endif /* WPRFLAG */#ifndef _SYSCRT if (argret < 0) _amsg_exit(_RT_SPACEARG);#endif /* _SYSCRT */}
staticint__tmainCRTStartup( void );#ifdef _WINMAIN_#ifdef WPRFLAGint wWinMainCRTStartup(#else /* WPRFLAG */int WinMainCRTStartup(#endif /* WPRFLAG */#else /* _WINMAIN_ */#ifdef WPRFLAGint wmainCRTStartup(#else /* WPRFLAG */int mainCRTStartup(#endif /* WPRFLAG */#endif /* _WINMAIN_ */ void ){ /* * The /GS security cookie must be initialized before any exception * handling targetting the current image is registered. No function * using exception handling can be called in the current image until * after __security_init_cookie has been called. */ __security_init_cookie(); return __tmainCRTStartup();}
/***
*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()中
关键代码:
#ifdef WPRFLAG mainret = wWinMain(#else /* WPRFLAG */ mainret = WinMain(#endif /* WPRFLAG */ (HINSTANCE)&__ImageBase, NULL, lpszCommandLine, StartupInfo.dwFlags & STARTF_USESHOWWINDOW ? StartupInfo.wShowWindow : SW_SHOWDEFAULT );#else /* _WINMAIN_ */#ifdef WPRFLAG __winitenv = envp; mainret = wmain(argc, argv, envp);#else /* WPRFLAG */ __initenv = envp; mainret = main(argc, argv, envp);#endif /* WPRFLAG */#endif /* _WINMAIN_ */
我们看到,根据宏WPRFLAG来判断是wWinmain()还是WinMain(),根据_WINMAIN_来判断入口函数是main(),wmain()还是WinMain(),wWinMain()
wmain()和wWinMain()是unicode版的,main()和WinMain()是ANSI版的 不过在程序中始终没有找到宏WPRFLAG是在哪里定义的,有空了再详细研究
然后就找到对应的入口程序执行。
- 编译器链接启动代码crtexe.c
- 编译器链接启动代码crtexe.c
- crtexe.c
- crtexe.c
- crtexe.c作用
- 编写cortex GCC编译器下的c启动代码
- C程序编译器和链接器
- C编译器、链接器、加载器详解
- C编译器、链接器、加载器详解
- C编译器、链接器、加载器详解
- C编译器、链接器、加载器详解
- C 编译器、链接器、加载器详解
- C编译器、链接器、加载器详解
- C编译器、链接器、加载器详解
- c代码编译器工作原理
- 从编译器的角度看C代码
- 拔河比赛---C语言代码,编译器Xcode
- C/C++在线编译器——链接地址
- ocs NG +GLPI安装和基本配置
- 深入VBS类与对象
- IMAGE控件出错代替图片的JS
- CArchive的使用
- NSURLRequest详解
- 编译器链接启动代码crtexe.c
- ?Linux修饰语__init
- Android[中级教程]第三章 数据存储之SQLite
- 使用hibernate进行增删改查
- 四种强制类型转换的总结(const_cast、static_cast、dynamic_cast、reinterpreter_cast)
- w3school学习1-jQuery 语法
- Frederick Brooks: 计算机科学家的使命是制造工具 II, 翻译连载第1部分
- Zend_Cache的使用
- HDOJ1195密码箱