linux c++ 编程之链接与装载 -基础篇--v0.3--20120509
DESCRIPTION
主要介绍编译,链接与装载的基本概念与原理静态链接常见错误分析,静态链接常用链接选项使用讲解dlopen/dlsym?常用链接选项讲解TRANSCRIPT
![Page 1: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/1.jpg)
五竹
一淘搜索与算法
Linux C++ 编程之链接与装载
—基础篇
![Page 2: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/2.jpg)
课程大纲页
• 编译与链接的基本概念
• 常见链接错误分析
• 静态链接
• 动态库 与 动态链接基础
• 常用链接选项
• 工具介绍
![Page 3: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/3.jpg)
编译与链接的基本概念
![Page 4: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/4.jpg)
编译与链接的基本概念
//hello.c
#include <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}
编译:
gcc hello.c
![Page 5: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/5.jpg)
编译与链接的基本概念
![Page 6: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/6.jpg)
编译与链接的基本概念—预处理
• 预处理(Prepressing) : -E 表示只进行预处理, 即 : gcc –E hello.c –o
hello.i
展开所有 #define 定义的宏
处理所有条件预编译指令,如 #if, #ifdef
递归的将 #include 的文件插入到该预编译文件中
删除各类注释
添加行和文件标识,如 #2 "hello.c" 2 ,用于调试或编译出错报警
保留所有的 #pragma 编译指令,编译器要使用
• 对于C++ 来说,预处理后的文件扩展名是 .ii
![Page 7: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/7.jpg)
编译与链接的基本概念—编译
• 编译(Compilation): gcc –S hello.i –o hello.s
编译过程就是把预处理完的文件进行一系列词法分析,
语法分析,语义分析及优化后生成相应的汇编代码文件.
• 现在的gcc 把预处理和编译两个步骤合成一个步骤,C语言
使用一个叫做 cc1 的程序来完成,C++则是 cc1plus ,位于
/usr/libexec/gcc/x86_64-redhat-linux/4.1.2/
• gcc 实际上是这些后台程序的包装,它会根据参数要求去调
用 cc1(cclplus), 汇编器 as 和链接器 ld
![Page 8: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/8.jpg)
编译与链接的基本概念—汇编
• 汇编(Assembly) :
gcc –C hello.s –o hello.o
或 as hello.s -o hello.o
• 汇编器是将编译语言转换成机器可以执行的指令.
![Page 9: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/9.jpg)
编译与链接的基本概念—链接
• 链接(Linking):解决一个程序被分割成多个模块后,
模块间最后如何组合成一个单一程序的问题.
• 链接的主要任务是把各个模块之间相互引用的部
分处理好,使各个模块之间能正确的衔接.
![Page 10: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/10.jpg)
常见链接错误分析 calu.c
#include <math.h> #include <stdio.h> int main (void) {
double x = sqrt (2.0); printf ("The square root of 2.0 is %f\n", x); return 0;
} gcc -Wall calu.c -o calc -fno-builtin
/tmp/ccKPlcED.o: In function `main':calu.c:(.text+0x1c): undefined reference to `sqrt'collect2: ld 返回 1
![Page 11: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/11.jpg)
常见链接错误分析
导致符号未定义的原因:
1. 链接时缺少某个库, 目标文件的路径不正确, 符号
的声明与定义不一样,父类声明的虚函数,父或子类
都没有实现等.
2. C与C++的库之间兼容问题
3. 链接时库的顺序问题
![Page 12: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/12.jpg)
常见链接错误分析—C与C++之间兼容问题
--符号修饰与函数签名// plusplus_example.hint func(int);float func(float);class C {
int func(int);class C2 {
int func(int);};
};namespace N {
int func(int);class C {
int func(int);};
}
// cplusplus_example.cpp
#include "example.h"int func(int){};float func(float){};int C::func(int){};int C::C2::func(int){};namespace N {
int func(int){};int C::func(int){};
}
![Page 13: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/13.jpg)
函数签名 修饰后名称(符号名)
int func(int) _Z4funcifloat func(float) _Z4funcfint C::func(int) _ZN1C4funcEiint C::C2::func(int) _ZN1C2C24funcEiint N::func(int) _ZN1N4funcEiint N::C::func(int) _ZN1N1C4funcEi
GCC的基本C++名称修饰方法:1. 所有的符号都以"_Z"开头,
2. 对于嵌套的名字(在名称空间或在类里面的),后面紧
跟"N",3. 然后是各个名称空间和类的名字,每个名字前是名字字
符串长度,再以"E"结尾。
4. 函数来说,它的参数列表紧跟在"E"后面
常见链接错误分析—C与C++之间兼容问题
--符号修饰与函数签名
![Page 14: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/14.jpg)
常见链接错误分析—C与C++之间兼容问题
--符号修饰与函数签名
#ifdef __cplusplusextern "C" {#endif
void * memset(void *, int ,size_t);
#ifdef __cplusplus}#endif
extern "C" 关键字
条件宏 __cplusplus
![Page 15: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/15.jpg)
链接时库的顺序问题--libtimeutil
![Page 16: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/16.jpg)
链接时库的顺序问题--libtimeutil
![Page 17: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/17.jpg)
链接时库的顺序问题--libdso
![Page 18: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/18.jpg)
库的顺序问题—示例A(1)• case02:
• case03:
• Case04:
• Case05:
![Page 19: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/19.jpg)
库的顺序问题—示例A(2)
• case02:
• case03:
• case04:
• case05:
![Page 20: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/20.jpg)
库的顺序问题—示例B(1)
• Case06:
![Page 21: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/21.jpg)
库的顺序问题—示例B(2)
• Case07:
• Case08:
• Case09:
![Page 22: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/22.jpg)
库的顺序问题—示例B(3)• Case06:
• Case08:
• Case09:
• Case07:
![Page 23: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/23.jpg)
库的顺序问题—示例C(1)
• libdso:
![Page 24: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/24.jpg)
库的顺序问题—示例C(2)• Case10:
• Case14:
• Case11:
![Page 25: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/25.jpg)
库的顺序问题—示例C(3)
• Case16:
• Case17:
• Case15:
![Page 26: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/26.jpg)
库的顺序问题—示例C(4)• Case10:
• Case14:
• Case11:
![Page 27: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/27.jpg)
库的顺序问题—示例C(5)• Case15:
• Case17:
• Case16:
![Page 28: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/28.jpg)
库的顺序问题—示例D(1)• libaba:
![Page 29: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/29.jpg)
库的顺序问题—示例D(2)• Makefile
![Page 30: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/30.jpg)
库的顺序问题—示例D(3)• aba_main.cpp:
• Case20:
• Case21:
• Case22:
![Page 31: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/31.jpg)
库的顺序问题—示例D(4)• Case20:
• Case22:
• Case21:
![Page 32: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/32.jpg)
库的顺序问题—总结
• 在链接静态库时, 如果目标文件(.o) 与静态库之间存在依赖关系,
则有依赖关系的目标文件(.o)与静态库存在链接顺序问题。
• 在链接静态库时, 如果动态库 与静态库之间存在依赖关系,则有
依赖关系的动态库与静态库存在链接顺序问题。
• 在链接静态库时,如果多个静态库之间存在依赖关系,则有依
赖关系的静态库之间存在链接顺序问题。
• 静态库之间存在循环依赖的时候经常需要根据依赖关系,将静态
库列出多次.
• 遵守从左到右排序对象文件的惯例.
![Page 33: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/33.jpg)
静态链接
静态链接过程
符号解析
重定位过程
![Page 34: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/34.jpg)
静态链接—输入文件类型
• 重定位目标文件
• 归档库
• 共享库
![Page 35: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/35.jpg)
静态链接--处理过程
• 链接的主要内容是把各个模块之间相互引用的部
分处理好,使各个模块之间能正确的衔接.
• 两步链接(Two-passing Linking)
地址与空间分配(Address and Storage Allocation)
符号解析(Symbol Resolution)和重定位(Relocation)
• 全局符号表:链接器会保存一个全局符号表,在任
何输入文件中被引用或者定义的符号都会有一个
表项
![Page 36: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/36.jpg)
静态链接--地址与空间分配
![Page 37: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/37.jpg)
静态链接—符号分类与符号解析
• 符号分类
• 符号解析(symbol resolution)概念
![Page 38: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/38.jpg)
库的顺序问题—示例D
• Case22:
• Case24:
![Page 39: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/39.jpg)
静态链接—符号处理示例—case22
![Page 40: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/40.jpg)
静态链接—符号处理示例—case24
![Page 41: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/41.jpg)
静态链接时重定位
• 重定位概念
• 重定位表
• 符号解析与重定位的关系
![Page 42: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/42.jpg)
Elf64_Rela// Relocation table entry with addend (in section of type SHT_RELA).
typedef struct
{
Elf64_Addr r_offset; /* Address of need relocation*/
Elf64_Xword r_info; /* Relocation type and symbol index */
Elf64_Sxword r_addend; /* Addend */
} Elf64_Rela;
#define ELF64_R_SYM(i) ((i) >> 32) // 符号表中的下标
#define ELF64_R_TYPE(i) ((i) & 0xffffffff) // 重定位入口的类型
#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32)
+ (type))
![Page 43: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/43.jpg)
重定位类型表
名字 值 计算
R_X86_64_32 1 S+A
R_X86_64_PC32 2 S+A-P
R_X86_64_GOT32 3 G + A
R_X86_64_PLT32 4 L + A - P
R_X86_64_COPY 5 none
R_X86_64_GLOB_DAT 6 S
R_X86_64_JUMP_SLOT 7 S
R_X86_64_RELATIVE 8 B + A
R_X86_64_GOTPCREL 9 S + A - GOT
![Page 44: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/44.jpg)
静态链接时重定位示例
![Page 45: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/45.jpg)
静态链接时重定位示例
![Page 46: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/46.jpg)
动态库 与 动态链接基础
如何创建动态库
为什么要动态链接
动态链接的主要技术点
显式运行时加载(dlopen/dlsym/dlclose)
动态库连接与动态加载选项说明
![Page 47: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/47.jpg)
如何创建动态库
![Page 48: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/48.jpg)
为什么要动态链接
• 内存与磁盘空间
• 程序开发与发布
• 程序的可扩展性与兼容性
![Page 49: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/49.jpg)
动态链接
• 基本思想:把程序按
照模块分拆成各个
相对独立部分,在程
序运行时才将它们
链接在一起形成一
个单独的可执行文
件.
![Page 50: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/50.jpg)
动态链接的实现
• 方便程序开发,部属:
方法:程序的各模块独立,
装载时才链接(符号查找,
重定位).
• 节约内存:
方法: 地址无关代码(PIC)
技术实现:全局偏移量表
(GOT)
• 性能优化:
方法:延迟绑定(Lazy
Binding)
技术实现:函数链接表
(PLT)
• 程序的可扩展性与兼容性:
方法: 显式运行时加载
![Page 51: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/51.jpg)
动态链接的实现—GOT,PLT
![Page 52: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/52.jpg)
动态链接的实现—GOT,PLT
类型 2:模块内部的数据访问
类型 4:模块外部的数据访问
类型 1:模块内部的函数调用
类型 3:模块外部的函数调用
![Page 53: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/53.jpg)
动态链接的实现—GOT,PLT
![Page 54: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/54.jpg)
常用链接选项(1)
• -Wl:这个选项可以将指定的参数传递给链接器。
• -Bstatic : 将其后的库作为静态库链入.
• -Bdynamic: 将其后的库作为动态库链入.
• 示例: -Wl,-Bstatic -lanet -lalog -Wl,-Bdynamic –ldl
![Page 55: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/55.jpg)
ld 链接选项
• -Xlinker –rpath:
示例: -Xlinker -rpath ../timeutil
• --enable-new-dtags
示例: -Xlinker -rpath ../timeutil -Xlinker --enable-new-
dtags
• -export-dynamic 或 -rdynamic:
• -Bsymbolic:
示例: -Wl, -Bsymbolic
![Page 56: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/56.jpg)
动态链接过程—库的搜索路径
1. DT_RPATH: 在 .dynamic 节的 DT_RPATH的表项指定,
且没有 RUNPATH表项,是由分号分隔开的可以搜索库
的目录列表.
2. 环境变量 LD_LIBRARY_PATH
3. RUNPATH : 如果在 .dynamic 节有项,则DT_RPATH 项
失效.
4. 库缓冲文件/etc/ld.so.cache
5. 缺省目录: /usr/lib; /lib ; /usr/local/lib等
![Page 57: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/57.jpg)
分析工具
![Page 58: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/58.jpg)
binutls工具集
ld - the GNU linker.
as - the GNU assembler.
addr2line - Converts addresses into filenames and line numbers.
ar - A utility for creating, modifying and extracting from archives.
c++filt - Filter to demangle encoded C++ symbols.
gprof - Displays profiling information.
![Page 59: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/59.jpg)
binutls工具集 nm - Lists symbols from object files.
objcopy - Copys and translates object files.
objdump - Displays information from object files.
ranlib - Generates an index to the contents of an archive.
readelf - Displays information from any ELF format object file.
size - Lists the section sizes of an object or archive file.
strings - Lists printable strings from files.
strip - Discards symbols.
![Page 60: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/60.jpg)
参考资料
• <程序员的自我修养—链接、装载与库>
• <连接器和加载器>
![Page 61: Linux c++ 编程之链接与装载 -基础篇--v0.3--20120509](https://reader034.vdocuments.site/reader034/viewer/2022050706/559400681a28abac7f8b47ba/html5/thumbnails/61.jpg)
谢 谢 !