标签 · 编译工具链

9 篇文章,记录每一次探索。

[链接器的世界-原理篇16] 链接器工程:从能链接,到值得信赖
当输入增长到数万个目标文件,链接器既要提高速度,又要保持结果确定、错误可诊断。从并行阶段的依赖关系出发,讨论结构不变式、运行测试、差分测试、变异测试与模糊测试,分析增量链接和工具链集成怎样改变工程取舍。
阅读全文
[链接器的世界-原理篇15] 走出 ELF:Mach-O 与 PE/COFF 的另一套规则
从文件头、目录记录与内容的关系出发,对照 Mach-O 与 PE/COFF 的符号、重定位和加载机制;通过字节布局与地址换算解释导入、指针链、展开记录、去重及 TLS,并区分文件结构、链接接口与运行时契约。
阅读全文
[链接器的世界-原理篇12] 链接期优化:看见更多代码之后
分开编译形成了优化的信息边界,LTO 通过保留 IR 并协调符号决议跨越这条边界。本文解释定义选择、内部化与代码生成的分工,分析 ThinLTO 的并行与缓存机制,再讨论 ICF 的等价判定、地址身份,以及函数布局如何影响代码局部性。
阅读全文
[链接器的世界-原理篇06] 从入口到 main:程序启动之前发生了什么
链接器写完程序头表就退场了,剩下的事归加载器。本文先读 xv6 的 kexec,看一个最小的加载器只用哪几个字段、做哪三道检查;再读 Linux 的 load_elf_binary,看 PT_INTERP、PT_GNU_STACK、基址选择、.bss 的页尾清零与匿名页、按需调页和 brk;然后打印初始进程栈和辅助向量,跟着 musl 的源码从 _start 走到 main,手工复现驱动程序加的五个启动文件,构建一个 static-pie 看 rcrt1.o 怎样自己处理 R_X86_64_RELATIVE;最后在真实内核上改坏 ELF,看加载器怎样守住安全边界。
阅读全文
[链接器的世界-原理篇05] 布局与 GC:给每个节找位置,让无用代码退场
同一个目标文件,用不同的链接器、不同的选项链接,填进机器码的数字都不一样。这些数字取决于布局:输入节怎么并成输出节、输出节怎么分进段、段放在哪个地址、哪些节被垃圾回收删掉。本文用 GNU ld 和 lld 的真实输出,讲清楚程序头的每个字段、文件偏移与虚拟地址为什么要同余、-z separate-code、PIE 与基址、--gc-sections 的标记过程、__start_/__stop_ 符号,以及链接器脚本和映射文件。
阅读全文
[链接器的世界-原理篇04] 重定位:一次调用,四个字节的距离
从一个真正能运行的 Linux 程序出发,追踪 call 指令里的四个字节:输入节偏移如何变成 P,CPU 为什么从下一条指令算起,S+A-P 又如何落成机器码。再逐步进入负位移、绝对指针、不同加数、溢出和链接期指令改写。
阅读全文
[链接器的世界-原理篇03] 符号解析:同一个名字,究竟指向谁
从一个能独立运行的加法程序开始,亲手制造缺失定义、重复定义和库顺序错误。沿着“谁需要、谁提供、提供者是否进入链接”理解符号解析,再讨论弱定义、common、类型检查与 C++ 的边界。
阅读全文
[链接器的世界-原理篇01] 地址不能总靠手填:链接器的演化之路
从 1949 年 EDSAC 的子程序库讲起,沿着"一个问题催生一个发明"的线索,看重定位、汇编器、目标文件、ELF、共享库、DWARF、.eh_frame、COMDAT、可执行栈标记和四代链接器是怎么一个接一个出现的,以及它们怎样把链接器推到今天的位置。
阅读全文
[链接器的世界-原理篇00] 从一条编译命令出发:程序如何连成整体
从一个正常的跨文件函数调用出发,拆开编译器驱动的预处理、编译、汇编与链接过程,再借类型不一致的程序辨认链接器的信息边界。沿着目标文件、可执行文件与内存映射,建立符号解析、布局、重定位以及编译、链接、加载、运行四个时期的联系,并提供统一的 Linux 本机实验环境。
阅读全文