高通Camx框架拥有庞大的代码并且各个厂商都有定制开发专有的功能,一旦遇到内存问题面对庞大的代码排查比较麻烦。本身Linux就提供了地址消毒剂的功能,可以利用其来有效定位潜在的隐患内存问题或者遇到的内存引发的崩溃,是有个利器。
一、如何开启camx地址消毒剂
这里需要配置bitbak中的poky/meta-qti-camera-prop/recipes/camx/*.bb配置,具体如下:
            
            
              makefile
              
              
            
          
          # 在 camx_1.0.bb 中添加
TARGET_CFLAGS += "-fsanitize=address -fno-omit-frame-pointer"
TARGET_CXXFLAGS:append = " -fsanitize=address -fno-omit-frame-pointer"
TARGET_LDFLAGS += "-static-libsan"
# 排除不需要 ASan 的库
ASAN_EXCLUDE_LIBS = "libmmcamera libqtiutil"
INSANE_SKIP_${PN} += "ldflags"- -fsanitize=address:启用AddressSanitizer。
- -fno-omit-frame-pointer:确保生成帧指针,以便获得完整的堆栈跟踪信息。
- -static-libsan:静态链接ASan运行时库。这是关键点,因为在嵌入式设备上可能没有动态的ASan库。
⚠️这里使用
-static-libsan而不是-static-libasan
二、如何配置指定程序能检测内存问题
这里需要添加指定程序的启动脚本,或者添加环境变量来启动需要指定的程序,具体如下:
            
            
              bash
              
              
            
          
          #!/bin/bash
export ASAN_SYMBOLIZER_PATH=$(which llvm-symbolizer)
export ASAN_OPTIONS="symbolize=1:print_stacktrace=1:halt_on_error=0:abort_on_error=0"
/sbin/main [args]三、如何让地址消毒剂能符号化
- 
这里需要代码编译支持地址消毒剂外,还需要开启编译调试模式,这里具体修改 poky/meta-qti-camera-prop/recipes/camx/*.bb配置,具体修改如下:iniINSANE_SKIP:${PN}-dbg = "arch" INSANE_SKIP:${PN} = "already-stripped" INHIBIT_PACKAGE_STRIP = "1" #添加这一行 INHIBIT_SYSROOT_STRIP = "1"
- 
使用符号化工具 llvm-symbolizer来自动解析代码的符号以及行号等信息,具体工具以及依赖库- llvm-symbolizer工具至- /usr/bin
- 依赖库libtinfo.so.6放至/usr/lib
 
- 
替换硬件平台系统的camx相关的动态库为包含调试信息的动态库 
四、地址消毒剂错误类型及示例
1. 堆缓冲区溢出 (Heap-buffer-overflow)
            
            
              c
              
              
            
          
          // 示例代码
int *arr = malloc(10 * sizeof(int));
arr[10] = 42; // 越界访问ASan 报告:
            
            
              arduino
              
              
            
          
          ==10988==ERROR: AddressSanitizer: heap-buffer-overflow
WRITE of size 4 at 0x60200000eff4 thread T0
    #0 0x4012d6 in main program.c:52. 栈缓冲区溢出 (Stack-buffer-overflow)
            
            
              arduino
              
              
            
          
          void func() {
    char buffer[10];
    strcpy(buffer, "This string is too long!");
}ASan 报告:
            
            
              arduino
              
              
            
          
          ==10989==ERROR: AddressSanitizer: stack-buffer-overflow
WRITE of size 25 at 0x7ffc7e3a0df0 thread T0
    #0 0x4013a2 in func program.c:33. 使用后释放 (Use-after-free)
            
            
              ini
              
              
            
          
          int *ptr = malloc(sizeof(int));
free(ptr);
*ptr = 42; // 危险操作ASan 报告:
            
            
              ini
              
              
            
          
          ==10990==ERROR: AddressSanitizer: heap-use-after-free
WRITE of size 4 at 0x60200000eff0 thread T0
    #0 0x4012f6 in main program.c:64. 内存泄漏 (Memory leak)
            
            
              scss
              
              
            
          
          void leak_memory() {
    malloc(100); // 未释放
}ASan 报告:
            
            
              csharp
              
              
            
          
          ==10991==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 100 byte(s) in 1 object(s) allocated from:
    #0 0x7f0a5b in malloc
    #1 0x40125f in leak_memory program.c:2五、地址消毒剂高级使用技巧
1. 忽略特定错误
            
            
              scss
              
              
            
          
          // 使用 __attribute__((no_sanitize("address")))
void __attribute__((no_sanitize("address"))) ignore_this_function() {
    // 该函数内的内存错误将被忽略
}
// 或在代码中临时禁用
void sensitive_operation() {
    __asan_disable();
    // 不受 ASan 监控的操作
    __asan_enable();
}2. 自定义报告处理
            
            
              c
              
              
            
          
          // 自定义错误回调函数
void __asan_on_error() {
    fprintf(stderr, "Custom ASan error handler!\n");
    // 保存额外调试信息
}3. 与调试器配合使用
            
            
              bash
              
              
            
          
          # GDB 调试 ASan 程序
gdb --args ./program args...
# 常用 GDB 命令
(gdb) break __asan_report_error  # 在 ASan 报错时中断
(gdb) p __asan_describe_address(0x60200000eff4)  # 查看地址信息