tsan_platform_linux.cc revision 0c2feef1067818db0ede4531a2e71c9b5595d57a
1603c4be006d8c53905d736bf1f19a49f5ce98276Alexey Samsonov//===-- tsan_platform_linux.cc --------------------------------------------===// 27ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 37ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The LLVM Compiler Infrastructure 47ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 57ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is distributed under the University of Illinois Open Source 67ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// License. See LICENSE.TXT for details. 77ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 87ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===// 97ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is a part of ThreadSanitizer (TSan), a race detector. 117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Linux-specific code. 137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===// 147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 153f24d6386cea638f5d4bc1694d1de02917988bcdDmitry Vyukov#ifdef __linux__ 163f24d6386cea638f5d4bc1694d1de02917988bcdDmitry Vyukov 1784902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov#include "sanitizer_common/sanitizer_common.h" 1848aee681c0d800deb6c00f546bfaa377ece37326Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h" 1984902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov#include "sanitizer_common/sanitizer_procmaps.h" 207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_platform.h" 217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_rtl.h" 227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_flags.h" 237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <asm/prctl.h> 257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <fcntl.h> 267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <pthread.h> 277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <signal.h> 287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <stdio.h> 297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <stdlib.h> 307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <string.h> 317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <stdarg.h> 327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <sys/mman.h> 337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <sys/prctl.h> 347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <sys/syscall.h> 357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <sys/time.h> 367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <sys/types.h> 377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <sys/resource.h> 387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <sys/stat.h> 397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <unistd.h> 407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <errno.h> 417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <sched.h> 427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include <dlfcn.h> 437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 440a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovextern "C" int arch_prctl(int code, __sanitizer::uptr *addr); 457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 469edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonovnamespace __sanitizer { 479edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov 489edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonovvoid Die() { 499edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov _exit(1); 509edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov} 519edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov 529edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov} // namespace __sanitizer 539edf7508e4ad536d26a202224548081d36eddd70Alexey Samsonov 547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan { 557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 56b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 577ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyScopedInRtl::ScopedInRtl() 587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : thr_(cur_thread()) { 597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany in_rtl_ = thr_->in_rtl; 607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr_->in_rtl++; 617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany errno_ = errno; 627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 647ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyScopedInRtl::~ScopedInRtl() { 657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr_->in_rtl--; 667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany errno = errno_; 677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_EQ(in_rtl_, thr_->in_rtl); 687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 69b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#else 70b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry VyukovScopedInRtl::ScopedInRtl() { 71b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} 72b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 73b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry VyukovScopedInRtl::~ScopedInRtl() { 74b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} 75b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 7726127735454fddae3495794f38189d57dde6510fDmitry Vyukovuptr GetShadowMemoryConsumption() { 7826127735454fddae3495794f38189d57dde6510fDmitry Vyukov return 0; 7926127735454fddae3495794f38189d57dde6510fDmitry Vyukov} 8026127735454fddae3495794f38189d57dde6510fDmitry Vyukov 81adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovvoid FlushShadowMemory() { 82adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov madvise((void*)kLinuxShadowBeg, 83adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov kLinuxShadowEnd - kLinuxShadowBeg, 84adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov MADV_DONTNEED); 85adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov} 86adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov 87b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void ProtectRange(uptr beg, uptr end) { 897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ScopedInRtl in_rtl; 907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_LE(beg, end); 917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (beg == end) 927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 9384902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov if (beg != (uptr)Mprotect(beg, end - beg)) { 94e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov TsanPrintf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end); 9567a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("FATAL: Make sure you are not using unlimited stack\n"); 967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Die(); 977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 99b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid InitializeShadowMemory() { 10284902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov uptr shadow = (uptr)MmapFixedNoReserve(kLinuxShadowBeg, 10384902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov kLinuxShadowEnd - kLinuxShadowBeg); 1047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (shadow != kLinuxShadowBeg) { 10567a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); 10667a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("FATAL: Make sure to compile with -fPIE and " 1072e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov "to link with -pie (%p, %p).\n", shadow, kLinuxShadowBeg); 1087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Die(); 1097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 110b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 111b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov const uptr kClosedLowBeg = 0x200000; 112b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov const uptr kClosedLowEnd = kLinuxShadowBeg - 1; 113b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov const uptr kClosedMidBeg = kLinuxShadowEnd + 1; 114b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov const uptr kClosedMidEnd = kLinuxAppMemBeg - 1; 1157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ProtectRange(kClosedLowBeg, kClosedLowEnd); 1167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ProtectRange(kClosedMidBeg, kClosedMidEnd); 117b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 118b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 119e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov DPrintf("kClosedLow %zx-%zx (%zuGB)\n", 1207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany kClosedLowBeg, kClosedLowEnd, (kClosedLowEnd - kClosedLowBeg) >> 30); 121b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 122e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov DPrintf("kLinuxShadow %zx-%zx (%zuGB)\n", 1237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany kLinuxShadowBeg, kLinuxShadowEnd, 1247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (kLinuxShadowEnd - kLinuxShadowBeg) >> 30); 125b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 126e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov DPrintf("kClosedMid %zx-%zx (%zuGB)\n", 1277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany kClosedMidBeg, kClosedMidEnd, (kClosedMidEnd - kClosedMidBeg) >> 30); 128b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 129e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov DPrintf("kLinuxAppMem %zx-%zx (%zuGB)\n", 1307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany kLinuxAppMemBeg, kLinuxAppMemEnd, 1317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (kLinuxAppMemEnd - kLinuxAppMemBeg) >> 30); 132e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov DPrintf("stack %zx\n", (uptr)&shadow); 1337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1350c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukovstatic uptr g_tls_size; 1360c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukovstatic uptr g_data_start; 1370c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukovstatic uptr g_data_end; 1380c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov 139b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 1407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void CheckPIE() { 1417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Ensure that the binary is indeed compiled with -pie. 142e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov MemoryMappingLayout proc_maps; 14384902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov uptr start, end; 14484902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov if (proc_maps.Next(&start, &end, 14584902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov /*offset*/0, /*filename*/0, /*filename_size*/0)) { 14684902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov if ((u64)start < kLinuxAppMemBeg) { 14767a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("FATAL: ThreadSanitizer can not mmap the shadow memory (" 148e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov "something is mapped at 0x%zx < 0x%zx)\n", 14984902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov start, kLinuxAppMemBeg); 15067a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("FATAL: Make sure to compile with -fPIE" 1517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany " and to link with -pie.\n"); 1527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Die(); 1537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1570c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukovstatic void InitDataSeg() { 1580c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov MemoryMappingLayout proc_maps; 1590c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov uptr start, end, offset; 1600c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov char name[128]; 1610c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov bool prev_is_data = false; 1620c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov while (proc_maps.Next(&start, &end, &offset, name, ARRAY_SIZE(name))) { 1630c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov DPrintf("%p-%p %p %s\n", start, end, offset, name); 1640c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov bool is_data = offset != 0 && name[0] != 0; 1650c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov bool is_bss = offset == 0 && name[0] == 0 && prev_is_data; 1660c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov if (g_data_start == 0 && is_data) 1670c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov g_data_start = start; 1680c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov if (is_bss) 1690c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov g_data_end = end; 1700c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov prev_is_data = is_data; 1710c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov } 1720c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov DPrintf("guessed data_start=%p data_end=%p\n", g_data_start, g_data_end); 1730c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov CHECK_LT(g_data_start, g_data_end); 1740c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov CHECK_GE((uptr)&g_data_start, g_data_start); 1750c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov CHECK_LT((uptr)&g_data_start, g_data_end); 1760c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov} 177b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 1787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#ifdef __i386__ 1797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany# define INTERNAL_FUNCTION __attribute__((regparm(3), stdcall)) 1807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else 1817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany# define INTERNAL_FUNCTION 1827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 1837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void _dl_get_tls_static_info(size_t*, size_t*) 1847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany __attribute__((weak)) INTERNAL_FUNCTION; 1857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic int InitTlsSize() { 1877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany typedef void (*get_tls_func)(size_t*, size_t*) INTERNAL_FUNCTION; 1887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany get_tls_func get_tls = &_dl_get_tls_static_info; 1897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (get_tls == 0) 1907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany get_tls = (get_tls_func)dlsym(RTLD_NEXT, "_dl_get_tls_static_info"); 1917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_NE(get_tls, 0); 1927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany size_t tls_size = 0; 1937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany size_t tls_align = 0; 1947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany get_tls(&tls_size, &tls_align); 1957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return tls_size; 1967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 197b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif // #ifndef TSAN_GO 1987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst char *InitializePlatform() { 2007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void *p = 0; 2017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (sizeof(p) == 8) { 2027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Disable core dumps, dumping of 16TB usually takes a bit long. 2037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // The following magic is to prevent clang from replacing it with memset. 2047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany volatile rlimit lim; 2057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany lim.rlim_cur = 0; 2067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany lim.rlim_max = 0; 2077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany setrlimit(RLIMIT_CORE, (rlimit*)&lim); 2087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 210b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 2117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CheckPIE(); 2127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany g_tls_size = (uptr)InitTlsSize(); 2130c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov InitDataSeg(); 214b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 2157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return getenv("TSAN_OPTIONS"); 2167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FinalizePlatform() { 2197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany fflush(0); 2207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyuptr GetTlsSize() { 223b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 2247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return g_tls_size; 225b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#else 226b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov return 0; 227b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 2287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 230789b6c5669547b550034fc9888059b17e2ff1417Dmitry Vyukovvoid GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, 2317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr *tls_addr, uptr *tls_size) { 232b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 2337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany arch_prctl(ARCH_GET_FS, tls_addr); 2347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany *tls_addr -= g_tls_size; 2357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany *tls_size = g_tls_size; 2367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 23784902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov uptr stack_top, stack_bottom; 23884902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); 23984902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov *stk_addr = stack_bottom; 24084902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov *stk_size = stack_top - stack_bottom; 241789b6c5669547b550034fc9888059b17e2ff1417Dmitry Vyukov 24284902c716abf9ba0dc6e7b1cd0522759f29b3179Alexey Samsonov if (!main) { 243789b6c5669547b550034fc9888059b17e2ff1417Dmitry Vyukov // If stack and tls intersect, make them non-intersecting. 244789b6c5669547b550034fc9888059b17e2ff1417Dmitry Vyukov if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) { 245789b6c5669547b550034fc9888059b17e2ff1417Dmitry Vyukov CHECK_GT(*tls_addr + *tls_size, *stk_addr); 246789b6c5669547b550034fc9888059b17e2ff1417Dmitry Vyukov CHECK_LE(*tls_addr + *tls_size, *stk_addr + *stk_size); 247789b6c5669547b550034fc9888059b17e2ff1417Dmitry Vyukov *stk_size -= *tls_size; 248789b6c5669547b550034fc9888059b17e2ff1417Dmitry Vyukov *tls_addr = *stk_addr + *stk_size; 249789b6c5669547b550034fc9888059b17e2ff1417Dmitry Vyukov } 2507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 251b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#else 252b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov *stk_addr = 0; 253b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov *stk_size = 0; 254b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov *tls_addr = 0; 255b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov *tls_size = 0; 256b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 2577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2590c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukovbool IsGlobalVar(uptr addr) { 2600c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov return g_data_start && addr >= g_data_start && addr < g_data_end; 2610c2feef1067818db0ede4531a2e71c9b5595d57aDmitry Vyukov} 262b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 2637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 2643f24d6386cea638f5d4bc1694d1de02917988bcdDmitry Vyukov 2653f24d6386cea638f5d4bc1694d1de02917988bcdDmitry Vyukov#endif // #ifdef __linux__ 266