关于调试:通过AddressSanitizer输出获取行号?

Get line numbers with AddressSanitizer output?

我正在尝试让AddressSanitizer在其堆栈跟踪中生成行号。我已经在Mac和Fedora 19系统上进行了尝试,并得到了相似的结果。

这是一个简单的程序:

1
2
3
4
5
6
7
8
9
10
11
12
#include <cstdio>
#include <cstdlib>

int main(int argc,char **argv)
{
    char *buf = (char *)malloc(5);
    free(buf);
    puts("get ready");
    buf[4] = '3';
    puts("done");
    return(0);
}

我编译它:

1
$  g++ -g -o x -fsanitize=address x.cpp

然后运行它(llvm-symbolizer在我的路径中):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
$ ASAN_SYMBOLIZER_PATH=`which llvm-symbolizer` ASAN_OPTIONS=symbolize=1 ./x
get ready
=================================================================
==9309== ERROR: AddressSanitizer: heap-use-after-free on address 0x60040000dff4 at pc 0x40091f bp 0x7fff1b721140 sp 0x7fff1b721138
WRITE of size 1 at 0x60040000dff4 thread T0
    #0 0x40091e in main (/raid/nfs_home/xv32/asan/x+0x40091e)
    #1 0x3304021b44 in __libc_start_main (/lib64/libc.so.6+0x3304021b44)
    #2 0x4007e8 (/raid/nfs_home/xv32/asan/x+0x4007e8)
0x60040000dff4 is located 4 bytes inside of 5-byte region [0x60040000dff0,0x60040000dff5)
freed by thread T0 here:
    #0 0x7fe4ae58636a (/lib64/libasan.so.0+0x1536a)
    #1 0x4008d8 in main (/raid/nfs_home/xv32/asan/x+0x4008d8)
    #2 0x3304021b44 in __libc_start_main (/lib64/libc.so.6+0x3304021b44)
previously allocated by thread T0 here:
    #0 0x7fe4ae58644a (/lib64/libasan.so.0+0x1544a)
    #1 0x4008c8 in main (/raid/nfs_home/xv32/asan/x+0x4008c8)
    #2 0x3304021b44 in __libc_start_main (/lib64/libc.so.6+0x3304021b44)
SUMMARY: AddressSanitizer: heap-use-after-free ??:0 main
Shadow bytes around the buggy address:
  0x0c00ffff9ba0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c00ffff9bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c00ffff9bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c00ffff9bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c00ffff9be0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c00ffff9bf0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa[fd]fa
  0x0c00ffff9c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c00ffff9c10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c00ffff9c20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c00ffff9c30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c00ffff9c40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:     fa
  Heap righ redzone:     fb
  Freed Heap region:     fd
  Stack left redzone:    f1
  Stack mid redzone:     f2
  Stack right redzone:   f3
  Stack partial redzone: f4
  Stack after return:    f5
  Stack use after scope: f8
  Global redzone:        f9
  Global init order:     f6
  Poisoned by user:      f7
  ASan internal:         fe
==9309== ABORTING
[r4 ~/asan 19:34:50]$

如您所见,我有符号但没有行号。如何获得行号?

在回答问题时,这是objdump -h x

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
$ objdump -h x

x:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .interp       0000001c  0000000000400238  0000000000400238  00000238  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .note.ABI-tag 00000020  0000000000400254  0000000000400254  00000254  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .note.gnu.build-id 00000024  0000000000400274  0000000000400274  00000274  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .gnu.hash     0000003c  0000000000400298  0000000000400298  00000298  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .dynsym       000001b0  00000000004002d8  00000000004002d8  000002d8  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .dynstr       00000141  0000000000400488  0000000000400488  00000488  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .gnu.version  00000024  00000000004005ca  00000000004005ca  000005ca  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .gnu.version_r 00000020  00000000004005f0  00000000004005f0  000005f0  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .rela.dyn     00000018  0000000000400610  0000000000400610  00000610  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .rela.plt     000000d8  0000000000400628  0000000000400628  00000628  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 10 .init         0000001a  0000000000400700  0000000000400700  00000700  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 11 .plt          000000a0  0000000000400720  0000000000400720  00000720  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .text         00000224  00000000004007c0  00000000004007c0  000007c0  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 13 .fini         00000009  00000000004009e4  00000000004009e4  000009e4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 14 .rodata       000000bc  0000000000400a00  0000000000400a00  00000a00  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 15 .eh_frame_hdr 00000044  0000000000400abc  0000000000400abc  00000abc  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 16 .eh_frame     00000134  0000000000400b00  0000000000400b00  00000b00  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 17 .preinit_array 00000008  0000000000600d98  0000000000600d98  00000d98  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 18 .init_array   00000010  0000000000600da0  0000000000600da0  00000da0  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 19 .fini_array   00000010  0000000000600db0  0000000000600db0  00000db0  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 20 .jcr          00000008  0000000000600dc0  0000000000600dc0  00000dc0  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 21 .dynamic      00000230  0000000000600dc8  0000000000600dc8  00000dc8  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 22 .got          00000008  0000000000600ff8  0000000000600ff8  00000ff8  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 23 .got.plt      00000060  0000000000601000  0000000000601000  00001000  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 24 .data         00000070  0000000000601060  0000000000601060  00001060  2**5
                  CONTENTS, ALLOC, LOAD, DATA
 25 .bss          00000008  00000000006010d0  00000000006010d0  000010d0  2**2
                  ALLOC
 26 .comment      00000058  0000000000000000  0000000000000000  000010d0  2**0
                  CONTENTS, READONLY
 27 .debug_aranges 00000050  0000000000000000  0000000000000000  00001128  2**0
                  CONTENTS, READONLY, DEBUGGING
 28 .debug_info   00001041  0000000000000000  0000000000000000  00001178  2**0
                  CONTENTS, READONLY, DEBUGGING
 29 .debug_abbrev 0000038e  0000000000000000  0000000000000000  000021b9  2**0
                  CONTENTS, READONLY, DEBUGGING
 30 .debug_line   00000239  0000000000000000  0000000000000000  00002547  2**0
                  CONTENTS, READONLY, DEBUGGING
 31 .debug_str    00000a9a  0000000000000000  0000000000000000  00002780  2**0
                  CONTENTS, READONLY, DEBUGGING
$


答案发布在如何使用clangs -fsanitize = address获取调试输出中的行号?

您需要使用llvm-symbolizeraddr2line


与Clang相比,GCC的一个优势是它具有基于libbacktrace的良好内置符号。因此,只需摆脱ASAN_SYMBOLIZER_PATHASAN_OPTIONS并享受用户友好的输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ g++ -g -fsanitize=address tmp.c && ./a.out
get ready
=================================================================
==30328==ERROR: AddressSanitizer: heap-use-after-free on address 0x60200000eff4 at pc 0x000000400985 bp 0x7fffeafad920 sp 0x7fffeafad918
WRITE of size 1 at 0x60200000eff4 thread T0
    #0 0x400984 in main /home/iuriig/tmp.c:9
    #1 0x7f1f99850f44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)
    #2 0x400848  (/home/iuriig/a.out+0x400848)

0x60200000eff4 is located 4 bytes inside of 5-byte region [0x60200000eff0,0x60200000eff5)
freed by thread T0 here:
    #0 0x7f1f9a5548a0 in __interceptor_free /home/iuriig/src/gcc-6.2.0/libsanitizer/asan/asan_malloc_linux.cc:45
    #1 0x40093e in main /home/iuriig/tmp.c:7
    #2 0x7f1f99850f44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)

(以上内容在带有GCC 6.2.0的Ubuntu 16上复制)。