position-independent code (PIC) 编译动态库 .so
position-independent code (PIC),用于生成位置无关代码。位置无关代码,可以理解为代码无绝对跳转,跳转都为相对跳转。生成动态库时,需要加上
-fPIC
选项。
1. 无 -fPIC
选项
不添加
-fPIC
也可以生成
.so
文件,但是对于源文件有要求。因为不加
-fPIC
编译的
.so
必须要在加载到用户程序的地址空间时重定向所有表目,所以在它里面不能引用其它地方的代码。
1.1 编译错误
/*
============================================================================
Name : function_validation.c
Author : Foreverstrong Cheng
Version :
Copyright : Copyright 2019 ForeverStrong License
Description : function_validation in C, Ansi-style
============================================================================
*/
#include
int function_validation(int num)
{
puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
num += 1;
return num;
}
1.2 编译通过
/*
============================================================================
Name : function_validation.c
Author : Foreverstrong Cheng
Version :
Copyright : Copyright 2019 ForeverStrong License
Description : function_validation in C, Ansi-style
============================================================================
*/
#include
int function_validation(int num)
{
// puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
num += 1;
return num;
}
strong@foreverstrong:~/dbscan_work/fPIC_validation$ pwd
/home/strong/dbscan_work/fPIC_validation
strong@foreverstrong:~/dbscan_work/fPIC_validation$
strong@foreverstrong:~/dbscan_work/fPIC_validation$ ll
total 12
drwxrwxr-x 2 strong strong 4096 Feb 27 09:30 ./
drwxrwxr-x 14 strong strong 4096 Feb 27 09:18 ../
-rw-rw-r-- 1 strong strong 492 Feb 27 09:30 function_validation.c
strong@foreverstrong:~/dbscan_work/fPIC_validation$
strong@foreverstrong:~/dbscan_work/fPIC_validation$ gcc -shared function_validation.c -o validation.so
/usr/bin/ld: /tmp/ccL12xkz.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/tmp/ccL12xkz.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
strong@foreverstrong:~/dbscan_work/fPIC_validation$
strong@foreverstrong:~/dbscan_work/fPIC_validation$ gcc -shared function_validation.c -o validation.so
strong@foreverstrong:~/dbscan_work/fPIC_validation$ ll
total 20
drwxrwxr-x 2 strong strong 4096 Feb 27 09:34 ./
drwxrwxr-x 14 strong strong 4096 Feb 27 09:18 ../
-rw-rw-r-- 1 strong strong 495 Feb 27 09:34 function_validation.c
-rwxrwxr-x 1 strong strong 7904 Feb 27 09:34 validation.so*
strong@foreverstrong:~/dbscan_work/fPIC_validation$
不添加
-fPIC
生成的动态库,生成时假定它被加载在地址 0 处。加载时它会被加载到一个地址 (base),需要进行一次重定位 (relocation),代码、数据段中所有的地址加上这个 base 的值。这时代码运行时就能使用正确的地址了。
2. 有 -fPIC
选项
添加
-fPIC
选项生成的动态库,是位置无关。这样的代码本身就能被放到线性地址空间的任意位置,无需修改就能正确执行。通常的方法是获取指令指针的值,加上一个偏移得到全局变量/函数的地址。添加
-fPIC
选项的源文件对于它引用的函数头文件编写有较宽松的尺度。比如只需要包含声明的函数的头文件,即使没有相应的 C 文件来实现,编译成
.so
库照样可以通过。
添加
-fPIC
选项实现真正意义上的多个进程共享
.so
库。多个进程引用同一个
-fPIC
动态库时,可以共用内存。这一个库在不同进程中的虚拟地址不同,操作系统会把它们映射到同一块物理内存上。
不添加
-fPIC
选项,加载
.so
库时,需要对代码段引用的数据对象重定位,重定位会修改代码段的内容,造成每个使用这个
.so
文件代码段的进程在内核里都会生成这个
.so
文件代码段的 copy,每个 copy 都不一样,取决于这个
.so
文件代码段和数据段内存映射的位置。不添加
-fPIC
选项,消耗内存,编译的
.so
文件的优点是加载速度快。
不能使用
.so
库来静态编译 (-static) 一个可执行程序,会出现错误提示:
attempted static link of dynamic object
/*
============================================================================
Name : function_validation.c
Author : Foreverstrong Cheng
Version :
Copyright : Copyright 2019 ForeverStrong License
Description : function_validation in C, Ansi-style
============================================================================
*/
#include
int function_validation(int num)
{
puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
num += 1;
return num;
}
strong@foreverstrong:~/dbscan_work/fPIC_validation$ pwd
/home/strong/dbscan_work/fPIC_validation
strong@foreverstrong:~/dbscan_work/fPIC_validation$
strong@foreverstrong:~/dbscan_work/fPIC_validation$ ll
total 12
drwxrwxr-x 2 strong strong 4096 Feb 27 10:11 ./
drwxrwxr-x 14 strong strong 4096 Feb 27 09:18 ../
-rw-rw-r-- 1 strong strong 492 Feb 27 10:11 function_validation.c
strong@foreverstrong:~/dbscan_work/fPIC_validation$
strong@foreverstrong:~/dbscan_work/fPIC_validation$ gcc -fPIC -shared function_validation.c -o validation.so
strong@foreverstrong:~/dbscan_work/fPIC_validation$
strong@foreverstrong:~/dbscan_work/fPIC_validation$ ls -l
total 12
-rw-rw-r-- 1 strong strong 492 Feb 27 10:11 function_validation.c
-rwxrwxr-x 1 strong strong 8144 Feb 27 10:12 validation.so
strong@foreverstrong:~/dbscan_work/fPIC_validation$