Handle segfaults while walking native heap
Vendor blobs on ryu mprotect heap pages, causing segfaults when dumping
unreachable memory. Handle segfaults within HeapWalker by mapping a
zero page over any unreadable pages. HeapWalker runs in the forked
process, so the mapping will not affect the original process.
Bug: 28269332
Change-Id: I16245af722123f2ad467cbc6f245a70666c55544
(cherry picked from commit ba5d9ff6d9674a0f1e985b49f53863045aff558d)
diff --git a/libmemunreachable/HeapWalker.h b/libmemunreachable/HeapWalker.h
index 7b851c4..140f3ea 100644
--- a/libmemunreachable/HeapWalker.h
+++ b/libmemunreachable/HeapWalker.h
@@ -17,9 +17,12 @@
#ifndef LIBMEMUNREACHABLE_HEAP_WALKER_H_
#define LIBMEMUNREACHABLE_HEAP_WALKER_H_
+#include <signal.h>
+
#include "android-base/macros.h"
#include "Allocator.h"
+#include "ScopedSignalHandler.h"
#include "Tarjan.h"
// A range [begin, end)
@@ -41,10 +44,17 @@
public:
HeapWalker(Allocator<HeapWalker> allocator) : allocator_(allocator),
allocations_(allocator), allocation_bytes_(0),
- roots_(allocator), root_vals_(allocator) {
+ roots_(allocator), root_vals_(allocator),
+ segv_handler_(allocator), walking_ptr_(0) {
valid_allocations_range_.end = 0;
valid_allocations_range_.begin = ~valid_allocations_range_.end;
+
+ segv_handler_.install(SIGSEGV,
+ [=](ScopedSignalHandler& handler, int signal, siginfo_t* siginfo, void* uctx) {
+ this->HandleSegFault(handler, signal, siginfo, uctx);
+ });
}
+
~HeapWalker() {}
bool Allocation(uintptr_t begin, uintptr_t end);
void Root(uintptr_t begin, uintptr_t end);
@@ -70,7 +80,8 @@
private:
void RecurseRoot(const Range& root);
- bool IsAllocationPtr(uintptr_t ptr, Range* range, AllocationInfo** info);
+ bool WordContainsAllocationPtr(uintptr_t ptr, Range* range, AllocationInfo** info);
+ void HandleSegFault(ScopedSignalHandler&, int, siginfo_t*, void*);
DISALLOW_COPY_AND_ASSIGN(HeapWalker);
Allocator<HeapWalker> allocator_;
@@ -81,6 +92,9 @@
allocator::vector<Range> roots_;
allocator::vector<uintptr_t> root_vals_;
+
+ ScopedSignalHandler segv_handler_;
+ uintptr_t walking_ptr_;
};
template<class F>
@@ -92,7 +106,7 @@
for (uintptr_t i = begin; i < range.end; i += sizeof(uintptr_t)) {
Range ref_range;
AllocationInfo* ref_info;
- if (IsAllocationPtr(*reinterpret_cast<uintptr_t*>(i), &ref_range, &ref_info)) {
+ if (WordContainsAllocationPtr(i, &ref_range, &ref_info)) {
f(ref_range, ref_info);
}
}