Evgeniy Stepanov | 78c56c3 | 2012-12-11 12:27:27 +0000 | [diff] [blame] | 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-specific code. |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
Evgeniy Stepanov | 24e1372 | 2013-03-19 14:33:38 +0000 | [diff] [blame] | 15 | #include "sanitizer_common/sanitizer_platform.h" |
| 16 | #if SANITIZER_LINUX |
Evgeniy Stepanov | 78c56c3 | 2012-12-11 12:27:27 +0000 | [diff] [blame] | 17 | |
| 18 | #include "msan.h" |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame^] | 19 | #include "msan_thread.h" |
Evgeniy Stepanov | 78c56c3 | 2012-12-11 12:27:27 +0000 | [diff] [blame] | 20 | |
Reid Kleckner | 0f92deb | 2013-03-11 18:07:42 +0000 | [diff] [blame] | 21 | #include <elf.h> |
| 22 | #include <link.h> |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame^] | 23 | #include <pthread.h> |
Evgeniy Stepanov | 78c56c3 | 2012-12-11 12:27:27 +0000 | [diff] [blame] | 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 | |
| 36 | namespace __msan { |
| 37 | |
| 38 | static const uptr kMemBeg = 0x600000000000; |
| 39 | static const uptr kMemEnd = 0x7fffffffffff; |
| 40 | static const uptr kShadowBeg = MEM_TO_SHADOW(kMemBeg); |
| 41 | static const uptr kShadowEnd = MEM_TO_SHADOW(kMemEnd); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame^] | 42 | static const uptr kBad1Beg = 0; |
Evgeniy Stepanov | 78c56c3 | 2012-12-11 12:27:27 +0000 | [diff] [blame] | 43 | static const uptr kBad1End = kShadowBeg - 1; |
| 44 | static const uptr kBad2Beg = kShadowEnd + 1; |
| 45 | static const uptr kBad2End = kMemBeg - 1; |
| 46 | static const uptr kOriginsBeg = kBad2Beg; |
| 47 | static const uptr kOriginsEnd = kBad2End; |
| 48 | |
| 49 | bool InitShadow(bool prot1, bool prot2, bool map_shadow, bool init_origins) { |
Evgeniy Stepanov | 62355e9 | 2013-11-11 09:27:20 +0000 | [diff] [blame] | 50 | if ((uptr) & InitShadow < kMemBeg) { |
| 51 | Printf("FATAL: Code below application range: %p < %p. Non-PIE build?\n", |
| 52 | &InitShadow, (void *)kMemBeg); |
| 53 | return false; |
| 54 | } |
| 55 | |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame^] | 56 | VPrintf(1, "__msan_init %p\n", &__msan_init); |
| 57 | VPrintf(1, "Memory : %p %p\n", kMemBeg, kMemEnd); |
| 58 | VPrintf(1, "Bad2 : %p %p\n", kBad2Beg, kBad2End); |
| 59 | VPrintf(1, "Origins : %p %p\n", kOriginsBeg, kOriginsEnd); |
| 60 | VPrintf(1, "Shadow : %p %p\n", kShadowBeg, kShadowEnd); |
| 61 | VPrintf(1, "Bad1 : %p %p\n", kBad1Beg, kBad1End); |
Evgeniy Stepanov | 78c56c3 | 2012-12-11 12:27:27 +0000 | [diff] [blame] | 62 | |
Evgeniy Stepanov | 4c9ddc1 | 2012-12-26 06:37:23 +0000 | [diff] [blame] | 63 | if (!MemoryRangeIsAvailable(kShadowBeg, |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame^] | 64 | init_origins ? kOriginsEnd : kShadowEnd) || |
| 65 | (prot1 && !MemoryRangeIsAvailable(kBad1Beg, kBad1End)) || |
| 66 | (prot2 && !MemoryRangeIsAvailable(kBad2Beg, kBad2End))) { |
Evgeniy Stepanov | 4c9ddc1 | 2012-12-26 06:37:23 +0000 | [diff] [blame] | 67 | Printf("FATAL: Shadow memory range is not available.\n"); |
| 68 | return false; |
| 69 | } |
| 70 | |
Evgeniy Stepanov | 78c56c3 | 2012-12-11 12:27:27 +0000 | [diff] [blame] | 71 | if (prot1 && !Mprotect(kBad1Beg, kBad1End - kBad1Beg)) |
| 72 | return false; |
| 73 | if (prot2 && !Mprotect(kBad2Beg, kBad2End - kBad2Beg)) |
| 74 | return false; |
| 75 | if (map_shadow) { |
| 76 | void *shadow = MmapFixedNoReserve(kShadowBeg, kShadowEnd - kShadowBeg); |
| 77 | if (shadow != (void*)kShadowBeg) return false; |
| 78 | } |
| 79 | if (init_origins) { |
| 80 | void *origins = MmapFixedNoReserve(kOriginsBeg, kOriginsEnd - kOriginsBeg); |
| 81 | if (origins != (void*)kOriginsBeg) return false; |
| 82 | } |
| 83 | return true; |
| 84 | } |
| 85 | |
Evgeniy Stepanov | 78c56c3 | 2012-12-11 12:27:27 +0000 | [diff] [blame] | 86 | void MsanDie() { |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame^] | 87 | if (death_callback) |
| 88 | death_callback(); |
Evgeniy Stepanov | 78c56c3 | 2012-12-11 12:27:27 +0000 | [diff] [blame] | 89 | _exit(flags()->exit_code); |
| 90 | } |
Evgeniy Stepanov | 99bf1d7 | 2013-01-10 11:17:55 +0000 | [diff] [blame] | 91 | |
| 92 | static void MsanAtExit(void) { |
| 93 | if (msan_report_count > 0) { |
| 94 | ReportAtExitStatistics(); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame^] | 95 | if (flags()->print_stats) |
| 96 | ReportStats(); |
Evgeniy Stepanov | 99bf1d7 | 2013-01-10 11:17:55 +0000 | [diff] [blame] | 97 | if (flags()->exit_code) |
| 98 | _exit(flags()->exit_code); |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | void InstallAtExitHandler() { |
| 103 | atexit(MsanAtExit); |
| 104 | } |
Reid Kleckner | 0f92deb | 2013-03-11 18:07:42 +0000 | [diff] [blame] | 105 | |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame^] | 106 | // ---------------------- TSD ---------------- {{{1 |
| 107 | |
| 108 | static pthread_key_t tsd_key; |
| 109 | static bool tsd_key_inited = false; |
| 110 | void MsanTSDInit(void (*destructor)(void *tsd)) { |
| 111 | CHECK(!tsd_key_inited); |
| 112 | tsd_key_inited = true; |
| 113 | CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); |
| 114 | } |
| 115 | |
| 116 | void *MsanTSDGet() { |
| 117 | CHECK(tsd_key_inited); |
| 118 | return pthread_getspecific(tsd_key); |
| 119 | } |
| 120 | |
| 121 | void MsanTSDSet(void *tsd) { |
| 122 | CHECK(tsd_key_inited); |
| 123 | pthread_setspecific(tsd_key, tsd); |
| 124 | } |
| 125 | |
| 126 | void MsanTSDDtor(void *tsd) { |
| 127 | MsanThread *t = (MsanThread*)tsd; |
| 128 | if (t->destructor_iterations_ > 1) { |
| 129 | t->destructor_iterations_--; |
| 130 | CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); |
| 131 | return; |
| 132 | } |
| 133 | MsanThread::TSDDtor(tsd); |
| 134 | } |
| 135 | |
Alexey Samsonov | ba5e996 | 2013-01-30 07:45:58 +0000 | [diff] [blame] | 136 | } // namespace __msan |
Evgeniy Stepanov | 78c56c3 | 2012-12-11 12:27:27 +0000 | [diff] [blame] | 137 | |
| 138 | #endif // __linux__ |