ASan 不同选项下的行为
结论:
- 如果可执行文件没有链接 ASan,但是动态库使用了 ASan,为了保证 ASan 运行时能够第一个被加载,通常需要设置
LD_PRELOAD环境变量 - 只要有 ASan 运行时,就能检测内存泄漏和 Double-Free 等只需要 hook malloc/free 等内存管理函数即可检测的错误;但对于越界访问等,只有在编译时打开 ASan,让编译器插桩才能检测
- 即使没有编译或链接 ASan,也可以用
LD_PRELOAD加载 ASan,不过此时只有 ASan 运行时,没有编译器插桩 - 不要加载多个 ASan 运行时(比如一个静态链接、一个动态链接),也不要混合来自不同编译器的 ASan(比如一个来来自 GCC、一个来自 Clang),否则会遇到
Your application is linked against incompatible ASan runtimes.报错
特定编译器行为:
- GCC 默认动态链接
libasan.so.x,通常在/usr/lib/$arch-linux-gnu目录下,通过gcc -print-file-name=libasan.so命令可以找到;如果想要静态链接,可以传入-static-libasan链接参数;GCC 不支持-shared-libasan链接参数 - Clang 默认静态链接
libclang_rt.asan-$arch.a,通常在/usr/lib/llvm-$ver/lib/clang/$ver/lib/linux目录下,通过clang -print-file-name=libclang_rt.asan-$arch.a命令可以找到;如果想要动态链接,可以传入-shared-libasan链接参数;Clang 也支持-static-libasan链接参数 - Clang 使用
-shared-libasan动态链接 ASan 时,它的运行时库libclang_rt.asan-$arch.so通常不在默认的动态库搜索路径下,需要添加libclang_rt.asan-$arch.so所在路径到LD_LIBRARY_PATH当中;而 GCC 的 ASan 运行时库libasan.so.x通常就在默认的/usr/lib/$arch-linux-gnu动态库搜索路径下,因此通常不需要设置LD_LIBRARY_PATH环境变量