msan_linux.cc revision 86277eb844c4983c81de62d7c050e92fe7155788
1//===-- msan_linux.cc -----------------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file is a part of MemorySanitizer. 11// 12// Linux- and FreeBSD-specific code. 13//===----------------------------------------------------------------------===// 14 15#include "sanitizer_common/sanitizer_platform.h" 16#if SANITIZER_FREEBSD || SANITIZER_LINUX 17 18#include "msan.h" 19#include "msan_thread.h" 20 21#include <elf.h> 22#include <link.h> 23#include <pthread.h> 24#include <stdio.h> 25#include <stdlib.h> 26#include <signal.h> 27#include <unistd.h> 28#include <unwind.h> 29#include <execinfo.h> 30#include <sys/time.h> 31#include <sys/resource.h> 32 33#include "sanitizer_common/sanitizer_common.h" 34#include "sanitizer_common/sanitizer_procmaps.h" 35 36namespace __msan { 37 38void ReportMapRange(const char *descr, uptr beg, uptr size) { 39 if (size > 0) { 40 uptr end = beg + size - 1; 41 VPrintf(1, "%s : %p - %p\n", descr, beg, end); 42 } 43} 44 45static bool CheckMemoryRangeAvailability(uptr beg, uptr size) { 46 if (size > 0) { 47 uptr end = beg + size - 1; 48 if (!MemoryRangeIsAvailable(beg, end)) { 49 Printf("FATAL: Memory range %p - %p is not available.\n", beg, end); 50 return false; 51 } 52 } 53 return true; 54} 55 56static bool ProtectMemoryRange(uptr beg, uptr size) { 57 if (size > 0) { 58 uptr end = beg + size - 1; 59 if (!Mprotect(beg, size)) { 60 Printf("FATAL: Cannot protect memory range %p - %p.\n", beg, end); 61 return false; 62 } 63 } 64 return true; 65} 66 67static void CheckMemoryLayoutSanity() { 68 uptr prev_end = 0; 69 for (unsigned i = 0; i < kMemoryLayoutSize; ++i) { 70 uptr start = kMemoryLayout[i].start; 71 uptr end = kMemoryLayout[i].end; 72 MappingDesc::Type type = kMemoryLayout[i].type; 73 CHECK_LT(start, end); 74 CHECK_EQ(prev_end, start); 75 CHECK(addr_is_type(start, type)); 76 CHECK(addr_is_type((start + end) / 2, type)); 77 CHECK(addr_is_type(end - 1, type)); 78 if (type == MappingDesc::APP) { 79 uptr addr = start; 80 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr))); 81 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr))); 82 CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr))); 83 84 addr = (start + end) / 2; 85 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr))); 86 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr))); 87 CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr))); 88 89 addr = end - 1; 90 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr))); 91 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr))); 92 CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr))); 93 } 94 prev_end = end; 95 } 96} 97 98bool InitShadow(bool map_shadow, bool init_origins) { 99 // Let user know mapping parameters first. 100 VPrintf(1, "__msan_init %p\n", &__msan_init); 101 for (unsigned i = 0; i < kMemoryLayoutSize; ++i) 102 VPrintf(1, "%s: %zx - %zx\n", kMemoryLayout[i].name, kMemoryLayout[i].start, 103 kMemoryLayout[i].end - 1); 104 105 CheckMemoryLayoutSanity(); 106 107 if (!MEM_IS_APP(&__msan_init)) { 108 Printf("FATAL: Code %p is out of application range. Non-PIE build?\n", 109 (uptr)&__msan_init); 110 return false; 111 } 112 113 for (unsigned i = 0; i < kMemoryLayoutSize; ++i) { 114 uptr start = kMemoryLayout[i].start; 115 uptr end = kMemoryLayout[i].end; 116 uptr size= end - start; 117 MappingDesc::Type type = kMemoryLayout[i].type; 118 if ((map_shadow && type == MappingDesc::SHADOW) || 119 (init_origins && type == MappingDesc::ORIGIN)) { 120 if (!CheckMemoryRangeAvailability(start, size)) return false; 121 if ((uptr)MmapFixedNoReserve(start, size) != start) return false; 122 if (common_flags()->use_madv_dontdump) 123 DontDumpShadowMemory(start, size); 124 } else if (type == MappingDesc::INVALID) { 125 if (!CheckMemoryRangeAvailability(start, size)) return false; 126 if (!ProtectMemoryRange(start, size)) return false; 127 } 128 } 129 130 return true; 131} 132 133void MsanDie() { 134 if (common_flags()->coverage) 135 __sanitizer_cov_dump(); 136 if (death_callback) 137 death_callback(); 138 internal__exit(flags()->exit_code); 139} 140 141static void MsanAtExit(void) { 142 if (flags()->print_stats && (flags()->atexit || msan_report_count > 0)) 143 ReportStats(); 144 if (msan_report_count > 0) { 145 ReportAtExitStatistics(); 146 if (flags()->exit_code) _exit(flags()->exit_code); 147 } 148} 149 150void InstallAtExitHandler() { 151 atexit(MsanAtExit); 152} 153 154// ---------------------- TSD ---------------- {{{1 155 156static pthread_key_t tsd_key; 157static bool tsd_key_inited = false; 158 159void MsanTSDInit(void (*destructor)(void *tsd)) { 160 CHECK(!tsd_key_inited); 161 tsd_key_inited = true; 162 CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); 163} 164 165static THREADLOCAL MsanThread* msan_current_thread; 166 167MsanThread *GetCurrentThread() { 168 return msan_current_thread; 169} 170 171void SetCurrentThread(MsanThread *t) { 172 // Make sure we do not reset the current MsanThread. 173 CHECK_EQ(0, msan_current_thread); 174 msan_current_thread = t; 175 // Make sure that MsanTSDDtor gets called at the end. 176 CHECK(tsd_key_inited); 177 pthread_setspecific(tsd_key, (void *)t); 178} 179 180void MsanTSDDtor(void *tsd) { 181 MsanThread *t = (MsanThread*)tsd; 182 if (t->destructor_iterations_ > 1) { 183 t->destructor_iterations_--; 184 CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); 185 return; 186 } 187 msan_current_thread = nullptr; 188 // Make sure that signal handler can not see a stale current thread pointer. 189 atomic_signal_fence(memory_order_seq_cst); 190 MsanThread::TSDDtor(tsd); 191} 192 193} // namespace __msan 194 195#endif // SANITIZER_FREEBSD || SANITIZER_LINUX 196