本文共 2661 字,大约阅读时间需要 8 分钟。
仅仅是提供一种思路去解决编译出的so库在loadLibrary时找不到符号的问题。
这里以查找静态库文件为例,首先基本可以认为需要的.a库文件都是可以在NDK中找到的,连接后生成的so在运行时发生错误大部分是因为没有连接到一些需要的库,如libz、libm等,所以会有找不到"xxx"符号的问题。 以找不到"__aeabi_uidiv"符号为例,用如下的方法看一下:进入NDK的根目录,输入:
grep -r "\b__aeabi_uidiv\b" ./ | grep "\.a\b" | egrep -o "\./.+" | xargs nm | egrep "(\.a\b)|(T __aeabi_uidiv\b)"
这条命令的意思是:
1.从当前目录及其子目录下找到匹配"\b__aeabi_uidiv\b"(\b表示空格,因为可能会有其它的符号影响查找,例如搜索cos时cosh也会作为结果)模式的字符串的文件,目的是找到包含__aeabi_uidiv符号的二进制文件,如果找到时,会输出字符串"匹配到二进制文件 xxxxxxxx(文件路径)" 2.从上一步的结果中匹配".a"后缀,以去除无用的文件名 3.上一步的结果中去除"匹配到二进制文件"这样的修饰字符串,提取出文件名 4.对这些文件执行nm命令 5.从输出结果中找出匹配"T __aeabi_uidiv"的行,意思是要寻找"__aeabi_uidiv"符号,且该符号的类型应该为T,也即在代码区中的符号。平常报找不到符号的问题,基本都是因为在编出来的库中,这些符号是未定义的,也就是U(Undefined)。所以需要找到包含这些符号的库文件。显示有T类型符号的语句的上面一条语句就是对应的静态库文件,例如这里可以看出__aeabi_uidiv在libgcc.a中定义,所以在连接时需要把libgcc.a也连接进来。具体地就是在ld的语句中加入-L库路径 -l库名称,如:
-L$TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a \-lgcc
前面-L指定库文件的路径,后面的-l指定库的名称,这里的库文件为libgcc.a,去掉后缀.a及前缀的lib,其库的名称为gcc,表示需要连接到gcc库。
另外这里可以看到多个libgcc.a文件,具体应该选择哪个就需要看经验或者做其它检测了。以现在的情况举例,针对armv7-a平台进行编译时,可以推断出应该选择arm-linux-androideabi工具链下的文件,其中路径中有thumb的表示与arm的thumb指令集相关(没用过,不是很了解,但应该在编译时指定了-mthumb参数才会需要这个),路径中有hard的可能是与浮点数(软浮点/硬浮点)的计算方式相关,还没求证,只是推断。所以理论上普通编译的话应当选择:
./toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a
或者 ./toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a/libgcc.a根据经验应该选择/armv7-a路径下的libgcc.a。
那如果真的有强迫症,怎么看这两个文件有什么区别呢?
可以通过工具链(./toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin)路径下的ar来解压.a文件来展开其中的.o文件,再使用objdump工具或readelf工具查看并比对,首先新建两个路径:mkdir /mnt/unpack01mkdir /mnt/unpack02
然后进入路径中调用ar工具解压.a文件:
这里的$TOOLCHAIN是环境变量,其值为大致为"android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64"cd /mnt/unpack01$TOOLCHAIN/bin/arm-linux-androideabi-ar -x $TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.acd /mnt/unpack02$TOOLCHAIN/bin/arm-linux-androideabi-ar -x $TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a/libgcc.a
然后通过readelf工具查看任意两个.o文件并进行对比
$TOOLCHAIN/bin/arm-linux-androideabi-readelf -all /mnt/unpack_01/_udivUDA.o > /mnt/1.txt$TOOLCHAIN/bin/arm-linux-androideabi-readelf -all /mnt/unpack_02/_udivUDA.o > /mnt/2.txt
打开1.txt及2.txt对比后,可以发现1.txt中有:
File Attributes Tag_CPU_name: “5TE” Tag_CPU_arch: v5TE而2.txt中为:
File Attributes Tag_CPU_name: “7-A” Tag_CPU_arch: v7 故可以知道两个libgcc.a对应的cpu平台有差别,按一般的需求而言都是需要armv7-a的库,所以需要的也就是armv7-a路径下的libgcc.a。上面的做法比较复杂,在预先知道需要查看的内容后,可以直接通过readelf命令并通过-A参数查看架构相关的信息,如:
$TOOLCHAIN/bin/arm-linux-androideabi-readelf -A $TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a/libgcc.a > /mnt/1.txt
输出的是所有.o文件的信息,但是只需要看最后面一个文件的就好了
转载地址:https://blog.csdn.net/no_367/article/details/103364931 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!