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