Factor out error reporting in WriteProtected.
Partly to buff our coverage numbers, but also for improved consistency
in error reporting.
Test: treehugger
Change-Id: Iffc32833a35f9e9535c1bc3e0f7cb3c4bbba5f7f
diff --git a/libc/private/WriteProtected.h b/libc/private/WriteProtected.h
index 8f5b32d..746f72a 100644
--- a/libc/private/WriteProtected.h
+++ b/libc/private/WriteProtected.h
@@ -40,23 +40,11 @@
// explicitly.
template <typename T>
class WriteProtected {
+ public:
static_assert(sizeof(T) < PAGE_SIZE,
"WriteProtected only supports contents up to PAGE_SIZE");
static_assert(__is_pod(T), "WriteProtected only supports POD contents");
- WriteProtectedContents<T> contents;
-
- int set_protection(int prot) {
- auto addr = &contents;
-#if __has_feature(hwaddress_sanitizer)
- // The mprotect system call does not currently untag pointers, so do it
- // ourselves.
- addr = untag_address(addr);
-#endif
- return mprotect(reinterpret_cast<void*>(addr), PAGE_SIZE, prot);
- }
-
- public:
WriteProtected() = default;
BIONIC_DISALLOW_COPY_AND_ASSIGN(WriteProtected);
@@ -64,10 +52,7 @@
// Not strictly necessary, but this will hopefully segfault if we initialize
// multiple times by accident.
memset(&contents, 0, sizeof(contents));
-
- if (set_protection(PROT_READ)) {
- async_safe_fatal("failed to make WriteProtected nonwritable in initialize");
- }
+ set_protection(PROT_READ);
}
const T* operator->() {
@@ -80,14 +65,23 @@
template <typename Mutator>
void mutate(Mutator mutator) {
- if (set_protection(PROT_READ | PROT_WRITE) != 0) {
- async_safe_fatal("failed to make WriteProtected writable in mutate: %s",
- strerror(errno));
- }
+ set_protection(PROT_READ | PROT_WRITE);
mutator(&contents.value);
- if (set_protection(PROT_READ) != 0) {
- async_safe_fatal("failed to make WriteProtected nonwritable in mutate: %s",
- strerror(errno));
+ set_protection(PROT_READ);
+ }
+
+ private:
+ WriteProtectedContents<T> contents;
+
+ void set_protection(int prot) {
+ auto addr = &contents;
+#if __has_feature(hwaddress_sanitizer)
+ // The mprotect system call does not currently untag pointers, so do it
+ // ourselves.
+ addr = untag_address(addr);
+#endif
+ if (mprotect(reinterpret_cast<void*>(addr), PAGE_SIZE, prot) == -1) {
+ async_safe_fatal("WriteProtected mprotect %x failed: %s", prot, strerror(errno));
}
}
};