kubo39's blog

ただの雑記です。

LDCのsanitizeオプション

LDCはバックエンドがLLVMであるので、sanitizerの機能が一部使える。 一応 address, fuzzer, memory, thread とあるけれど、手元のLDC 1.4.0でまともに使うことができたのはThreadSanitizerのみであった。

AddressSanitizer

asan/outofbounds.d

void main()
{
    auto arr = [0, 1, 2, 3];
    auto y = arr.ptr + 4;
}

これLeakSanitizerでひっかかってるけど、どうなんだ。

(ldc-1.4.0)$ ( cd asan && ldc2 -fsanitize=address -boundscheck=off outofbounds.d && ./outofbounds )

=================================================================
==7758==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 72 byte(s) in 1 object(s) allocated from:
    #0 0x55ecd0e3f5b0  (/home/kubo39/dev/dlang/ldc-san/asan/outofbounds+0xb75b0)
    #1 0x55ecd0e87ddc  (/home/kubo39/dev/dlang/ldc-san/asan/outofbounds+0xffddc)

Direct leak of 16 byte(s) in 1 object(s) allocated from:
    #0 0x55ecd0e3f3b8  (/home/kubo39/dev/dlang/ldc-san/asan/outofbounds+0xb73b8)
    #1 0x55ecd0e8876a  (/home/kubo39/dev/dlang/ldc-san/asan/outofbounds+0x10076a)
    #2 0x55ecd0d9b5e4  (/home/kubo39/dev/dlang/ldc-san/asan/outofbounds+0x135e4)

SUMMARY: AddressSanitizer: 88 byte(s) leaked in 2 allocation(s).

どうやらGCが入るとそもそもLeakSanitizerでひっかかるのでだめらしい。

void main()
{
}
(ldc-1.4.0)$ ( cd asan && ldc2 -fsanitize=address emptymain.d && ./emptymain )

=================================================================
==19717==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 72 byte(s) in 1 object(s) allocated from:
    #0 0x55934f6ffd90  (/home/kubo39/dev/dlang/ldc-san/asan/emptymain+0xb2d90)
    #1 0x55934f74cafc  (/home/kubo39/dev/dlang/ldc-san/asan/emptymain+0xffafc)

Direct leak of 16 byte(s) in 1 object(s) allocated from:
    #0 0x55934f6ffb98  (/home/kubo39/dev/dlang/ldc-san/asan/emptymain+0xb2b98)
    #1 0x55934f74d48a  (/home/kubo39/dev/dlang/ldc-san/asan/emptymain+0x10048a)
    #2 0x55934f660304  (/home/kubo39/dev/dlang/ldc-san/asan/emptymain+0x13304)

SUMMARY: AddressSanitizer: 88 byte(s) leaked in 2 allocation(s).

それでは、とGCを外してみるとAddressSantizerはちゃんと動いていないように見受けられる。

extern(C) void main()
{
    int[4] arr = [0, 1, 2, 3];
    auto y = arr.ptr + 10;
}
(ldc-1.4.0)$ ( cd asan && ldc2 -fsanitize=address outofbounds2.d && ./outofbounds2 )
(ldc-1.4.0)$

結論からいうと、-fsanitize=address はLeakSanitizerを有効にし、GCを起動するようなプログラムの場合は必ずリーク検出が発生してしまうようだ。

ちなみに -sanitize=memory の結果は以下のようになった。

(ldc-1.4.0)$ ( cd asan && ldc2 -fsanitize=memory emptymain.d && ./emptymain )
gcc: error: unrecognized argument to -fsanitize= option: ‘memory’
Error: /usr/bin/gcc failed with status: 1

ThreadSanitizer

tsan/datarace.d

import core.thread;

__gshared static int ANSWER = 32;

void f()
{
    ANSWER = 42;
}

void main()
{
    auto t = new Thread(&f).start();
    ANSWER = 24;
    t.join();
}

表示は質素だけど、競合条件を判定できている。

(ldc-1.4.0)$ ( cd tsan && ldc2 -fsanitize=thread datarace.d && ./datarace )
FATAL: ThreadSanitizer: unexpected memory mapping 0x56288abe3000-0x56288ac1b000

追記

いろいろ追試したところ、ThreadSanitizerも信頼できない。

(ldc-1.4.0)$ ldc2 -fsanitize=thread emptymain.d
(ldc-1.4.0)$ ./emptymain
FATAL: ThreadSanitizer: unexpected memory mapping 0x562d389a0000-0x562d389d7000

AddressSanitizerに至っては、いつのまにかリンカエラーでこけるようになっている。

(ldc-1.4.0)$ ( cd asan && ldc2 -fsanitize=address emptymain.d && ./emptymain )
/usr/bin/ld: /home/kubo39/dlang/ldc-1.4.0/lib/libldc_rt.asan-x86_64.a(asan_allocator.cc.o): 誤った再配置シンボル索引 (0x1fd8ca57 >= 0x11f) (オフセット 0x1fd8000000027079、セクション `.debug_loc' 内用) です
/usr/bin/ld: /home/kubo39/dlang/ldc-1.4.0/lib/libldc_rt.asan-x86_64.a(asan_allocator.cc.o): 誤った再配置シンボル索引 (0x1fd8ca57 >= 0x11f) (オフセット 0x1fd8000000027079、セクション `.debug_loc' 内用) です
/usr/bin/ld: 最終リンクに失敗しました: 不正な値です
collect2: error: ld returned 1 exit status
Error: /usr/bin/gcc failed with status: 1

GNU ld側の問題な気がするが、追求するのがおっくうになっている。どうせ現時点では使い物にならないだろう。

(ldc-1.4.0)$ ( LANG=C; cd asan && LD_DEBUG=reloc ldc2 -fsanitize=address emptymain.d && ./emptymain )
...
     22218:     relocation processing: /usr/lib/gcc/x86_64-linux-gnu/6/liblto_plugin.so
     22218:
     22218:     calling init: /usr/lib/gcc/x86_64-linux-gnu/6/liblto_plugin.so     
     22218:                                                                  
/usr/bin/ld: /home/kubo39/dlang/ldc-1.4.0/lib/libldc_rt.asan-x86_64.a(asan_allocator.cc.o): bad reloc symbol index (0x1fd8ca57 >= 0x11f)
 for offset 0x1fd8000000027079 in section `.debug_loc'                       
/usr/bin/ld: /home/kubo39/dlang/ldc-1.4.0/lib/libldc_rt.asan-x86_64.a(asan_allocator.cc.o): bad reloc symbol index (0x1fd8ca57 >= 0x11f)
 for offset 0x1fd8000000027079 in section `.debug_loc'                        
/usr/bin/ld: final link failed: Bad value                 
     22218:                                                                                  
     22218:     calling fini: /usr/lib/gcc/x86_64-linux-gnu/6/liblto_plugin.so [0]
     22218:                                       
...