I have a native Android, SDK style library which depends on OpenCV.
In order to avoid conflict when a user uses the library and their own usage with OpenCV, I want to compile OpenCV statically into my library and hide its symbols.
I compiled OpenCV (3.4.13 world
module) statically and used it, along with its 3rd party libraries in my library.
When I try and use my library, and it throws an exception, even if the exception is caught by the user, a SIGABRT
is causing the app to terminate.
This is the stack trace from the logcat
A/libc: Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 24115 (.test), pid 24115 (.test)
...
A/DEBUG: backtrace:
A/DEBUG: #00 pc 0000000000051948 /apex/com.android.runtime/lib64/bionic/libc.so (abort 168) (BuildId: 931371c1098ffd5adc489b9ff4da8e82)
A/DEBUG: #01 pc 00000000000b2ba0 /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libc _shared.so (BuildId: ece72a2ebc3774a1be9fd21271258acd3bcdfaa7)
A/DEBUG: #02 pc 00000000000aec8c /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libc _shared.so (__gxx_personality_v0 348) (BuildId: ece72a2ebc3774a1be9fd21271258acd3bcdfaa7)
A/DEBUG: #03 pc 00000000004dd2dc /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libmylib.so (BuildId: 790f2880373cb985055ab9b7b2efc48b1afb82fd)
A/DEBUG: #04 pc 00000000004dd7e4 /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libmylib.so (BuildId: 790f2880373cb985055ab9b7b2efc48b1afb82fd)
A/DEBUG: #05 pc 0000000000170600 /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libmylib.so (mylib::TestClass::TestClass(char const*, char const*) 908) (BuildId: 790f2880373cb985055ab9b7b2efc48b1afb82fd)
A/DEBUG: #06 pc 000000000000c5d0 /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libJnilibrary.so (BuildId: 7f3605ea8cb95dc87864e3df22f6b77b46c2e592)
A/DEBUG: #07 pc 000000000000c3b8 /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libJnilibrary.so (BuildId: 7f3605ea8cb95dc87864e3df22f6b77b46c2e592)
A/DEBUG: #08 pc 000000000000c308 /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libJnilibrary.so (Java_com_example_lib_Engine_cxxInit 56) (BuildId: 7f3605ea8cb95dc87864e3df22f6b77b46c2e592)
A/DEBUG: #09 pc 00000000002d7644 /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline 148) (BuildId: 2b417e2566f5eb686666666b6ee952ea)
(It also happens if the JNI library uses c _static
, but in that case the __gxx_personality_v0
and 1 above it come from the libJnilibrary.so
)
If I compile OpenCV as a shared library and link my library against it, then everything works fine.
I've had issues with exceptions in my library before, see this question I asked. I solved it by compiling everything using c _static
STL. The problem looks similar to this, and indeed I was missing the key function
, but even after adding it, the problem keeps happening.
I looked at the symbols using llvm-readelf -CWs
and noticed that when OpenCV is linked dynamically, in addition to OpenCV symbols, the output contains some ndk and cxxabi symbols which doesn't exist when OpenCV is used statically. I don't know if it's related at all but for example
110: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::uncaught_exception()
...
201: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND vtable for __cxxabiv1::__vmi_class_type_info
...
231: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::__ndk1::to_string(unsigned int)
(All of these are missing when using statically built OpenCV)
I'm using ndk version 21e
(I can't use higher version at the moment because another library uses Bazel
and it only supports up to 21 at the moment)
OpenCV is built with the following flags
cmake -DCMAKE_BUILD_TYPE=Release -DINSTALL_ANDROID_EXAMPLES=OFF -DANDROID_EXAMPLES_WITH_LIBS=OFF -DANDROID_ABI="arm64-v8a"
-DBUILD_EXAMPLES=OFF -DBUILD_DOCS=OFF -DWITH_OPENCL=OFF -DBUILD_ANDROID_PROJECTS=OFF -DBUILD_ANDROID_EXAMPLES=OFF -DANDROID_ARM_NEON=1
-DANDROID_STL=c _static -DANDROID_PLATFORM=android-21 -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake"
-DBUILD_SHARED_LIBS=OFF -DBUILD_FAT_JAVA_LIB=OFF -DBUILD_JAVA=OFF -DINSTALL_CREATE_DISTRIB=ON -DINSTALL_ANDROID_EXAMPLES=OFF -DBUILD_opencv_objdetect=OFF
-DBUILD_opencv_video=ON -DBUILD_opencv_videoio=ON -DBUILD_opencv_features2d=ON -DBUILD_opencv_flann=OFF -DBUILD_opencv_highgui=ON -DBUILD_opencv_ml=OFF
-DBUILD_opencv_photo=OFF -DBUILD_opencv_python=OFF -DBUILD_opencv_shape=OFF -DBUILD_opencv_stitching=OFF -DBUILD_opencv_superres=OFF -DBUILD_opencv_ts=OFF
-DBUILD_opencv_videostab=OFF -DBUILD_ANDROID_PROJECTS=OFF -DBUILD_opencv_world=ON -DBUILD_opencv_dnn=OFF -DBUILD_opencv_core=ON -DBUILD_opencv_imgcodecs=ON
-DBUILD_opencv_imgproc=ON -DBUILD_opencv_calib3d=ON -GNinja -DCMAKE_INSTALL_PREFIX=../install -DBUILD_ZLIB=1 -DWITH_PROTOBUF=OFF -DWITH_QUIRC=OFF ..
My libray is compiled using Gradle and Android Studio with these CMake flags
externalNativeBuild {
cmake {
cppFlags "-std=c 17 -static-openmp -fopenmp -fexceptions -frtti -Wno-unused-command-line-argument -Wl,-s"
cppFlags "-Wl,--exclude-libs,libc _static.a -Wl,--exclude-libs,libc abi.a"
arguments "-DANDROID_STL=c _static", "-DANDROID_ARM_NEON=TRUE"
}
}
CodePudding user response:
The issue wasn't related to the 3rd party or anything like this at all eventually.
I was using NDK version r21e
. Upgrading the NDK to r24
fixed the issue.
It seems that when linking OpenCV
as a shared object, it masked the actual NDK bug by importing or including some of the missing/problematic symbols and when we stopped using it, the error appeared.