一 簡(jiǎn)述
android 的libc中有malloc_debug的hook調(diào)用,我們可以使用malloc_debug中的hook函數(shù)對(duì)內(nèi)存分配進(jìn)行跟蹤加測(cè)。
malloc_debug主要包含的功能如下:
- 內(nèi)存分配和釋放跟蹤,支持的函數(shù)如下:
malloc
free
calloc
realloc
posix_memalign
memalign
aligned_alloc
malloc_usable_size
2) 支持內(nèi)存邊界,可以在申請(qǐng)的內(nèi)存頭部和尾部添加guard,內(nèi)存越界檢查,use after free,內(nèi)存崩潰檢查等。
3) 調(diào)用棧跟蹤和打印,跟蹤內(nèi)存分配的同時(shí)保存內(nèi)存分配的調(diào)用棧,方便內(nèi)存泄漏檢查。
二 malloc_debug使用
1) 開(kāi)啟malloc_debug
adb shell setprop libc.debug.malloc.program
- 設(shè)置相關(guān)檢測(cè)項(xiàng)
adb shell setprop libc.debug.malloc.options backtrace
3)重啟應(yīng)用程序
三) malloc_debug原理
libc在初始化時(shí)會(huì)調(diào)用MallocInitImpl判斷屬性來(lái)加載debug so,調(diào)用InitMallocFunctions替換掉Libc原生的內(nèi)存分配和釋放函數(shù)。
// Initializes memory allocation framework once per process.
static void MallocInitImpl(libc_globals* globals) {
char prop[PROP_VALUE_MAX];
char* options = prop;
MaybeInitGwpAsanFromLibc(globals);
// Prefer malloc debug since it existed first and is a more complete
// malloc interceptor than the hooks.
bool hook_installed = false;
if (CheckLoadMallocDebug(&options)) {
hook_installed = InstallHooks(globals, options, kDebugPrefix, kDebugSharedLib);
} else if (CheckLoadMallocHooks(&options)) {
hook_installed = InstallHooks(globals, options, kHooksPrefix, kHooksSharedLib);
}
if (!hook_installed) {
if (HeapprofdShouldLoad()) {
HeapprofdInstallHooksAtInit(globals);
}
} else {
// Record the fact that incompatible hooks are active, to skip any later
// heapprofd signal handler invocations.
HeapprofdRememberHookConflict();
}
}
除了內(nèi)存分配和釋放,常見(jiàn)如下:
"initialize",
"finalize",
"get_malloc_leak_info",
"free_malloc_leak_info",
"malloc_backtrace",
"write_malloc_leak_info",
比如在完成注冊(cè)后,調(diào)用FinishInstallHooks,initialize,將finalize注冊(cè)到process退出時(shí)。
四 malloc_debug option選項(xiàng)
1) 內(nèi)存邊界檢查
front_guard[=SIZE_BYTES]Enables a small buffer placed before the allocated data.
rear_guard[=SIZE_BYTES] Enables a small buffer placed after the allocated data.
guard[=SIZE_BYTES] Enables both a front guard and a rear guard on all allocations.
主要原理是在分配內(nèi)存的頭部和尾部添加一段數(shù)據(jù),作為邊界,頭部初始化為0xaa,尾部初始化為0xbb。
2)調(diào)用棧功能
backtrace[=MAX_FRAMES]
backtrace_enable_on_signal[=MAX_FRAMES]
backtrace_dump_on_exit
backtrace_dump_prefix
backtrace_full
設(shè)置保存的調(diào)用棧個(gè)數(shù),在信號(hào)量或者退出時(shí)打印調(diào)用棧
3) malloc內(nèi)存默認(rèn)值
fill_on_alloc[=MAX_FILLED_BYTES] size will be set to 0xeb.
fill_on_free[=MAX_FILLED_BYTES] When an allocation is freed, fill it with 0xef.
fill[=MAX_FILLED_BYTES] This enables both the fill_on_alloc option and the fill_on_free option.
expand_alloc[=EXPAND_BYTES] Add an extra amount to allocate for every allocation.
- 釋放內(nèi)存存檔
free_track[=ALLOCATION_COUNT] 默認(rèn)值是100,最大值是16384
free_track_backtrace_num_frames[=MAX_FRAMES]
5)分配釋放檢測(cè)
leak_track 在進(jìn)程退出時(shí),執(zhí)行finalize函數(shù),打印當(dāng)前分配的內(nèi)存
record_allocs[=TOTAL_ENTRIES] 記錄alloc操作,The default value is 8,000,000 and the maximum value this can be set to is 50,000,000.
record_allocs_file[=FILE_NAME] 設(shè)置record_allocs保存地址
verify_pointers free/malloc_usable_size/realloc 有效檢查
abort_on_error When malloc debug detects an error, abort after sending the error log message.內(nèi)存泄漏檢測(cè)不在此處,只在進(jìn)程退出時(shí)檢測(cè)
6) verbose 開(kāi)啟debug info log,如果要看更多的信息,建議開(kāi)啟此選項(xiàng)
五 常見(jiàn)用法
1) 內(nèi)存泄漏檢測(cè)
在shell命令下執(zhí)行 #setprop libc.debug.malloc.options "backtrace leak_track verbose"
這樣開(kāi)啟后在進(jìn)程退出時(shí)會(huì)打印leak信息,在發(fā)送kill -47時(shí)會(huì)打印當(dāng)前內(nèi)存申請(qǐng)
2) 內(nèi)存崩潰檢查
在shell命令中添加guard #setprop libc.debug.malloc.options "backtrace leak_track verbose guard"
這樣會(huì)檢測(cè)內(nèi)存覆蓋等檢測(cè)
3) verify_pointers 開(kāi)啟可以檢測(cè)use after free和double free等操作