*当执行”Hello World“程序时,是从main函数开始执行的吗?答案当然是No,No,No!*
一个程序的运行步骤如下:
操作系统在在创建进程后,把控制权交给了程序的入口,这个入口一般是运行库中的某个入口函数
入口函数对运行库和程序运行环境进行初始化,包括堆、I/O、线程、全局变量构造等
入口函数完成初始化后,调用main函数,正式开始执行程序主体部分
main函数执行完毕后,返回到入口函数,入口函数进行清理工作,包括全局变量析构、堆销毁、关闭I/O等,然后进行系统调用结束进程
接下来具体分析的是基于glibc 2.6.1中静态链接的、用于可执行文件的情况
第一步:glibc的程序入口为_start(这个入口是有ld链接器默认的链接脚本指定的,可以通过相关参数设定入口)
_start由汇编实现且和平台相关
//将汇编改写为伪代码 void start() { %ebp = 0;//使ebp为0,证明其是最外层函数 int argc = pop from stack;//从栈中获取argc,隐含envp char **argv = top from stack;//从栈中获取argv //调用_libc_start_main()函数 _libc_start_main(main, argc, argv, _libc_csu_init, _libc_csu_fini, edx, top of stack); }
栈分布情况