Merge "Use -Werror in system/core/healthd"
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index d9db1bd..f1c6793 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -238,6 +238,10 @@
     {"watchdog_apps_bite", 98},
     {"xpu_err", 99},
     {"power_on_usb", 100},
+    {"watchdog_rpm", 101},
+    {"watchdog_nonsec", 102},
+    {"watchdog_apps_bark", 103},
+    {"reboot_dmverity_corrupted", 104},
 };
 
 // Converts a string value representing the reason the system booted to an
diff --git a/liblog/logger_write.c b/liblog/logger_write.c
index 589ce84..d03a2b6 100644
--- a/liblog/logger_write.c
+++ b/liblog/logger_write.c
@@ -270,7 +270,7 @@
       /* If only we could reset downstream logd counter */
       return -EPERM;
     }
-  } else if (log_id == LOG_ID_EVENTS) {
+  } else if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS) {
     const char* tag;
     size_t len;
     EventTagMap *m, *f;
diff --git a/libunwindstack/DwarfMemory.cpp b/libunwindstack/DwarfMemory.cpp
index 901f492..6ffdc0d 100644
--- a/libunwindstack/DwarfMemory.cpp
+++ b/libunwindstack/DwarfMemory.cpp
@@ -27,7 +27,7 @@
 namespace unwindstack {
 
 bool DwarfMemory::ReadBytes(void* dst, size_t num_bytes) {
-  if (!memory_->Read(cur_offset_, dst, num_bytes)) {
+  if (!memory_->ReadFully(cur_offset_, dst, num_bytes)) {
     return false;
   }
   cur_offset_ += num_bytes;
diff --git a/libunwindstack/DwarfOp.cpp b/libunwindstack/DwarfOp.cpp
index b3fd0df..3b3d340 100644
--- a/libunwindstack/DwarfOp.cpp
+++ b/libunwindstack/DwarfOp.cpp
@@ -141,7 +141,7 @@
   // Read the address and dereference it.
   AddressType addr = StackPop();
   AddressType value;
-  if (!regular_memory()->Read(addr, &value, sizeof(value))) {
+  if (!regular_memory()->ReadFully(addr, &value, sizeof(value))) {
     last_error_ = DWARF_ERROR_MEMORY_INVALID;
     return false;
   }
@@ -159,7 +159,7 @@
   // Read the address and dereference it.
   AddressType addr = StackPop();
   AddressType value = 0;
-  if (!regular_memory()->Read(addr, &value, bytes_to_read)) {
+  if (!regular_memory()->ReadFully(addr, &value, bytes_to_read)) {
     last_error_ = DWARF_ERROR_MEMORY_INVALID;
     return false;
   }
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index 805dcd3..0954187 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -142,7 +142,7 @@
         return false;
       }
       if (loc->type == DWARF_LOCATION_EXPRESSION) {
-        if (!regular_memory->Read(value, &cfa, sizeof(AddressType))) {
+        if (!regular_memory->ReadFully(value, &cfa, sizeof(AddressType))) {
           last_error_ = DWARF_ERROR_MEMORY_INVALID;
           return false;
         }
@@ -175,7 +175,8 @@
     const DwarfLocation* loc = &entry.second;
     switch (loc->type) {
       case DWARF_LOCATION_OFFSET:
-        if (!regular_memory->Read(cfa + loc->values[0], &(*cur_regs)[reg], sizeof(AddressType))) {
+        if (!regular_memory->ReadFully(cfa + loc->values[0], &(*cur_regs)[reg],
+                                       sizeof(AddressType))) {
           last_error_ = DWARF_ERROR_MEMORY_INVALID;
           return false;
         }
@@ -210,7 +211,7 @@
           return false;
         }
         if (loc->type == DWARF_LOCATION_EXPRESSION) {
-          if (!regular_memory->Read(value, &(*cur_regs)[reg], sizeof(AddressType))) {
+          if (!regular_memory->ReadFully(value, &(*cur_regs)[reg], sizeof(AddressType))) {
             last_error_ = DWARF_ERROR_MEMORY_INVALID;
             return false;
           }
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index 48e33ee..97ade56 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -136,7 +136,7 @@
 
   // Verify that this is a valid elf file.
   uint8_t e_ident[SELFMAG + 1];
-  if (!memory->Read(0, e_ident, SELFMAG)) {
+  if (!memory->ReadFully(0, e_ident, SELFMAG)) {
     return false;
   }
 
@@ -156,7 +156,7 @@
 
   // Now read the section header information.
   uint8_t class_type;
-  if (!memory->Read(EI_CLASS, &class_type, 1)) {
+  if (!memory->ReadFully(EI_CLASS, &class_type, 1)) {
     return;
   }
   if (class_type == ELFCLASS32) {
@@ -174,12 +174,12 @@
   }
 
   std::unique_ptr<ElfInterface> interface;
-  if (!memory->Read(EI_CLASS, &class_type_, 1)) {
+  if (!memory->ReadFully(EI_CLASS, &class_type_, 1)) {
     return nullptr;
   }
   if (class_type_ == ELFCLASS32) {
     Elf32_Half e_machine;
-    if (!memory->Read(EI_NIDENT + sizeof(Elf32_Half), &e_machine, sizeof(e_machine))) {
+    if (!memory->ReadFully(EI_NIDENT + sizeof(Elf32_Half), &e_machine, sizeof(e_machine))) {
       return nullptr;
     }
 
@@ -200,7 +200,7 @@
     }
   } else if (class_type_ == ELFCLASS64) {
     Elf64_Half e_machine;
-    if (!memory->Read(EI_NIDENT + sizeof(Elf64_Half), &e_machine, sizeof(e_machine))) {
+    if (!memory->ReadFully(EI_NIDENT + sizeof(Elf64_Half), &e_machine, sizeof(e_machine))) {
       return nullptr;
     }
     if (e_machine != EM_AARCH64 && e_machine != EM_X86_64) {
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index d5d158f..9bdb094 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -53,7 +53,7 @@
   Crc64GenerateTable();
 
   std::vector<uint8_t> src(gnu_debugdata_size_);
-  if (!memory_->Read(gnu_debugdata_offset_, src.data(), gnu_debugdata_size_)) {
+  if (!memory_->ReadFully(gnu_debugdata_offset_, src.data(), gnu_debugdata_size_)) {
     gnu_debugdata_offset_ = 0;
     gnu_debugdata_size_ = static_cast<uint64_t>(-1);
     return nullptr;
@@ -131,7 +131,7 @@
 template <typename EhdrType, typename PhdrType, typename ShdrType>
 bool ElfInterface::ReadAllHeaders(uint64_t* load_bias) {
   EhdrType ehdr;
-  if (!memory_->Read(0, &ehdr, sizeof(ehdr))) {
+  if (!memory_->ReadFully(0, &ehdr, sizeof(ehdr))) {
     return false;
   }
 
@@ -242,7 +242,7 @@
     }
 
     if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
-      if (!memory_->Read(offset, &shdr, sizeof(shdr))) {
+      if (!memory_->ReadFully(offset, &shdr, sizeof(shdr))) {
         return false;
       }
       // Need to go get the information about the section that contains
@@ -324,7 +324,7 @@
   uint64_t offset = dynamic_offset_;
   uint64_t max_offset = offset + dynamic_size_;
   for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) {
-    if (!memory_->Read(offset, &dyn, sizeof(dyn))) {
+    if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) {
       return false;
     }
 
@@ -388,7 +388,7 @@
 template <typename EhdrType>
 void ElfInterface::GetMaxSizeWithTemplate(Memory* memory, uint64_t* size) {
   EhdrType ehdr;
-  if (!memory->Read(0, &ehdr, sizeof(ehdr))) {
+  if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
     return;
   }
   if (ehdr.e_shnum == 0) {
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
index 5417659..8a7ad9c 100644
--- a/libunwindstack/MapInfo.cpp
+++ b/libunwindstack/MapInfo.cpp
@@ -102,7 +102,7 @@
   if (!(flags & PROT_READ)) {
     return nullptr;
   }
-  return new MemoryRange(process_memory, start, end);
+  return new MemoryRange(process_memory, start, end - start, 0);
 }
 
 Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gnu_debugdata) {
diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp
index 32753df..2479655 100644
--- a/libunwindstack/Memory.cpp
+++ b/libunwindstack/Memory.cpp
@@ -32,14 +32,69 @@
 
 #include "Check.h"
 
+static size_t ProcessVmRead(pid_t pid, void* dst, uint64_t remote_src, size_t len) {
+  struct iovec dst_iov = {
+      .iov_base = dst,
+      .iov_len = len,
+  };
+
+  // Split up the remote read across page boundaries.
+  // From the manpage:
+  //   A partial read/write may result if one of the remote_iov elements points to an invalid
+  //   memory region in the remote process.
+  //
+  //   Partial transfers apply at the granularity of iovec elements.  These system calls won't
+  //   perform a partial transfer that splits a single iovec element.
+  constexpr size_t kMaxIovecs = 64;
+  struct iovec src_iovs[kMaxIovecs];
+  size_t iovecs_used = 0;
+
+  uint64_t cur = remote_src;
+  while (len > 0) {
+    if (iovecs_used == kMaxIovecs) {
+      errno = EINVAL;
+      return 0;
+    }
+
+    // struct iovec uses void* for iov_base.
+    if (cur >= UINTPTR_MAX) {
+      errno = EFAULT;
+      return 0;
+    }
+
+    src_iovs[iovecs_used].iov_base = reinterpret_cast<void*>(cur);
+
+    uintptr_t misalignment = cur & (getpagesize() - 1);
+    size_t iov_len = getpagesize() - misalignment;
+    iov_len = std::min(iov_len, len);
+
+    len -= iov_len;
+    if (__builtin_add_overflow(cur, iov_len, &cur)) {
+      errno = EFAULT;
+      return 0;
+    }
+
+    src_iovs[iovecs_used].iov_len = iov_len;
+    ++iovecs_used;
+  }
+
+  ssize_t rc = process_vm_readv(pid, &dst_iov, 1, src_iovs, iovecs_used, 0);
+  return rc == -1 ? 0 : rc;
+}
+
 namespace unwindstack {
 
+bool Memory::ReadFully(uint64_t addr, void* dst, size_t size) {
+  size_t rc = Read(addr, dst, size);
+  return rc == size;
+}
+
 bool Memory::ReadString(uint64_t addr, std::string* string, uint64_t max_read) {
   string->clear();
   uint64_t bytes_read = 0;
   while (bytes_read < max_read) {
     uint8_t value;
-    if (!Read(addr, &value, sizeof(value))) {
+    if (!ReadFully(addr, &value, sizeof(value))) {
       return false;
     }
     if (value == '\0') {
@@ -59,16 +114,17 @@
   return std::shared_ptr<Memory>(new MemoryRemote(pid));
 }
 
-bool MemoryBuffer::Read(uint64_t addr, void* dst, size_t size) {
-  uint64_t last_read_byte;
-  if (__builtin_add_overflow(size, addr, &last_read_byte)) {
-    return false;
+size_t MemoryBuffer::Read(uint64_t addr, void* dst, size_t size) {
+  if (addr >= raw_.size()) {
+    return 0;
   }
-  if (last_read_byte > raw_.size()) {
-    return false;
-  }
-  memcpy(dst, &raw_[addr], size);
-  return true;
+
+  size_t bytes_left = raw_.size() - static_cast<size_t>(addr);
+  const unsigned char* actual_base = static_cast<const unsigned char*>(raw_.data()) + addr;
+  size_t actual_len = std::min(bytes_left, size);
+
+  memcpy(dst, actual_base, actual_len);
+  return actual_len;
 }
 
 uint8_t* MemoryBuffer::GetPtr(size_t offset) {
@@ -129,145 +185,77 @@
   return true;
 }
 
-bool MemoryFileAtOffset::Read(uint64_t addr, void* dst, size_t size) {
-  uint64_t max_size;
-  if (__builtin_add_overflow(addr, size, &max_size) || max_size > size_) {
-    return false;
+size_t MemoryFileAtOffset::Read(uint64_t addr, void* dst, size_t size) {
+  if (addr >= size_) {
+    return 0;
   }
-  memcpy(dst, &data_[addr], size);
-  return true;
+
+  size_t bytes_left = size_ - static_cast<size_t>(addr);
+  const unsigned char* actual_base = static_cast<const unsigned char*>(data_) + addr;
+  size_t actual_len = std::min(bytes_left, size);
+
+  memcpy(dst, actual_base, actual_len);
+  return actual_len;
 }
 
-bool MemoryRemote::PtraceRead(uint64_t addr, long* value) {
-#if !defined(__LP64__)
-  // Cannot read an address greater than 32 bits.
-  if (addr > UINT32_MAX) {
-    return false;
-  }
-#endif
-  // ptrace() returns -1 and sets errno when the operation fails.
-  // To disambiguate -1 from a valid result, we clear errno beforehand.
-  errno = 0;
-  *value = ptrace(PTRACE_PEEKTEXT, pid_, reinterpret_cast<void*>(addr), nullptr);
-  if (*value == -1 && errno) {
-    return false;
-  }
-  return true;
+size_t MemoryRemote::Read(uint64_t addr, void* dst, size_t size) {
+  return ProcessVmRead(pid_, dst, addr, size);
 }
 
-bool MemoryRemote::Read(uint64_t addr, void* dst, size_t bytes) {
-  // Make sure that there is no overflow.
-  uint64_t max_size;
-  if (__builtin_add_overflow(addr, bytes, &max_size)) {
-    return false;
-  }
-
-  size_t bytes_read = 0;
-  long data;
-  size_t align_bytes = addr & (sizeof(long) - 1);
-  if (align_bytes != 0) {
-    if (!PtraceRead(addr & ~(sizeof(long) - 1), &data)) {
-      return false;
-    }
-    size_t copy_bytes = std::min(sizeof(long) - align_bytes, bytes);
-    memcpy(dst, reinterpret_cast<uint8_t*>(&data) + align_bytes, copy_bytes);
-    addr += copy_bytes;
-    dst = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(dst) + copy_bytes);
-    bytes -= copy_bytes;
-    bytes_read += copy_bytes;
-  }
-
-  for (size_t i = 0; i < bytes / sizeof(long); i++) {
-    if (!PtraceRead(addr, &data)) {
-      return false;
-    }
-    memcpy(dst, &data, sizeof(long));
-    dst = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(dst) + sizeof(long));
-    addr += sizeof(long);
-    bytes_read += sizeof(long);
-  }
-
-  size_t left_over = bytes & (sizeof(long) - 1);
-  if (left_over) {
-    if (!PtraceRead(addr, &data)) {
-      return false;
-    }
-    memcpy(dst, &data, left_over);
-    bytes_read += left_over;
-  }
-  return true;
+size_t MemoryLocal::Read(uint64_t addr, void* dst, size_t size) {
+  return ProcessVmRead(getpid(), dst, addr, size);
 }
 
-bool MemoryLocal::Read(uint64_t addr, void* dst, size_t size) {
-  // Make sure that there is no overflow.
-  uint64_t max_size;
-  if (__builtin_add_overflow(addr, size, &max_size)) {
-    return false;
+MemoryRange::MemoryRange(const std::shared_ptr<Memory>& memory, uint64_t begin, uint64_t length,
+                         uint64_t offset)
+    : memory_(memory), begin_(begin), length_(length), offset_(offset) {}
+
+size_t MemoryRange::Read(uint64_t addr, void* dst, size_t size) {
+  if (addr < offset_) {
+    return 0;
   }
 
-  // The process_vm_readv call will not always work on remote
-  // processes, so only use it for reads from the current pid.
-  // Use this method to avoid crashes if an address is invalid since
-  // unwind data could try to access any part of the address space.
-  struct iovec local_io;
-  local_io.iov_base = dst;
-  local_io.iov_len = size;
-
-  struct iovec remote_io;
-  remote_io.iov_base = reinterpret_cast<void*>(static_cast<uintptr_t>(addr));
-  remote_io.iov_len = size;
-
-  ssize_t bytes_read = process_vm_readv(getpid(), &local_io, 1, &remote_io, 1, 0);
-  if (bytes_read == -1) {
-    return false;
+  uint64_t read_offset = addr - offset_;
+  if (read_offset >= length_) {
+    return 0;
   }
-  return static_cast<size_t>(bytes_read) == size;
+
+  uint64_t read_length = std::min(static_cast<uint64_t>(size), length_ - read_offset);
+  uint64_t read_addr;
+  if (__builtin_add_overflow(read_offset, begin_, &read_addr)) {
+    return 0;
+  }
+
+  return memory_->Read(read_addr, dst, read_length);
 }
 
 bool MemoryOffline::Init(const std::string& file, uint64_t offset) {
-  if (!MemoryFileAtOffset::Init(file, offset)) {
+  auto memory_file = std::make_shared<MemoryFileAtOffset>();
+  if (!memory_file->Init(file, offset)) {
     return false;
   }
+
   // The first uint64_t value is the start of memory.
-  if (!MemoryFileAtOffset::Read(0, &start_, sizeof(start_))) {
+  uint64_t start;
+  if (!memory_file->ReadFully(0, &start, sizeof(start))) {
     return false;
   }
-  // Subtract the first 64 bit value from the total size.
-  size_ -= sizeof(start_);
+
+  uint64_t size = memory_file->Size();
+  if (__builtin_sub_overflow(size, sizeof(start), &size)) {
+    return false;
+  }
+
+  memory_ = std::make_unique<MemoryRange>(memory_file, sizeof(start), size, start);
   return true;
 }
 
-bool MemoryOffline::Read(uint64_t addr, void* dst, size_t size) {
-  uint64_t max_size;
-  if (__builtin_add_overflow(addr, size, &max_size)) {
-    return false;
+size_t MemoryOffline::Read(uint64_t addr, void* dst, size_t size) {
+  if (!memory_) {
+    return 0;
   }
 
-  uint64_t real_size;
-  if (__builtin_add_overflow(start_, offset_, &real_size) ||
-      __builtin_add_overflow(real_size, size_, &real_size)) {
-    return false;
-  }
-
-  if (addr < start_ || max_size > real_size) {
-    return false;
-  }
-  memcpy(dst, &data_[addr + offset_ - start_ + sizeof(start_)], size);
-  return true;
-}
-
-MemoryRange::MemoryRange(const std::shared_ptr<Memory>& memory, uint64_t begin, uint64_t end)
-    : memory_(memory), begin_(begin), length_(end - begin) {
-  CHECK(end > begin);
-}
-
-bool MemoryRange::Read(uint64_t addr, void* dst, size_t size) {
-  uint64_t max_read;
-  if (__builtin_add_overflow(addr, size, &max_read) || max_read > length_) {
-    return false;
-  }
-  // The check above guarantees that addr + begin_ will not overflow.
-  return memory_->Read(addr + begin_, dst, size);
+  return memory_->Read(addr, dst, size);
 }
 
 }  // namespace unwindstack
diff --git a/libunwindstack/Regs.cpp b/libunwindstack/Regs.cpp
index 36b8e25..28a77dc 100644
--- a/libunwindstack/Regs.cpp
+++ b/libunwindstack/Regs.cpp
@@ -58,7 +58,7 @@
   if (adjusted_rel_pc & 1) {
     // This is a thumb instruction, it could be 2 or 4 bytes.
     uint32_t value;
-    if (rel_pc < 5 || !elf->memory()->Read(adjusted_rel_pc - 5, &value, sizeof(value)) ||
+    if (rel_pc < 5 || !elf->memory()->ReadFully(adjusted_rel_pc - 5, &value, sizeof(value)) ||
         (value & 0xe000f000) != 0xe000f000) {
       return rel_pc - 2;
     }
@@ -193,7 +193,7 @@
 bool RegsX86::SetPcFromReturnAddress(Memory* process_memory) {
   // Attempt to get the return address from the top of the stack.
   uint32_t new_pc;
-  if (!process_memory->Read(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) {
+  if (!process_memory->ReadFully(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) {
     return false;
   }
 
@@ -240,7 +240,7 @@
 bool RegsX86_64::SetPcFromReturnAddress(Memory* process_memory) {
   // Attempt to get the return address from the top of the stack.
   uint64_t new_pc;
-  if (!process_memory->Read(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) {
+  if (!process_memory->ReadFully(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) {
     return false;
   }
 
@@ -474,7 +474,7 @@
   Memory* elf_memory = elf->memory();
   // Read from elf memory since it is usually more expensive to read from
   // process memory.
-  if (!elf_memory->Read(rel_pc, &data, sizeof(data))) {
+  if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data))) {
     return false;
   }
 
@@ -493,7 +493,7 @@
     // Form 3 (thumb):
     // 0x77 0x27              movs r7, #77
     // 0x00 0xdf              svc 0
-    if (!process_memory->Read(sp(), &data, sizeof(data))) {
+    if (!process_memory->ReadFully(sp(), &data, sizeof(data))) {
       return false;
     }
     if (data == 0x5ac3c35a) {
@@ -517,7 +517,7 @@
     // Form 3 (thumb):
     // 0xad 0x27              movs r7, #ad
     // 0x00 0xdf              svc 0
-    if (!process_memory->Read(sp(), &data, sizeof(data))) {
+    if (!process_memory->ReadFully(sp(), &data, sizeof(data))) {
       return false;
     }
     if (data == sp() + 8) {
@@ -532,7 +532,7 @@
     return false;
   }
 
-  if (!process_memory->Read(offset, regs_.data(), sizeof(uint32_t) * ARM_REG_LAST)) {
+  if (!process_memory->ReadFully(offset, regs_.data(), sizeof(uint32_t) * ARM_REG_LAST)) {
     return false;
   }
   SetFromRaw();
@@ -544,7 +544,7 @@
   Memory* elf_memory = elf->memory();
   // Read from elf memory since it is usually more expensive to read from
   // process memory.
-  if (!elf_memory->Read(rel_pc, &data, sizeof(data))) {
+  if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data))) {
     return false;
   }
 
@@ -557,8 +557,8 @@
   }
 
   // SP + sizeof(siginfo_t) + uc_mcontext offset + X0 offset.
-  if (!process_memory->Read(sp() + 0x80 + 0xb0 + 0x08, regs_.data(),
-                            sizeof(uint64_t) * ARM64_REG_LAST)) {
+  if (!process_memory->ReadFully(sp() + 0x80 + 0xb0 + 0x08, regs_.data(),
+                                 sizeof(uint64_t) * ARM64_REG_LAST)) {
     return false;
   }
 
@@ -571,7 +571,7 @@
   Memory* elf_memory = elf->memory();
   // Read from elf memory since it is usually more expensive to read from
   // process memory.
-  if (!elf_memory->Read(rel_pc, &data, sizeof(data))) {
+  if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data))) {
     return false;
   }
 
@@ -587,7 +587,7 @@
     //   int signum
     //   struct sigcontext (same format as mcontext)
     struct x86_mcontext_t context;
-    if (!process_memory->Read(sp() + 4, &context, sizeof(context))) {
+    if (!process_memory->ReadFully(sp() + 4, &context, sizeof(context))) {
       return false;
     }
     regs_[X86_REG_EBP] = context.ebp;
@@ -613,12 +613,12 @@
 
     // Get the location of the sigcontext data.
     uint32_t ptr;
-    if (!process_memory->Read(sp() + 8, &ptr, sizeof(ptr))) {
+    if (!process_memory->ReadFully(sp() + 8, &ptr, sizeof(ptr))) {
       return false;
     }
     // Only read the portion of the data structure we care about.
     x86_ucontext_t x86_ucontext;
-    if (!process_memory->Read(ptr + 0x14, &x86_ucontext.uc_mcontext, sizeof(x86_mcontext_t))) {
+    if (!process_memory->ReadFully(ptr + 0x14, &x86_ucontext.uc_mcontext, sizeof(x86_mcontext_t))) {
       return false;
     }
     SetFromUcontext(&x86_ucontext);
@@ -632,12 +632,12 @@
   Memory* elf_memory = elf->memory();
   // Read from elf memory since it is usually more expensive to read from
   // process memory.
-  if (!elf_memory->Read(rel_pc, &data, sizeof(data)) || data != 0x0f0000000fc0c748) {
+  if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data)) || data != 0x0f0000000fc0c748) {
     return false;
   }
 
   uint16_t data2;
-  if (!elf_memory->Read(rel_pc + 8, &data2, sizeof(data2)) || data2 != 0x0f05) {
+  if (!elf_memory->ReadFully(rel_pc + 8, &data2, sizeof(data2)) || data2 != 0x0f05) {
     return false;
   }
 
@@ -649,7 +649,8 @@
   // Read the mcontext data from the stack.
   // sp points to the ucontext data structure, read only the mcontext part.
   x86_64_ucontext_t x86_64_ucontext;
-  if (!process_memory->Read(sp() + 0x28, &x86_64_ucontext.uc_mcontext, sizeof(x86_64_mcontext_t))) {
+  if (!process_memory->ReadFully(sp() + 0x28, &x86_64_ucontext.uc_mcontext,
+                                 sizeof(x86_64_mcontext_t))) {
     return false;
   }
   SetFromUcontext(&x86_64_ucontext);
diff --git a/libunwindstack/Symbols.cpp b/libunwindstack/Symbols.cpp
index 42d816a..b4b92d6 100644
--- a/libunwindstack/Symbols.cpp
+++ b/libunwindstack/Symbols.cpp
@@ -71,7 +71,7 @@
   bool return_value = false;
   while (cur_offset_ + entry_size_ <= end_) {
     SymType entry;
-    if (!elf_memory->Read(cur_offset_, &entry, sizeof(entry))) {
+    if (!elf_memory->ReadFully(cur_offset_, &entry, sizeof(entry))) {
       // Stop all processing, something looks like it is corrupted.
       cur_offset_ = UINT64_MAX;
       return false;
diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h
index 183b899..8163152 100644
--- a/libunwindstack/include/unwindstack/Memory.h
+++ b/libunwindstack/include/unwindstack/Memory.h
@@ -36,7 +36,9 @@
 
   virtual bool ReadString(uint64_t addr, std::string* string, uint64_t max_read = UINT64_MAX);
 
-  virtual bool Read(uint64_t addr, void* dst, size_t size) = 0;
+  virtual size_t Read(uint64_t addr, void* dst, size_t size) = 0;
+
+  bool ReadFully(uint64_t addr, void* dst, size_t size);
 
   inline bool ReadField(uint64_t addr, void* start, void* field, size_t size) {
     if (reinterpret_cast<uintptr_t>(field) < reinterpret_cast<uintptr_t>(start)) {
@@ -47,12 +49,16 @@
       return false;
     }
     // The read will check if offset + size overflows.
-    return Read(offset, field, size);
+    return ReadFully(offset, field, size);
   }
 
-  inline bool Read32(uint64_t addr, uint32_t* dst) { return Read(addr, dst, sizeof(uint32_t)); }
+  inline bool Read32(uint64_t addr, uint32_t* dst) {
+    return ReadFully(addr, dst, sizeof(uint32_t));
+  }
 
-  inline bool Read64(uint64_t addr, uint64_t* dst) { return Read(addr, dst, sizeof(uint64_t)); }
+  inline bool Read64(uint64_t addr, uint64_t* dst) {
+    return ReadFully(addr, dst, sizeof(uint64_t));
+  }
 };
 
 class MemoryBuffer : public Memory {
@@ -60,7 +66,7 @@
   MemoryBuffer() = default;
   virtual ~MemoryBuffer() = default;
 
-  bool Read(uint64_t addr, void* dst, size_t size) override;
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
 
   uint8_t* GetPtr(size_t offset);
 
@@ -79,7 +85,9 @@
 
   bool Init(const std::string& file, uint64_t offset, uint64_t size = UINT64_MAX);
 
-  bool Read(uint64_t addr, void* dst, size_t size) override;
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
+
+  size_t Size() { return size_; }
 
   void Clear();
 
@@ -89,31 +97,15 @@
   uint8_t* data_ = nullptr;
 };
 
-class MemoryOffline : public MemoryFileAtOffset {
- public:
-  MemoryOffline() = default;
-  virtual ~MemoryOffline() = default;
-
-  bool Init(const std::string& file, uint64_t offset);
-
-  bool Read(uint64_t addr, void* dst, size_t size) override;
-
- private:
-  uint64_t start_;
-};
-
 class MemoryRemote : public Memory {
  public:
   MemoryRemote(pid_t pid) : pid_(pid) {}
   virtual ~MemoryRemote() = default;
 
-  bool Read(uint64_t addr, void* dst, size_t size) override;
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
 
   pid_t pid() { return pid_; }
 
- protected:
-  virtual bool PtraceRead(uint64_t addr, long* value);
-
  private:
   pid_t pid_;
 };
@@ -123,20 +115,38 @@
   MemoryLocal() = default;
   virtual ~MemoryLocal() = default;
 
-  bool Read(uint64_t addr, void* dst, size_t size) override;
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
 };
 
+// MemoryRange maps one address range onto another.
+// The range [src_begin, src_begin + length) in the underlying Memory is mapped onto offset,
+// such that range.read(offset) is equivalent to underlying.read(src_begin).
 class MemoryRange : public Memory {
  public:
-  MemoryRange(const std::shared_ptr<Memory>& memory, uint64_t begin, uint64_t end);
+  MemoryRange(const std::shared_ptr<Memory>& memory, uint64_t begin, uint64_t length,
+              uint64_t offset);
   virtual ~MemoryRange() = default;
 
-  bool Read(uint64_t addr, void* dst, size_t size) override;
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
 
  private:
   std::shared_ptr<Memory> memory_;
   uint64_t begin_;
   uint64_t length_;
+  uint64_t offset_;
+};
+
+class MemoryOffline : public Memory {
+ public:
+  MemoryOffline() = default;
+  virtual ~MemoryOffline() = default;
+
+  bool Init(const std::string& file, uint64_t offset);
+
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
+
+ private:
+  std::unique_ptr<MemoryRange> memory_;
 };
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
index bdcb652..866b5b4 100644
--- a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
+++ b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
@@ -120,14 +120,14 @@
 
   // Read the entire file.
   std::vector<uint8_t> buffer(1024);
-  ASSERT_TRUE(memory->Read(0, buffer.data(), 1024));
+  ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 1024));
   ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0);
   ASSERT_EQ(ELFCLASS32, buffer[EI_CLASS]);
   for (size_t i = EI_CLASS + 1; i < buffer.size(); i++) {
     ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
   }
 
-  ASSERT_FALSE(memory->Read(1024, buffer.data(), 1));
+  ASSERT_FALSE(memory->ReadFully(1024, buffer.data(), 1));
 }
 
 // Verify that if the offset is non-zero and there is an elf at that
@@ -141,14 +141,14 @@
 
   // Read the valid part of the file.
   std::vector<uint8_t> buffer(0x100);
-  ASSERT_TRUE(memory->Read(0, buffer.data(), 0x100));
+  ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 0x100));
   ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0);
   ASSERT_EQ(ELFCLASS64, buffer[EI_CLASS]);
   for (size_t i = EI_CLASS + 1; i < buffer.size(); i++) {
     ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
   }
 
-  ASSERT_FALSE(memory->Read(0x100, buffer.data(), 1));
+  ASSERT_FALSE(memory->ReadFully(0x100, buffer.data(), 1));
 }
 
 // Verify that if the offset is non-zero and there is an elf at that
@@ -164,11 +164,11 @@
 
   // Verify the memory is a valid elf.
   uint8_t e_ident[SELFMAG + 1];
-  ASSERT_TRUE(memory->Read(0, e_ident, SELFMAG));
+  ASSERT_TRUE(memory->ReadFully(0, e_ident, SELFMAG));
   ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG));
 
   // Read past the end of what would normally be the size of the map.
-  ASSERT_TRUE(memory->Read(0x1000, e_ident, 1));
+  ASSERT_TRUE(memory->ReadFully(0x1000, e_ident, 1));
 }
 
 TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
@@ -180,11 +180,11 @@
 
   // Verify the memory is a valid elf.
   uint8_t e_ident[SELFMAG + 1];
-  ASSERT_TRUE(memory->Read(0, e_ident, SELFMAG));
+  ASSERT_TRUE(memory->ReadFully(0, e_ident, SELFMAG));
   ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG));
 
   // Read past the end of what would normally be the size of the map.
-  ASSERT_TRUE(memory->Read(0x1000, e_ident, 1));
+  ASSERT_TRUE(memory->ReadFully(0x1000, e_ident, 1));
 }
 
 // Verify that device file names will never result in Memory object creation.
@@ -221,13 +221,13 @@
   ASSERT_TRUE(memory.get() != nullptr);
 
   memset(buffer.data(), 0, buffer.size());
-  ASSERT_TRUE(memory->Read(0, buffer.data(), buffer.size()));
+  ASSERT_TRUE(memory->ReadFully(0, buffer.data(), buffer.size()));
   for (size_t i = 0; i < buffer.size(); i++) {
     ASSERT_EQ(i % 256, buffer[i]) << "Failed at byte " << i;
   }
 
   // Try to read outside of the map size.
-  ASSERT_FALSE(memory->Read(buffer.size(), buffer.data(), 1));
+  ASSERT_FALSE(memory->ReadFully(buffer.size(), buffer.data(), 1));
 }
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/MapInfoGetElfTest.cpp b/libunwindstack/tests/MapInfoGetElfTest.cpp
index 9973794..948597b 100644
--- a/libunwindstack/tests/MapInfoGetElfTest.cpp
+++ b/libunwindstack/tests/MapInfoGetElfTest.cpp
@@ -216,13 +216,13 @@
 
   // Read the entire file.
   memset(buffer.data(), 0, buffer.size());
-  ASSERT_TRUE(elf->memory()->Read(0, buffer.data(), buffer.size()));
+  ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), buffer.size()));
   ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
   for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
     ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
   }
 
-  ASSERT_FALSE(elf->memory()->Read(buffer.size(), buffer.data(), 1));
+  ASSERT_FALSE(elf->memory()->ReadFully(buffer.size(), buffer.data(), 1));
 }
 
 // Verify that if the offset is non-zero and there is an elf at that
@@ -244,13 +244,13 @@
   ASSERT_EQ(0U, info.elf_offset);
 
   // Read the valid part of the file.
-  ASSERT_TRUE(elf->memory()->Read(0, buffer.data(), 0x1000));
+  ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
   ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
   for (size_t i = sizeof(ehdr); i < 0x1000; i++) {
     ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
   }
 
-  ASSERT_FALSE(elf->memory()->Read(0x1000, buffer.data(), 1));
+  ASSERT_FALSE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
 }
 
 // Verify that if the offset is non-zero and there is an elf at that
@@ -278,11 +278,11 @@
 
   // Verify the memory is a valid elf.
   memset(buffer.data(), 0, buffer.size());
-  ASSERT_TRUE(elf->memory()->Read(0, buffer.data(), 0x1000));
+  ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
   ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
 
   // Read past the end of what would normally be the size of the map.
-  ASSERT_TRUE(elf->memory()->Read(0x1000, buffer.data(), 1));
+  ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
 }
 
 TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
@@ -306,11 +306,11 @@
 
   // Verify the memory is a valid elf.
   memset(buffer.data(), 0, buffer.size());
-  ASSERT_TRUE(elf->memory()->Read(0, buffer.data(), 0x1000));
+  ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
   ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
 
   // Read past the end of what would normally be the size of the map.
-  ASSERT_TRUE(elf->memory()->Read(0x1000, buffer.data(), 1));
+  ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
 }
 
 TEST_F(MapInfoGetElfTest, process_memory_not_read_only) {
diff --git a/libunwindstack/tests/MemoryBufferTest.cpp b/libunwindstack/tests/MemoryBufferTest.cpp
index 50a8a1b..28e0e76 100644
--- a/libunwindstack/tests/MemoryBufferTest.cpp
+++ b/libunwindstack/tests/MemoryBufferTest.cpp
@@ -36,7 +36,7 @@
 TEST_F(MemoryBufferTest, empty) {
   ASSERT_EQ(0U, memory_->Size());
   std::vector<uint8_t> buffer(1024);
-  ASSERT_FALSE(memory_->Read(0, buffer.data(), 1));
+  ASSERT_FALSE(memory_->ReadFully(0, buffer.data(), 1));
   ASSERT_EQ(nullptr, memory_->GetPtr(0));
   ASSERT_EQ(nullptr, memory_->GetPtr(1));
 }
@@ -55,7 +55,7 @@
   }
 
   std::vector<uint8_t> buffer(memory_->Size());
-  ASSERT_TRUE(memory_->Read(0, buffer.data(), buffer.size()));
+  ASSERT_TRUE(memory_->ReadFully(0, buffer.data(), buffer.size()));
   for (size_t i = 0; i < buffer.size(); i++) {
     ASSERT_EQ(i, buffer[i]) << "Failed at byte " << i;
   }
@@ -64,18 +64,38 @@
 TEST_F(MemoryBufferTest, read_failures) {
   memory_->Resize(100);
   std::vector<uint8_t> buffer(200);
-  ASSERT_FALSE(memory_->Read(0, buffer.data(), 101));
-  ASSERT_FALSE(memory_->Read(100, buffer.data(), 1));
-  ASSERT_FALSE(memory_->Read(101, buffer.data(), 2));
-  ASSERT_FALSE(memory_->Read(99, buffer.data(), 2));
-  ASSERT_TRUE(memory_->Read(99, buffer.data(), 1));
+  ASSERT_FALSE(memory_->ReadFully(0, buffer.data(), 101));
+  ASSERT_FALSE(memory_->ReadFully(100, buffer.data(), 1));
+  ASSERT_FALSE(memory_->ReadFully(101, buffer.data(), 2));
+  ASSERT_FALSE(memory_->ReadFully(99, buffer.data(), 2));
+  ASSERT_TRUE(memory_->ReadFully(99, buffer.data(), 1));
 }
 
 TEST_F(MemoryBufferTest, read_failure_overflow) {
   memory_->Resize(100);
   std::vector<uint8_t> buffer(200);
 
-  ASSERT_FALSE(memory_->Read(UINT64_MAX - 100, buffer.data(), 200));
+  ASSERT_FALSE(memory_->ReadFully(UINT64_MAX - 100, buffer.data(), 200));
+}
+
+TEST_F(MemoryBufferTest, Read) {
+  memory_->Resize(256);
+  ASSERT_EQ(256U, memory_->Size());
+  ASSERT_TRUE(memory_->GetPtr(0) != nullptr);
+  ASSERT_TRUE(memory_->GetPtr(1) != nullptr);
+  ASSERT_TRUE(memory_->GetPtr(255) != nullptr);
+  ASSERT_TRUE(memory_->GetPtr(256) == nullptr);
+
+  uint8_t* data = memory_->GetPtr(0);
+  for (size_t i = 0; i < memory_->Size(); i++) {
+    data[i] = i;
+  }
+
+  std::vector<uint8_t> buffer(memory_->Size());
+  ASSERT_EQ(128U, memory_->Read(128, buffer.data(), buffer.size()));
+  for (size_t i = 0; i < 128; i++) {
+    ASSERT_EQ(128 + i, buffer[i]) << "Failed at byte " << i;
+  }
 }
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryFake.cpp b/libunwindstack/tests/MemoryFake.cpp
index 2026acc..60936cd 100644
--- a/libunwindstack/tests/MemoryFake.cpp
+++ b/libunwindstack/tests/MemoryFake.cpp
@@ -35,16 +35,16 @@
   }
 }
 
-bool MemoryFake::Read(uint64_t addr, void* memory, size_t size) {
+size_t MemoryFake::Read(uint64_t addr, void* memory, size_t size) {
   uint8_t* dst = reinterpret_cast<uint8_t*>(memory);
   for (size_t i = 0; i < size; i++, addr++) {
     auto value = data_.find(addr);
     if (value == data_.end()) {
-      return false;
+      return i;
     }
     dst[i] = value->second;
   }
-  return true;
+  return size;
 }
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryFake.h b/libunwindstack/tests/MemoryFake.h
index d374261..764a6c3 100644
--- a/libunwindstack/tests/MemoryFake.h
+++ b/libunwindstack/tests/MemoryFake.h
@@ -32,7 +32,7 @@
   MemoryFake() = default;
   virtual ~MemoryFake() = default;
 
-  bool Read(uint64_t addr, void* buffer, size_t size) override;
+  size_t Read(uint64_t addr, void* buffer, size_t size) override;
 
   void SetMemory(uint64_t addr, const void* memory, size_t length);
 
@@ -71,21 +71,9 @@
   MemoryFakeAlwaysReadZero() = default;
   virtual ~MemoryFakeAlwaysReadZero() = default;
 
-  bool Read(uint64_t, void* buffer, size_t size) override {
+  size_t Read(uint64_t, void* buffer, size_t size) override {
     memset(buffer, 0, size);
-    return true;
-  }
-};
-
-class MemoryFakeRemote : public MemoryRemote {
- public:
-  MemoryFakeRemote() : MemoryRemote(0) {}
-  virtual ~MemoryFakeRemote() = default;
-
- protected:
-  bool PtraceRead(uint64_t, long* value) override {
-    *value = 0;
-    return true;
+    return size;
   }
 };
 
diff --git a/libunwindstack/tests/MemoryFileTest.cpp b/libunwindstack/tests/MemoryFileTest.cpp
index a204bae..d7d1ace 100644
--- a/libunwindstack/tests/MemoryFileTest.cpp
+++ b/libunwindstack/tests/MemoryFileTest.cpp
@@ -49,7 +49,7 @@
 
   ASSERT_TRUE(memory_.Init(tf_->path, 0));
   std::vector<char> buffer(11);
-  ASSERT_TRUE(memory_.Read(0, buffer.data(), 10));
+  ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10));
   buffer[10] = '\0';
   ASSERT_STREQ("0123456789", buffer.data());
 }
@@ -59,7 +59,7 @@
 
   ASSERT_TRUE(memory_.Init(tf_->path, 10));
   std::vector<char> buffer(11);
-  ASSERT_TRUE(memory_.Read(0, buffer.data(), 10));
+  ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10));
   buffer[10] = '\0';
   ASSERT_STREQ("abcdefghij", buffer.data());
 }
@@ -75,7 +75,7 @@
 
   ASSERT_TRUE(memory_.Init(tf_->path, pagesize + 15));
   std::vector<char> buffer(9);
-  ASSERT_TRUE(memory_.Read(0, buffer.data(), 8));
+  ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 8));
   buffer[8] = '\0';
   ASSERT_STREQ("abcdefgh", buffer.data());
 }
@@ -91,7 +91,7 @@
 
   ASSERT_TRUE(memory_.Init(tf_->path, 2 * pagesize));
   std::vector<char> buffer(11);
-  ASSERT_TRUE(memory_.Read(0, buffer.data(), 10));
+  ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10));
   buffer[10] = '\0';
   std::string expected_str;
   for (size_t i = 0; i < 5; i++) {
@@ -112,7 +112,7 @@
 
   ASSERT_TRUE(memory_.Init(tf_->path, 2 * pagesize + 10));
   std::vector<char> buffer(11);
-  ASSERT_TRUE(memory_.Read(0, buffer.data(), 10));
+  ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10));
   buffer[10] = '\0';
   std::string expected_str;
   for (size_t i = 0; i < 5; i++) {
@@ -149,19 +149,19 @@
   std::vector<char> buffer(100);
 
   // Read before init.
-  ASSERT_FALSE(memory_.Read(0, buffer.data(), 10));
+  ASSERT_FALSE(memory_.ReadFully(0, buffer.data(), 10));
 
   ASSERT_TRUE(memory_.Init(tf_->path, 0));
 
-  ASSERT_FALSE(memory_.Read(10000, buffer.data(), 10));
-  ASSERT_FALSE(memory_.Read(5000, buffer.data(), 10));
-  ASSERT_FALSE(memory_.Read(4990, buffer.data(), 11));
-  ASSERT_TRUE(memory_.Read(4990, buffer.data(), 10));
-  ASSERT_FALSE(memory_.Read(4999, buffer.data(), 2));
-  ASSERT_TRUE(memory_.Read(4999, buffer.data(), 1));
+  ASSERT_FALSE(memory_.ReadFully(10000, buffer.data(), 10));
+  ASSERT_FALSE(memory_.ReadFully(5000, buffer.data(), 10));
+  ASSERT_FALSE(memory_.ReadFully(4990, buffer.data(), 11));
+  ASSERT_TRUE(memory_.ReadFully(4990, buffer.data(), 10));
+  ASSERT_FALSE(memory_.ReadFully(4999, buffer.data(), 2));
+  ASSERT_TRUE(memory_.ReadFully(4999, buffer.data(), 1));
 
   // Check that overflow fails properly.
-  ASSERT_FALSE(memory_.Read(UINT64_MAX - 100, buffer.data(), 200));
+  ASSERT_FALSE(memory_.ReadFully(UINT64_MAX - 100, buffer.data(), 200));
 }
 
 TEST_F(MemoryFileTest, read_past_file_within_mapping) {
@@ -178,7 +178,8 @@
 
   for (size_t i = 0; i < 100; i++) {
     uint8_t value;
-    ASSERT_FALSE(memory_.Read(buffer.size() + i, &value, 1)) << "Should have failed at value " << i;
+    ASSERT_FALSE(memory_.ReadFully(buffer.size() + i, &value, 1))
+        << "Should have failed at value " << i;
   }
 }
 
@@ -195,8 +196,8 @@
 
   std::vector<uint8_t> read_buffer(pagesize * 2);
   // Make sure that reading after mapped data is a failure.
-  ASSERT_FALSE(memory_.Read(pagesize * 2, read_buffer.data(), 1));
-  ASSERT_TRUE(memory_.Read(0, read_buffer.data(), pagesize * 2));
+  ASSERT_FALSE(memory_.ReadFully(pagesize * 2, read_buffer.data(), 1));
+  ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize * 2));
   for (size_t i = 0; i < pagesize; i++) {
     ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i;
   }
@@ -219,8 +220,8 @@
 
   std::vector<uint8_t> read_buffer(pagesize * 2);
   // Make sure that reading after mapped data is a failure.
-  ASSERT_FALSE(memory_.Read(pagesize * 2, read_buffer.data(), 1));
-  ASSERT_TRUE(memory_.Read(0, read_buffer.data(), pagesize * 2));
+  ASSERT_FALSE(memory_.ReadFully(pagesize * 2, read_buffer.data(), 1));
+  ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize * 2));
   for (size_t i = 0; i < pagesize - 0x100; i++) {
     ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i;
   }
@@ -245,8 +246,8 @@
   ASSERT_TRUE(memory_.Init(tf_->path, pagesize + 0x100, UINT64_MAX));
 
   std::vector<uint8_t> read_buffer(pagesize * 10);
-  ASSERT_FALSE(memory_.Read(pagesize * 9 - 0x100 + 1, read_buffer.data(), 1));
-  ASSERT_TRUE(memory_.Read(0, read_buffer.data(), pagesize * 9 - 0x100));
+  ASSERT_FALSE(memory_.ReadFully(pagesize * 9 - 0x100 + 1, read_buffer.data(), 1));
+  ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize * 9 - 0x100));
 }
 
 TEST_F(MemoryFileTest, init_reinit) {
@@ -259,14 +260,14 @@
 
   ASSERT_TRUE(memory_.Init(tf_->path, 0));
   std::vector<uint8_t> read_buffer(buffer.size());
-  ASSERT_TRUE(memory_.Read(0, read_buffer.data(), pagesize));
+  ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize));
   for (size_t i = 0; i < pagesize; i++) {
     ASSERT_EQ(1, read_buffer[i]) << "Failed at byte " << i;
   }
 
   // Now reinit.
   ASSERT_TRUE(memory_.Init(tf_->path, pagesize));
-  ASSERT_TRUE(memory_.Read(0, read_buffer.data(), pagesize));
+  ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize));
   for (size_t i = 0; i < pagesize; i++) {
     ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i;
   }
diff --git a/libunwindstack/tests/MemoryLocalTest.cpp b/libunwindstack/tests/MemoryLocalTest.cpp
index 73eebdd..5a389d0 100644
--- a/libunwindstack/tests/MemoryLocalTest.cpp
+++ b/libunwindstack/tests/MemoryLocalTest.cpp
@@ -16,6 +16,7 @@
 
 #include <stdint.h>
 #include <string.h>
+#include <sys/mman.h>
 
 #include <vector>
 
@@ -32,14 +33,14 @@
   MemoryLocal local;
 
   std::vector<uint8_t> dst(1024);
-  ASSERT_TRUE(local.Read(reinterpret_cast<uint64_t>(src.data()), dst.data(), 1024));
+  ASSERT_TRUE(local.ReadFully(reinterpret_cast<uint64_t>(src.data()), dst.data(), 1024));
   ASSERT_EQ(0, memcmp(src.data(), dst.data(), 1024));
   for (size_t i = 0; i < 1024; i++) {
     ASSERT_EQ(0x4cU, dst[i]);
   }
 
   memset(src.data(), 0x23, 512);
-  ASSERT_TRUE(local.Read(reinterpret_cast<uint64_t>(src.data()), dst.data(), 1024));
+  ASSERT_TRUE(local.ReadFully(reinterpret_cast<uint64_t>(src.data()), dst.data(), 1024));
   ASSERT_EQ(0, memcmp(src.data(), dst.data(), 1024));
   for (size_t i = 0; i < 512; i++) {
     ASSERT_EQ(0x23U, dst[i]);
@@ -53,8 +54,8 @@
   MemoryLocal local;
 
   std::vector<uint8_t> dst(100);
-  ASSERT_FALSE(local.Read(0, dst.data(), 1));
-  ASSERT_FALSE(local.Read(0, dst.data(), 100));
+  ASSERT_FALSE(local.ReadFully(0, dst.data(), 1));
+  ASSERT_FALSE(local.ReadFully(0, dst.data(), 100));
 }
 
 TEST(MemoryLocalTest, read_overflow) {
@@ -64,7 +65,47 @@
   // version will always go through the overflow check.
   std::vector<uint8_t> dst(100);
   uint64_t value;
-  ASSERT_FALSE(local.Read(reinterpret_cast<uint64_t>(&value), dst.data(), SIZE_MAX));
+  ASSERT_FALSE(local.ReadFully(reinterpret_cast<uint64_t>(&value), dst.data(), SIZE_MAX));
+}
+
+TEST(MemoryLocalTest, Read) {
+  char* mapping = static_cast<char*>(
+      mmap(nullptr, 2 * getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
+
+  ASSERT_NE(MAP_FAILED, mapping);
+
+  mprotect(mapping + getpagesize(), getpagesize(), PROT_NONE);
+  memset(mapping + getpagesize() - 1024, 0x4c, 1024);
+
+  MemoryLocal local;
+
+  std::vector<uint8_t> dst(4096);
+  ASSERT_EQ(1024U, local.Read(reinterpret_cast<uint64_t>(mapping + getpagesize() - 1024),
+                              dst.data(), 4096));
+  for (size_t i = 0; i < 1024; i++) {
+    ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
+  }
+
+  ASSERT_EQ(0, munmap(mapping, 2 * getpagesize()));
+}
+
+TEST(MemoryLocalTest, read_hole) {
+  void* mapping =
+      mmap(nullptr, 3 * 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+  ASSERT_NE(MAP_FAILED, mapping);
+  memset(mapping, 0xFF, 3 * 4096);
+  mprotect(static_cast<char*>(mapping) + 4096, 4096, PROT_NONE);
+
+  MemoryLocal local;
+  std::vector<uint8_t> dst(4096 * 3, 0xCC);
+  ASSERT_EQ(4096U, local.Read(reinterpret_cast<uintptr_t>(mapping), dst.data(), 4096 * 3));
+  for (size_t i = 0; i < 4096; ++i) {
+    ASSERT_EQ(0xFF, dst[i]);
+  }
+  for (size_t i = 4096; i < 4096 * 3; ++i) {
+    ASSERT_EQ(0xCC, dst[i]);
+  }
+  ASSERT_EQ(0, munmap(mapping, 3 * 4096));
 }
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryRangeTest.cpp b/libunwindstack/tests/MemoryRangeTest.cpp
index 680fae9..cb1a0c9 100644
--- a/libunwindstack/tests/MemoryRangeTest.cpp
+++ b/libunwindstack/tests/MemoryRangeTest.cpp
@@ -35,10 +35,10 @@
   std::shared_ptr<Memory> process_memory(memory_fake);
   memory_fake->SetMemory(9001, src);
 
-  MemoryRange range(process_memory, 9001, 9001 + src.size());
+  MemoryRange range(process_memory, 9001, src.size(), 0);
 
   std::vector<uint8_t> dst(1024);
-  ASSERT_TRUE(range.Read(0, dst.data(), src.size()));
+  ASSERT_TRUE(range.ReadFully(0, dst.data(), src.size()));
   for (size_t i = 0; i < 1024; i++) {
     ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
   }
@@ -51,29 +51,44 @@
   std::shared_ptr<Memory> process_memory(memory_fake);
   memory_fake->SetMemory(1000, src);
 
-  MemoryRange range(process_memory, 1000, 2024);
+  MemoryRange range(process_memory, 1000, 1024, 0);
 
   std::vector<uint8_t> dst(1024);
-  ASSERT_TRUE(range.Read(1020, dst.data(), 4));
+  ASSERT_TRUE(range.ReadFully(1020, dst.data(), 4));
   for (size_t i = 0; i < 4; i++) {
     ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
   }
 
   // Verify that reads outside of the range will fail.
-  ASSERT_FALSE(range.Read(1020, dst.data(), 5));
-  ASSERT_FALSE(range.Read(1024, dst.data(), 1));
-  ASSERT_FALSE(range.Read(1024, dst.data(), 1024));
+  ASSERT_FALSE(range.ReadFully(1020, dst.data(), 5));
+  ASSERT_FALSE(range.ReadFully(1024, dst.data(), 1));
+  ASSERT_FALSE(range.ReadFully(1024, dst.data(), 1024));
 
   // Verify that reading up to the end works.
-  ASSERT_TRUE(range.Read(1020, dst.data(), 4));
+  ASSERT_TRUE(range.ReadFully(1020, dst.data(), 4));
 }
 
 TEST(MemoryRangeTest, read_overflow) {
   std::vector<uint8_t> buffer(100);
 
   std::shared_ptr<Memory> process_memory(new MemoryFakeAlwaysReadZero);
-  std::unique_ptr<MemoryRange> overflow(new MemoryRange(process_memory, 100, 200));
-  ASSERT_FALSE(overflow->Read(UINT64_MAX - 10, buffer.data(), 100));
+  std::unique_ptr<MemoryRange> overflow(new MemoryRange(process_memory, 100, 200, 0));
+  ASSERT_FALSE(overflow->ReadFully(UINT64_MAX - 10, buffer.data(), 100));
+}
+
+TEST(MemoryRangeTest, Read) {
+  std::vector<uint8_t> src(4096);
+  memset(src.data(), 0x4c, 4096);
+  MemoryFake* memory_fake = new MemoryFake;
+  std::shared_ptr<Memory> process_memory(memory_fake);
+  memory_fake->SetMemory(1000, src);
+
+  MemoryRange range(process_memory, 1000, 1024, 0);
+  std::vector<uint8_t> dst(1024);
+  ASSERT_EQ(4U, range.Read(1020, dst.data(), 1024));
+  for (size_t i = 0; i < 4; i++) {
+    ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
+  }
 }
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryRemoteTest.cpp b/libunwindstack/tests/MemoryRemoteTest.cpp
index a66d0c5..8aa4c3f 100644
--- a/libunwindstack/tests/MemoryRemoteTest.cpp
+++ b/libunwindstack/tests/MemoryRemoteTest.cpp
@@ -71,7 +71,7 @@
   MemoryRemote remote(pid);
 
   std::vector<uint8_t> dst(1024);
-  ASSERT_TRUE(remote.Read(reinterpret_cast<uint64_t>(src.data()), dst.data(), 1024));
+  ASSERT_TRUE(remote.ReadFully(reinterpret_cast<uint64_t>(src.data()), dst.data(), 1024));
   for (size_t i = 0; i < 1024; i++) {
     ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
   }
@@ -79,6 +79,39 @@
   ASSERT_TRUE(Detach(pid));
 }
 
+TEST_F(MemoryRemoteTest, Read) {
+  char* mapping = static_cast<char*>(
+      mmap(nullptr, 2 * getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
+
+  ASSERT_NE(MAP_FAILED, mapping);
+
+  mprotect(mapping + getpagesize(), getpagesize(), PROT_NONE);
+  memset(mapping + getpagesize() - 1024, 0x4c, 1024);
+
+  pid_t pid;
+  if ((pid = fork()) == 0) {
+    while (true)
+      ;
+    exit(1);
+  }
+  ASSERT_LT(0, pid);
+  TestScopedPidReaper reap(pid);
+
+  ASSERT_TRUE(Attach(pid));
+
+  MemoryRemote remote(pid);
+
+  std::vector<uint8_t> dst(4096);
+  ASSERT_EQ(1024U, remote.Read(reinterpret_cast<uint64_t>(mapping + getpagesize() - 1024),
+                               dst.data(), 4096));
+  for (size_t i = 0; i < 1024; i++) {
+    ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
+  }
+
+  ASSERT_TRUE(Detach(pid));
+  ASSERT_EQ(0, munmap(mapping, 2 * getpagesize()));
+}
+
 TEST_F(MemoryRemoteTest, read_fail) {
   int pagesize = getpagesize();
   void* src = mmap(nullptr, pagesize * 2, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,-1, 0);
@@ -101,17 +134,17 @@
   MemoryRemote remote(pid);
 
   std::vector<uint8_t> dst(pagesize);
-  ASSERT_TRUE(remote.Read(reinterpret_cast<uint64_t>(src), dst.data(), pagesize));
+  ASSERT_TRUE(remote.ReadFully(reinterpret_cast<uint64_t>(src), dst.data(), pagesize));
   for (size_t i = 0; i < 1024; i++) {
     ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
   }
 
-  ASSERT_FALSE(remote.Read(reinterpret_cast<uint64_t>(src) + pagesize, dst.data(), 1));
-  ASSERT_TRUE(remote.Read(reinterpret_cast<uint64_t>(src) + pagesize - 1, dst.data(), 1));
-  ASSERT_FALSE(remote.Read(reinterpret_cast<uint64_t>(src) + pagesize - 4, dst.data(), 8));
+  ASSERT_FALSE(remote.ReadFully(reinterpret_cast<uint64_t>(src) + pagesize, dst.data(), 1));
+  ASSERT_TRUE(remote.ReadFully(reinterpret_cast<uint64_t>(src) + pagesize - 1, dst.data(), 1));
+  ASSERT_FALSE(remote.ReadFully(reinterpret_cast<uint64_t>(src) + pagesize - 4, dst.data(), 8));
 
   // Check overflow condition is caught properly.
-  ASSERT_FALSE(remote.Read(UINT64_MAX - 100, dst.data(), 200));
+  ASSERT_FALSE(remote.ReadFully(UINT64_MAX - 100, dst.data(), 200));
 
   ASSERT_EQ(0, munmap(src, pagesize));
 
@@ -119,11 +152,24 @@
 }
 
 TEST_F(MemoryRemoteTest, read_overflow) {
-  MemoryFakeRemote remote;
+  pid_t pid;
+  if ((pid = fork()) == 0) {
+    while (true)
+      ;
+    exit(1);
+  }
+  ASSERT_LT(0, pid);
+  TestScopedPidReaper reap(pid);
+
+  ASSERT_TRUE(Attach(pid));
+
+  MemoryRemote remote(pid);
 
   // Check overflow condition is caught properly.
   std::vector<uint8_t> dst(200);
-  ASSERT_FALSE(remote.Read(UINT64_MAX - 100, dst.data(), 200));
+  ASSERT_FALSE(remote.ReadFully(UINT64_MAX - 100, dst.data(), 200));
+
+  ASSERT_TRUE(Detach(pid));
 }
 
 TEST_F(MemoryRemoteTest, read_illegal) {
@@ -140,10 +186,38 @@
   MemoryRemote remote(pid);
 
   std::vector<uint8_t> dst(100);
-  ASSERT_FALSE(remote.Read(0, dst.data(), 1));
-  ASSERT_FALSE(remote.Read(0, dst.data(), 100));
+  ASSERT_FALSE(remote.ReadFully(0, dst.data(), 1));
+  ASSERT_FALSE(remote.ReadFully(0, dst.data(), 100));
 
   ASSERT_TRUE(Detach(pid));
 }
 
+TEST_F(MemoryRemoteTest, read_hole) {
+  void* mapping =
+      mmap(nullptr, 3 * 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+  ASSERT_NE(MAP_FAILED, mapping);
+  memset(mapping, 0xFF, 3 * 4096);
+  mprotect(static_cast<char*>(mapping) + 4096, 4096, PROT_NONE);
+
+  pid_t pid;
+  if ((pid = fork()) == 0) {
+    while (true);
+    exit(1);
+  }
+  ASSERT_LT(0, pid);
+  TestScopedPidReaper reap(pid);
+
+  ASSERT_TRUE(Attach(pid));
+
+  MemoryRemote remote(pid);
+  std::vector<uint8_t> dst(4096 * 3, 0xCC);
+  ASSERT_EQ(4096U, remote.Read(reinterpret_cast<uintptr_t>(mapping), dst.data(), 4096 * 3));
+  for (size_t i = 0; i < 4096; ++i) {
+    ASSERT_EQ(0xFF, dst[i]);
+  }
+  for (size_t i = 4096; i < 4096 * 3; ++i) {
+    ASSERT_EQ(0xCC, dst[i]);
+  }
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp
index 66c8ba6..b372fd0 100644
--- a/libunwindstack/tests/UnwindTest.cpp
+++ b/libunwindstack/tests/UnwindTest.cpp
@@ -174,7 +174,7 @@
       MemoryRemote memory(pid);
       // Read the remote value to see if we are ready.
       bool value;
-      if (memory.Read(addr, &value, sizeof(value)) && value) {
+      if (memory.ReadFully(addr, &value, sizeof(value)) && value) {
         *completed = true;
       }
       if (!*completed || !leave_attached) {
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 43362fb..560f490 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -213,7 +213,7 @@
         int prio = ANDROID_LOG_INFO;
         const char* tag = nullptr;
         size_t tag_len = 0;
-        if (log_id == LOG_ID_EVENTS) {
+        if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS) {
             tag = tagToName(elem->getTag());
             if (tag) {
                 tag_len = strlen(tag);
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp
index 9620d63..4203db4 100644
--- a/shell_and_utilities/Android.bp
+++ b/shell_and_utilities/Android.bp
@@ -1,6 +1,8 @@
 phony {
     name: "shell_and_utilities",
     required: [
+        "awk",
+        "awk_vendor",
         "bzip2",
         "grep",
         "grep_vendor",
diff --git a/shell_and_utilities/README.md b/shell_and_utilities/README.md
index c4e8aac..206204b 100644
--- a/shell_and_utilities/README.md
+++ b/shell_and_utilities/README.md
@@ -21,7 +21,8 @@
 Not everything is provided by toybox, though. We currently still use
 the BSD dd and grep (because the toybox versions are still unfinished),
 and for the bzip2 command-line tools we use the ones that are part of
-the bzip2 distribution.
+the bzip2 distribution. The awk added in Android P is Brian Kernighan's
+"one true" awk.
 
 The lists below show what tools were provided and where they came from in
 each release starting with Gingerbread. This doesn't tell the full story,
@@ -164,3 +165,29 @@
 sysctl tac tail tar taskset tee time timeout top touch tr true truncate
 tty ulimit umount uname uniq unix2dos uptime usleep uudecode uuencode
 vmstat wc which whoami xargs xxd yes zcat
+
+Android P
+---------
+
+BSD: dd grep
+
+bzip2: bzcat bzip2 bunzip2
+
+one-true-awk: awk
+
+toolbox: getevent newfs\_msdos
+
+toybox: acpi base64 basename blockdev cal cat chcon chgrp chmod chown
+chroot chrt cksum clear cmp comm cp cpio cut date df diff dirname dmesg
+dos2unix du echo env expand expr fallocate false file find flock free
+getenforce getprop groups gunzip gzip head hostname hwclock id ifconfig
+inotifyd insmod ionice iorenice kill killall ln load\_policy log logname
+losetup ls lsmod lsof lspci lsusb md5sum microcom mkdir mkfifo mknod
+mkswap mktemp modinfo modprobe more mount mountpoint mv netstat nice
+nl nohup od paste patch pgrep pidof pkill pmap printenv printf ps pwd
+readlink realpath renice restorecon rm rmdir rmmod runcon sed sendevent
+seq setenforce setprop setsid sha1sum sha224sum sha256sum sha384sum
+sha512sum sleep sort split start stat stop strings swapoff swapon sync
+sysctl tac tail tar taskset tee time timeout top touch tr true truncate
+tty ulimit umount uname uniq unix2dos uptime usleep uudecode uuencode
+vmstat wc which whoami xargs xxd yes zcat
diff --git a/storaged/Android.bp b/storaged/Android.bp
index 35868bb..2c7dea1 100644
--- a/storaged/Android.bp
+++ b/storaged/Android.bp
@@ -61,7 +61,7 @@
         "storaged_uid_monitor.cpp",
         "uid_info.cpp",
         "storaged.proto",
-        "binder/android/os/IStoraged.aidl",
+        ":storaged_aidl",
         "binder/android/os/storaged/IStoragedPrivate.aidl",
     ],
 
@@ -100,3 +100,11 @@
 
     static_libs: ["libstoraged"],
 }
+
+// AIDL interface between storaged and framework.jar
+filegroup {
+    name: "storaged_aidl",
+    srcs: [
+        "binder/android/os/IStoraged.aidl",
+    ],
+}