Add a ProcessSnapshot::Memory method

Add a method to the ProcessSnapshot to expose a ProcessMemory object to
allow reading memory directly from the underlying process.

CQ-DEPEND=CL:1278830

BUG=crashpad:262

Change-Id: Ied2a5510a9b051c7ac8c41cdd060e8daa531086e
Reviewed-on: https://chromium-review.googlesource.com/c/1315428
Commit-Queue: Vlad Tsyrklevich <vtsyrklevich@chromium.org>
Reviewed-by: Mark Mentovai <mark@chromium.org>
diff --git a/snapshot/fuchsia/process_reader_fuchsia.h b/snapshot/fuchsia/process_reader_fuchsia.h
index 28a1e93..36201af 100644
--- a/snapshot/fuchsia/process_reader_fuchsia.h
+++ b/snapshot/fuchsia/process_reader_fuchsia.h
@@ -109,7 +109,7 @@
   const std::vector<Thread>& Threads();
 
   //! \brief Return a memory reader for the target process.
-  ProcessMemory* Memory() { return process_memory_.get(); }
+  const ProcessMemory* Memory() const { return process_memory_.get(); }
 
  private:
   //! Performs lazy initialization of the \a modules_ vector on behalf of
diff --git a/snapshot/fuchsia/process_snapshot_fuchsia.cc b/snapshot/fuchsia/process_snapshot_fuchsia.cc
index 6750c3d..12122f6 100644
--- a/snapshot/fuchsia/process_snapshot_fuchsia.cc
+++ b/snapshot/fuchsia/process_snapshot_fuchsia.cc
@@ -188,6 +188,11 @@
   return std::vector<const MemorySnapshot*>();
 }
 
+const ProcessMemory* ProcessSnapshotFuchsia::Memory() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  return process_reader_.Memory();
+}
+
 void ProcessSnapshotFuchsia::InitializeThreads() {
   const std::vector<ProcessReaderFuchsia::Thread>& process_reader_threads =
       process_reader_.Threads();
diff --git a/snapshot/fuchsia/process_snapshot_fuchsia.h b/snapshot/fuchsia/process_snapshot_fuchsia.h
index 237e17d..15c3bb7 100644
--- a/snapshot/fuchsia/process_snapshot_fuchsia.h
+++ b/snapshot/fuchsia/process_snapshot_fuchsia.h
@@ -121,6 +121,7 @@
   std::vector<const MemoryMapRegionSnapshot*> MemoryMap() const override;
   std::vector<HandleSnapshot> Handles() const override;
   std::vector<const MemorySnapshot*> ExtraMemory() const override;
+  const ProcessMemory* Memory() const override;
 
  private:
   // Initializes threads_ on behalf of Initialize().
diff --git a/snapshot/linux/process_reader_linux.h b/snapshot/linux/process_reader_linux.h
index dbe436a..1b30f53 100644
--- a/snapshot/linux/process_reader_linux.h
+++ b/snapshot/linux/process_reader_linux.h
@@ -120,7 +120,7 @@
   pid_t ParentProcessID() const { return process_info_.ParentProcessID(); }
 
   //! \brief Return a memory reader for the target process.
-  ProcessMemory* Memory() { return connection_->Memory(); }
+  const ProcessMemory* Memory() const { return connection_->Memory(); }
 
   //! \brief Return a memory map of the target process.
   MemoryMap* GetMemoryMap() { return &memory_map_; }
diff --git a/snapshot/linux/process_snapshot_linux.cc b/snapshot/linux/process_snapshot_linux.cc
index 190e869..041653a 100644
--- a/snapshot/linux/process_snapshot_linux.cc
+++ b/snapshot/linux/process_snapshot_linux.cc
@@ -234,6 +234,11 @@
   return std::vector<const MemorySnapshot*>();
 }
 
+const ProcessMemory* ProcessSnapshotLinux::Memory() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  return process_reader_.Memory();
+}
+
 void ProcessSnapshotLinux::InitializeThreads() {
   const std::vector<ProcessReaderLinux::Thread>& process_reader_threads =
       process_reader_.Threads();
diff --git a/snapshot/linux/process_snapshot_linux.h b/snapshot/linux/process_snapshot_linux.h
index 49d648f..236926d 100644
--- a/snapshot/linux/process_snapshot_linux.h
+++ b/snapshot/linux/process_snapshot_linux.h
@@ -115,6 +115,7 @@
   std::vector<const MemoryMapRegionSnapshot*> MemoryMap() const override;
   std::vector<HandleSnapshot> Handles() const override;
   std::vector<const MemorySnapshot*> ExtraMemory() const override;
+  const ProcessMemory* Memory() const override;
 
  private:
   void InitializeThreads();
diff --git a/snapshot/mac/process_snapshot_mac.cc b/snapshot/mac/process_snapshot_mac.cc
index cf5233a..68837ff 100644
--- a/snapshot/mac/process_snapshot_mac.cc
+++ b/snapshot/mac/process_snapshot_mac.cc
@@ -217,6 +217,12 @@
   return std::vector<const MemorySnapshot*>();
 }
 
+const ProcessMemory* ProcessSnapshotMac::Memory() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  NOTREACHED();  // https://crashpad.chromium.org/bug/263
+  return nullptr;
+}
+
 void ProcessSnapshotMac::InitializeThreads() {
   const std::vector<ProcessReaderMac::Thread>& process_reader_threads =
       process_reader_.Threads();
diff --git a/snapshot/mac/process_snapshot_mac.h b/snapshot/mac/process_snapshot_mac.h
index 06bac74..2edc222 100644
--- a/snapshot/mac/process_snapshot_mac.h
+++ b/snapshot/mac/process_snapshot_mac.h
@@ -131,6 +131,7 @@
   std::vector<const MemoryMapRegionSnapshot*> MemoryMap() const override;
   std::vector<HandleSnapshot> Handles() const override;
   std::vector<const MemorySnapshot*> ExtraMemory() const override;
+  const ProcessMemory* Memory() const override;
 
  private:
   // Initializes threads_ on behalf of Initialize().
diff --git a/snapshot/minidump/process_snapshot_minidump.cc b/snapshot/minidump/process_snapshot_minidump.cc
index 1273843..5cc5ad8 100644
--- a/snapshot/minidump/process_snapshot_minidump.cc
+++ b/snapshot/minidump/process_snapshot_minidump.cc
@@ -229,6 +229,11 @@
   return std::vector<const MemorySnapshot*>();
 }
 
+const ProcessMemory* ProcessSnapshotMinidump::Memory() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  return nullptr;
+}
+
 bool ProcessSnapshotMinidump::InitializeCrashpadInfo() {
   const auto& stream_it = stream_map_.find(kMinidumpStreamTypeCrashpadInfo);
   if (stream_it == stream_map_.end()) {
diff --git a/snapshot/minidump/process_snapshot_minidump.h b/snapshot/minidump/process_snapshot_minidump.h
index 3f25618..2a868a1 100644
--- a/snapshot/minidump/process_snapshot_minidump.h
+++ b/snapshot/minidump/process_snapshot_minidump.h
@@ -81,6 +81,7 @@
   std::vector<const MemoryMapRegionSnapshot*> MemoryMap() const override;
   std::vector<HandleSnapshot> Handles() const override;
   std::vector<const MemorySnapshot*> ExtraMemory() const override;
+  const ProcessMemory* Memory() const override;
 
  private:
   // Initializes data carried in a MinidumpCrashpadInfo stream on behalf of
diff --git a/snapshot/process_snapshot.h b/snapshot/process_snapshot.h
index 8d5520c..f5859d2 100644
--- a/snapshot/process_snapshot.h
+++ b/snapshot/process_snapshot.h
@@ -31,6 +31,7 @@
 class MemoryMapRegionSnapshot;
 class MemorySnapshot;
 class ModuleSnapshot;
+class ProcessMemory;
 class SystemSnapshot;
 class ThreadSnapshot;
 class UnloadedModuleSnapshot;
@@ -193,6 +194,14 @@
   //!     are scoped to the lifetime of the ProcessSnapshot object that they
   //!     were obtained from.
   virtual std::vector<const MemorySnapshot*> ExtraMemory() const = 0;
+
+  //! \brief Returns a ProcessMemory object that allows accessing the process'
+  //!     memory directly.
+  //!
+  //! \return A ProcessMemory object. The caller does not take ownership of this
+  //!     object, it is scoped to the lifetime of the ProcessSnapshot object
+  //!     that it was obtained from.
+  virtual const ProcessMemory* Memory() const = 0;
 };
 
 }  // namespace crashpad
diff --git a/snapshot/sanitized/process_snapshot_sanitized.cc b/snapshot/sanitized/process_snapshot_sanitized.cc
index 76caeb5..20807b9 100644
--- a/snapshot/sanitized/process_snapshot_sanitized.cc
+++ b/snapshot/sanitized/process_snapshot_sanitized.cc
@@ -262,4 +262,10 @@
   return snapshot_->ExtraMemory();
 }
 
+const ProcessMemory* ProcessSnapshotSanitized::Memory() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  NOTREACHED();  // https://crashpad.chromium.org/bug/263
+  return nullptr;
+}
+
 }  // namespace crashpad
diff --git a/snapshot/sanitized/process_snapshot_sanitized.h b/snapshot/sanitized/process_snapshot_sanitized.h
index f5cf5fa..b5f0c40 100644
--- a/snapshot/sanitized/process_snapshot_sanitized.h
+++ b/snapshot/sanitized/process_snapshot_sanitized.h
@@ -83,6 +83,7 @@
   std::vector<const MemoryMapRegionSnapshot*> MemoryMap() const override;
   std::vector<HandleSnapshot> Handles() const override;
   std::vector<const MemorySnapshot*> ExtraMemory() const override;
+  const ProcessMemory* Memory() const override;
 
  private:
   // Only used when annotations_whitelist_ != nullptr.
diff --git a/snapshot/test/test_process_snapshot.cc b/snapshot/test/test_process_snapshot.cc
index c430fd9..1a31370 100644
--- a/snapshot/test/test_process_snapshot.cc
+++ b/snapshot/test/test_process_snapshot.cc
@@ -35,7 +35,8 @@
       exception_(),
       memory_map_(),
       handles_(),
-      extra_memory_() {
+      extra_memory_(),
+      process_memory_() {
 }
 
 TestProcessSnapshot::~TestProcessSnapshot() {
@@ -126,5 +127,9 @@
   return extra_memory;
 }
 
+const ProcessMemory* TestProcessSnapshot::Memory() const {
+  return process_memory_.get();
+}
+
 }  // namespace test
 }  // namespace crashpad
diff --git a/snapshot/test/test_process_snapshot.h b/snapshot/test/test_process_snapshot.h
index 5c63e12..bfa26ab 100644
--- a/snapshot/test/test_process_snapshot.h
+++ b/snapshot/test/test_process_snapshot.h
@@ -35,6 +35,7 @@
 #include "snapshot/thread_snapshot.h"
 #include "snapshot/unloaded_module_snapshot.h"
 #include "util/misc/uuid.h"
+#include "util/process/process_memory.h"
 
 namespace crashpad {
 namespace test {
@@ -134,6 +135,15 @@
     extra_memory_.push_back(std::move(extra_memory));
   }
 
+  //! \brief Add a process memory object to be returned by Memory().
+  //!
+  //! \param[in] process_memory The memory object that will be returned by
+  //!     Memory(). The TestProcessSnapshot object takes ownership of \a
+  //!     extra_memory.
+  void SetProcessMemory(std::unique_ptr<ProcessMemory> process_memory) {
+    process_memory_ = std::move(process_memory);
+  }
+
   // ProcessSnapshot:
 
   pid_t ProcessID() const override;
@@ -153,6 +163,7 @@
   std::vector<const MemoryMapRegionSnapshot*> MemoryMap() const override;
   std::vector<HandleSnapshot> Handles() const override;
   std::vector<const MemorySnapshot*> ExtraMemory() const override;
+  const ProcessMemory* Memory() const override;
 
  private:
   pid_t process_id_;
@@ -172,6 +183,7 @@
   std::vector<std::unique_ptr<MemoryMapRegionSnapshot>> memory_map_;
   std::vector<HandleSnapshot> handles_;
   std::vector<std::unique_ptr<MemorySnapshot>> extra_memory_;
+  std::unique_ptr<ProcessMemory> process_memory_;
 
   DISALLOW_COPY_AND_ASSIGN(TestProcessSnapshot);
 };
diff --git a/snapshot/win/process_snapshot_win.cc b/snapshot/win/process_snapshot_win.cc
index 7f1f93a..af6fe4d 100644
--- a/snapshot/win/process_snapshot_win.cc
+++ b/snapshot/win/process_snapshot_win.cc
@@ -232,6 +232,11 @@
   return extra_memory;
 }
 
+const ProcessMemory* ProcessSnapshotWin::Memory() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  return process_reader_.Memory();
+}
+
 void ProcessSnapshotWin::InitializeThreads(
     bool gather_indirectly_referenced_memory,
     uint32_t indirectly_referenced_memory_cap) {
diff --git a/snapshot/win/process_snapshot_win.h b/snapshot/win/process_snapshot_win.h
index 9250c13..092aaf1 100644
--- a/snapshot/win/process_snapshot_win.h
+++ b/snapshot/win/process_snapshot_win.h
@@ -129,6 +129,7 @@
   std::vector<const MemoryMapRegionSnapshot*> MemoryMap() const override;
   std::vector<HandleSnapshot> Handles() const override;
   std::vector<const MemorySnapshot*> ExtraMemory() const override;
+  const ProcessMemory* Memory() const override;
 
  private:
   // Initializes threads_ on behalf of Initialize().