如何判断 Android .so 是使用哪个运行时编译的?

And*_*wel 3 android runtime android-ndk android-stlport

我有一些预编译的 so 文件,所以谁知道使用什么标志来生成它们。我很想知道它们是用哪个运行时/版本的 STL 编译的(gnustl_shared?stlport_shared?)以避免与我自己的代码发生冲突。

如何从编译后的 so 文件中找出它们编译使用的运行时?

这是所有 Android NDK C++ 代码。

Dan*_*ert 5

就像 Alex 所说,你可以使用 readelf 来弄清楚其中的一些内容。下面可以让您知道该库是否依赖于共享 STL,以及是哪一个:

$ readelf -dW path/to/libfoo.so | grep NEEDED
 0x00000001 (NEEDED)                     Shared library: [libc++_shared.so]
 0x00000001 (NEEDED)                     Shared library: [libc.so]
 0x00000001 (NEEDED)                     Shared library: [libm.so]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so]
 0x00000001 (NEEDED)                     Shared library: [libdl.so]
Run Code Online (Sandbox Code Playgroud)

如您所见,该库依赖于 libc++_shared。忽略libstdc++。这样你也看到了。那是https://github.com/android-ndk/ndk/issues/105

如果它依赖于静态 STL(或者您的库是静态库)并且不是使用 构建的-fvisibility=hidden,则该方法将不起作用。在这种情况下,您仍然可以确定该库是针对 libc++ 还是非 libc++ 构建的。所有 libc++ 符号都位于内部命名空间中(std::__ndk1而不仅仅是std),以支持 STL 的版本控制并避免与系统 STL 发生冲突。如果它是一个非常旧的(r10 或更旧的)libc++,它将只是__1.

$ readelf -sW path/to/libfoo.so | grep __ndk1
     6: 000008bf    86 FUNC    WEAK   DEFAULT   12 _ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcj
     7: 000008a9    22 FUNC    WEAK   DEFAULT   12 _ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev
Run Code Online (Sandbox Code Playgroud)

如果您想确定某个库是使用哪个版本的 NDK 构建的,可以使用https://android.googlesource.com/platform/ndk/+/master/parse_elfnote.py

$ python parse_elfnote.py foo/libs/armeabi-v7a/libfoo.so 
----------ABI INFO----------
ABI_NOTETYPE: 1
ABI_VENDOR: Android
ABI_ANDROID_API: 14
ABI_NDK_VERSION: r17-canary
ABI_NDK_BUILD_NUMBER: dev
Run Code Online (Sandbox Code Playgroud)

大多数信息仅适用于使用相对较新的 NDK 构建的库(r14?我不记得我们何时添加此内容)。