微信号:code_gg_home

介绍:分享技术干货,分享最新新闻动态,分享开心段子,让大家轻松愉快的成长.

android native内存检测方案(二)

2017-09-13 10:00 陆晓明

android native 代码内存泄露 定位方案(一)

什么是 AddressSanitizer


clang 是一个 C、C++、Objective-C 编程语言的编译器前端。它采用
了底层虚拟机作为其后端。它的目标是提供一个 GNU 编译器套装
(GCC)的替代品, 作者是克里斯·拉特纳,在苹果公司的赞助下进
行开发。
AddressSanitizer 是 clang 中的一个内存错误检测器,它可以检测到
以下问题:
Out-of-bounds accesses to heap, stack and globals
Use-after-free
Use-after-return (to some extent)
Double-free, invalid free
Memory leaks (experimental)

使 用 clang 编 译 代 码 时 用 -fsanitize=address 就 能 打 开
AddressSanitizer 工具,为了在检测到内存错误时打印出您的程序调
用栈,需要在编译时加上选项 -fno-omit-frame-pointer 选项,同时为
了得出更清晰的调用栈信息,请用-O1 选项编译程序。

sanitizer 例子


我们编写一个 android.mk 文件,内容为:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
#优化,加入 AddressSanitizer 功能
LOCAL_CFLAGS := -std=c11 -Wall -Werror -O0 -fsanitize=address
-fno-omit-frame-pointer

LOCAL_SRC_FILES:= sanitizer-status.c
LOCAL_MODULE:= sanitizer-status
LOCAL_MODULE_TAGS := debug
#这三行是后面的 UndefinedBehaviorSanitizer
要加的参数
LOCAL_CLANG := true
LOCAL_SANITIZE := alignment bounds null unreachable integer
LOCAL_SANITIZE_DIAG := alignment bounds null unreachable
integer
#加入需要的库
LOCAL_SHARED_LIBRARIES += libclang_rt.asan-arm-android
include $(BUILD_EXECUTABLE)

其中更多的参数为:

-fsanitize=address: AddressSanitizer, a memory error
detector.

-fsanitize=thread: ThreadSanitizer, a data race detector.
-fsanitize=memory:MemorySanitizer,a detector of uninitialized reads. Requires instrumentation of all program code.

-fsanitize=undefined: UndefinedBehaviorSanitizer, a fast
and compatible undefined behavior checker.

-fsanitize=dataflow: DataFlowSanitizer, a general data flow
analysis.

-fsanitize=cfi: control flow integrity checks. Requires -flto.
-fsanitize=safe-stack:safe stack protection against stack-based memory corruption errors.

更加完整的,参考:
http://clang.llvm.org/docs/UsersManual.html
官方文档.

添加c代码


sanitizer-status.c 内容为:
#include <stdlib.h>
int main() {
char *x = (char*)malloc(10 * sizeof(char*));
free(x);
return x[5];
}
这里使用了已经释放的内存.
mm 编译出来 bin 文件,我们来继续操作.
官方的完整代码如下:
https://github.com/google/sanitizers


检测效果


我们将 libclang_rt.asan-arm-android.so

放入手机里面
adb  push 'prebuilts/clang/host/linux-x86/clang-2690385/lib64/
clang/3.8/lib/linux/libclang_rt.asan-arm-android.so' /system/lib
将此 bin 放入手机
adb push /system/bin/sanitizer-status /system/bin/
运行此 sanitizer-status,出现最终效果,检测出来当前有使
用了释放的内存.

完整的检测出来内存泄漏,可以去细看此图。打印出来堆栈,以及内存图。

介绍


/docs/source.android.com/src/devices/tech/debug 里 面 , 有
个 asan.jd 我们使用网页打开
主要介绍了检测都可以完成哪些目标
 Building executables with AddressSanitizer
 Building shared libraries with AddressSanitizer
 Symbolization(测试没效果,没有找到 bin 文件)
 AddressSanitizer in the apps
 SANITIZE_TARGET
更多内容,我们直接去文档阅读即可.


UndefinedBehaviorSanitizer


UndefinedBehaviorSanitizer
说白了也是 clang 的一种检测方式,检测代码中未初始化,
未赋值等等一系列的错误使用.
#这三行是后面的 UndefinedBehaviorSanitizer
要加的参数
LOCAL_CLANG := true
LOCAL_SANITIZE := alignment bounds null unreachable integer
LOCAL_SANITIZE_DIAG := alignment bounds null unreachable
integer

在需要的地方,加入上面的几行,则可以使用此检测方案.

Kernel Address Sanitizer

参考文档 https://www.ibm.com/developerworks/cn/linux/1608_tengr_kasan/index.html

可以发现,
我们当前的 kernel 是没有 ksan 功能的,我们的 mtk mtk6757-n-v1.0 这条线有,
(因为 kernel 版本为 4.4)于是在此版本上可以开启
编译方式,添加 kconfig
CONFIG_KASAN
CONFIG_KASAN_INLINE
CONFIG_TEST_KASAN
CONFIG_KCOV
CONFIG_SLUB
CONFIG_SLUB_DEBUG
CONFIG_CC_OPTIMIZE_FOR_SIZE
移除一些
CONFIG_SLUB_DEBUG_ON
CONFIG_SLUB_DEBUG_PANIC_ON
CONFIG_KASAN_OUTLINE
CONFIG_KERNEL_LZ4
然后编译系统
启动时候,出现 log
[[0.000000] c0 0 Virtual kernel memory layout:0.000000] c0 0
kasan
: 0xffffff8000000000 -
技术说明
0xffffff9000000000
(64 GB)
说明 kasan 加入成功
然后,如果 kernel 里面有错误出现,则会有如下信息:
[18.539668] c3 1
==================================================================
[ 18.547662] c3 1 BUG: KASAN: null-ptr-deref on address 0000000000000008
[ 18.554689] c3 1 Read of size 8 by task swapper/0/1
[ 18.559988] c3 1 CPU: 3 PID: 1 Comm: swapper/0 Tainted: GW
#1
[ 18.569275] c3 1 Hardware name: Android Device
[ 18.577433] c3 1 Call trace:
[ 18.580739] c3 1 [<ffffffc00008b32c>] dump_backtrace+0x0/0x2c4
指示错误类型,以及栈信息 3.18.24-xxx

编译整个系统


使用 make USE_CLANG_PLATFORM_BUILD:=true SANITIZE_TARGET=address -j42
来编译系统,调整下 userdata 数据区域大小,然后刷机,此
时整个系统是处在可以检测的状态,所有应用的内存问题,
都会在运行时报出来.




 
代码GG之家 更多文章 80后的我,记忆里和吃有关的那些事 ANR 原理与实战技巧 大荔冬枣,你值得拥有 Android 启动过程框架 深入Android源码系列(二) HOOK技术大作战
猜您喜欢 必看|10个帮程序员减压放松的网站! 2017SANS网络威胁情报峰会 微服务和元数据驱动下的架构平滑演进 “机器人之父”——约瑟夫·恩格尔伯格 Go语言并发模型:像Unix Pipe那样使用channel