问题现象
源码一样,使用diab工具链编译生成的dl库,可以加载动态库。但是使用gnu工具链编译生成的dl库,可以加载动态库。
问题修改
修改dl库里的load.c中的_rtld_load_got_pointer接口和_rtld_load_object接口。
rtld_load_got_pointer
修改如下:
[图片上传失败...(image-b06640-1588307653871)]
改为:
[图片上传失败...(image-8fb25b-1588307653872)]
rtld_load_object
修改如下:
[图片上传失败...(image-79ce12-1588307653872)]
改为:
[图片上传失败...(image-f040bc-1588307653872)]
问题分析
写了一个最简单的c文件:
[图片上传失败...(image-1948fb-1588307653872)]
分别使用vx工具链下的gnu和diab,以及linaro下的gnu工具链,以及裝发下自己编译生成的工具链编译生成.o过程文件,并使用objdump反汇编查看。只有vx工具链下的gnu会生成memset接口,如下:
[图片上传失败...(image-fc5218-1588307653872)]
而memcpy接口存在于c库,而没有存在于dl中。因此在生成rtp.vxe的时候,会因为找不到该接口,而认为该类似接口存在于动态库中,因为会跳转到PLT表查找该接口执行。而dl库此时还处于加载动态库到内存,并生成GLOBAL_OFFSET_TABLE,PROCEDURE_LINKAGE_TABLE的过程中,因此会报错。
[图片上传失败...(image-f85146-1588307653872)]
解决方法
方法1
把需要gnu自动生成类似memcpy这种赋初值的地方,先不赋初值,而是在之后使用strcpy赋初值,因为,该接口在dl库中会在预处理时被替换为_rtld_strcpy,而gnu自动生成类似memcpy这种赋初值的地方,却不会被替换。
[图片上传失败...(image-802d83-1588307653872)]
而这些接口在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
出差必备
买火车票、高铁票、机票,订酒店都打9折的出行工具TRIP,点击注册
网友评论