1b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov//===-- tsan_go.cc --------------------------------------------------------===// 2b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov// 3b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov// The LLVM Compiler Infrastructure 4b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov// 5b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov// This file is distributed under the University of Illinois Open Source 6b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov// License. See LICENSE.TXT for details. 7b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov// 8b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov//===----------------------------------------------------------------------===// 9b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov// 10b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov// ThreadSanitizer runtime for Go language. 11b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov// 12b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov//===----------------------------------------------------------------------===// 13b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 14b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#include "tsan_rtl.h" 15b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#include "tsan_symbolize.h" 16b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#include "sanitizer_common/sanitizer_common.h" 17b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#include <stdlib.h> 18b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 19b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovnamespace __tsan { 20b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 21b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovvoid InitializeInterceptors() { 22b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} 23b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 24b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovvoid InitializeDynamicAnnotations() { 25b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} 26b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 27b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovbool IsExpectedReport(uptr addr, uptr size) { 28b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov return false; 29b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} 30b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 315a1f23310cc4a1debae8741653defe620518e612Dmitry VyukovReportLocation *SymbolizeData(uptr addr) { 32b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov return 0; 33b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} 34b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 35b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovvoid *internal_alloc(MBlockType typ, uptr sz) { 36b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov return InternalAlloc(sz); 37b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} 38b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 39b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovvoid internal_free(void *p) { 40b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov InternalFree(p); 41b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} 42b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstruct SymbolizeContext { 442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr pc; 452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines char *func; 462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines char *file; 472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr line; 482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr off; 492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr res; 502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}; 512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 526b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov// Callback into Go. 532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void (*symbolize_cb)(SymbolizeContext *ctx); 54b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 5586277eb844c4983c81de62d7c050e92fe7155788Stephen HinesSymbolizedStack *SymbolizeCode(uptr addr) { 5686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SymbolizedStack *s = SymbolizedStack::New(addr); 572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines SymbolizeContext ctx; 582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines internal_memset(&ctx, 0, sizeof(ctx)); 592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx.pc = addr; 602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines symbolize_cb(&ctx); 612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (ctx.res) { 6286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AddressInfo &info = s->info; 6386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines info.module_offset = ctx.off; 6486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines info.function = internal_strdup(ctx.func ? ctx.func : "??"); 6586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines info.file = internal_strdup(ctx.file ? ctx.file : "-"); 6686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines info.line = ctx.line; 6786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines info.column = 0; 686b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov } 696b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov return s; 706b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov} 716b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov 726b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukovextern "C" { 73b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 746faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukovstatic ThreadState *main_thr; 752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic bool inited; 766faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukov 776faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukovstatic ThreadState *AllocGoroutine() { 787d15f5dc87f980d7931fbc036a0b38e2eee16718Dmitry Vyukov ThreadState *thr = (ThreadState*)internal_alloc(MBlockThreadContex, 79cb3a6b82ae406613f8870519d2acda1ee1c8f2b5Dmitry Vyukov sizeof(ThreadState)); 807d15f5dc87f980d7931fbc036a0b38e2eee16718Dmitry Vyukov internal_memset(thr, 0, sizeof(*thr)); 816faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukov return thr; 82cb3a6b82ae406613f8870519d2acda1ee1c8f2b5Dmitry Vyukov} 83cb3a6b82ae406613f8870519d2acda1ee1c8f2b5Dmitry Vyukov 842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid __tsan_init(ThreadState **thrp, void (*cb)(SymbolizeContext *cb)) { 852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines symbolize_cb = cb; 866faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukov ThreadState *thr = AllocGoroutine(); 876faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukov main_thr = *thrp = thr; 88b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov Initialize(thr); 892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines inited = true; 90b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} 91b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 92b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovvoid __tsan_fini() { 93b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov // FIXME: Not necessary thread 0. 946faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukov ThreadState *thr = main_thr; 95b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov int res = Finalize(thr); 961bf56b76cf08ab19800cf5a30849277bf1e084d4Dmitry Vyukov exit(res); 97b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} 98b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 99a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukovvoid __tsan_map_shadow(uptr addr, uptr size) { 100a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov MapShadow(addr, size); 101a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov} 102a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov 1036faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukovvoid __tsan_read(ThreadState *thr, void *addr, void *pc) { 104334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1); 1056b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov} 1066b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov 1072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid __tsan_read_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) { 1082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (callpc != 0) 1092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines FuncEntry(thr, callpc); 1102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1); 1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (callpc != 0) 1122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines FuncExit(thr); 1132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1156faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukovvoid __tsan_write(ThreadState *thr, void *addr, void *pc) { 116334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1); 1176b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov} 1186b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov 1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid __tsan_write_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) { 1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (callpc != 0) 1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines FuncEntry(thr, callpc); 1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1); 1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (callpc != 0) 1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines FuncExit(thr); 1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid __tsan_read_range(ThreadState *thr, void *addr, uptr size, uptr pc) { 12848cd12d0398914db195c1a25852b153f3345090dDmitry Vyukov MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, false); 1291a9cd8ddea1985ab4941a8bd2f6e20822d1e9c1dDmitry Vyukov} 1301a9cd8ddea1985ab4941a8bd2f6e20822d1e9c1dDmitry Vyukov 1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid __tsan_write_range(ThreadState *thr, void *addr, uptr size, uptr pc) { 13248cd12d0398914db195c1a25852b153f3345090dDmitry Vyukov MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, true); 1331a9cd8ddea1985ab4941a8bd2f6e20822d1e9c1dDmitry Vyukov} 1341a9cd8ddea1985ab4941a8bd2f6e20822d1e9c1dDmitry Vyukov 1356faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukovvoid __tsan_func_enter(ThreadState *thr, void *pc) { 1366b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov FuncEntry(thr, (uptr)pc); 1376b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov} 1386b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov 1396faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukovvoid __tsan_func_exit(ThreadState *thr) { 1406b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov FuncExit(thr); 1416b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov} 1426b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov 1432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid __tsan_malloc(void *p, uptr sz) { 1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!inited) 1451bf56b76cf08ab19800cf5a30849277bf1e084d4Dmitry Vyukov return; 1462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MemoryResetRange(0, 0, (uptr)p, sz); 1476b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov} 1486b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov 1496faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukovvoid __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) { 1506faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukov ThreadState *thr = AllocGoroutine(); 1516faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukov *pthr = thr; 1526faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukov int goid = ThreadCreate(parent, (uptr)pc, 0, true); 1536faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukov ThreadStart(thr, goid, 0); 1546b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov} 1556b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov 1566faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukovvoid __tsan_go_end(ThreadState *thr) { 1576b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov ThreadFinish(thr); 1587d15f5dc87f980d7931fbc036a0b38e2eee16718Dmitry Vyukov internal_free(thr); 1596b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov} 1606b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov 1616faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukovvoid __tsan_acquire(ThreadState *thr, void *addr) { 1626b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov Acquire(thr, 0, (uptr)addr); 1636b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov} 1646b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov 1656faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukovvoid __tsan_release(ThreadState *thr, void *addr) { 1669d150bdb433ddd092073dabd87ba15aa176603a1Dmitry Vyukov ReleaseStore(thr, 0, (uptr)addr); 1676b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov} 1686b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov 1696faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukovvoid __tsan_release_merge(ThreadState *thr, void *addr) { 1706b2804f4a5d8891728c030e1ac93f719eaad3171Dmitry Vyukov Release(thr, 0, (uptr)addr); 171b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} 172b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 1736faa20f2441cd845d98cb390ae2bacca908537eeDmitry Vyukovvoid __tsan_finalizer_goroutine(ThreadState *thr) { 174538f1ba8cb57cfa02d25f8f922feb00975e0a286Dmitry Vyukov AcquireGlobal(thr, 0); 1758f1104cbf1af615242e14c66d1b3dd9e8437b152Dmitry Vyukov} 1768f1104cbf1af615242e14c66d1b3dd9e8437b152Dmitry Vyukov 1776a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesvoid __tsan_mutex_before_lock(ThreadState *thr, uptr addr, uptr write) { 1782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1806a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesvoid __tsan_mutex_after_lock(ThreadState *thr, uptr addr, uptr write) { 1812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (write) 1822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexLock(thr, 0, addr); 1832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines else 1842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexReadLock(thr, 0, addr); 1852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1876a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesvoid __tsan_mutex_before_unlock(ThreadState *thr, uptr addr, uptr write) { 1882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (write) 1892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexUnlock(thr, 0, addr); 1902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines else 1912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexReadUnlock(thr, 0, addr); 1922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1946d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid __tsan_go_ignore_sync_begin(ThreadState *thr) { 1956d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ThreadIgnoreSyncBegin(thr, 0); 1966d1862363c88c183b0ed7740fca876342cf0474bStephen Hines} 1976d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 1986d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid __tsan_go_ignore_sync_end(ThreadState *thr) { 1996d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ThreadIgnoreSyncEnd(thr, 0); 2006d1862363c88c183b0ed7740fca876342cf0474bStephen Hines} 2016d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 202b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} // extern "C" 203b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} // namespace __tsan 2043086d7bd6456e43b6695c8356db364ade826dce3Alexander Potapenko 2053086d7bd6456e43b6695c8356db364ade826dce3Alexander Potapenkonamespace __sanitizer { 2063086d7bd6456e43b6695c8356db364ade826dce3Alexander Potapenko 2073086d7bd6456e43b6695c8356db364ade826dce3Alexander Potapenkovoid SymbolizerPrepareForSandboxing() { 2083086d7bd6456e43b6695c8356db364ade826dce3Alexander Potapenko // Nothing to do here for Go. 2093086d7bd6456e43b6695c8356db364ade826dce3Alexander Potapenko} 2103086d7bd6456e43b6695c8356db364ade826dce3Alexander Potapenko 2113086d7bd6456e43b6695c8356db364ade826dce3Alexander Potapenko} // namespace __sanitizer 212