动态库问题

2020-04-13

问题现象

源码一样,使用diab工具链编译生成的dl库,可以加载动态库。但是使用gnu工具链编译生成的dl库,可以加载动态库。

问题修改

修改dl库里的load.c中的_rtld_load_got_pointer接口和_rtld_load_object接口。

rtld_load_got_pointer

修改如下:

4

改为:

2

rtld_load_object

修改如下:

5

改为:

1

问题分析

写了一个最简单的c文件:

6

分别使用vx工具链下的gnu和diab,以及linaro下的gnu工具链,以及裝发下自己编译生成的工具链编译生成.o过程文件,并使用objdump反汇编查看。只有vx工具链下的gnu会生成memset接口,如下:

3

而memcpy接口存在于c库,而没有存在于dl中。因此在生成rtp.vxe的时候,会因为找不到该接口,而认为该类似接口存在于动态库中,因为会跳转到PLT表查找该接口执行。而dl库此时还处于加载动态库到内存,并生成_GLOBAL_OFFSET_TABLE_,_PROCEDURE_LINKAGE_TABLE_的过程中,因此会报错。

7

解决方法

方法1

把需要gnu自动生成类似memcpy这种赋初值的地方,先不赋初值,而是在之后使用strcpy赋初值,因为,该接口在dl库中会在预处理时被替换为_rtld_strcpy,而gnu自动生成类似memcpy这种赋初值的地方,却不会被替换。

rtldenv

而这些接口在dl库中是有实现的。

目前可以确认使用vx的GCC工具链对函数的局部变量(字符串,结构体)赋初值时,会使用memset来处理,而使用其它GNU工具链则是使用普通汇编指令完成变量在栈空间的初始化,不会出现调用C库接口的情况。

方法2

在生成dl库以后,使用objcopy对生成的dl进行替换memset为_rtld_memset.

这种方法更好,命名如下:

dcore-objcopy-arm --redefine-sym memcpy=_rtld_memcpy --redefine-sym memset=_rtld_memset libdl.a