From 2f56276fbfe519913845565f178cfa385da93657 Mon Sep 17 00:00:00 2001
From: "ted.mielczarek" <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e>
Date: Thu, 19 Jul 2012 22:03:39 +0000
Subject: Allow adding extra memory regions to minidump on linux/windows A=Bill
 McCloskey <wmccloskey@mozilla.com> R=ted at
 https://bugzilla.mozilla.org/show_bug.cgi?id=662646

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@989 4c0a9323-5329-0410-9bdc-e9ce6186880e
---
 src/client/linux/handler/exception_handler.cc      | 18 +++++++++-
 src/client/linux/handler/exception_handler.h       | 11 ++++++
 .../linux/handler/exception_handler_unittest.cc    | 39 ++++++++++++++++++++++
 3 files changed, 67 insertions(+), 1 deletion(-)

(limited to 'src/client/linux/handler')

diff --git a/src/client/linux/handler/exception_handler.cc b/src/client/linux/handler/exception_handler.cc
index f505ff33..fffc3e64 100644
--- a/src/client/linux/handler/exception_handler.cc
+++ b/src/client/linux/handler/exception_handler.cc
@@ -465,7 +465,8 @@ bool ExceptionHandler::DoDump(pid_t crashing_process, const void* context,
                                         crashing_process,
                                         context,
                                         context_size,
-                                        mapping_list_);
+                                        mapping_list_,
+                                        app_memory_list_);
 }
 
 // static
@@ -515,4 +516,19 @@ void ExceptionHandler::AddMappingInfo(const string& name,
   mapping_list_.push_back(mapping);
 }
 
+void ExceptionHandler::RegisterAppMemory(void *ptr, size_t length) {
+  app_memory_list_.push_back(AppMemory(ptr, length));
+}
+
+void ExceptionHandler::UnregisterAppMemory(void *ptr) {
+  for (AppMemoryList::iterator iter = app_memory_list_.begin();
+       iter != app_memory_list_.end();
+       ++iter) {
+    if (iter->ptr == ptr) {
+      app_memory_list_.erase(iter);
+      return;
+    }
+  }
+}
+
 }  // namespace google_breakpad
diff --git a/src/client/linux/handler/exception_handler.h b/src/client/linux/handler/exception_handler.h
index 4bc8ba72..fab74d28 100644
--- a/src/client/linux/handler/exception_handler.h
+++ b/src/client/linux/handler/exception_handler.h
@@ -194,6 +194,13 @@ class ExceptionHandler {
                       size_t mapping_size,
                       size_t file_offset);
 
+  // Register a block of memory of len bytes starting at address p
+  // to be copied to the minidump when a crash happens.
+  void RegisterAppMemory(void *ptr, size_t length);
+
+  // Unregister a block of memory that was registered with RegisterAppMemory.
+  void UnregisterAppMemory(void *ptr);
+
  private:
   void Init(const string &dump_path,
             const int server_fd);
@@ -252,6 +259,10 @@ class ExceptionHandler {
   // Callers can add extra info about mappings for cases where the
   // dumper code cannot extract enough information from /proc/<pid>/maps.
   MappingList mapping_list_;
+
+  // Callers can request additional memory regions to be included in
+  // the dump.
+  AppMemoryList app_memory_list_;
 };
 
 }  // namespace google_breakpad
diff --git a/src/client/linux/handler/exception_handler_unittest.cc b/src/client/linux/handler/exception_handler_unittest.cc
index f9314729..2bad5fb5 100644
--- a/src/client/linux/handler/exception_handler_unittest.cc
+++ b/src/client/linux/handler/exception_handler_unittest.cc
@@ -785,3 +785,42 @@ TEST(ExceptionHandlerTest, ExternalDumper) {
   ASSERT_GT(st.st_size, 0u);
   unlink(templ.c_str());
 }
+
+// Test that an additional memory region can be added to the minidump.
+TEST(ExceptionHandlerTest, AdditionalMemory) {
+  const u_int32_t kMemorySize = sysconf(_SC_PAGESIZE);
+  // Get some heap memory.
+  u_int8_t* memory = new u_int8_t[kMemorySize];
+  const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
+  ASSERT_TRUE(memory);
+  // Stick some data into the memory so the contents can be verified.
+  for (unsigned int i = 0; i < kMemorySize; ++i) {
+    memory[i] = i % 255;
+  }
+
+  string minidump_filename;
+  AutoTempDir temp_dir;
+  ExceptionHandler handler(temp_dir.path(), NULL, SimpleCallback,
+                           (void*)&minidump_filename, true);
+  // Add the memory region to the list of memory to be included.
+  handler.RegisterAppMemory(memory, kMemorySize);
+  handler.WriteMinidump();
+
+  // Read the minidump. Ensure that the memory region is present
+  Minidump minidump(minidump_filename);
+  ASSERT_TRUE(minidump.Read());
+
+  MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
+  ASSERT_TRUE(dump_memory_list);
+  const MinidumpMemoryRegion* region =
+    dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
+  ASSERT_TRUE(region);
+
+  EXPECT_EQ(kMemoryAddress, region->GetBase());
+  EXPECT_EQ(kMemorySize, region->GetSize());
+
+  // Verify memory contents.
+  EXPECT_EQ(0, memcmp(region->GetMemory(), memory, kMemorySize));
+
+  delete[] memory;
+}
-- 
cgit v1.2.1