基于Address Sanitizer实现Android NDK的内存错误检测DEMO

1.简介

基于Address Sanitizer实现Android NDK的内存错误检测Demo。
ps:适用于Android 13(API 级别 33)以下的设备,Android 14(API 级别 34)或更高版本的 ARM64设备推荐使用HWAddress Sanitizer配置更简单。

GitHub源码地址https://github.com/shiyinghan/AddressSanitizerDemo

2.实现过程

参考Address Sanitizer(也称为 ASan)的官方教程,具体实现步骤如下:

2.1 配置CMake

对于 CMakeLists.txt 中的每个目标:

target_compile_options(${CMAKE_PROJECT_NAME} PUBLIC -fsanitize=address -fno-omit-frame-pointer)
target_link_options(${CMAKE_PROJECT_NAME} PUBLIC -fsanitize=address)

在模块的 build.gradle 中:

android {
    ......

    defaultConfig {
        ......

        externalNativeBuild {
            cmake {
                // Can also use system or none as ANDROID_STL.
                arguments "-DANDROID_ARM_MODE=arm", "-DANDROID_STL=c++_shared", "-DSANITIZE=asan"
            }
        }
    }
}

2.2 配置ndk-build(可选)

在 Application.mk 中:

APP_STL := c++_shared
APP_CFLAGS += -fsanitize=address -fno-omit-frame-pointer
APP_LDFLAGS += -fsanitize=address

APP_OPTIM := debug

对于 Android.mk 中的每个模块:

LOCAL_ARM_MODE := arm

设置“LOCAL_ARM_MODE := arm”不是必须的,因为通过将 Application.mk 文件中的 APP_OPTIM 设置为 debug,会强制构建系统生成 ARM 二进制文件,有同样的效果。

2.3 将 android:debuggable 和android:extractNativeLibs添加到应用清单中

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        .....
        android:debuggable="true"
        android:extractNativeLibs="true"
        .....
        >
    </application>

</manifest>

2.4 将 ASan 运行时库添加到应用模块的 jniLibs 中

ASan运行库的文件夹:NDK目录/toolchains/llvm/prebuilt/host平台/lib64/clang/版本号/lib/linux/
我用的NDK版本是21.4.7075529,所以ASan运行库的文件夹如下:
在这里插入图片描述
复制运行库so文件到jniLibs对应的文件夹下面:
在这里插入图片描述

2.5 将wrap.sh 文件添加到 src/main/resources/lib 目录中的每个目录

wrap.sh脚本文件内容如下:

#!/system/bin/sh
HERE="$(cd "$(dirname "$0")" && pwd)"
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
ASAN_LIB=$(ls $HERE/libclang_rt.asan-*-android.so)
if [ -f "$HERE/libc++_shared.so" ]; then
    # Workaround for https://github.com/android-ndk/ndk/issues/988.
    export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so"
else
    export LD_PRELOAD="$ASAN_LIB"
fi
"$@"

创建并复制wrap.sh文件到src/main/resources/lib对应的文件夹下面:
在这里插入图片描述

3.测试效果

模拟一个很常见的内存已经释放但还在使用的情况:

	char *heap = static_cast<char *>(malloc(1024));
    free(heap);
    char *str = "str";
    memcpy(heap, str, strlen(str));

运行应用,logcat会出现以下错误提示:
在这里插入图片描述
这就说明检测出了上面故意加入的内存错误操作!

4. 兼容性问题

ndk-build的兼容性可能比CMake好一点,使用CMake配置好之后,在一个armeabi-v7a的设备上无法正常加载asan工具,出现卡死的现象,但是使用ndk-build就是正常的。而在arm64-v8a设备上面,CMake和ndk-build的配置,都可以正常加载asan工具。

5. 修改ASAN_OPTIONS

一些asan的选项可以通过ASAN_OPTIONS进行配置,比如我使用libjpeg-turbo软件库,打开asan之后,会出现以下错误:
在这里插入图片描述
咱们可能不关心odr-violation问题,就可以添加detect_odr_violation=0配置,找到对应cpu架构wrap.sh文件,修改如下:
在这里插入图片描述
再运行就不会出现对应的错误提示了,asan会忽略odr-violation检测。

6. 其他

ASan的一些高级用法可以参考“安仔都有人用”的这篇文章:android 如何分析应用的内存(十一)——ASan

相关推荐

  1. RASP技术相关内容DEMO实现

    2024-07-12 23:48:03       53 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-12 23:48:03       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-12 23:48:03       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-12 23:48:03       58 阅读
  4. Python语言-面向对象

    2024-07-12 23:48:03       69 阅读

热门阅读

  1. C# Modbus

    2024-07-12 23:48:03       22 阅读
  2. 安卓热门面试题一

    2024-07-12 23:48:03       20 阅读
  3. React组件间通信的几种方式

    2024-07-12 23:48:03       18 阅读
  4. TCP/IP模型和OSI模型的区别(面试题)

    2024-07-12 23:48:03       21 阅读
  5. opencv--把cv::Mat数据转为二进制数据的保存和读取

    2024-07-12 23:48:03       20 阅读
  6. 扫地机器人如何进行MTBF测试

    2024-07-12 23:48:03       19 阅读
  7. ffmpeg和imagemagick制作gif动图

    2024-07-12 23:48:03       23 阅读
  8. 基于深度学习的PID

    2024-07-12 23:48:03       20 阅读
  9. 【C++】C++中struct结构体和class类的区别

    2024-07-12 23:48:03       16 阅读
  10. CAS详解

    CAS详解

    2024-07-12 23:48:03      16 阅读