Refactor ProcessReaderWin to use ProcessMemoryWin

Remove ProcessReaderWin's ReadMemory() and ReadAvailableMemory() methods
and replace their uses with a new method that exposes an instance of
ProcessMemoryWin instead.

BUG=crashpad:262

Change-Id: Ief5b660b0504d7a740ee53c7cd2fa7672ae56249
Reviewed-on: https://chromium-review.googlesource.com/c/1278830
Reviewed-by: Mark Mentovai <mark@chromium.org>
Commit-Queue: Vlad Tsyrklevich <vtsyrklevich@chromium.org>
diff --git a/snapshot/win/capture_memory_delegate_win.cc b/snapshot/win/capture_memory_delegate_win.cc
index fc1c608..b652f4a 100644
--- a/snapshot/win/capture_memory_delegate_win.cc
+++ b/snapshot/win/capture_memory_delegate_win.cc
@@ -39,7 +39,8 @@
 bool CaptureMemoryDelegateWin::ReadMemory(uint64_t at,
                                           uint64_t num_bytes,
                                           void* into) const {
-  return process_reader_->ReadMemory(at, num_bytes, into);
+  return process_reader_->Memory()->Read(
+      at, base::checked_cast<size_t>(num_bytes), into);
 }
 
 std::vector<CheckedRange<uint64_t>> CaptureMemoryDelegateWin::GetReadableRanges(
diff --git a/snapshot/win/exception_snapshot_win.cc b/snapshot/win/exception_snapshot_win.cc
index 64b5342..cba6f12 100644
--- a/snapshot/win/exception_snapshot_win.cc
+++ b/snapshot/win/exception_snapshot_win.cc
@@ -176,9 +176,9 @@
                                   CPUContext* context,
                                   CPUContextUnion* context_union)) {
   ExceptionPointersType exception_pointers;
-  if (!process_reader->ReadMemory(exception_pointers_address,
-                                  sizeof(exception_pointers),
-                                  &exception_pointers)) {
+  if (!process_reader->Memory()->Read(exception_pointers_address,
+                                      sizeof(exception_pointers),
+                                      &exception_pointers)) {
     LOG(ERROR) << "EXCEPTION_POINTERS read failed";
     return false;
   }
@@ -188,7 +188,7 @@
   }
 
   ExceptionRecordType first_record;
-  if (!process_reader->ReadMemory(
+  if (!process_reader->Memory()->Read(
           static_cast<WinVMAddress>(exception_pointers.ExceptionRecord),
           sizeof(first_record),
           &first_record)) {
@@ -240,7 +240,7 @@
     }
 
     ContextType context_record;
-    if (!process_reader->ReadMemory(
+    if (!process_reader->Memory()->Read(
             static_cast<WinVMAddress>(exception_pointers.ContextRecord),
             sizeof(context_record),
             &context_record)) {
diff --git a/snapshot/win/memory_snapshot_win.cc b/snapshot/win/memory_snapshot_win.cc
index 17e8ac1..d56b952 100644
--- a/snapshot/win/memory_snapshot_win.cc
+++ b/snapshot/win/memory_snapshot_win.cc
@@ -60,7 +60,7 @@
   }
 
   std::unique_ptr<uint8_t[]> buffer(new uint8_t[size_]);
-  if (!process_reader_->ReadMemory(address_, size_, buffer.get())) {
+  if (!process_reader_->Memory()->Read(address_, size_, buffer.get())) {
     return false;
   }
   return delegate->MemorySnapshotDelegateRead(buffer.get(), size_);
diff --git a/snapshot/win/module_snapshot_win.cc b/snapshot/win/module_snapshot_win.cc
index 880e9da..d76a187 100644
--- a/snapshot/win/module_snapshot_win.cc
+++ b/snapshot/win/module_snapshot_win.cc
@@ -278,7 +278,7 @@
 
   std::vector<SimpleAddressRangeBag::Entry> simple_ranges(
       SimpleAddressRangeBag::num_entries);
-  if (!process_reader_->ReadMemory(
+  if (!process_reader_->Memory()->Read(
           crashpad_info.extra_address_ranges,
           simple_ranges.size() * sizeof(simple_ranges[0]),
           &simple_ranges[0])) {
@@ -304,8 +304,8 @@
 
   for (uint64_t cur = crashpad_info.user_data_minidump_stream_head; cur;) {
     internal::UserDataMinidumpStreamListEntry list_entry;
-    if (!process_reader_->ReadMemory(
-          cur, sizeof(list_entry), &list_entry)) {
+    if (!process_reader_->Memory()->Read(
+            cur, sizeof(list_entry), &list_entry)) {
       LOG(WARNING) << "could not read user data stream entry from "
                    << base::UTF16ToUTF8(name_);
       return;
diff --git a/snapshot/win/pe_image_annotations_reader.cc b/snapshot/win/pe_image_annotations_reader.cc
index 6796145..4c1f66f 100644
--- a/snapshot/win/pe_image_annotations_reader.cc
+++ b/snapshot/win/pe_image_annotations_reader.cc
@@ -92,7 +92,7 @@
 
   std::vector<SimpleStringDictionary::Entry>
       simple_annotations(SimpleStringDictionary::num_entries);
-  if (!process_reader_->ReadMemory(
+  if (!process_reader_->Memory()->Read(
           crashpad_info.simple_annotations,
           simple_annotations.size() * sizeof(simple_annotations[0]),
           &simple_annotations[0])) {
@@ -127,9 +127,9 @@
   }
 
   process_types::AnnotationList<Traits> annotation_list_object;
-  if (!process_reader_->ReadMemory(crashpad_info.annotations_list,
-                                   sizeof(annotation_list_object),
-                                   &annotation_list_object)) {
+  if (!process_reader_->Memory()->Read(crashpad_info.annotations_list,
+                                       sizeof(annotation_list_object),
+                                       &annotation_list_object)) {
     LOG(WARNING) << "could not read annotations list object in "
                  << base::UTF16ToUTF8(name_);
     return;
@@ -140,7 +140,7 @@
        current.link_node != annotation_list_object.tail_pointer &&
        index < kMaxNumberOfAnnotations;
        ++index) {
-    if (!process_reader_->ReadMemory(
+    if (!process_reader_->Memory()->Read(
             current.link_node, sizeof(current), &current)) {
       LOG(WARNING) << "could not read annotation at index " << index << " in "
                    << base::UTF16ToUTF8(name_);
@@ -155,7 +155,7 @@
     snapshot.type = current.type;
 
     char name[Annotation::kNameMaxLength];
-    if (!process_reader_->ReadMemory(current.name, arraysize(name), name)) {
+    if (!process_reader_->Memory()->Read(current.name, arraysize(name), name)) {
       LOG(WARNING) << "could not read annotation name at index " << index
                    << " in " << base::UTF16ToUTF8(name_);
       continue;
@@ -167,7 +167,7 @@
     size_t value_length =
         std::min(static_cast<size_t>(current.size), Annotation::kValueMaxSize);
     snapshot.value.resize(value_length);
-    if (!process_reader_->ReadMemory(
+    if (!process_reader_->Memory()->Read(
             current.value, value_length, snapshot.value.data())) {
       LOG(WARNING) << "could not read annotation value at index " << index
                    << " in " << base::UTF16ToUTF8(name_);
diff --git a/snapshot/win/process_reader_win.cc b/snapshot/win/process_reader_win.cc
index 2fa0258..16280e9 100644
--- a/snapshot/win/process_reader_win.cc
+++ b/snapshot/win/process_reader_win.cc
@@ -204,6 +204,7 @@
 ProcessReaderWin::ProcessReaderWin()
     : process_(INVALID_HANDLE_VALUE),
       process_info_(),
+      process_memory_(),
       threads_(),
       modules_(),
       suspension_state_(),
@@ -220,67 +221,15 @@
 
   process_ = process;
   suspension_state_ = suspension_state;
-  process_info_.Initialize(process);
+  if (!process_info_.Initialize(process))
+    return false;
+  if (!process_memory_.Initialize(process))
+    return false;
 
   INITIALIZATION_STATE_SET_VALID(initialized_);
   return true;
 }
 
-bool ProcessReaderWin::ReadMemory(WinVMAddress at,
-                                  WinVMSize num_bytes,
-                                  void* into) const {
-  if (num_bytes == 0)
-    return 0;
-
-  SIZE_T bytes_read;
-  if (!ReadProcessMemory(process_,
-                         reinterpret_cast<void*>(at),
-                         into,
-                         base::checked_cast<SIZE_T>(num_bytes),
-                         &bytes_read) ||
-      num_bytes != bytes_read) {
-    PLOG(ERROR) << "ReadMemory at 0x" << std::hex << at << std::dec << " of "
-                << num_bytes << " bytes failed";
-    return false;
-  }
-  return true;
-}
-
-WinVMSize ProcessReaderWin::ReadAvailableMemory(WinVMAddress at,
-                                                WinVMSize num_bytes,
-                                                void* into) const {
-  if (num_bytes == 0)
-    return 0;
-
-  auto ranges = process_info_.GetReadableRanges(
-      CheckedRange<WinVMAddress, WinVMSize>(at, num_bytes));
-
-  // We only read up until the first unavailable byte, so we only read from the
-  // first range. If we have no ranges, then no bytes were accessible anywhere
-  // in the range.
-  if (ranges.empty()) {
-    LOG(ERROR) << base::StringPrintf(
-        "range at 0x%llx, size 0x%llx completely inaccessible", at, num_bytes);
-    return 0;
-  }
-
-  // If the start address was adjusted, we couldn't read even the first
-  // requested byte.
-  if (ranges.front().base() != at) {
-    LOG(ERROR) << base::StringPrintf(
-        "start of range at 0x%llx, size 0x%llx inaccessible", at, num_bytes);
-    return 0;
-  }
-
-  DCHECK_LE(ranges.front().size(), num_bytes);
-
-  // If we fail on a normal read, then something went very wrong.
-  if (!ReadMemory(ranges.front().base(), ranges.front().size(), into))
-    return 0;
-
-  return ranges.front().size();
-}
-
 bool ProcessReaderWin::StartTime(timeval* start_time) const {
   FILETIME creation, exit, kernel, user;
   if (!GetProcessTimes(process_, &creation, &exit, &kernel, &user)) {
@@ -398,7 +347,7 @@
     process_types::NT_TIB<Traits> tib;
     thread.teb_address = thread_basic_info.TebBaseAddress;
     thread.teb_size = sizeof(process_types::TEB<Traits>);
-    if (ReadMemory(thread.teb_address, sizeof(tib), &tib)) {
+    if (process_memory_.Read(thread.teb_address, sizeof(tib), &tib)) {
       WinVMAddress base = 0;
       WinVMAddress limit = 0;
       // If we're reading a WOW64 process, then the TIB we just retrieved is the
@@ -409,7 +358,7 @@
         thread.teb_address = tib.Wow64Teb;
         thread.teb_size =
             sizeof(process_types::TEB<process_types::internal::Traits32>);
-        if (ReadMemory(thread.teb_address, sizeof(tib32), &tib32)) {
+        if (process_memory_.Read(thread.teb_address, sizeof(tib32), &tib32)) {
           base = tib32.StackBase;
           limit = tib32.StackLimit;
         }
diff --git a/snapshot/win/process_reader_win.h b/snapshot/win/process_reader_win.h
index 1794a51..a4e32aa 100644
--- a/snapshot/win/process_reader_win.h
+++ b/snapshot/win/process_reader_win.h
@@ -23,6 +23,7 @@
 #include "base/macros.h"
 #include "build/build_config.h"
 #include "util/misc/initialization_state_dcheck.h"
+#include "util/process/process_memory_win.h"
 #include "util/win/address_types.h"
 #include "util/win/process_info.h"
 
@@ -84,25 +85,8 @@
   //! \return `true` if the target task is a 64-bit process.
   bool Is64Bit() const { return process_info_.Is64Bit(); }
 
-  //! \brief Attempts to read \a num_bytes bytes from the target process
-  //!     starting at address \a at into \a into.
-  //!
-  //! \return `true` if the entire region could be read, or `false` with an
-  //!     error logged.
-  //!
-  //! \sa ReadAvailableMemory
-  bool ReadMemory(WinVMAddress at, WinVMSize num_bytes, void* into) const;
-
-  //! \brief Attempts to read \a num_bytes bytes from the target process
-  //!     starting at address \a at into \a into. If some of the specified range
-  //!     is not accessible, reads up to the first inaccessible byte.
-  //!
-  //! \return The actual number of bytes read.
-  //!
-  //! \sa ReadMemory
-  WinVMSize ReadAvailableMemory(WinVMAddress at,
-                                WinVMSize num_bytes,
-                                void* into) const;
+  //! \brief Return a memory reader for the target process.
+  const ProcessMemoryWin* Memory() const { return &process_memory_; }
 
   //! \brief Determines the target process' start time.
   //!
@@ -145,6 +129,7 @@
 
   HANDLE process_;
   ProcessInfo process_info_;
+  ProcessMemoryWin process_memory_;
   std::vector<Thread> threads_;
   std::vector<ProcessInfo::Module> modules_;
   ProcessSuspensionState suspension_state_;
diff --git a/snapshot/win/process_reader_win_test.cc b/snapshot/win/process_reader_win_test.cc
index d0d4d96..0f122fb 100644
--- a/snapshot/win/process_reader_win_test.cc
+++ b/snapshot/win/process_reader_win_test.cc
@@ -43,7 +43,7 @@
 
   static constexpr char kTestMemory[] = "Some test memory";
   char buffer[arraysize(kTestMemory)];
-  ASSERT_TRUE(process_reader.ReadMemory(
+  ASSERT_TRUE(process_reader.Memory()->Read(
       reinterpret_cast<uintptr_t>(kTestMemory), sizeof(kTestMemory), &buffer));
   EXPECT_STREQ(kTestMemory, buffer);
 }
@@ -72,7 +72,7 @@
 
     char buffer[sizeof(kTestMemory)];
     ASSERT_TRUE(
-        process_reader.ReadMemory(address, sizeof(kTestMemory), &buffer));
+        process_reader.Memory()->Read(address, sizeof(kTestMemory), &buffer));
     EXPECT_EQ(strcmp(kTestMemory, buffer), 0);
   }
 
diff --git a/snapshot/win/process_snapshot_win.cc b/snapshot/win/process_snapshot_win.cc
index 289f50c..7f1f93a 100644
--- a/snapshot/win/process_snapshot_win.cc
+++ b/snapshot/win/process_snapshot_win.cc
@@ -21,7 +21,7 @@
 #include <utility>
 
 #include "base/logging.h"
-#include "base/strings/stringprintf.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "util/misc/from_pointer_cast.h"
 #include "util/misc/time.h"
@@ -63,9 +63,9 @@
 
   if (exception_information_address != 0) {
     ExceptionInformation exception_information = {};
-    if (!process_reader_.ReadMemory(exception_information_address,
-                                    sizeof(exception_information),
-                                    &exception_information)) {
+    if (!process_reader_.Memory()->Read(exception_information_address,
+                                        sizeof(exception_information),
+                                        &exception_information)) {
       LOG(WARNING) << "ReadMemory ExceptionInformation failed";
       return false;
     }
@@ -298,9 +298,9 @@
       FromPointerCast<WinVMAddress>(event_trace_address);
 
   Traits::Pointer pointer_to_array;
-  if (!process_reader_.ReadMemory(address_in_target_process,
-                                  sizeof(pointer_to_array),
-                                  &pointer_to_array)) {
+  if (!process_reader_.Memory()->Read(address_in_target_process,
+                                      sizeof(pointer_to_array),
+                                      &pointer_to_array)) {
     LOG(ERROR) << "failed to read target address";
     return;
   }
@@ -311,7 +311,7 @@
 
   const size_t data_size = *element_size * *element_count;
   std::vector<uint8_t> data(data_size);
-  if (!process_reader_.ReadMemory(pointer_to_array, data_size, &data[0])) {
+  if (!process_reader_.Memory()->Read(pointer_to_array, data_size, &data[0])) {
     LOG(ERROR) << "failed to read unloaded module data";
     return;
   }
@@ -377,14 +377,15 @@
   AddMemorySnapshot(peb_address, peb_size, &extra_memory_);
 
   process_types::PEB<Traits> peb_data;
-  if (!process_reader_.ReadMemory(peb_address, peb_size, &peb_data)) {
+  if (!process_reader_.Memory()->Read(
+          peb_address, base::checked_cast<size_t>(peb_size), &peb_data)) {
     LOG(ERROR) << "ReadMemory PEB";
     return;
   }
 
   process_types::PEB_LDR_DATA<Traits> peb_ldr_data;
   AddMemorySnapshot(peb_data.Ldr, sizeof(peb_ldr_data), &extra_memory_);
-  if (!process_reader_.ReadMemory(
+  if (!process_reader_.Memory()->Read(
           peb_data.Ldr, sizeof(peb_ldr_data), &peb_ldr_data)) {
     LOG(ERROR) << "ReadMemory PEB_LDR_DATA";
   } else {
@@ -406,9 +407,9 @@
   }
 
   process_types::RTL_USER_PROCESS_PARAMETERS<Traits> process_parameters;
-  if (!process_reader_.ReadMemory(peb_data.ProcessParameters,
-                                  sizeof(process_parameters),
-                                  &process_parameters)) {
+  if (!process_reader_.Memory()->Read(peb_data.ProcessParameters,
+                                      sizeof(process_parameters),
+                                      &process_parameters)) {
     LOG(ERROR) << "ReadMemory RTL_USER_PROCESS_PARAMETERS";
     return;
   }
@@ -496,7 +497,7 @@
   for (;;) {
     // |cur| is the pointer to LIST_ENTRY embedded in the LDR_DATA_TABLE_ENTRY.
     // So we need to offset back to the beginning of the structure.
-    if (!process_reader_.ReadMemory(
+    if (!process_reader_.Memory()->Read(
             cur - offset_of_member, sizeof(entry), &entry)) {
       return;
     }
@@ -520,7 +521,7 @@
   // be more than enough.
   std::wstring env_block;
   env_block.resize(32768);
-  WinVMSize bytes_read = process_reader_.ReadAvailableMemory(
+  size_t bytes_read = process_reader_.Memory()->ReadAvailableMemory(
       start_of_environment_block,
       env_block.size() * sizeof(env_block[0]),
       &env_block[0]);
@@ -543,7 +544,7 @@
   // RTL_CRITICAL_SECTION_DEBUG.
 
   process_types::RTL_CRITICAL_SECTION<Traits> critical_section;
-  if (!process_reader_.ReadMemory(
+  if (!process_reader_.Memory()->Read(
           start, sizeof(critical_section), &critical_section)) {
     LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION";
     return;
diff --git a/snapshot/win/process_subrange_reader.cc b/snapshot/win/process_subrange_reader.cc
index 996fbdf..124c5d0 100644
--- a/snapshot/win/process_subrange_reader.cc
+++ b/snapshot/win/process_subrange_reader.cc
@@ -15,6 +15,7 @@
 #include "snapshot/win/process_subrange_reader.h"
 
 #include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
 #include "snapshot/win/process_reader_win.h"
 
 namespace crashpad {
@@ -82,7 +83,8 @@
     return false;
   }
 
-  return process_reader_->ReadMemory(address, size, into);
+  return process_reader_->Memory()->Read(
+      address, base::checked_cast<size_t>(size), into);
 }
 
 bool ProcessSubrangeReader::InitializeInternal(ProcessReaderWin* process_reader,