【问题标题】:How do I get line numbers in the debug output with clang's -fsanitize=address?如何使用 clang 的 -fsanitize=address 在调试输出中获取行号?
【发布时间】:2014-07-04 03:46:57
【问题描述】:

我正在尝试用asan 调试clang 检测到的内存错误,但valgrind 错过了。但是我无法获得我的clang 构建的二进制文件来给我任何有用的调试信息。我可以用一个简短的测试程序来证明这一点:

#include <stdlib.h>
#include <string.h>

int main(void)
{
    char *a = malloc(8);
    memset(a, 0, 9);
    free(a);
    return 0;
}

(很明显这个错误valgrind捡起来,纯粹是为了说明clang的问题。)

我用 Clang 3.4-1ubuntu1 像这样编译它:

clang -fsanitize=address -fno-sanitize-recover -o test -O0 -g test.c

果然,./test 中止,我看到一些调试信息:

==3309==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000eff8 at pc 0x43e950 bp 0x7fff168724f0 sp 0x7fff168724e8
WRITE of size 9 at 0x60200000eff8 thread T0
    #0 0x43e94f (/home/jason/Code/astest/test+0x43e94f)
    #1 0x7faa43c47de4 (/lib/x86_64-linux-gnu/libc.so.6+0x21de4)
    #2 0x43e6ac (/home/jason/Code/astest/test+0x43e6ac)
0x60200000eff8 is located 0 bytes to the right of 8-byte region [0x60200000eff0,0x60200000eff8)
allocated by thread T0 here:
    #0 0x42cc25 (/home/jason/Code/astest/test+0x42cc25)
    #1 0x43e874 (/home/jason/Code/astest/test+0x43e874)
    #2 0x7faa43c47de4 (/lib/x86_64-linux-gnu/libc.so.6+0x21de4)

但我真正想知道的是发生错误的行号,以及分配内存的位置。

如何从clang+asan 获取此信息?

【问题讨论】:

  • This page我的帮助。
  • @ShafikYaghmour 该页面让我找到了使用ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer-3.4 ./test 的解决方案,这比为堆栈跟踪中的每个条目手动运行addr2line 要好得多。你想把它作为答案发布,还是留给我?
  • 我本来打算把它作为答案发布但我没有时间测试它,让我现在发布它。

标签: c clang address-sanitizer


【解决方案1】:

如果我们查看 clang AddressSanitizer documentation 它会说:

要使 AddressSanitizer 符号化其输出,您需要设置 ASAN_SYMBOLIZER_PATH 环境变量指向 llvm-symbolizer 二进制文件(或确保 llvm-symbolizer 在您的 $PATH):

并显示以下示例:

ASAN_SYMBOLIZER_PATH=/usr/local/bin/llvm-symbolizer ./a.out

正如 OP 所述,安装位置可能会有所不同,但一旦您知道 llvm-symbolizer 的位置,步骤是相同的​​。

【讨论】:

  • 请注意,对于最近的 Ubuntu 用户,这可能是 /usr/bin/llvm-symbolizer-3.4(或类似,取决于版本);或者您可以将/usr/lib/llvm-3.4/bin 添加到您的路径中,而不是设置环境变量。
  • 我在 /usr/local/bin 或 /usr/bin 中找不到 llvm-symbolizer。我正在使用 ubuntu 12.04
  • @Durgesh - 您可能必须从 PPA 或手动从源代码安装 LLVM clang,尽管我不能为您推荐 PPA - 不幸的是,我曾经使用的那个已被删除 :/
  • @Durgesh - 哦,你看过/usr/lib/llvm-x.y/bin吗? (...x.y 是您的 LLVM 版本)
  • 我已经按照github.com/pacs-course/pacs/wiki/… 中给出的步骤手动安装了llvm3.1。之后,我检查了 /usr/lib/llvm-3.1/bin 的 llvm-symbolizer。它不在那个目录中。我需要安装另一个版本的 LLVM 吗?
【解决方案2】:

addr2line 是你要找的吗?

 $ addr2line -e ./test 0x43e94f
 some/file.c:1234

【讨论】:

    【解决方案3】:

    有时使用带有版本号的符号会报错:

    ERROR: External symbolizer path is set to '/usr/bin/llvm-symbolizer-5.0' which isn't a known symbolizer. Please set the path to the llvm-symbolizer binary or other known tool.
    

    这可以通过指向一个朴素的llvm-symbolizer 二进制文件来解决:

    export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-5.0/bin/llvm-symbolizer
    

    然后像往常一样运行您的可执行文件。

    【讨论】:

      【解决方案4】:

      有时一切(符号器的路径、环境变量等)都是正确的,但您仍然不会得到file:line 格式的输出。

      所以跑

      dsymutil path/to/your.app/Contents/MacOS/binary
      

      然后运行应用程序,您将获得格式良好的输出。文档中也提到了这一点。

      请注意,在 macOS 上,您可能需要在二进制文件上运行 dsymutil 才能在 AddressSanitizer 报告中获得 file:line 信息。

      http://clang.llvm.org/docs/AddressSanitizer.html#symbolizing-the-reports

      【讨论】:

        【解决方案5】:

        对我来说,/usr/bin 中没有 llvm-symbolizer,我需要先使用

        sudo ln -s /usr/bin/llvm-symbolizer-3.8 /usr/bin/llvm-symbolizer
        

        创建符号器,然后将其添加到 PATH:

        ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer ./test
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-06-23
          • 2020-01-26
          • 1970-01-01
          • 2018-12-06
          • 2017-06-24
          • 1970-01-01
          • 1970-01-01
          • 2015-11-16
          相关资源
          最近更新 更多