首页/新闻资讯/正文详情

从 `hello.c` 到 ELF:亲手走一遍 GCC 编译、汇编与链接全过程

发布时间:2026/11/14 13:24:42 来源:云帆数科 栏目:资讯中心
从 `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、动态库找不到或者程序明明存在却无法运行就可以先判断问题发生在编译、链接还是装载阶段而不是只盯着最后一条报错。

相关推荐

深度解析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/14 12:17:42

Timeline Scan:精准标注照片日期,让家庭照片有序整理不再难!
Timeline Scan:精准标注照片日期,让家庭照片有序整理不再难!

Timeline Scan:家庭照片整理神器各位,如果你已经是 Timeline Scan 的用户,可直接登录仪表盘。Timeline Scan 能实现家庭照片的数字化、标注日期和有序整理。其官网有主页、定价、常见问题解答、关于我们、联系我们、照片扫描等板块。为家庭照… · 2026/11/6 12:37:07

企业知识管理困境破解:金曲AI知识库落地实践分享
企业知识管理困境破解:金曲AI知识库落地实践分享

很多企业在数字化转型过程中,普遍面临知识管理难题:技术文档、行业规范、项目资料分散存放,资料查找低效、知识复用率低。同时,内部知识沉淀混乱、权限管控薄弱,跨部门共享困难,公有云AI工具还存在数据外泄… · 2026/9/19 17:31:55

电工证在网上能考试吗?千万别踩坑,实操考试不能少
电工证在网上能考试吗?千万别踩坑,实操考试不能少

电工证在网上能考试吗?千万别踩坑,实操考试不能少 怕考不过白交培训费?现在网上一堆“包过”“代考”“远程考试”信息,把人绕得晕头转向。很多人以为电工证能在网上考试,省事又省力,结果要么被坑钱,要么拿到假证,一不小心就耽误了工作和前途。今天我… · 2026/11/14 13:24:08

工地太忙根本没时间复习考试?江西吉安办电工证在哪考全攻略
工地太忙根本没时间复习考试?江西吉安办电工证在哪考全攻略

工地太忙根本没时间复习考试?江西吉安办电工证在哪考全攻略 你是不是也经常在工地忙得连饭都顾不上吃,更别说抽空复习电工证考试了?别急,今天就来聊聊【江西吉安办电工证】这事,告诉你在哪考、怎么考、怎么拿证,还能提升收入,关键还… · 2026/11/14 13:24:08

遵义市电工证查询内部消息:电工证没过期也能上岗?别被坑了!
遵义市电工证查询内部消息:电工证没过期也能上岗?别被坑了!

遵义市电工证查询内部消息:电工证没过期也能上岗?别被坑了! 你还在为找不到电工证而发愁?最近很多郑州房建工程的朋友在私信我,说 急需特种作业证才能上岗找工作 ,但不知道怎么查自己有没有电工证,或者怎么补办、复审。其实, 遵义市电工证查询… · 2026/11/14 13:24:08

龙江电工证学校报名全攻略:学历不高也能考电工证,全国通用
龙江电工证学校报名全攻略:学历不高也能考电工证,全国通用

龙江电工证学校报名全攻略:学历不高也能考电工证,全国通用 你是不是也担心学历不高报不了名?别急,龙江电工证学校专门为像你这样想进入电工行业的朋友们提供专业培训,全国通用的电工证,让你轻松拿到手,不再被学历限制。下面我来给你详细说说报名、考试… · 2026/11/14 13:24:08

增城哪里考电工证最新政策解读:南阳卧龙区电工证报考避坑指南
增城哪里考电工证最新政策解读:南阳卧龙区电工证报考避坑指南

增城哪里考电工证最新政策解读:南阳卧龙区电工证报考避坑指南 你是不是正愁找不到电工证报考点?别急,增城哪里考电工证,南阳卧龙区的朋友也一样着急。电工证不是你想考就能考的,尤其是现在 急需特种作业证才能上岗找工作… · 2026/11/14 13:24:08

低压电工证广州考试费用及电子证书怎么拿?转省证也能用
低压电工证广州考试费用及电子证书怎么拿?转省证也能用

低压电工证广州考试费用及电子证书怎么拿?转省证也能用 之前考的证在外省能不能转过来?这个问题几乎是每个打算考低压电工证的人最关心的。特别是在广州这样的大城市,很多持证人是从外地过来工作的, 电子证书… · 2026/11/14 13:23:08

电工证丢失还能补吗?千万别踩坑,丢了证等于失业
电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/13 22:30:50

电力电缆作业证直播报名入口与办理流程良心建议
电力电缆作业证直播报名入口与办理流程良心建议

电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/14 13:23:47

英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑

英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/14 13:20:59

有初级电工证怎么工作 2026河南最新政策怎么应对
有初级电工证怎么工作 2026河南最新政策怎么应对

有初级电工证怎么工作 2026河南最新政策怎么应对 之前考的证在外省能不能转过来?这个问题我每天被问上百次。2026年河南最新政策对证书跨省转移有了明确说明,特别是南阳市的从业者,需要特别关注。… · 2026/11/14 0:00:31

电工证过期了不知道怎么复审?考电工证自学书+官方报名入口全攻略
电工证过期了不知道怎么复审?考电工证自学书+官方报名入口全攻略

电工证过期了不知道怎么复审?考电工证自学书+官方报名入口全攻略 证书过期了不知道怎么复审延期?很多人遇到这种情况,要么是工作太忙没时间处理,要么是不知道具体流程,导致证书失效,影响工作和项目进展。其实复审并不难,关键是要找准官方报名入口,掌… · 2026/11/14 0:00:31

为什么要低压电工证实操考试考什么
为什么要低压电工证实操考试考什么

为什么低压电工证值不值得考?别再被中介骗了 你是不是也经常看到网上有人在问“低压电工证到底值不值得考”?或者在找报名点时,担心被中间人骗钱?这些问题,我懂,我也经历过。作为一名在应急管理行业摸爬滚打多年的从业者,我深知低压电工证不仅是一个从… · 2026/11/14 0:00:31

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/13 6:12:21

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/13 6:11:51

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/13 22:31:30

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码