linux中查找NDK中需要的.a库文件
发布日期:2022-01-31 02:37:38 浏览次数:35 分类:技术文章

本文共 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:JNI抛出异常
下一篇:C++计算二进制数中1的个数

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2024年03月22日 09时16分18秒