diff options
author | ted.mielczarek@gmail.com <ted.mielczarek@gmail.com@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2012-09-18 13:54:58 +0000 |
---|---|---|
committer | ted.mielczarek@gmail.com <ted.mielczarek@gmail.com@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2012-09-18 13:54:58 +0000 |
commit | 61d9b9ff9626bf57c68a12c53c6e4804b8ef93d8 (patch) | |
tree | c85f99a0216bb237a36c59af6f196ca79e91e418 /src/client/linux/handler | |
parent | Change an always true comparison to another conditional. Since (diff) | |
download | breakpad-61d9b9ff9626bf57c68a12c53c6e4804b8ef93d8.tar.xz |
Allow adding extra memory regions to minidump on linux/windows
A=Bill McCloskey <wmccloskey@mozilla.com>, ted, original patch from https://bugzilla.mozilla.org/show_bug.cgi?id=662646
R=mark at https://breakpad.appspot.com/450002/
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1041 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/client/linux/handler')
-rw-r--r-- | src/client/linux/handler/exception_handler.cc | 28 | ||||
-rw-r--r-- | src/client/linux/handler/exception_handler.h | 11 | ||||
-rw-r--r-- | src/client/linux/handler/exception_handler_unittest.cc | 81 |
3 files changed, 117 insertions, 3 deletions
diff --git a/src/client/linux/handler/exception_handler.cc b/src/client/linux/handler/exception_handler.cc index 490b6eb9..6f0b8de4 100644 --- a/src/client/linux/handler/exception_handler.cc +++ b/src/client/linux/handler/exception_handler.cc @@ -495,13 +495,15 @@ bool ExceptionHandler::DoDump(pid_t crashing_process, const void* context, crashing_process, context, context_size, - mapping_list_); + mapping_list_, + app_memory_list_); } return google_breakpad::WriteMinidump(minidump_descriptor_.path(), crashing_process, context, context_size, - mapping_list_); + mapping_list_, + app_memory_list_); } // static @@ -562,4 +564,26 @@ void ExceptionHandler::AddMappingInfo(const string& name, mapping_list_.push_back(mapping); } +void ExceptionHandler::RegisterAppMemory(void* ptr, size_t length) { + AppMemoryList::iterator iter = + std::find(app_memory_list_.begin(), app_memory_list_.end(), ptr); + if (iter != app_memory_list_.end()) { + // Don't allow registering the same pointer twice. + return; + } + + AppMemory app_memory; + app_memory.ptr = ptr; + app_memory.length = length; + app_memory_list_.push_back(app_memory); +} + +void ExceptionHandler::UnregisterAppMemory(void* ptr) { + AppMemoryList::iterator iter = + std::find(app_memory_list_.begin(), app_memory_list_.end(), ptr); + if (iter != app_memory_list_.end()) { + app_memory_list_.erase(iter); + } +} + } // namespace google_breakpad diff --git a/src/client/linux/handler/exception_handler.h b/src/client/linux/handler/exception_handler.h index 95817424..68953adf 100644 --- a/src/client/linux/handler/exception_handler.h +++ b/src/client/linux/handler/exception_handler.h @@ -193,6 +193,13 @@ class ExceptionHandler { size_t mapping_size, size_t file_offset); + // Register a block of memory of length bytes starting at address ptr + // 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); + // Force signal handling for the specified signal. bool SimulateSignalDelivery(int sig); private: @@ -238,6 +245,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 6de9b8d4..341d2fb0 100644 --- a/src/client/linux/handler/exception_handler_unittest.cc +++ b/src/client/linux/handler/exception_handler_unittest.cc @@ -939,6 +939,85 @@ TEST(ExceptionHandlerTest, GenerateMultipleDumpsWithPath) { ASSERT_TRUE(minidump2.Read()); unlink(minidump_2.path()); - // We expect 2 distinct files. + // 2 distinct files should be produced. ASSERT_STRNE(minidump_1_path.c_str(), minidump_2_path.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 (u_int32_t i = 0; i < kMemorySize; ++i) { + memory[i] = i % 255; + } + + AutoTempDir temp_dir; + ExceptionHandler handler( + MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1); + + // Add the memory region to the list of memory to be included. + handler.RegisterAppMemory(memory, kMemorySize); + handler.WriteMinidump(); + + const MinidumpDescriptor& minidump_desc = handler.minidump_descriptor(); + + // Read the minidump. Ensure that the memory region is present + Minidump minidump(minidump_desc.path()); + 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; +} + +// Test that a memory region that was previously registered +// can be unregistered. +TEST(ExceptionHandlerTest, AdditionalMemoryRemove) { + 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); + + AutoTempDir temp_dir; + ExceptionHandler handler( + MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1); + + // Add the memory region to the list of memory to be included. + handler.RegisterAppMemory(memory, kMemorySize); + + // ...and then remove it + handler.UnregisterAppMemory(memory); + handler.WriteMinidump(); + + const MinidumpDescriptor& minidump_desc = handler.minidump_descriptor(); + + // Read the minidump. Ensure that the memory region is not present. + Minidump minidump(minidump_desc.path()); + ASSERT_TRUE(minidump.Read()); + + MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList(); + ASSERT_TRUE(dump_memory_list); + const MinidumpMemoryRegion* region = + dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress); + EXPECT_FALSE(region); + + delete[] memory; +} |