[FAQ08836]如何调试malloc(堆越界)问题
开debug15卡顿的话,如果只关注Native Exception
可以将Java layer所有Exception忽略,但专项测试后,务必记得恢复,否则无法抓取上传异常!
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
13965 public void addErrorToDropBox(String eventType,
...
14076 /// M: @{
14077 if (!(dbox == null || !dbox.isTagEnabled(dropboxTag))) {
14078 dbox.addText(dropboxTag, sb.toString());
14079 }
// 将下面的if全部注释
14080 // if ((exceptionLog != null) && mNotTargetException) {
14081 // exceptionLog.handle(dropboxTag, sb.toString(), sb_pid.toString());
14082 // }
可以将Java layer所有Exception忽略,但专项测试后,务必记得恢复,否则无法抓取上传异常!
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
13965 public void addErrorToDropBox(String eventType,
...
14076 /// M: @{
14077 if (!(dbox == null || !dbox.isTagEnabled(dropboxTag))) {
14078 dbox.addText(dropboxTag, sb.toString());
14079 }
// 将下面的if全部注释
14080 // if ((exceptionLog != null) && mNotTargetException) {
14081 // exceptionLog.handle(dropboxTag, sb.toString(), sb_pid.toString());
14082 // }
FAQs 1 of 17 |
内容[DESCRIPTION]
有一类NE比较特殊,就是堆引起的异常(调用malloc申请的内存后使用不当引起的异常):
1. 申请后多次释放 (double free)
2. 释放后又去使用 (used after free)
3. 使用越界 (比如申请了50节内存,结果在使用时多用了8字节的内存,这样就把后面的内存的内容踩坏,引起堆结构异常)
4. 释放时传给free()的地址不是malloc()申请的地址,比如:p = malloc(10); free(p + 5);
5. 内存泄露:申请内存后,忘记释放或某些代码路径没有释放。此类问题的调试请参考FAQ05872 如何用DDMS分析native memory leak
那如何去识别这类NE呢?
如果从调用栈(main log/aee_exp里的db里的_exp_detail.txt或/data/tombstone下的文件里可能存在)查看到#0~3帧有malloc/free这些函数,那么认为是malloc问题(也就是执行到这些函数时发生了异常):
![]() [SOLUTION]
如何调试此类问题呢?方法是每次调用malloc时记录调用栈并做相关的安全检查(在头尾做特定的标记),调用free时检查标记是否被踩坏,如果是则报错
android本身有集成集中调试机制,代码在bionic/libc/bionic/malloc_debug_common.c/h/cpp,可以通过属性控制:
setprop libc.debug.malloc 0: 这是默认的等级,仅作最基本的判断
setprop libc.debug.malloc 1: 这会在malloc记录调用栈,用于分析内存泄露
setprop libc.debug.malloc 5: 在申请后会填充固定的pattern,用于检查是否越界访问
setprop libc.debug.malloc 10: 增加foot/head头,记录调用栈
setprop persist.libc.debug.malloc 15: MTK增加的调试等级,会记录调用栈,额外存在其他地方以免被踩坏
setprop persist.libc.debug.malloc 16: MTK增加的调试等级,包含debug15,并且还支持对dvm堆调试
setprop libc.debug.malloc 20: 模拟器使用
以后如果遇到此类问题,请按以下配置重新复现即可:
KK及以前版本:(如果是JB2.MP版本请先打上patch:ALPS00448232)(请使用eng或userdebug版本)
开机后用adb输入:
adb shell setprop persist.libc.debug.malloc 15 adb shell setprop persist.debug15.prog xxxx (xxxx为应用程序,比如java程序都是app_process) adb shell setprop persist.debug15.config 0x24002020 (只有JB5及之后才支持,不是这些版本的不用设置这个属性)
adb reboot L及之后版本(eng/userdebug/user版本都可以,但user版本需获取adb shell的root权限,请查看[FAQ06317] 如何永久性开启adb的root权限):
在vendor/mediatek/proprietary/external/aee/config_external/init.aee.customer.rc添加:
on init
export LD_PRELOAD libsigchain.so:libudf.so 重新打包bootimage并下载, 开机后用adb输入: adb shell setprop persist.libc.debug.malloc 15
adb shell setprop persist.libc.debug15.prog xxxx adb shell setprop persist.debug15.config 0x4a003024 adb reboot 其中xxxx为要监控的应用程序,对应于system/bin目录下的可执行文件名,比如java程序都是app_process或者app_process64。需要监控的应用程序一般是DB通过GAT解析开的_exp_main.txt中的Current
Executing Process,也即使用E-consulter工具得到的分析报告中的命令行。
0x4a003024是对记录调用栈的存储内存的设置,包括属性,分配的size等。
注意:对于L版本,还需要额外做如下修改(M版本及之后版本不需要):
将/bionic/libc/bionic/malloc_debug_common.cpp中
#ifdef _MTK_MALLOC_DEBUG_ const MallocDebug* __libc_malloc_dispatch = &__libc_malloc_default_dispatch; #else static const MallocDebug* __libc_malloc_dispatch = &__libc_malloc_default_dispatch; #endif 修改为 const MallocDebug* __libc_malloc_dispatch = &__libc_malloc_default_dispatch; 这时会重启手机,再次开机后就进入malloc/free的调试方式,此时overhead会比较重,可能会有一些不预期的anr(出现ANR时请点击等待),但不影响测试。
测试前,请注意保留out/target/product/$project/symbols目录 问题复现之后,请用GAT(和flashtool一起释放,并且在DCC上有说明文档)的bugreport功能抓取异常信息并打包,提交e-service并提供打包后的文件。
-----------------------------------------------------------------------------------------------------------------------------
如果一定要在KK及以前版本的user版本使用malloc debug功能,请:
1. 获取adb shell的root权限,请查看[FAQ06317] 如何永久性开启adb的root权限
2.
请编译eng版本的libc.so和libc_malloc_debug_mtk.so(放在vendor/mediatek/$proj/artifacts/out/target/product/$proj/system/lib目录下,如果没有请提e-service申请),用adb
push到/system/lib目录下
3. 如果是GB3版本,在编译eng版本的libc.so之前,注释掉bionic/libc/malloc_debug_common.c以下代码再编译:
if (__system_property_get("ro.build.type", env)) {
if (strncmp(env, "eng", 3)) debug_level = 0; } 4. 如果是JB3/GB3以后的版本,请设置
adb shell aee -d coreon
5. 然后在按照eng版本连adb设置persist.libc.debug.malloc/persist.debug15.prog/persist.debug15.config属性,重开机复现即可。
|
联系方式:emhhbmdfbGlhbmcxOTkxQDEyNi5jb20=
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2017-04-10 Android Jni调用浅述