如何在树莓派上使用为Android编译的闭源共享库
解决方案
以下两种方案均可以快速解决符号不匹配问题,不需要逆向原库。
方案1:批量重命名libfoo.so内的符号(推荐,最快生效)
直接修改原库的符号名,删除@LIBC后缀匹配glibc的标准符号,操作步骤如下:
- 先备份原库避免修改失败:
cp /usr/lib/libfoo.so /usr/lib/libfoo.so.bak
- 用
objcopy工具执行批量符号重命名:
objcopy \ --redefine-sym __cxa_atexit@LIBC=__cxa_atexit \ --redefine-sym calloc@LIBC=calloc \ --redefine-sym malloc@LIBC=malloc \ --redefine-sym free@LIBC=free \ --redefine-sym memset@LIBC=memset \ --redefine-sym memcpy@LIBC=memcpy \ --redefine-sym raise@LIBC=raise \ --redefine-sym __cxa_finalize@LIBC=__cxa_finalize \ --redefine-sym abort@LIBC=abort \ /usr/lib/libfoo.so.bak /usr/lib/libfoo.so
- 验证修改结果:执行
nm -D /usr/lib/libfoo.so查看导出符号,确认所有@LIBC后缀已经消失,此时重新编译链接你的程序即可正常运行。
你之前用patchelf修改依赖不生效的原因是:该操作只改了依赖的库名,没有修改符号本身的后缀,glibc的libc.so.6中不存在带
@LIBC后缀的符号,因此还是会报错。
方案2:编写垫片共享库转发符号(不修改原库)
如果需要保留原库文件不变,可以通过GCC的别名属性定义带@LIBC后缀的符号,转发到glibc的原生实现:
- 新建垫片库源码
libc_shim.c:
#include <stdlib.h> #include <string.h> #include <signal.h> #include <cxxabi.h> // 定义宏快速生成符号别名,将带@LIBC的符号转发到原生实现 #define MAKE_ALIAS(orig) extern __typeof__(orig) orig##@LIBC __attribute__((alias(#orig), visibility("default"))) MAKE_ALIAS(__cxa_atexit) MAKE_ALIAS(calloc) MAKE_ALIAS(malloc) MAKE_ALIAS(free) MAKE_ALIAS(memset) MAKE_ALIAS(memcpy) MAKE_ALIAS(raise) MAKE_ALIAS(__cxa_finalize) MAKE_ALIAS(abort)
- 编译生成垫片共享库:
gcc -shared -fPIC libc_shim.c -o libc_shim.so -lc
- 运行程序时预加载该垫片库即可:
LD_PRELOAD=./libc_shim.so ./你的可执行程序
如果需要永久生效,可以把libc_shim.so放到/usr/lib目录下,然后在你的程序链接参数里加上-lc_shim即可。
注意:以上两种方案都需要原Android共享库的架构和树莓派运行的系统架构一致(例如均为armv7 32位/armv8 64位),架构不匹配的场景需要额外做二进制转译。
内容的提问来源于stack exchange,提问作者Anonymix321
相关产品推荐
相关产品推荐

