NE 如何调试malloc(堆越界)问题

如何调试malloc(堆越界)问题

有一类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呢?
如果从调用栈aee_exp里的db里的_exp_detail.txt或/data/tombstone下的文件里可能存在)查看到#0~3帧有malloc/free这些函数,那么认为是malloc问题(也就是执行到这些函数时发生了异常)。


1:vendor/mediatek/proprietary/external/aee/config_external/init.aee.customer.rc添加:
on init
export LD_PRELOAD libsigchain.so:libudf.so

libudf.so should be the first preload library 指LD_PRELOAD只能设置为libudf.so ?
指的是libudf.so 应该放在最前面,但如果有libsigchain.so的话,就要放在它后面。
case1:
libudf.so:libdirect-coredump.so
case2:
libsigchain.so:libudf.so:libdirect-coredump.so


重新编译,需要有root权限。

2:download img 到手机
adb shell setprop persist.libc.debug.malloc 15
adb shell setprop persist.libc.debug15.prog system_server
adb shell setprop persist.debug15.config 0x4a003024

或者adb shell setprop persist.libc.debug15.prog "/system/bin/mediaserver"
多个程序adb shell setprop persist.libc.debug15.prog "\"/system/bin/mediaserver  ls\""
/system/bin/mediaserver  ls  同时这两个程序

其中xxxx为要监控的应用程序,对应于/system/bin目录下的可执行文件名,比如java程序都是app_process或app_process64。需要监控的应用程序一般是DB通过GAT解析开的_exp_main.txt中的Current Executing Process,也即使用E-consulter工具得
到的分析报告中的命令行。
0x4a003024是对记录调用栈的存储内存的设置,包括属性,分配的size等。

3:需要将mtk release 的libudf.so  push 到/system/vendor/lib/ 下替换旧的

4:验证debug15开启成功。
echo $LD_PRELOAD | grep libudf.so
libsigchain.so:libudf.so

cat /proc/system_server的PID/maps | grep "malloc debug"
f3540000-f5940000 rw-p 00000000 00:00 0 [anon:malloc debug]

malloc/free的调试方式,此时overhead会比较重,可能会有一些不预期的anr(出现ANR时请点击等待),但不影响测试。

4:

开启mobilelog,和taglog,root后,setprop ro.monkey true,开始monkey测试,复现NE


Android Native进程内存泄露检测

对于Android的native进程, Android源码中的Bionic库提供了一个很棒的API,get_malloc_leak_info用来检测Native代码内存泄露。
设置 libc.debug.mallo 不为0,分配内存是会调用leak_malloc(),与malloc()区别是在在头部会额外分配一块内存来保存内存分配的情况。

get_malloc_leak_info 就可以使用leak_malloc()获取内存分配情况。


MemoryTrackUtil.cpp 有封装get_malloc_leak_info ,可以在可以的函数调用位置增加

dumpMemoryAddresses 调用从而打印出内存分配信息。


运行时使用:

1.如果system.img中不存在libc_malloc_debug_leak.so,那么把它push到/system/lib中并修改权限

2.setprop libc.debug.malloc 1

3.kill需要检测的进程,使这个property设置后生效


dump出来的文件如以下的格式:

 size   262888, dup    1, 0x769a2032, 0x76ed9cce, 0x76ec991a, 0x76f52034, 0x76f62af8,
 size   262144, dup    1, 0x769a2032, 0x76ed9cce, 0x76a824d4, 0x76a5e99a, 0x76bf39c2,
 size   172036, dup    3, 0x769a2032, 0x76ed9cce, 0x764378c6, 0x7643791e, 0x76414912,
 size   172036, dup    3, 0x769a2032, 0x76ed9cce, 0x764378c6, 0x7643791e, 0x76414912,

size代表malloc的内存大小。

dup值代表同一个地方分配的内存次数。对比dump出的不同时间段的文件,如果发现某一条malloc信息的dup越来越大,那么可以怀疑这个地方存在内存泄露。

最后一串字符串表示的是调用的堆栈。这个堆栈需要去减掉栈区间的起始位置,然后才能使用addr2line去查找这个调用堆栈。

举个例子:

size   262888, dup    1, 0x765a2032,
------------------------------------------
765b1000-76688000 r-xp 00000000 b3:05 875        /system/lib/libc.so

那么实际去使用addr2line的stack值应该是 0x765a2032 - 765b1000

在MediaServer中调用这个API就很容易了

Android天然的已经在mediaserver中支持了这个功能。在MediaPlayerService.cpp中已经加入了dumpMemory 这个API。 并且以dumpsys的接口提供给用户使用,所以在对mediaserver相关进程进行dubug的时候只需要如下几步即可:

setprop libc.debug.malloc 1
busybox killall -HUP mediaserver
dumpsys media.player -m

当然,如果需要dump不同时间段的信息,那么只需要写一个shell脚本就可以了。


Android中native进程内存泄露的调试技巧 






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值