From: Hiroshi Yamauchi Date: Mon, 8 Feb 2016 22:18:21 +0000 (-0800) Subject: Check pages are readable after mprotect for SEGV_ACCERR diagnosis X-Git-Tag: android-x86-7.1-r1~408^2~7^2~57^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=6edb9aecdbe8b31f7ae1d35f21d013631337a424;p=android-x86%2Fart.git Check pages are readable after mprotect for SEGV_ACCERR diagnosis We have a suspected mprotect issue where we see seg faults after pages are mprotected with PROT_READ|PROT_WRITE with the SS collector on host. This change attempts to see if earlier reads would cause faults similarly. Bug: 19894268 Change-Id: I041a663c6b55b747120915f73a0db5f566744ed8 --- diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 8269f7662..3c9312f25 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -2622,6 +2622,10 @@ collector::GcType Heap::CollectGarbageInternal(collector::GcType gc_type, } if (collector != mark_compact_collector_ && collector != concurrent_copying_collector_) { temp_space_->GetMemMap()->Protect(PROT_READ | PROT_WRITE); + if (kIsDebugBuild) { + // Try to read each page of the memory map in case mprotect didn't work properly b/19894268. + temp_space_->GetMemMap()->TryReadable(); + } CHECK(temp_space_->IsEmpty()); } gc_type = collector::kGcTypeFull; // TODO: Not hard code this in. diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc index 18c52e47b..c908b3920 100644 --- a/runtime/mem_map.cc +++ b/runtime/mem_map.cc @@ -877,4 +877,22 @@ std::ostream& operator<<(std::ostream& os, const MemMap& mem_map) { return os; } +void MemMap::TryReadable() { + if (base_begin_ == nullptr && base_size_ == 0) { + return; + } + CHECK_NE(prot_ & PROT_READ, 0); + volatile uint8_t* begin = reinterpret_cast(base_begin_); + volatile uint8_t* end = begin + base_size_; + DCHECK(IsAligned(begin)); + DCHECK(IsAligned(end)); + // Read the first byte of each page. Use volatile to prevent the compiler from optimizing away the + // reads. + for (volatile uint8_t* ptr = begin; ptr < end; ptr += kPageSize) { + // This read could fault if protection wasn't set correctly. + uint8_t value = *ptr; + UNUSED(value); + } +} + } // namespace art diff --git a/runtime/mem_map.h b/runtime/mem_map.h index ebd550a55..3eaf57684 100644 --- a/runtime/mem_map.h +++ b/runtime/mem_map.h @@ -184,6 +184,11 @@ class MemMap { static void Init() REQUIRES(!Locks::mem_maps_lock_); static void Shutdown() REQUIRES(!Locks::mem_maps_lock_); + // If the map is PROT_READ, try to read each page of the map to check it is in fact readable (not + // faulting). This is used to diagnose a bug b/19894268 where mprotect doesn't seem to be working + // intermittently. + void TryReadable(); + private: MemMap(const std::string& name, uint8_t* begin,