Android NDK开发详解调试和减少内存错误之HWAddress Sanitizer

Android NDK开发详解调试和减少内存错误之HWAddress Sanitizer


注意:本文档介绍了如何在 HWAddress Sanitizer 下运行使用 NDK 构建的 Android 应用。如需了解如何对 Android 平台组件使用 HWAddress Sanitizer,请参阅 AOSP 文档。

从 NDK r21 和 Android 10(API 级别 29)开始,Android NDK 支持 HWAddress Sanitizer(也称为 HWASan)。HWASan 仅适用于 64 位 Arm 设备。
重要提示:HWAsan 是用于调试和减少内存错误的众多工具之一。如需简要了解所有工具,请参阅调试和减少内存错误。

HWASan 是一款类似于 ASan 的内存错误检测工具。与传统的 ASan 相比,HWASan 具有如下特征:

类似的 CPU 开销(约为 2 倍)
类似的代码大小开销 (40 - 50%)
更小的 RAM 开销 (10% - 35%)

HWASan 能检测到 ASan 所能检测到的同一系列错误:

堆栈和堆缓冲区上溢或下溢
释放之后的堆使用情况
超出范围的堆栈使用情况
重复释放或错误释放

此外,HWASan 还可以检测:

返回之后的堆栈使用情况

示例应用

示例应用展示了如何为 hwasan 配置 build 变体。

Android 13 或更低版本:设置

如果您的设备搭载的是 Android 14 或更高版本,您可以跳过此步骤,然后按照下文构建部分中的使用 wrap.sh 的说明进行操作。您也可以选择按照本部分操作,并跳过下文中使用 wrap.sh 的说明。

在 Android 14 之前,HWASan 应用需要 Android 的 HWASan build 才能运行。您可以将预构建的 HWASan 映像刷写到支持的 Pixel 设备上。在 ci.android.com 上可以找到这些 build,您可以在此页面上点击所需的确切 build 的方格来获取 Flash Build 链接。您需要知道您手机的代号。
在这里插入图片描述

刷写设备 build

改为直接访问 flash.android.com 会使操作更简单,因为该流程会首先检测您的设备,且仅显示您可以使用的 build。下面的图片说明了此工具中的设置流程。

在设备上启用开发者模式,然后使用 USB 线将其连接到计算机。点击 Add new device,从对话框中选择您的设备,然后点击 Connect。
在这里插入图片描述
在这里插入图片描述

检测要刷写的设备 选择要连接的设备

您的设备连接后,点击它来配置 build。在 Select a build ID 框中,选择 aosp-master-with-phones-throttled 分支以自动为您连接的设备选择正确的映像。
在这里插入图片描述
在这里插入图片描述

选择要刷写的设备 确认刷写选项并刷写设备

点击 Install 以刷写您的设备。

如需详细了解必要的设置,请参阅 Android 刷写工具文档。或者,您也可以查看 AOSP 文档,了解如何从源代码构建 HWASan 映像。

构建

重要提示:请务必使用最新的 NDK 来构建代码。

若要使用 HWAddress Sanitizer 构建应用的原生 (JNI) 代码,请执行以下操作:
ndk-build
在您的 Application.mk 文件中:

APP_STL := c++_shared # Or system, or none, but not c++_static.
APP_CFLAGS := -fsanitize=hwaddress -fno-omit-frame-pointer
APP_LDFLAGS := -fsanitize=hwaddress

CMake

在模块的 build.gradle 文件中:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                # Can also use system or none as ANDROID_STL, but not c++_static.
                arguments "-DANDROID_STL=c++_shared"
            }
        }
    }
}

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

target_compile_options(${TARGET} PUBLIC -fsanitize=hwaddress -fno-omit-frame-pointer)
target_link_options(${TARGET} PUBLIC -fsanitize=hwaddress)

注意:必须提供共享库 STL,因为 STL 中的 new 和 delete 运算符的实现通常是在没有框架指针的情况下构建的。HWASan 可提供自己的实现,但如果 STL 是以静态方式链接到应用,您将无法使用此实现。

Android 14 或更高版本:添加 wrap.sh

注意:此功能从 Android 14 Beta 3 开始提供。

如果您运行的是 Android 14 或更高版本,则可以使用 wrap.sh 脚本在任何由 Android 提供支持的设备上运行您的可调试应用。如果您选择按照上述设置中的步骤操作,则可以跳过此步骤。

按照说明打包 wrap.sh 脚本,为 arm64-v8a 添加以下 wrap.sh 脚本。

#!/system/bin/sh
LD_HWASAN=1 exec "$@"

运行

在 HWASan 构建的 Android 映像上照常运行应用。当检测到内存错误时,应用会因 SIGABRT 而崩溃,并向 Logcat 输出详细消息。您可以在 /data/tombstones 下的文件中找到该消息的副本,内容如下:

ERROR: HWAddressSanitizer: tag-mismatch on address 0x0042a0826510 at pc 0x007b24d90a0c
WRITE of size 1 at 0x0042a0826510 tags: 32/3d (ptr/mem) in thread T0
    #0 0x7b24d90a08  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x2a08)
    #1 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)
    #2 0x7b8f1db364  (/apex/com.android.art/lib64/libart.so+0x18f364)
    #3 0x7b8f2ad8d4  (/apex/com.android.art/lib64/libart.so+0x2618d4)

0x0042a0826510 is located 0 bytes to the right of 16-byte region [0x0042a0826500,0x0042a0826510)
allocated here:
    #0 0x7b92a322bc  (/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so+0x212bc)
    #1 0x7b24d909e0  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x29e0)
    #2 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)

消息后面可能还跟着其他调试信息,包括应用中的活动线程列表、临近内存分配的标记和 CPU 寄存器值。

如需详细了解 HWASan 错误消息,请参阅了解 HWASan 报告。

本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。

最后更新时间 (UTC):2023-09-01。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Android NDK开发是指利用NDK(Native Development Kit)将C/C++开发的代码编译成so库,然后通过JNI(Java Native Interface)让Java程序调用。在Android开发中,默认使用的是Android SDK进行Java语言的开发,而对于一些需要使用C/C++的高性能计算、底层操作或跨平台需求的场景,可以使用NDK进行开发。 在Android Studio中进行NDK开发相对于Eclipse来说更加方便,特别是在Android Studio 3.0及以上版本中,配置更加简化,并引入了CMake等工具,使得开发更加便捷。首先要进行NDK开发,需要配置环境,包括导入NDK、LLDB和CMake等工具。可以通过打开Android Studio的SDK Manager,选择SDK Tools,在其中选中相应的工具进行导入。 在项目的build.gradle文件中,可以配置一些NDK相关的参数,例如编译版本、ABI过滤器等。其中,可以通过externalNativeBuild配置CMake的相关设置,包括CMakeLists.txt文件的路径和版本号。此外,在sourceSets.main中还可以设置jniLibs.srcDirs,指定so库的位置。 在进行NDK开发时,可以在jni文件夹中编写C/C++代码,并通过JNI调用相关的函数。通过JNI接口,可以实现Java与C/C++之间的相互调用,从而实现跨语言的开发。 综上所述,Android NDK开发是指利用NDK将C/C++开发的代码编译成so库,并通过JNI实现与Java的相互调用。在Android Studio中进行NDK开发相对方便,可以通过配置环境和相应的参数来进行开发。<span class="em">1</span><span class="em">2</span><span class="em">3</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五一编程

程序之路有我与你同行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值