ASAN使用教程
1. 需要在单板上配置的环境变量
export ASAN_OPTIONS=halt_on_error=0:log_path=/home/asan/log:detect_leaks=1
export UBSAN_OPTIONS=halt_on_error=0:log_path=/home/asan/log:detect_leaks=1
export LSAN_OPTIONS=exitcode=0:use_unaligned=1:leak_check_at_exit=1:verbosity=1:log_threads=1
export PATH=$PATH:/home/asan
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/asan2. 修改编译选项
增加如下选项:
-fsanitize=address -fsanitize=leak -fsanitize=undefined -fsanitize-recover=address,all -fno-var-tracking -fno-omit-frame-pointer -fno-stack-protector -static-libasan3. 导入ASAN库文件
路径:/opt/hcc_arm64le/aarch64-linux-gnu/lib64/
需要两个文件:libubsan.so.0.0.0和libasan.so.4.0.0
修改名称为libubsan.so.0和libasan.so.4,放到单板/home/asan目录下。
4. 修改App注册信号处理函数
因为ASAN内存泄漏只在进程结束时检查,所以常驻进程需要增加退出接口。
int __lsan_do_leak_check();
LOCAL void redfish_exit_for_asan(int sig)
{
debug_log(DLOG_ERROR, "start appname exit for asan!");
__lsan_do_leak_check();
vos_task_delay(5000UL);
exit(0);
debug_log(DLOG_ERROR, "end appname exit for asan!");
}在init函数中增加注册:signal(44, redfish_exit_for_asan);
5. 编译App
需要使用带符号表的App进行检测。
6. 确认App执行权限
内存泄漏检测会用到ptrace连接到线程进行内存泄漏检测。
ptrace当前rtos权限限制,只有root用户有权限使用。所以要去掉App降权限操作。
7. 导入App到单板,使用root用户执行
复现问题,使用如下命令启动App:
LD_PRELOAD=/home/asan/libasan.so.4:/home/asan/libubsan.so.0:$LD_LIBRARY_PATH ./kvm_vmm &8. 触发内存泄漏检测
执行:kill -s 44 pid 触发内存泄漏检测。
9. 查看日志
在/home/asan/目录下查看日志,查看log.pid文件。
其他编译选项说明:
如下两个参数同时使用,会一个输出到log日志,一个输出到当前窗口:
-fsanitize=address
-fsanitize=undefined如下选项链接静态库使用:
-static-libasan其他说明
规避SEGV错误
增加环境变量:handle_segv=0
export ASAN_OPTIONS=halt_on_error=0:use_sigaltstack=0:fast_unwind_on_fatal=1:fast_unwind_on_check=1:fast_unwind_on_malloc=1:malloc_context_size=15:dump_instruction_bytes=1:quarantine_size=4194304:log_path=/mbsc/maintain_log/asan.log:allow_user_segv_handler=1:intercept_tls_get_addr=0:detect_leaks=0:suppressions=$SUPP_FILE:print_suppressions=0:alloc_dealloc_mismatch=0:use_unaligned=1:new_delete_type_mismatch=0ASAN_OPTIONS参数说明:
- ASAN_OPTIONS是Address-Sanitizer的运行选项环境变量
- log_path是执行检查报告的输出路径
- alloc_dealloc_mismatch:申请内存与释放内存不匹配,=0表示关闭
- new_delete_type_mismatch:new与delete申请释放类型不匹配,例如new[]的内存用delete释放,=0表示关闭
export LSAN_OPTIONS=exitcode=0:use_unaligned=1LSAN_OPTIONS参数说明:
LSAN_OPTIONS是LeakSanitizer运行选项的环境变量,而LeakSanitizer是ASAN的内存泄漏检测模块。
App实践示例
需要的编译选项
-fsanitize=address -fsanitize-recover=address,all -fno-var-tracking -fno-omit-frame-pointer -fno-stack-protector -O0注意: -fsanitize-recover这个选项必须加上,否则检测到一个错误就直接退出。
环境变量
export ASAN_OPTIONS=halt_on_error=false:detect_leaks=1也可以指定日志路径:
export ASAN_OPTIONS=halt_on_error=false:detect_leaks=1:log_path=/home/asan说明: halt_on_error是配合-fsanitize-recover一起起作用的,保证检测到错误后继续运行。
执行方式
在编译完成后,如果使用CLion执行会直接报错退出,需要用命令行执行,才能正确显示ASAN信息。
检测classtree中的内存泄漏示例
进行了10次加载与释放,每次泄漏了121个objects,242bytes的内存。最后定位到是hashtable没有释放内存。
提示: g_hash_table_new_full如果使用int作为key,有两种写法:
- 一种是
g_direct_hash+GINT_TO_POINTER(这种不需要释放内存) - 一种是
g_int_hash(需要释放)
使用ASAN库
使用的时候,需要指定ASAN的lib库:
LD_PRELOAD=/usr/lib/gcc/x86_64-linux-gnu/9/libasan.so ./security_policy所有环境变量
ASAN_OPTIONS=halt_on_error=false:detect_leaks=1;LD_PRELOAD=/usr/lib/gcc/x86_64-linux-gnu/9/libasan.so