运行库和程序初始化

入口函数和函数初始化

 程序在进入我们编写的入口之前,就已经初始化好了堆栈,外围IO,全局变量等。
 这些工作都是函数库完成的,他们才是一个独立程序最开始执行的代码。

在这里插入图片描述

入口函数的实现(静态glibc+可执行文件)

 首先我们要明白在PC指向E入口地址执行之前,是谁在handle这个ELF文件?应该是装载器(ld),装载器按照其ELF文件中的Program Header等信息将其相关的部分装载内存中,同时也会将用户的参数和环境变量压入栈中。有了这个背景知识,我们可以从Entry point address出发,分析该ELF文件的执行过程。

tar xvf glibc-2.35.tar
vim .//sysdeps/arm/start.S
我们来看看arm平台的入口实现:

_start:
       /* Protect against unhandled exceptions.  */
       .fnstart
	/* Clear the frame pointer and link register since this is the outermost frame. */
	/* 清栈帧指针和lr指针,说明这是最外层的栈(FP实际上就是R11寄存器,在APCS调用规则中,使用R11作为帧指针寄存器) */
	mov fp, #0
	mov lr, #0

	/* Pop argc off the stack and save a pointer to argv */
	/* a2 a3代表的是x2 x3寄存器,代表的是传参argc和argv */
	pop { a2 }
	mov a3, sp

	/* Push stack limit a3保存的argv参数指针压栈 */
	push { a3 }

	/* Push rtld_fini 压栈rtld函数*/
	push { a1 }

#ifdef PIC  /* 编译时候加-fPIC参数 PIC就是position independent code  地址无关代码 PIC使.so文件的代码段变为真正意义上的共享库 */
	ldr sl, .L_GOT       /* 加载GOT表 */
	adr a4, .L_GOT
	add sl, sl, a4

	mov a4, #0		/* Used to be init.  */
	push { a4 }		/* Used to be fini.  */

	ldr a1, .L_GOT+4	/* main */
	ldr a1, [sl, a1]

	/* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
	/* Let the libc call main and exit with its return code.  */
	bl __libc_start_main(PLT)
#else

	mov a4, #0		/* Used to init.  */
	push { a4 }		/* Used to fini.  */
	ldr a1, =main  /* 这就是我们常说的main是入口函数由来 */

	/* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
	/*实际上前面对于a1 a2 a3的操作都成为了__libc_start_main的入参;
	* a1 = main使我们要执行的函数入口
	* a2/a3是包含环境变量的传参
	* a4 = init是加载main之前的一些初始化工作
	* a5 = fini是main结束之后的收尾工作
	* a6 = rtld_fini是动态加载器的收尾工作
	* a7 = stack_end标明了栈底的地址,即最高的栈地址
	*/
	/* Let the libc call main and exit with its return code.  */
	bl __libc_start_main 
	 /*跳转执行,这个函数就完整了我们整个程序的运行,
	* 其实主要功能就是:__libc_start_main这个函数完成了运行环境的初始化,然后再调用了我们函数中的main,
	* 执行完成后,使用exit函数结束程序。finit用的函数注册在了exit函数中,所以调用exit会执行finit的过程。
	* 到此我们就明白了运行时库是如何帮助我们初始化运行环境,并执行我们的函数,然后退出的过程
	* */
#endif

	/* should never get here....*/
	bl abort

#ifdef PIC
	.align 2
.L_GOT:
	.word _GLOBAL_OFFSET_TABLE_ - .L_GOT
	.word main(GOT)
#endif

       .cantunwind
       .fnend

C语言运行库

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值