aboutsummaryrefslogtreecommitdiff
path: root/lib/msan/msan_linux.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/msan/msan_linux.cc')
-rw-r--r--lib/msan/msan_linux.cc125
1 files changed, 66 insertions, 59 deletions
diff --git a/lib/msan/msan_linux.cc b/lib/msan/msan_linux.cc
index 0b67b531d51c..6c185165fc50 100644
--- a/lib/msan/msan_linux.cc
+++ b/lib/msan/msan_linux.cc
@@ -64,41 +64,45 @@ static bool ProtectMemoryRange(uptr beg, uptr size) {
return true;
}
+static void CheckMemoryLayoutSanity() {
+ uptr prev_end = 0;
+ for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
+ uptr start = kMemoryLayout[i].start;
+ uptr end = kMemoryLayout[i].end;
+ MappingDesc::Type type = kMemoryLayout[i].type;
+ CHECK_LT(start, end);
+ CHECK_EQ(prev_end, start);
+ CHECK(addr_is_type(start, type));
+ CHECK(addr_is_type((start + end) / 2, type));
+ CHECK(addr_is_type(end - 1, type));
+ if (type == MappingDesc::APP) {
+ uptr addr = start;
+ CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
+ CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
+ CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
+
+ addr = (start + end) / 2;
+ CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
+ CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
+ CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
+
+ addr = end - 1;
+ CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
+ CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
+ CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
+ }
+ prev_end = end;
+ }
+}
+
bool InitShadow(bool map_shadow, bool init_origins) {
// Let user know mapping parameters first.
VPrintf(1, "__msan_init %p\n", &__msan_init);
- ReportMapRange("Low Memory ", kLowMemBeg, kLowMemSize);
- ReportMapRange("Bad1 ", kBad1Beg, kBad1Size);
- ReportMapRange("Shadow ", kShadowBeg, kShadowSize);
- ReportMapRange("Bad2 ", kBad2Beg, kBad2Size);
- ReportMapRange("Origins ", kOriginsBeg, kOriginsSize);
- ReportMapRange("Bad3 ", kBad3Beg, kBad3Size);
- ReportMapRange("High Memory", kHighMemBeg, kHighMemSize);
-
- // Check mapping sanity (the invariant).
- CHECK_EQ(kLowMemBeg, 0);
- CHECK_EQ(kBad1Beg, kLowMemBeg + kLowMemSize);
- CHECK_EQ(kShadowBeg, kBad1Beg + kBad1Size);
- CHECK_GT(kShadowSize, 0);
- CHECK_GE(kShadowSize, kLowMemSize + kHighMemSize);
- CHECK_EQ(kBad2Beg, kShadowBeg + kShadowSize);
- CHECK_EQ(kOriginsBeg, kBad2Beg + kBad2Size);
- CHECK_EQ(kOriginsSize, kShadowSize);
- CHECK_EQ(kBad3Beg, kOriginsBeg + kOriginsSize);
- CHECK_EQ(kHighMemBeg, kBad3Beg + kBad3Size);
- CHECK_GT(kHighMemSize, 0);
- CHECK_GE(kHighMemBeg + kHighMemSize, kHighMemBeg); // Tests for no overflow.
-
- if (kLowMemSize > 0) {
- CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(kLowMemBeg)));
- CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(kLowMemBeg + kLowMemSize - 1)));
- CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(kLowMemBeg)));
- CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(kLowMemBeg + kLowMemSize - 1)));
- }
- CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(kHighMemBeg)));
- CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(kHighMemBeg + kHighMemSize - 1)));
- CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(kHighMemBeg)));
- CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(kHighMemBeg + kHighMemSize - 1)));
+ for (unsigned i = 0; i < kMemoryLayoutSize; ++i)
+ VPrintf(1, "%s: %zx - %zx\n", kMemoryLayout[i].name, kMemoryLayout[i].start,
+ kMemoryLayout[i].end - 1);
+
+ CheckMemoryLayoutSanity();
if (!MEM_IS_APP(&__msan_init)) {
Printf("FATAL: Code %p is out of application range. Non-PIE build?\n",
@@ -106,29 +110,23 @@ bool InitShadow(bool map_shadow, bool init_origins) {
return false;
}
- if (!CheckMemoryRangeAvailability(kShadowBeg, kShadowSize) ||
- (init_origins &&
- !CheckMemoryRangeAvailability(kOriginsBeg, kOriginsSize)) ||
- !CheckMemoryRangeAvailability(kBad1Beg, kBad1Size) ||
- !CheckMemoryRangeAvailability(kBad2Beg, kBad2Size) ||
- !CheckMemoryRangeAvailability(kBad3Beg, kBad3Size)) {
- return false;
- }
-
- if (!ProtectMemoryRange(kBad1Beg, kBad1Size) ||
- !ProtectMemoryRange(kBad2Beg, kBad2Size) ||
- !ProtectMemoryRange(kBad3Beg, kBad3Size)) {
- return false;
+ for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
+ uptr start = kMemoryLayout[i].start;
+ uptr end = kMemoryLayout[i].end;
+ uptr size= end - start;
+ MappingDesc::Type type = kMemoryLayout[i].type;
+ if ((map_shadow && type == MappingDesc::SHADOW) ||
+ (init_origins && type == MappingDesc::ORIGIN)) {
+ if (!CheckMemoryRangeAvailability(start, size)) return false;
+ if ((uptr)MmapFixedNoReserve(start, size) != start) return false;
+ if (common_flags()->use_madv_dontdump)
+ DontDumpShadowMemory(start, size);
+ } else if (type == MappingDesc::INVALID) {
+ if (!CheckMemoryRangeAvailability(start, size)) return false;
+ if (!ProtectMemoryRange(start, size)) return false;
+ }
}
- if (map_shadow) {
- void *shadow = MmapFixedNoReserve(kShadowBeg, kShadowSize);
- if (shadow != (void*)kShadowBeg) return false;
- }
- if (init_origins) {
- void *origins = MmapFixedNoReserve(kOriginsBeg, kOriginsSize);
- if (origins != (void*)kOriginsBeg) return false;
- }
return true;
}
@@ -137,7 +135,7 @@ void MsanDie() {
__sanitizer_cov_dump();
if (death_callback)
death_callback();
- _exit(flags()->exit_code);
+ internal__exit(flags()->exit_code);
}
static void MsanAtExit(void) {
@@ -157,20 +155,26 @@ void InstallAtExitHandler() {
static pthread_key_t tsd_key;
static bool tsd_key_inited = false;
+
void MsanTSDInit(void (*destructor)(void *tsd)) {
CHECK(!tsd_key_inited);
tsd_key_inited = true;
CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
}
-void *MsanTSDGet() {
- CHECK(tsd_key_inited);
- return pthread_getspecific(tsd_key);
+static THREADLOCAL MsanThread* msan_current_thread;
+
+MsanThread *GetCurrentThread() {
+ return msan_current_thread;
}
-void MsanTSDSet(void *tsd) {
+void SetCurrentThread(MsanThread *t) {
+ // Make sure we do not reset the current MsanThread.
+ CHECK_EQ(0, msan_current_thread);
+ msan_current_thread = t;
+ // Make sure that MsanTSDDtor gets called at the end.
CHECK(tsd_key_inited);
- pthread_setspecific(tsd_key, tsd);
+ pthread_setspecific(tsd_key, (void *)t);
}
void MsanTSDDtor(void *tsd) {
@@ -180,6 +184,9 @@ void MsanTSDDtor(void *tsd) {
CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
return;
}
+ msan_current_thread = nullptr;
+ // Make sure that signal handler can not see a stale current thread pointer.
+ atomic_signal_fence(memory_order_seq_cst);
MsanThread::TSDDtor(tsd);
}