和AI对话的日常--(link.exe)链接过程中符号的查找规则和处理方法
下面梳理一下 lld-link 执行链接时的符号查找与处理流程,特别是符号在 obj 和 lib(静态库/导入库)中的情况:
1. 加载输入文件
- 命令行输入的每个文件(obj、lib、import lib等)都被解析为
InputFile的子类(如ObjFile、ArchiveFile、ImportFile)。 - obj 文件会立即解析所有符号,lib 文件则注册为“懒加载”。
2. 符号表构建
a. obj 文件中的符号
- 解析 obj 时,所有符号(定义和未定义)都被加入符号表(
SymbolTable)。 - 已定义的符号(如函数、全局变量)会直接插入符号表,类型如
DefinedRegular。 - 未定义的符号(引用的外部符号)会插入为
Undefined。
b. lib(静态库)中的符号
- 解析 lib 时,不会立即解包所有成员(obj),而是为每个符号注册一个
LazyArchive。 - 只有当链接器遇到未定义符号且该符号在 lib 中有定义时,才会解包对应成员(obj),并将其符号插入符号表。
c. import lib(导入库)中的符号
- 解析 import lib 时,每个成员(通常一个 API)会被解包为
ImportFile,并立即注册导入符号(如MessageBoxA、__imp_MessageBoxA)到符号表。 - 这些符号类型为
DefinedImportThunk、DefinedImportData。
3. 符号查找与决策
a. 符号只在 obj 中
- 直接用 obj 中的定义。
- 如果有未定义符号,继续查找其它 obj、lib、import lib。
b. 符号只在 lib 中
- 如果 obj/其它输入文件引用了该符号,链接器会解包 lib 中对应成员(obj),并将其符号插入符号表。
- 只解包被引用的成员,未被引用的不处理。
c. 符号只在 import lib 中
- 如果 obj/其它输入文件引用了该符号,直接用 import lib 注册的导入符号(thunk/IAT)。
- 这些符号会生成导入表项,最终链接到 DLL。
d. 符号在 obj 和 lib 中都存在
- obj 优先:如果 obj 已经定义了符号,lib 中的同名符号不会被解包。
- 如果两个都是强符号,且都被解包,会报 duplicate symbol 错误。
e. 符号在 obj 和 import lib 中都存在
- obj 优先:如果 obj 已经定义了符号,import lib 的同名符号不会覆盖 obj 的定义。
- 如果两个都是强符号,会报 duplicate symbol 错误(见
reportDuplicate)。
4. 相关代码路径
SymbolTable::insert:所有符号插入符号表的入口。SymbolTable::addRegular:obj 文件定义符号。SymbolTable::addLazyArchive:lib 注册懒加载符号。SymbolTable::addImportData/addImportThunk:import lib 注册导入符号。forceLazy:遇到 undefined 符号时,触发 lib 解包成员。reportDuplicate:遇到重复定义时报错。
5. 总结
- obj 优先于 lib 和 import lib。
- lib 只解包被引用的成员。
- import lib 的所有符号都注册,但只有被引用的才会被链接进最终输出。
- 重复定义会报错,除非是弱符号或用
/FORCE:MULTIPLE。
如需具体代码行或更细致的流程,可进一步追踪 SymbolTable.cpp 中的相关函数实现。

浙公网安备 33010602011771号