您的位置:首页 > 编程语言

编译器链接启动代码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是在哪里定义的,有空了再详细研究

然后就找到对应的入口程序执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: