编译器链接启动代码crtexe.c
2013-10-18 11:05
295 查看
你是否想过为什么有时候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?
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中被调用,详细介绍,略去
第二个函数
[cpp] view
plaincopyprint?
static void __cdecl pre_cpp_init(void)
[cpp] view
plaincopyprint?
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 */
}
下面是程序的第一个入口处
[cpp] view
plaincopyprint?
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 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()中
关键代码:
[cpp] view
plaincopyprint?
#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代码
第一个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?
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中被调用,详细介绍,略去
第二个函数
[cpp] view
plaincopyprint?
static void __cdecl pre_cpp_init(void)
[cpp] view
plaincopyprint?
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 */
}
下面是程序的第一个入口处
[cpp] view
plaincopyprint?
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 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()中
关键代码:
[cpp] view
plaincopyprint?
#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
- 考虑下列生成二进制的过程,编译器被用来生成单个单元的目标代码,链接器被用来将多个目标单元合并成一个程序二进制,链接器如何改变指令和数据到内存地址的绑定?需要什么信息从编译器传递给链接器,以协助完成链接
- 常用即时通讯软件在网页上启动临时对话的链接代码
- 编写cortex GCC编译器下的c启动代码
- SQLServer\framework启动报异常:Module的类型初始值设定项引发异常 [转]QQ空间、新浪微博、腾讯微博等一键分享API链接代码 window下 mongodb快速安装 数据表查询所有子/父节点 C#学习笔记1
- android通过访问链接启动应用app(服务器加android代码)
- 即时通讯软件在网页上启动临时对话的链接代码
- 代码 生成迅雷链接启动迅雷下载
- 用C#代码来安装、卸载、启动、关闭服务
- flume启动代码加载分析
- 图片自动切换并改变链接代码
- S5PV210--1---210启动方式和代码前16字节
- SQL Server无法启动,错误代码 3417
- [转]VC 开机自动启动程序代码
- Android自带分享和应用市场(进行软件评分)启动代码
- Pixhawk之启动代码和入口函数(.mk、rcS、__start、hrt)
- Windows服务代码控制安装卸载、启动停止
- 在java代码中输出Html代码实现按钮点击链接跳转
- nodejs代码初探之nodejs启动