zoukankan      html  css  js  c++  java
  • 在AndroidStudio上使用AddressSanitizer

    在AndroidStudio上使用AddressSanitizer

    AddressSanitizer是Google主导的一个开源内存问题检测工具。现在也开始支持Android平台,且受Google推荐来替代之前的Valgrind。目前AddressSanitizer能够发现如下问题:

    • Out-of-bounds accesses to heap, stack and globals
    • Use-after-free
    • Use-after-return (runtime flag ASAN_OPTIONS=detect_stack_use_after_return=1)
    • Use-after-scope (clang flag -fsanitize-address-use-after-scope)
    • Double-free, invalid free
    • Memory leaks (experimental)

    其中,值得一提的是Memory leaks,现在还是experiment,准确的说,现在还只支持Linux平台,并不支持Android。所以,想写一个内存泄露来检验AddressSanitizer是否生效就要注意了,就像本人一样,其实AddressSanitizer都已经正常运行了,然后一直没有检测出来Memory leaks就以为没有生效,导致浪费了很多时间。

    For more information on leak detector in AddressSanitizer, see LeakSanitizer. The leak detection is turned on by default on Linux, and can be enabled using ASAN_OPTIONS=detect_leaks=1 on OS X; however, it is not yet supported on other platforms.

    也许有人会说,Android不也是Linux嘛。这个的话,从它的Supported Platforms:

    • Linux i386/x86_64 (tested on Ubuntu 12.04)
    • OS X 10.7 - 10.11 (i386/x86_64)
    • iOS Simulator
    • Android ARM
    • NetBSD i386/x86_64
    • FreeBSD i386/x86_64 (tested on FreeBSD 11-current)

    就可以看出来,Linux和Android是不同的。而且这里还注明了必须ARM,也就是说如果用非ARM的Android设备可能就不支持。个人认为这和AddressSanitizer的实现机制有关。因为它是通过重写比如malloc之类的函数,构造shadow Memory来实现的检测。而这些函数可能都是汇编语言写的,所以不同的CPU硬件就需要不同的实现版本。

    AS中的应用

    编译指令

    其实很简单,就两点,开启AddressSanitizer标志和使用clang编译器。

    1. 开启AddressSanitizer标志:在CMakeLists.txt中添加如下语句:
    SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -fsanitize=address -fno-omit-frame-pointer")
    SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g -fsanitize=address -fno-omit-frame-pointer")
    SET (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
    SET (CMAKE_ANDROID_ARM_MODE ARM)
    
    1. 使用clang编译:在build.gradle的cmake模块下面添加:
    arguments "-DANDROID_TOOLCHAIN=clang"
    
    在设备中安装ASAN

    要点:

    • 设备需要root
    • 运行ndk中的asan_device_setup脚本

    关于asan_device_setup脚本,在AS自带的ndk-bundle中,其脚本路径为ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/7.0.2/bin/asan_device_setup,而如果是自己单独安装的NDK,那么其路径为NDKROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/asan_device_setup。如果脚本执行成功,那么设备就会自动重启,在本人实践中,最后部分信息如下:

    >> Pushing files to the device
    Installing /system/lib/libclang_rt.asan-arm-android.so 644 
    [100%] /system/lib/libclang_rt.asan-arm-android.so
    Installing /system/lib64/libclang_rt.asan-aarch64-android.so 644 
    [100%] /system/lib64/libclang_rt.asan-aarch64-android.so
    Installing /system/bin/app_process32 755 u:object_r:zygote_exec:s0
    [100%] /system/bin/app_process32
    Installing /system/bin/app_process32.real 755 u:object_r:zygote_exec:s0
    [100%] /system/bin/app_process32.real
    Installing /system/bin/app_process64 755 u:object_r:zygote_exec:s0
    [100%] /system/bin/app_process64
    Installing /system/bin/app_process64.real 755 u:object_r:zygote_exec:s0
    [100%] /system/bin/app_process64.real
    Installing /system/bin/asanwrapper 755 
    [100%] /system/bin/asanwrapper
    Installing /system/bin/asanwrapper64 755 
    [100%] /system/bin/asanwrapper64
    >> Restarting shell (asynchronous)
    >> Please wait until the device restarts
    
    测试

    有了前面两步,就可以实验了,其实还是很简单的。

    使用AS新建一个C++支持的默认Android项目,然后修改其native函数如下:

    extern "C" JNIEXPORT jstring
    JNICALL
    Java_com_example_willhua_asantest_MainActivity_stringFromJNI(
            JNIEnv *env,
            jobject /* this */) {
        std::string hello = "Hello from C++";
    
        int *ptr = (int*)malloc(sizeof(int) * 3);
        ptr[4] = 6;
    
        return env->NewStringUTF(hello.c_str());
    }
    

    然后在注意Build Variant为debug,点击启动就OK啦。然后在log中可以看到检测到了heap-buffer-overflow:

    infteK.png

    参考

    clang: AddressSanitizer
    Android Native内存检测
    内存检测工具
    AddressSanitizerOnAndroid

  • 相关阅读:
    .Net常识 值类型和引用类型
    .net 开发人员的瓶颈和职业发展
    PPT Garbage Collection in .Net (内存管理)
    Why Sessionless Web Application ?
    一些.Net面试题 (BS 方向)
    开源一个小类库, 用于对象间灵活的拷贝属性,还有IDataReader到实体类的转换
    在 Visual Studio 单元测试中使用CallContext 导致的 Unit Test Adapter threw exception: Type is not resolved for member... 异常
    【设计原则和建议】 类
    轻量级 Lock Free 线程安全的 Queue<T> 的C#2.0实现
    实验一 命令解释程序的编写
  • 原文地址:https://www.cnblogs.com/willhua/p/9688266.html
Copyright © 2011-2022 走看看