diff --git a/client/crashpad_info.h b/client/crashpad_info.h index 7d894cb0..f75fd179 100644 --- a/client/crashpad_info.h +++ b/client/crashpad_info.h @@ -81,16 +81,25 @@ struct CrashpadInfo { //! this method is called, or they may be added, removed, or modified in \a //! address_range_bag after this method is called. //! - //! TODO(scottmg) This is currently only supported on Windows. + //! TODO(scottmg) This is currently only supported on Windows and iOS. //! //! \param[in] address_range_bag A bag of address ranges. The CrashpadInfo //! object does not take ownership of the SimpleAddressRangeBag object. //! It is the caller’s responsibility to ensure that this pointer remains //! valid while it is in effect for a CrashpadInfo object. + //! + //! \sa extra_memory_ranges() void set_extra_memory_ranges(SimpleAddressRangeBag* address_range_bag) { extra_memory_ranges_ = address_range_bag; } + //! \return The simple extra memory ranges SimpleAddressRangeBag object. + //! + //! \sa set_extra_memory_ranges() + SimpleAddressRangeBag* extra_memory_ranges() const { + return extra_memory_ranges_; + } + //! \brief Sets the simple annotations dictionary. //! //! Simple annotations set on a CrashpadInfo structure are interpreted by diff --git a/client/ios_handler/in_process_intermediate_dump_handler.cc b/client/ios_handler/in_process_intermediate_dump_handler.cc index 5e6c42df..d9a131c5 100644 --- a/client/ios_handler/in_process_intermediate_dump_handler.cc +++ b/client/ios_handler/in_process_intermediate_dump_handler.cc @@ -1144,6 +1144,7 @@ void InProcessIntermediateDumpHandler::WriteDataSegmentAnnotations( crashpad_info->version() == 1) { WriteCrashpadAnnotationsList(writer, crashpad_info.get()); WriteCrashpadSimpleAnnotationsDictionary(writer, crashpad_info.get()); + WriteCrashpadExtraMemoryRanges(writer, crashpad_info.get()); } } else if (strcmp(section_vm_read_ptr->sectname, "__crash_info") == 0) { ScopedVMRead crash_info; @@ -1257,5 +1258,35 @@ void InProcessIntermediateDumpHandler::WriteCrashpadAnnotationsList( } } +void InProcessIntermediateDumpHandler::WriteCrashpadExtraMemoryRanges( + IOSIntermediateDumpWriter* writer, + CrashpadInfo* crashpad_info) { + if (!crashpad_info->extra_memory_ranges()) { + return; + } + + ScopedVMRead extra_memory_ranges; + if (!extra_memory_ranges.Read(crashpad_info->extra_memory_ranges())) { + CRASHPAD_RAW_LOG("Unable to read extra memory ranges object"); + return; + } + + IOSIntermediateDumpWriter::ScopedArray module_extra_memory_regions_array( + writer, IntermediateDumpKey::kModuleExtraMemoryRegions); + + SimpleAddressRangeBag::Iterator iterator(*(extra_memory_ranges.get())); + while (const SimpleAddressRangeBag::Entry* entry = iterator.Next()) { + const uint64_t& address = entry->base; + const uint64_t& size = entry->size; + IOSIntermediateDumpWriter::ScopedArrayMap memory_region_map(writer); + WriteProperty( + writer, IntermediateDumpKey::kModuleExtraMemoryRegionAddress, &address); + WritePropertyBytes(writer, + IntermediateDumpKey::kModuleExtraMemoryRegionData, + reinterpret_cast(address), + size); + } +} + } // namespace internal } // namespace crashpad diff --git a/client/ios_handler/in_process_intermediate_dump_handler.h b/client/ios_handler/in_process_intermediate_dump_handler.h index d7358779..e7bb3b63 100644 --- a/client/ios_handler/in_process_intermediate_dump_handler.h +++ b/client/ios_handler/in_process_intermediate_dump_handler.h @@ -152,6 +152,10 @@ class InProcessIntermediateDumpHandler final { //! \brief Write Crashpad annotations list. static void WriteCrashpadAnnotationsList(IOSIntermediateDumpWriter* writer, CrashpadInfo* crashpad_info); + + //! \brief Write Crashpad extra memory data. + static void WriteCrashpadExtraMemoryRanges(IOSIntermediateDumpWriter* writer, + CrashpadInfo* crashpad_info); }; } // namespace internal diff --git a/client/ios_handler/in_process_intermediate_dump_handler_test.cc b/client/ios_handler/in_process_intermediate_dump_handler_test.cc index 70cbcab1..2619d720 100644 --- a/client/ios_handler/in_process_intermediate_dump_handler_test.cc +++ b/client/ios_handler/in_process_intermediate_dump_handler_test.cc @@ -38,6 +38,16 @@ namespace { using internal::InProcessIntermediateDumpHandler; +class ReadToString : public crashpad::MemorySnapshot::Delegate { + public: + std::string result; + + bool MemorySnapshotDelegateRead(void* data, size_t size) override { + result = std::string(reinterpret_cast(data), size); + return true; + } +}; + class InProcessIntermediateDumpHandlerTest : public testing::Test { protected: // testing::Test: @@ -230,6 +240,37 @@ TEST_F(InProcessIntermediateDumpHandlerTest, TestAnnotations) { } } +TEST_F(InProcessIntermediateDumpHandlerTest, TestExtraMemoryRanges) { +#if TARGET_OS_SIMULATOR + // This test will fail on older (set_extra_memory_ranges( + ios_extra_ranges); + ios_extra_ranges->Insert((void*)kSomeExtraMemoryString, 18); + WriteReportAndCloseWriter(); + crashpad::CrashpadInfo::GetCrashpadInfo()->set_extra_memory_ranges(nullptr); + internal::ProcessSnapshotIOSIntermediateDump process_snapshot; + ASSERT_TRUE(process_snapshot.InitializeWithFilePath(path(), {})); + ASSERT_EQ(process_snapshot.ExtraMemory().size(), 1LU); + auto memory = process_snapshot.ExtraMemory()[0]; + EXPECT_EQ(memory->Address(), + reinterpret_cast(kSomeExtraMemoryString)); + EXPECT_EQ(memory->Size(), 18LU); + ReadToString delegate; + ASSERT_TRUE(memory->Read(&delegate)); + EXPECT_EQ(delegate.result, kSomeExtraMemoryString); +} + TEST_F(InProcessIntermediateDumpHandlerTest, TestThreads) { const ScopedSetThreadName scoped_set_thread_name("TestThreads"); diff --git a/snapshot/ios/module_snapshot_ios_intermediate_dump.cc b/snapshot/ios/module_snapshot_ios_intermediate_dump.cc index 09498f14..5c3b4c2a 100644 --- a/snapshot/ios/module_snapshot_ios_intermediate_dump.cc +++ b/snapshot/ios/module_snapshot_ios_intermediate_dump.cc @@ -127,6 +127,33 @@ bool ModuleSnapshotIOSIntermediateDump::Initialize( } } + const IOSIntermediateDumpList* extra_memory_regions_array = + image_data->GetAsList(IntermediateDumpKey::kModuleExtraMemoryRegions); + if (extra_memory_regions_array) { + for (auto& region : *extra_memory_regions_array) { + vm_address_t address; + const IOSIntermediateDumpData* region_data = + region->GetAsData(Key::kModuleExtraMemoryRegionData); + if (!region_data) + continue; + if (GetDataValueFromMap( + region.get(), Key::kModuleExtraMemoryRegionAddress, &address)) { + const std::vector& bytes = region_data->bytes(); + vm_size_t data_size = bytes.size(); + if (data_size == 0) + continue; + + const vm_address_t data = + reinterpret_cast(bytes.data()); + + auto memory = + std::make_unique(); + memory->Initialize(address, data, data_size); + extra_memory_.push_back(std::move(memory)); + } + } + } + const IOSIntermediateDumpMap* crash_info_dump = image_data->GetAsMap(IntermediateDumpKey::kAnnotationsCrashInfo); if (crash_info_dump) { @@ -266,6 +293,15 @@ ModuleSnapshotIOSIntermediateDump::ExtraMemoryRanges() const { return std::set>(); } +std::vector +ModuleSnapshotIOSIntermediateDump::ExtraMemory() const { + std::vector extra_memory; + for (const auto& memory : extra_memory_) { + extra_memory.push_back(memory.get()); + } + return extra_memory; +} + std::vector ModuleSnapshotIOSIntermediateDump::CustomMinidumpStreams() const { return std::vector(); diff --git a/snapshot/ios/module_snapshot_ios_intermediate_dump.h b/snapshot/ios/module_snapshot_ios_intermediate_dump.h index a9f78158..e53c772c 100644 --- a/snapshot/ios/module_snapshot_ios_intermediate_dump.h +++ b/snapshot/ios/module_snapshot_ios_intermediate_dump.h @@ -24,6 +24,7 @@ #include #include "snapshot/crashpad_info_client_options.h" +#include "snapshot/ios/memory_snapshot_ios_intermediate_dump.h" #include "snapshot/module_snapshot.h" #include "util/ios/ios_intermediate_dump_map.h" #include "util/misc/initialization_state_dcheck.h" @@ -75,6 +76,9 @@ class ModuleSnapshotIOSIntermediateDump final : public ModuleSnapshot { std::set> ExtraMemoryRanges() const override; std::vector CustomMinidumpStreams() const override; + // Used by ProcessSnapshot + std::vector ExtraMemory() const; + private: std::string name_; uint64_t address_; @@ -87,7 +91,8 @@ class ModuleSnapshotIOSIntermediateDump final : public ModuleSnapshot { std::vector annotations_vector_; std::map annotations_simple_map_; std::vector annotation_objects_; - + std::vector> + extra_memory_; InitializationStateDcheck initialized_; }; diff --git a/snapshot/ios/process_snapshot_ios_intermediate_dump.cc b/snapshot/ios/process_snapshot_ios_intermediate_dump.cc index 609ea654..ee98b4a2 100644 --- a/snapshot/ios/process_snapshot_ios_intermediate_dump.cc +++ b/snapshot/ios/process_snapshot_ios_intermediate_dump.cc @@ -304,7 +304,13 @@ std::vector ProcessSnapshotIOSIntermediateDump::Handles() std::vector ProcessSnapshotIOSIntermediateDump::ExtraMemory() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); - return std::vector(); + std::vector extra_memory; + for (const auto& module : modules_) { + for (const auto& memory : module->ExtraMemory()) { + extra_memory.push_back(memory); + } + } + return extra_memory; } const ProcessMemory* ProcessSnapshotIOSIntermediateDump::Memory() const { diff --git a/snapshot/ios/process_snapshot_ios_intermediate_dump.h b/snapshot/ios/process_snapshot_ios_intermediate_dump.h index 8d5d048d..693b5b35 100644 --- a/snapshot/ios/process_snapshot_ios_intermediate_dump.h +++ b/snapshot/ios/process_snapshot_ios_intermediate_dump.h @@ -121,6 +121,8 @@ class ProcessSnapshotIOSIntermediateDump final : public ProcessSnapshot { UUID client_id_; std::map annotations_simple_map_; timeval snapshot_time_; + std::vector> + extra_memory_; InitializationStateDcheck initialized_; }; diff --git a/snapshot/ios/thread_snapshot_ios_intermediate_dump.cc b/snapshot/ios/thread_snapshot_ios_intermediate_dump.cc index d37ccef3..af9dd2b8 100644 --- a/snapshot/ios/thread_snapshot_ios_intermediate_dump.cc +++ b/snapshot/ios/thread_snapshot_ios_intermediate_dump.cc @@ -242,6 +242,7 @@ uint64_t ThreadSnapshotIOSIntermediateDump::ThreadSpecificDataAddress() const { std::vector ThreadSnapshotIOSIntermediateDump::ExtraMemory() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); std::vector extra_memory; for (const auto& memory : extra_memory_) { extra_memory.push_back(memory.get()); diff --git a/util/ios/ios_intermediate_dump_format.h b/util/ios/ios_intermediate_dump_format.h index 2f0a8980..437bf943 100644 --- a/util/ios/ios_intermediate_dump_format.h +++ b/util/ios/ios_intermediate_dump_format.h @@ -56,6 +56,9 @@ namespace internal { TD(kAnnotationsCrashInfoMessage1, 3016) \ TD(kAnnotationsCrashInfoMessage2, 3017) \ TD(kAnnotationsDyldErrorString, 3018) \ + TD(kModuleExtraMemoryRegions, 3019) \ + TD(kModuleExtraMemoryRegionAddress, 3020) \ + TD(kModuleExtraMemoryRegionData, 3021) \ TD(kProcessInfo, 4000) \ TD(kParentPID, 4001) \ TD(kPID, 4002) \