android 如何分析应用的内存(十一)——ASan

这篇具有很好参考价值的文章主要介绍了android 如何分析应用的内存(十一)——ASan。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

android 如何分析应用的内存(十一)

接下来是,heap的第五大板块——ASan(Address Sanitizer)和HWASan(Hardware Address Sanitizer)。可以将其称为:地址清理器

与其说是Heap板块,不如说是debug板块。

ASan是一个集成在编译器中的工具,因此只需要在编译的时候设置好Flag即可。而HWASan则可以认为是ASan的plus版本。HWASan比ASan有如下的优点:

  1. 更小的内存开销
  2. 还可以检测,返回之后的堆栈使用情况

注意:自2023年起,ASan不再支持,建议使用HWASan。

本文章先简单介绍一下原理,然后详细介绍ASan的使用,以及对输出结果的解析。在下一篇中介绍HWASan的使用

原理简述

ASan在编译和链接阶段,将一些特殊的检查代码和内存管理代码插入到程序中。当程序运行时,这些插入的代码将负责管理内存的分配和释放。

比如:当应用程序调用malloc时,实际上调用的是Asan提供的malloc版本。ASan版本的malloc除了基本的内存分配以外,还会做额外的动作如:在分配的内存周围加上一个特殊区域(Red zones)
用于检测内存越界问题;同时对分配的内存每8个字节一组,分配一个影子内存,记录该组的使用情况,这样可以精确的记录每个内存的使用情况。

除了上面的介绍的Red Zone和影子内存外,ASan还会使用,如下的技术:

  1. 内存填充:对已经释放的内存,填充特殊的字节,如果访问这些内存,就会触发相应的错误
  2. 内存泄漏:在程序退出时,会检测所有的内存,查看是否存在未释放的内存。

注意:ASan似乎和malloc debug功能一致。事实上,因为ASan可以在编译和链接阶段插入代码,它比malloc debug的动态检测更加丰富和齐全。当然ASan会有更大的开销。

将ASan加入编译

现在只需要修改相应的Flag即可。如下:

## 在编译的时候,启用ASan,并且不要省略栈帧(-fno-omit-frame-pointer),这对于打印可读的栈帧非常友好
APP_CFLAGS := -fsanitize=address -fno-omit-frame-pointer
## 在链接的时候,启用ASan
APP_LDFLAGS := -fsanitize=address

ASan对内存布局和寻址方式上面有一定的要求,如果是arm架构,需要明确指定,以arm模式编译,而不是thumb模式编译如下:

## 在每一个Android.mk中都需要添加如下的代码
LOCAL_ARM_MODE := arm

android 如何分析应用的内存(十一)——ASan,android  内存分析,ASan,ASan使用,ASan编译,ASan解析,ASan例子

除了makefie以外,还可以使用Cmakefile如下:

## 设置编译选项,启用ASan功能,并且不省略栈帧(-fno-omit-frame-pointer)
target_compile_options(${TARGET} PUBLIC -fsanitize=address -fno-omit-frame-pointer)
## 设置链接选项,启用ASan功能
set_target_properties(${TARGET} PROPERTIES LINK_FLAGS -fsanitize=address)

android 如何分析应用的内存(十一)——ASan,android  内存分析,ASan,ASan使用,ASan编译,ASan解析,ASan例子

同样也需要设置arm模式编译,如下:

defaultConfig {
        externalNativeBuild {
            cmake {
                abiFilters "arm64-v8a"
                cmake {
                    arguments "-DANDROID_ARM_MODE=arm"
                }
            }
        }
    }

自定义应用的启动过程

因为ASan需要使用各种动态库,而这些动态库在Android设备默认是没有的。因此需要将这些动态库,放入Android设备中。

有两种方法将相应的动态库放入设备中:

  1. 自定义APP的启动过程,使用wrap.sh。
  2. 使用NDK提供的脚本。

方法一:使用wrap.sh

wrap.sh的详细介绍,参见:android 如何分析应用的内存(七)下面只做使用说明。

  • 在AndroidManifest.xml中添加android:debuggable=“true”
  • 在build.gradle中使用 useLegacyPackaging。见android 如何分析应用的内存(七)
  • 将 ASan 运行时库添加到应用模块的 jniLibs 中。
    ASan的运行库在:NDK目录/toolchains/llvm/prebuilt/host平台/lib64/clang/版本/lib/linux/
    分别为一下四个:
    1. libclang_rt.asan-aarch64-android.so;
    2. libclang_rt.asan-arm-android.so;
    3. libclang_rt.asan-i686-android.so;
    4. libclang_rt.asan-x86_64-android.so
  • 然后将如下内容添加到wrap.sh中
#!/system/bin/sh
## 获取当前脚本的路径,并将其赋值给HERE
HERE="$(cd "$(dirname "$0")" && pwd)"
## 定义几个环境变量,其中allow_user_segv_handler表示当程序运行出现问题时,内核发出的
## SIGSEGV信号,可以被处理,而不是简单的结束程序
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
## ASAN_LIB为运行时库
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
## 执行程序
"$@"

下面是一个例子的截图
android 如何分析应用的内存(十一)——ASan,android  内存分析,ASan,ASan使用,ASan编译,ASan解析,ASan例子

上面的例子我只放入了arm64-v8a的运行时库。同时其他的so库,为前面文章需要的so库。

注意:使用wrap.sh只能是大于等于 Android 8.1的设备

方法二:使用NDK中的脚本

使用如下的脚本:NDK目录/toolchains/llvm/prebuilt/host平台/lib64/clang/版本/bin/asan_device_setup.
将运行时库,push到设备中,该设备必须能够取得root权限。功能如同wrap.sh中一样。asan_device_setup的内部细节不在赘述,因为这里更加推荐wrap.sh的用法。事实上,asan_device_setup会修改相应的app_process,让它能够方便的加载一些预定义库。

注意:这种方法,并未得到官方的大力支持,因此部分设备可能存在错误

如果想要撤销对应的运行时库,可如下运行:

asan_device_setup --revert

检测是否成功

做如下代码验证:

auto *p1 = new int;
*(p1+4) = 2345678;

可在log中看到如下的错误
android 如何分析应用的内存(十一)——ASan,android  内存分析,ASan,ASan使用,ASan编译,ASan解析,ASan例子

对输出进行解析

选取libtest_malloc.so加号后面的地址,传递给llvm-symbolizer或者addr2line.举例如下:

~/Library/Android/sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-symbolizer -e ./app/build/intermediates/merged_native_libs/debug/out/lib/arm64-v8a/libtest_malloc.so 0x289a0

Java_com_example_test_1malloc_MainActivity_stringFromJNI
/Users/biaowan/AndroidStudioProjects/Test_Malloc.old/app/src/main/cpp/native-lib.cpp:212:13

可以解析问题点在具体的文件和行数。

android 如何分析应用的内存(十一)——ASan,android  内存分析,ASan,ASan使用,ASan编译,ASan解析,ASan例子

ASan的高级用法

  1. 忽略特定函数。
    在一些已知问题,或者耗时特别长的函数上,可以使用属性__attribute__((no_sanitize_address))来添加忽略。如下:
__attribute__((no_sanitize_address))
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_test_1malloc_MainActivity_stringFromJNI(JNIEnv* env,jobject /* this */){}

android 如何分析应用的内存(十一)——ASan,android  内存分析,ASan,ASan使用,ASan编译,ASan解析,ASan例子

  1. 出现错误不中断,而是继续运行
  • 编译时添加-fsanitize-recover=address
  • 在wrap.sh中添加ASAN_OPTIONS=halt_on_error=0

android 如何分析应用的内存(十一)——ASan,android  内存分析,ASan,ASan使用,ASan编译,ASan解析,ASan例子
android 如何分析应用的内存(十一)——ASan,android  内存分析,ASan,ASan使用,ASan编译,ASan解析,ASan例子

  1. 查看ASAN_OPTIONS支持那些选项,添加ASAN_OPTIONS=help=1

可以看见如下选项

android 如何分析应用的内存(十一)——ASan,android  内存分析,ASan,ASan使用,ASan编译,ASan解析,ASan例子
其中可以打开,new和delete不匹配的检测,malloc和demalloc不匹配的检查等

  1. 将错误保存在特定的路径下

添加ASAN_OPTIONS=log_path=/sdcard/asan

会将信息输出到/sdcard/asan.pid文件中

  1. 打开泄漏检测(待定)

ASAN_OPTIONS=detect_leaks=true

注意:实验未通过,没有很好的检查出内存泄漏

  1. 崩溃的时候,生成coredump

ASAN_OPTIONS=disable_coredump=0

注意:如果无法生成coredump,则需要检查,Android是否打开了coredump。因为每个平台的打开coredump 的步骤不同,因此具体平台,请参阅相应文档

  1. ASAN单步

ASan还可以和gdb和lldb联合使用。gdb和lldb的使用,见前面的章节。

如果想要gdb或lldb停留在ASan报告错误之前,可以在如下函数设置断点:

__asan::ReportGenericError

如果想要gdb或lldb停留在ASan报告错误之后,可以在如下函数设置断点:

__sanitizer::Die

如果想要gdb或lldb打印Asan描述的内存信息,可以调用下面的函数

__asan_describe_address(地址)

如下:(gdb例子)

(gdb) set overload-resolution off
(gdb) p __asan_describe_address(0x7ffff73c3f80)
0x7ffff73c3f80 is located 0 bytes inside of 10-byte region [0x7ffff73c3f80,0x7ffff73c3f8a)
freed by thread T0 here: 
...

第一句话是关闭重载函数的解析。第二句话是,调用__asan_describe_address函数,解析0x7ffff73c3f80地址。输出则为对应地址的描述信息

至此,Android的ASan介绍完毕,下一篇会介绍HWASan的使用,因为HWAsan需要编译AOSP,篇幅较长,敬请期待文章来源地址https://www.toymoban.com/news/detail-543870.html

到了这里,关于android 如何分析应用的内存(十一)——ASan的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • android 如何分析应用的内存(十五)——Visual Studio Code 调试Android应用

    在上一篇文章介绍了jdb调试java应用 接下来介绍用UI界面调试java应用,达到同jdb一样的效果。 同样的UI界面有很多选择,如Eclipse,Android Studio,Visual Studio Code.因为Android Studio的诸多不便,结合自身的使用习惯,这里推荐并介绍Visual Studio Code 安装必要的插件 在插件市场中,搜索

    2024年02月14日
    浏览(51)
  • android 如何分析应用的内存(十七)——使用MAT查看Android堆

    前一篇文章,介绍了使用Android profiler中的memory profiler来查看Android的堆情况。 如Android 堆中有哪些对象,这些对象的引用情况是什么样子的。 可是我们依然面临一个比较严峻的挑战:不管是app开发者,还是内存分析者而言,堆中的对象,非常之多,不仅有Android 原生的类,还

    2024年02月13日
    浏览(69)
  • android 如何分析应用的内存(八)——Android 7.0以后的malloc debug

    接上文,介绍六大板块中的第三个————malloc调试和libc回调 上一篇文章中,仅仅是在分配和释放的时候,拦截对应的操作。而不能进一步的去检查内存问题。比如:释放之后再次使用指针,内存泄漏,内存损坏等等。 在这篇文章中,将会介绍malloc调试技术,它可以对nat

    2024年02月10日
    浏览(43)
  • 使用asan检测内存泄漏、堆栈溢出等问题

    操作过程参考:链接 缘起:程序在移动端崩溃,mac端复现不了,于是在写个崩溃位置函数的调用demo,使用ASAN工具进行排查。 验证过程 1、代码 main.cpp 使用附加ASAN工具的方式进行编译: 执行: 没有问题,以上是验证过程,如有问题执行时ASAN会提示有问题的相关位置。 介绍

    2024年02月11日
    浏览(60)
  • 内存检测工具——ASan(AddressSanitizer)的介绍和使用

    ASan全称AddressSanitizer,是一种内存错误检测工具,目的是帮助开发者检测和调试内存相关的问题,如使用未分配的内存、使用已释放的内存、堆内存溢出等。ASan是由Google开发的,广泛用于C、C++等语言的代码中。 ASan的工作原理是在编译时将额外的代码插入到目标程序中,对内

    2024年03月20日
    浏览(40)
  • ASan和HWAsan在Android中使用

    ASan HWASan 全称 Address Sanitizer Hardware-assisted AddressSanitizer 版本 可以在32位和64位的x86、x86-64上。 从API 27(Android O MR 1)开始,Android NDK 可支持ASAN。 在Android 11 之后的AOSP master中,弃用了arm64 上的平台开发ASan,改为使用HWASan。 只在Android 10 及以上版本有效,且只使用于AArch64硬件平台

    2024年02月15日
    浏览(28)
  • 如何使用KoodousFinder搜索和分析Android应用程序中的安全威胁

    KoodousFinder是一款功能强大的Android应用程序安全工具,在该工具的帮助下,广大研究人员可以轻松对目标Android应用程序执行安全研究和分析任务,并寻找出目标应用程序中潜在的安全威胁和安全漏洞。 在使用该工具之前,我们首选需要访问该工具的【开发者门户】创建一个

    2024年02月13日
    浏览(61)
  • Android笔记(二十一):Room组件实现Android应用的持久化处理

    Room是Android JetPack架构组件之一,是一个持久处理的库。Room提供了在SQLite数据库上提供抽象层,使之实现数据访问。 (1)实体类(Entity):映射并封装了数据库对应的数据表中对应的结构化数据。实体定义了数据库中的数据表。实体类中的数据域与表的列一一对应。 (2)数

    2024年01月20日
    浏览(53)
  • Android 内存分析(java/native heap内存、虚拟内存、处理器内存 )

    1.jvm 堆内存(dalvik 堆内存) 不同手机中app进程的 jvm 堆内存是不同的,因厂商在出厂设备时会自定义设置其峰值。比如,在Android Studio 创建模拟器时,会设置 jvm heap 默认384m , 如下图所示: 当app 进程中java 层 new 对象(加起来总和)占用的堆内存达到jvm heap 峰值时,就会抛出OOM 。

    2024年02月14日
    浏览(47)
  • Android Profiler 内存分析器使用

    Android Profiler是Android Studio的一部分,提供了一个集成的性能分析工具套件,包括内存分析。Android Profiler 工具可提供实时数据,帮助您了解应用的 CPU、内存、网络和电池资源使用情况。 在Android Profiler中,您可以查看内存使用情况的实时图表、堆转储快照、分析内存泄漏等,

    2024年02月08日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包