linux c gcc编译报错 can not be used when making a shared object; recompile with -fPIC

目录

错误现象

错误原因

解决方法

PIC 简介


错误现象

使用 google protobuf 时,出现错误

/usr/bin/ld: /usr/local/lib/libprotobuf.a(message_lite.o): relocation R_X86_64_32S against `_ZTVN6google8protobuf11MessageLiteE' can not be used when making a shared object; recompile with -fPIC
/usr/local/lib/libprotobuf.a: error adding symbols: Bad value
collect2: error: ld returned 1 exit status

错误原因

so动态库编译加上了-fPIC选项 但在链接 libprotobuf.a时, libprotobuf.a的编译未加入-fPIC选项,所以需要 重新编译libprotobuf 并加入 -fPIC选项

解决方法

重新编译libprotobuf 并加入 -fPIC选项

看protobuffer的README和INSTALL文档,看到需要添加特殊编译选项,需要在执行configure的时候引入 重新编译

make clean; make uninstall
./configure CXXFLAGS=-fPIC

PIC 简介

PIC是Position-Independent-Code的缩写。

在计算机系统中,PIC和PIE(Position-IndependentExecutable)是可以在主存中不同位置执行的目标代码。

PIC经常被用在共享库中,这样就能将相同的库代码为每个程序映射到一个位置,不用担心覆盖掉其他程序或共享库。

non-PIC 与 PIC 代码的区别主要在于 access global data, jump label 的不同。

比如一条 access global data 的指令,

non-PIC 的形势是:ld r3, var1

PIC 的形式则是:ld r3, var1-offset@GOT,意思是从 GOT 表的 index 为 var1-offset 的地方处

指示的地址处装载一个值,即 var1-offset@GOT 处的4个 byte 其实就是 var1 的地址。这个地址只有在运行的时候才知道,

是由 dynamic-loader(ld-linux.so) 填进去的。

再比如 jump label 指令

non-PIC 的形势是:jump printf ,意思是调用 printf。

PIC 的形式则是:jump printf-offset@GOT,意思是跳到 GOT 表的 index 为 printf-offset 的地方处

指示的地址去执行,这个地址处的代码摆放在 .plt section,每个外部函数对应一段这样的代码,其功能是呼叫

dynamic-loader(ld-linux.so) 来查找函数的地址(本例中是 printf),然后将其地址写到 GOT 表的 index 为 printf-offset 的地方,

同时执行这个函数。这样,第2次呼叫 printf 的时候,就会直接跳到 printf 的地址,而不必再查找了。

GOT 是 data section, 是一个 table, 除专用的几个 entry,每个 entry 的内容可以再执行的时候修改;

PLT 是 text section, 是一段一段的 code,执行中不需要修改。

每个 target 实现 PIC 的机制不同,但大同小异。比如 MIPS 没有 .plt, 而是叫 .stub,功能和 .plt 一样。

可见,动态链接执行很复杂,比静态链接执行时间长;但是,极大的节省了 size,PIC 和动态链接技术是计算机发展史上非常重要的一个里程碑。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值