对于在多种操作系统上使用 C++ 的开发者而言,理解应用程序的入口点,及其背后的底层架构至关重要。它不仅仅是一个简单的起点,而是通往理解程序如何从无到有、启动运行的钥匙。本章将深入剖析一个应用程序的启动过程,特别关注在进入熟悉的 main() 函数之前,那些默默完成初始化工作的底层代码。
首先在 Linux 系统的土壤中探索这一过程,将揭开可执行与可链接格式(Executable and Linkable Format,ELF)的神秘面纱,详细解读 execve() 系统调用如何加载并执行 _start() 函数。这个 _start() 函数就像是舞台的幕后总导演,在将控制权交给 main() 之前,精心布置好整个运行时环境。此外,还会触及一些编译器提供的巧妙扩展,允许开发者对这一启动流程进行精细的操控。
随后,将目光转向 Windows 平台,细致地分析其可移植可执行文件格式(Portable Executable,PE)中各个功能各异的节区(sections)。
为了更直观、更深入地洞悉这两个平台上可执行文件的内部构造,我们将借助一款强大的工具 —— Ghidra。它是由美国国家安全局(NSA)开发的优秀开源软件逆向工程套件,不仅能反汇编、反编译和调试二进制文件,更能为我们揭示应用程序启动过程中的底层机制。
完成本章后,你将对以下内容有更深入的理解: