尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
从 `hello.c` 到 ELF:亲手走一遍 GCC 编译、汇编与链接全过程
平时编译 C 程序我们往往只写一条命令gcc hello.c-ohello几秒之后可执行文件就生成了。但这条命令背后到底发生了什么头文件去了哪里.o为什么不能直接运行printf的实现什么时候进入程序动态链接和静态链接又差在哪为了把这些问题串起来我用一个简单的hello.c做了完整实验分别保留预处理文件、汇编文件和目标文件再借助objdump、readelf、ldd观察符号、重定位和 ELF 布局。这套过程不只适用于本机 GCC。以后换成 ARM 交叉编译器编译链路仍然相同只是目标架构和使用的库发生了变化。一条命令背后的四个阶段从 C 源文件到可执行程序通常会经过四个阶段hello.c --预处理-- hello.i --编译-- hello.s --汇编-- hello.o --链接-- hello阶段GCC 参数输出主要工作预处理-Ehello.i展开头文件和宏处理条件编译编译-Shello.s语法、语义分析生成汇编代码汇编-chello.o生成机器码和可重定位 ELF链接无停止参数hello解析符号、重定位并生成可执行文件这里有个很容易写错的地方汇编后停止使用的是小写-c。大写-C是预处理选项通常和-E搭配用来保留注释。准备一段测试代码为了方便观察库函数符号测试程序保留了printf、atoi和exit等调用#includestdio.h#includestdlib.hintmain(intargc,char*argv[]){if(argc!2){printf(Usage: %s number\n,argv[0]);exit(EXIT_FAILURE);}printf(program: %s, input: %s\n,argv[0],argv[1]);intnumberatoi(argv[1]);switch(number){case0:printf(h\n);break;case1:printf(e\n);break;case2:printf(l\n);break;case3:printf(l\n);break;case4:printf(o\n);break;default:printf(hello\n);break;}returnEXIT_SUCCESS;}atoi()无法可靠判断转换失败这里只是为了观察编译和链接过程。正式项目更适合使用strtol()并检查非法字符、溢出和数值范围。把四个阶段分别执行gcc-Ehello.c-ohello.i gcc-S-g-O0hello.i-ohello.s gcc-chello.s-ohello.o gcc hello.o-ohello-g用来保留调试信息方便后面混合显示源代码和汇编-O0关闭优化让生成结果更接近源代码结构。第一站预处理文件为什么这么大gcc-Ehello.c-ohello.i预处理器主要完成下面几件事展开#include引入的头文件替换宏定义处理#if、#ifdef等条件编译默认删除注释插入行标记保留内容对应的源文件和行号例如#12hello.c它告诉后续编译阶段接下来的内容与hello.c第 12 行相关。实际行标记还可能包含其他标志用来表示进入或离开头文件等状态。比较文件大小和行数stathello.c hello.iwc-lhello.c hello.i实验中几十行的源文件经过预处理后增长到近两千行。真正让文件膨胀的不是业务代码而是stdio.h、stdlib.h以及它们递归包含的类型、声明和宏。这也是hello.i最实用的用途当宏展开或条件编译不符合预期时直接查看预处理结果比盯着源文件猜更有效。第二站C 代码如何变成汇编gcc-S-g-O0hello.i-ohello.s编译阶段会完成词法分析、语法分析、语义检查、中间表示生成以及目标代码生成。开启优化后编译器还会对中间表示进行优化。这一阶段输出的hello.s已经是面向目标 CPU 的汇编代码但还不是机器码。外部函数也不会简单地在这个阶段“复制进来”。对于printf、atoi这类普通外部调用编译器主要生成调用指令和符号引用真正的实现由链接阶段处理。想观察优化的影响可以生成两份汇编文件gcc-S-O0hello.c-ohello_O0.s gcc-S-O2hello.c-ohello_O2.sdiff-uhello_O0.s hello_O2.s有些系统上编译器甚至会把简单的printf(h\n)优化成puts(h)。因此符号表里出现puts并不一定意味着源代码直接调用了它。第三站hello.o为什么还不能运行gcc-chello.s-ohello.o汇编器会把汇编助记符编码成 CPU 机器指令同时生成符号表和重定位信息。这时的hello.o已经包含机器码但它属于“可重定位目标文件”还不能直接执行。原因主要有两个printf、atoi等外部符号的最终位置还没有确定文件还没有形成操作系统可直接装载的完整程序映像hello.o也不是一段没有结构的二进制数据而是一个 ELF 文件通常包含ELF 文件头.text代码节.rodata只读数据节.data和.bss数据节符号表重定位节使用-g时生成的调试信息这里需要区分两个概念section通常译为“节”主要服务于编译和链接segment通常译为“段”主要描述程序如何装载到内存目标文件主要关注节可执行文件被内核加载时程序头表中的段更关键。用objdump拆开目标文件先看反汇编objdump-dhello.o同时显示源代码和汇编objdump-Shello.oobjdump -S需要目标文件包含调试信息否则通常只能看到反汇编无法正确对应源代码。继续查看符号表和重定位objdump-thello.o objdump-rhello.o如果想看更完整的 ELF 元数据可以使用readelf-hhello.o readelf-Shello.o readelf-sWhello.o readelf-rWhello.o第四站链接器如何把零散内容拼成程序gcc hello.o-ohello链接阶段主要完成四件事符号解析把未定义符号和目标文件或库中的定义对应起来。合并输入文件中的同类节并确定整体布局。根据最终布局修正代码和数据里的地址引用。生成 ELF 头和程序头表让内核与动态加载器知道如何装载程序。使用gcc链接时输入不只有hello.o和 C 标准库。GCC 还会自动加入启动文件、运行时支持库和默认链接选项。想看它实际调用了哪些工具和文件可以执行gcc-vhello.o-ohello输出里常见的crt1.o、crti.o、crtn.o属于 C 运行时启动文件。它们负责在进入main前后完成必要的初始化和收尾工作。动态链接和静态链接体积差多少普通命令默认通常生成动态链接程序gcc hello.o-ohello ldd helloldd可以看到libc.so.6和动态加载器等依赖。括号中的十六进制数是本次检查时观察到的映射地址启用 ASLR 后可能在不同运行间变化。再生成一个静态链接版本gcc hello.o-static-ohello_staticls-lhhello hello_static ldd hello_static实验中的动态版本只有几 KB静态版本接近 1 MB体积差距非常明显。原因在于动态链接程序主要记录共享库依赖运行时再由加载器映射库静态链接会把需要的库代码复制进可执行文件不过静态链接不等于“复制到任何同架构 Linux 都能运行”。程序仍然受到 CPU 指令集、内核 ABI、系统调用、设备文件和运行配置等条件约束。符号表里那些0到底代表什么objdump-thello.o objdump-thello在hello.o中可以看到两类典型符号printf、exit、atoi等显示为*UND*说明它们是未定义外部符号值通常为 0main已经定义在.text中它的值表示相对于所在节起点的偏移因此不能简单地说“.o里的符号地址全是 0”。更准确的理解是可重定位文件中的已定义符号通常保存节内偏移未定义外部符号等待链接器解析链接完成后已定义符号才会获得最终链接布局中的虚拟地址使用下面的命令可以更清楚地查看符号类型、绑定方式和节索引readelf-sWhello.oobjdump -r没输出就没有重定位了吗objdump-rhello.o objdump-rhellohello.o中能看到针对外部函数和只读数据的重定位条目。链接完成后objdump -r hello可能没有输出这表示普通静态重定位已经被链接器处理不能据此断言可执行文件完全没有重定位。动态链接程序通常仍然包含 GOT、PLT 和共享库相关的动态重定位。应该继续检查readelf-rWhello objdump-Rhello现代 Linux 发行版还可能默认生成 PIE也就是位置无关可执行文件。它在装载时会根据实际基址完成相应的动态重定位filehello readelf-hhello|grepType不同 GCC 和发行版的默认设置可能不同因此实验结果不必和其他机器逐字一致重点是看清 ELF 类型和工具输出。readelf常用命令速查观察目标命令ELF 类型、架构和入口地址readelf -h hello节头表观察链接视图readelf -S hello程序头表观察装载视图readelf -l hello符号表readelf -sW hello重定位表readelf -rW hello动态段和共享库依赖readelf -d hello反汇编代码objdump -d hello.o动态重定位objdump -R hello动态库依赖ldd helloreadelf -h会输出整个 ELF 文件头其中包含入口地址而不是只显示入口地址。这次实验真正看懂了什么走完这套流程后gcc hello.c -o hello就不再是一条黑盒命令了hello.i告诉我们头文件和宏在预处理阶段被展开hello.s展示编译器为目标 CPU 生成的汇编代码hello.o已经包含机器码但仍保留未解析符号和重定位信息链接器负责解析符号、安排地址并生成可装载的 ELF动态链接和静态链接的差别不只是文件大小还涉及部署和运行环境objdump更适合观察指令readelf更适合查看 ELF 元数据这也是学习交叉编译前很值得做的一次实验。把gcc换成 ARM 交叉编译器后四个阶段没有变但生成的机器码、ELF 架构、动态加载器和链接库都会换成目标板对应的版本。以后再遇到undefined reference、Exec format error、动态库找不到或者程序明明存在却无法运行就可以先判断问题发生在编译、链接还是装载阶段而不是只盯着最后一条报错。
RELATED

相关推荐

深度解析Grammarly Premium Cookie自动化采集架构与三级验证机制

深度解析Grammarly Premium Cookie自动化采集架构与三级验证机制

深度解析Grammarly Premium Cookie自动化采集架构与三级验证机制 【免费下载链接】autosearch-grammarly-premium-cookie 免费白嫖使用Grammarly Premium高级版 项目地址: https://gitcode.com/gh_mirrors/au/autosearch-grammarly-premium-cookie Grammarly Premium高级…

📅 2026/11/7 4:17:12
cann/asc-devkit printf调试接口

cann/asc-devkit printf调试接口

printf 【免费下载链接】asc-devkit 本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。 项目地址: https://gitcode.com/can…

📅 2026/9/6 5:03:44
2026西瓜视频图片去水印AI方法,手机电脑工具实操教程

2026西瓜视频图片去水印AI方法,手机电脑工具实操教程

日常浏览西瓜视频时,很多优质的视频封面、画面截图都会自带平台水印,水印遮挡画面细节,影响图片收藏、整理和个人素材备份的观感。2026年市面上的去水印工具种类繁杂,分为链接解析提取无水印原图、AI涂抹修复带水印截图两大核心方…

📅 2026/9/5 21:52:47
MORE NEWS

更多资讯

📰

高压电工证过期了不知道怎么复审?靠高压电工证技巧网上查询全攻略

高压电工证过期了不知道怎么复审?靠高压电工证技巧网上查询全攻略 证书过期了不知道怎么复审延期?你不是一个人!最近我们接到多个高压电工证持证人咨询,说证书快到期了,但完全不知道怎么操作,甚至有人因为没及时复审导致证件失效,影响了工作机会。今天…

📰

陕西电工证考试难不难?学历不高怕报不上名?良心建议来了!

陕西电工证考试难不难?学历不高怕报不上名?良心建议来了! 你是不是也在担心,学历不高、工作经验不够,能不能报陕西电工证?别急,我来给你掏心窝子讲讲, 陕西电工证考试难不难…

📰

电工证四级全称电子证书多久拿证?外省证能不能转过来?

电工证四级全称电子证书多久拿证?外省证能不能转过来? 之前考的证在外省能不能转过来?这是很多从业人员最关心的问题,尤其是在跨省工作或打算换城市发展的朋友。今天咱们就来说说【电工证四级全称】到底是什么,多久能拿证,外省证能不能转,以及你最关心…

📰

驻马店高级电工证怎么转异地?真实经历告诉你怎么搞定

驻马店高级电工证怎么转异地?真实经历告诉你怎么搞定 工地太忙根本没时间复习考试,这几乎是每个在驻马店从事电工工作的人都会遇到的难题。尤其是那些已经持有【驻马店高级电工证】的工人,想换地方干工地,却发现证书不能异地使用,这该怎么办?今天我就用…

📰

汕头特种工驾驶证千万别踩坑:学历不高怕报不上名?真相来了

汕头特种工驾驶证千万别踩坑:学历不高怕报不上名?真相来了 你是不是也这样想,学历不高就考不了特种作业证?别急, 汕头特种工驾驶证 虽然看起来门槛高,但其实只要你愿意花点心思, 学历不高也完全没问题…

📰

睢县 低压电工证实操考试考什么

睢县低压电工证上岗必备,学历不高也能考吗? 你是不是也担心自己学历不够,根本报不上睢县低压电工证?别慌,这证其实和学历关系不大,只要你满足基本条件,照样能考。别再被“文凭门槛”绊住脚步,低压电工证是很多岗位的 上岗必备…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬