0

I'm using Android Studio to build an app containing a module that uses the NDK. There is evidence of memory corruption so I'm trying the Address Sanitizer, following these instructions on the NDK developer site. But the app won't build.

I need to (A) ensure I'm targeting Android 27+ (I set minSdkVersion to 27; I'm building a debug build for a Galaxy S9, SDK 28), and (B) add compiler flags, which I've done:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                # Can also use system or none as ANDROID_STL.
                arguments "-DANDROID_ARM_MODE=arm", "-DANDROID_STL=c++_shared"
                cppFlags "-fsanitize=address -fno-omit-frame-pointer"
            }
        }
    }
}

I've also added wrap.sh scripts according to the instructions but I understand that they become relevant only at runtime.

The problem is that my app won't build. The output follows.

The C++ compiler
"C:/Users/user/AppData/Local/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/bin/clang++.exe" is not able to compile a simple test program.

It fails with the following output:

Change Dir: C:/Users/user/studio/app/android/audioengine/.externalNativeBuild/cmake/debug/arm64-v8a/CMakeFiles/CMakeTmp

Run Build
Command:"C:\Users\user\AppData\Local\Android\sdk\cmake\3.6.4111459\bin\ninja.exe" "cmTC_58655"

[1/2] Building CXX object CMakeFiles/cmTC_58655.dir/testCXXCompiler.cxx.o

[2/2] Linking CXX executable cmTC_58655

FAILED: cmd.exe /C "cd . &&
C:\Users\user\AppData\Local\Android\sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android27 --gcc-toolchain=C:/Users/user/AppData/Local/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/Users/user/AppData/Local/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/sysroot -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -Wa,--noexecstack -Wformat -Werror=format-security -stdlib=libc++ -fsanitize=address -fno-omit-frame-pointer -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--gc-sections CMakeFiles/cmTC_58655.dir/testCXXCompiler.cxx.o -o cmTC_58655 -latomic -lm && cd ."

C:/Users/user/AppData/Local/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/lib/gcc/aarch64-linux-android/4.9.x/../../../../aarch64-linux-android/bin\ld: warning: liblog.so, needed by
C:\Users\tim\AppData\Local\Android\sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\lib64\clang\8.0.2\lib\linux\libclang_rt.asan-aarch64-android.so, not found (try using -rpath or -rpath-link)

clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)

The compiler flags have been passed correctly. There is a warning concerning liblog.so not being found, but then a non-specific error.

The instructions show where to place the sanitizer libraries in the project (in the jniLibs folder), but not where to source them. I copied them from the NDK install on my machine. I tried doing the same with liblog libraries but It's not clear which variant to use; the one I tried (for SDK 28) didn't affect the result.

What am I missing? I've found posts struggling with understanding exactly how to use the address sanitizer, but none mentions this particular problem.

1 Answer 1

1

Looks like those docs are wrong. It seems that CMake isn't using all of the linker flags it needs when performing that test. I'm not sure if that's NDK bug or a CMake bug, but here's a way to make ASan work with CMake/gradle:

  1. Remove the cppFlags section from your build.gradle
  2. Add those options in your CMakeLists.txt instead, like so:

    add_library(app SHARED app.cpp)
    target_compile_options(app PUBLIC -fsanitize=address -fno-omit-frame-pointer)
    set_target_properties(app PROPERTIES LINK_FLAGS -fsanitize=address)
    

I've uploaded a change to fix the docs. Should be live soon.

Sign up to request clarification or add additional context in comments.

2 Comments

Now I can build my app. However there is a failure to load wrap.sh: "executing /data/app/fm.x.x-dlmU0MsHPppv3ajLKAQbxw==/lib/arm/wrap.sh failed: No such file or directory." The instructions say to place the wrap.sh scripts and the libclang_rt.asan-...-android.so files in very specific folders in the "project's application module" - none of them a folder called 'arm'. All my native code is in a separate (non-app) module, with its libraries in a different folder location with respect to that. Where should the wrap.sh and libclang_rt.asan-...-android.so files be?
To answer my own comment: I included the wrap.sh scripts and the libclang_rt.asan-...-android.so in both the app and the module with my native code, for good measure. and checked that both made it into the apk. Then I discovered the underlying problem was that I had the wrong line endings in wrap.sh (I'm using WIndows, it wanted Unix-style). I hope this helps someone else. github.com/google/sanitizers/issues/1023

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.