我正在阅读一本描述加载程序如何工作的教科书:
当加载程序运行时,它将可执行目标文件的块复制到代码和数据段中。接下来,加载器跳转到程序的入口点,该入口点始终是函数的地址。_start
_start
函数调用系统启动函数,__libc_start_main
从答案来看这个堆栈溢出问题,我们有以下关于执行流程的伪代码:
_start:
call __setup_for_c ; set up C environment
call __libc_start_main ; set up standard library
call _main ; call your main
call __libc_stop_main ; tear down standard library
call __teardown_for_c ; tear down C environment
jmp __exit ; return to OS
我的问题是:
答案1
链接答案中描述的其他函数调用给出了需要发生的事情的概要; GNU C 库中的实际实现细节有所不同,要么使用“构造函数”(
_dl_start_user
),要么在__libc_start_main
.__libc_start_main
还负责调用用户的main
,这就是为什么你看不到它被称为在你的反汇编中 - 但它的地址被传递(参见lea
)callq
。__libc_start_main
还负责程序退出,并且永不返回;这就是hlt
紧随其后的原因callq
,如果函数返回,它将使程序崩溃。如今,该库需要进行大量设置:
- 一些自己的搬迁
- 线程本地存储设置
- 并行线程设置
- 析构函数注册
- vDSO 设置(在 Linux 上)
- ctype初始化
- 将程序名称、参数和环境复制到各种库变量
等等。请参阅 x86-64 特定的
sysdeps/x86_64/start.S
和通用的csu/libc-start.c
,csu/init-first.c
, 和misc/init-misc.c
除其他外。