开了一个linkers的新坑
早上逛 reddit rust 时偶然看到了 Ian Lance Taylor 介绍 linkers 的系列文章,觉得很有意思,决定开一个新坑来看看能不能自己实现一个简单的 linkers,目前找了一些资料,看起来工作量并不小。这里先做个简单的记录,参考的文章和书籍:
可能会涉及到的基础知识包括:
第一印象
一个最简单的链接过程
--- title: 一个简单的链接过程 --- flowchart LR source1("source1"):::purple of1("object_file1.o"):::purple source2("source2"):::purple of2("object_file2.o"):::purple linkers("linkers"):::pink executable("executable"):::green source1 -->|gcc -o| of1 source2 -->|gcc -o| of2 of1 --> linkers of2 --> linkers linkers --> executable classDef pink 1,fill:#FFCCCC,stroke:#333; classDef green fill: #696,color: #fff,font-weight: bold; classDef purple fill:#969,stroke:#333; classDef error fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
链接过程可能涉及到的产物
--- title: 一个简单的链接过程 --- flowchart TB source_code("source_code") object_file("object_file.o") executable("executable") shared_lib("shared libraries") dynamic_linker("dynamic linker") program_linker("program linker") ELF("ELF(on SVR4/GNU/Linux)") DLLs("DLLs(on windows)") GOT("GOT:Global Offset Table") PLT("PLT:Procedure Linkage Table") shared_lib --> ELF:::purple shared_lib --> DLLs:::purple shared_lib --> GOT:::pink shared_lib --> PLT:::pink classDef pink 1,fill:#FFCCCC,stroke:#333; classDef green fill: #696,color: #fff,font-weight: bold; classDef purple fill:#969,stroke:#333; classDef error fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
ELF
section
表示的二进制文件中的代码段;weak
类型的绑定可以允许被覆盖,可以理解为给了某个symbol一个默认值 -- 在没有找到其他的同名symbol的情况下,使用weak绑定的symbol;visibility
提供了对 symbol 在 shared library 外可访问性的控制 -- 例如,我们可能希望某个 symbol 在 shared library 内是 global 的,但是在外部是 local 的。
--- title: go over ELF symbols in more details --- flowchart LR entry("entry in an ELF symbole"):::green name("a name"):::pink value("a value"):::pink size("a size"):::pink section("a section"):::pink binding("a binding"):::pink type("a type"):::pink visibility("a visibility"):::pink undefined("undefined additional information"):::pink text(".text") data(".data") rodata(".rodata") symtab(".symtab") global("global") local("local") weak("weak") entry --> name entry --> value entry --> size entry --> section entry --> binding entry --> type entry --> visibility entry --> undefined section --> text section --> data section --> rodata section --> symtab binding --> global binding --> local binding --> weak classDef pink 1,fill:#FFCCCC,stroke:#333; classDef green fill: #696,color: #fff,font-weight: bold; classDef purple fill:#969,stroke:#333; classDef error fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
这里需要注意一下,C 可以支持通过如下的方式来提示编译器生成指定的代码。
1
2
3
4
5
6
7
8
9
10
void __attribute__((weak)) foo() {
printf("Default foo\n");
}
int main() {
foo();
return 0;
}