diff --git a/snapshot/BUILD.gn b/snapshot/BUILD.gn index 8d331fc0..89257140 100644 --- a/snapshot/BUILD.gn +++ b/snapshot/BUILD.gn @@ -142,10 +142,16 @@ static_library("snapshot") { ] } - if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) { + if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia || + crashpad_is_win) { sources += [ "crashpad_types/crashpad_info_reader.cc", "crashpad_types/crashpad_info_reader.h", + ] + } + + if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) { + sources += [ "crashpad_types/image_annotation_reader.cc", "crashpad_types/image_annotation_reader.h", "elf/elf_dynamic_array_reader.cc", @@ -332,9 +338,13 @@ source_set("snapshot_test") { sources += [ "crashpad_info_client_options_test.cc" ] } + if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia || + crashpad_is_win) { + sources += [ "crashpad_types/crashpad_info_reader_test.cc" ] + } + if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) { sources += [ - "crashpad_types/crashpad_info_reader_test.cc", "crashpad_types/image_annotation_reader_test.cc", "elf/elf_image_reader_test.cc", "elf/elf_image_reader_test_note.S", diff --git a/snapshot/crashpad_types/crashpad_info_reader.cc b/snapshot/crashpad_types/crashpad_info_reader.cc index dfc438fc..527d3723 100644 --- a/snapshot/crashpad_types/crashpad_info_reader.cc +++ b/snapshot/crashpad_types/crashpad_info_reader.cc @@ -66,9 +66,8 @@ class CrashpadInfoReader::InfoContainerSpecific : public InfoContainer { return false; } - if (!memory->Read(address, - std::min(VMSize{info.size}, VMSize{sizeof(info)}), - &info)) { + if (!memory->Read( + address, std::min(info.size, sizeof(info)), &info)) { return false; } @@ -116,7 +115,7 @@ class CrashpadInfoReader::InfoContainerSpecific : public InfoContainer { #define NATIVE_TRAITS Traits32 #endif static_assert(!std::is_same::value || - sizeof(info) == sizeof(CrashpadInfo), + sizeof(decltype(info)) == sizeof(CrashpadInfo), "CrashpadInfo size mismtach"); #undef NATIVE_TRAITS }; diff --git a/snapshot/crashpad_types/crashpad_info_reader_test.cc b/snapshot/crashpad_types/crashpad_info_reader_test.cc index 87bafc68..ebc6a4d3 100644 --- a/snapshot/crashpad_types/crashpad_info_reader_test.cc +++ b/snapshot/crashpad_types/crashpad_info_reader_test.cc @@ -15,7 +15,6 @@ #include "snapshot/crashpad_types/crashpad_info_reader.h" #include -#include #include @@ -31,10 +30,6 @@ #include "util/misc/from_pointer_cast.h" #include "util/process/process_memory_native.h" -#if defined(OS_FUCHSIA) -#include -#endif - namespace crashpad { namespace test { namespace { diff --git a/snapshot/win/module_snapshot_win.cc b/snapshot/win/module_snapshot_win.cc index d76a187e..d9d74c1b 100644 --- a/snapshot/win/module_snapshot_win.cc +++ b/snapshot/win/module_snapshot_win.cc @@ -33,14 +33,16 @@ ModuleSnapshotWin::ModuleSnapshotWin() name_(), pdb_name_(), uuid_(), - pe_image_reader_(), + memory_range_(), + streams_(), + vs_fixed_file_info_(), + initialized_vs_fixed_file_info_(), process_reader_(nullptr), + pe_image_reader_(), + crashpad_info_(), timestamp_(0), age_(0), - initialized_(), - vs_fixed_file_info_(), - initialized_vs_fixed_file_info_() { -} + initialized_() {} ModuleSnapshotWin::~ModuleSnapshotWin() { } @@ -75,6 +77,26 @@ bool ModuleSnapshotWin::Initialize( pdb_name_ = base::UTF16ToUTF8(name_); } + if (!memory_range_.Initialize(process_reader_->Memory(), + process_reader_->Is64Bit())) { + return false; + } + + WinVMAddress crashpad_info_address; + WinVMSize crashpad_info_size; + if (pe_image_reader_->GetCrashpadInfoSection(&crashpad_info_address, + &crashpad_info_size)) { + ProcessMemoryRange info_range; + info_range.Initialize(memory_range_); + info_range.RestrictRange(crashpad_info_address, + crashpad_info_address + crashpad_info_size); + + auto info = std::make_unique(); + if (info->Initialize(&info_range, crashpad_info_address)) { + crashpad_info_ = std::move(info); + } + } + INITIALIZATION_STATE_SET_VALID(initialized_); return true; } @@ -228,8 +250,7 @@ ModuleSnapshotWin::CustomMinidumpStreams() const { template void ModuleSnapshotWin::GetCrashpadOptionsInternal( CrashpadInfoClientOptions* options) { - process_types::CrashpadInfo crashpad_info; - if (!pe_image_reader_->GetCrashpadInfo(&crashpad_info)) { + if (!crashpad_info_) { options->crashpad_handler_behavior = TriState::kUnset; options->system_crash_reporter_forwarding = TriState::kUnset; options->gather_indirectly_referenced_memory = TriState::kUnset; @@ -238,19 +259,13 @@ void ModuleSnapshotWin::GetCrashpadOptionsInternal( } options->crashpad_handler_behavior = - CrashpadInfoClientOptions::TriStateFromCrashpadInfo( - crashpad_info.crashpad_handler_behavior); - + crashpad_info_->CrashpadHandlerBehavior(); options->system_crash_reporter_forwarding = - CrashpadInfoClientOptions::TriStateFromCrashpadInfo( - crashpad_info.system_crash_reporter_forwarding); - + crashpad_info_->SystemCrashReporterForwarding(); options->gather_indirectly_referenced_memory = - CrashpadInfoClientOptions::TriStateFromCrashpadInfo( - crashpad_info.gather_indirectly_referenced_memory); - + crashpad_info_->GatherIndirectlyReferencedMemory(); options->indirectly_referenced_memory_cap = - crashpad_info.indirectly_referenced_memory_cap; + crashpad_info_->IndirectlyReferencedMemoryCap(); } const VS_FIXEDFILEINFO* ModuleSnapshotWin::VSFixedFileInfo() const { @@ -270,16 +285,13 @@ const VS_FIXEDFILEINFO* ModuleSnapshotWin::VSFixedFileInfo() const { template void ModuleSnapshotWin::GetCrashpadExtraMemoryRanges( std::set>* ranges) const { - process_types::CrashpadInfo crashpad_info; - if (!pe_image_reader_->GetCrashpadInfo(&crashpad_info) || - !crashpad_info.extra_address_ranges) { + if (!crashpad_info_ || !crashpad_info_->ExtraMemoryRanges()) return; - } std::vector simple_ranges( SimpleAddressRangeBag::num_entries); if (!process_reader_->Memory()->Read( - crashpad_info.extra_address_ranges, + crashpad_info_->ExtraMemoryRanges(), simple_ranges.size() * sizeof(simple_ranges[0]), &simple_ranges[0])) { LOG(WARNING) << "could not read simple address_ranges from " @@ -298,11 +310,10 @@ void ModuleSnapshotWin::GetCrashpadExtraMemoryRanges( template void ModuleSnapshotWin::GetCrashpadUserMinidumpStreams( std::vector>* streams) const { - process_types::CrashpadInfo crashpad_info; - if (!pe_image_reader_->GetCrashpadInfo(&crashpad_info)) + if (!crashpad_info_) return; - for (uint64_t cur = crashpad_info.user_data_minidump_stream_head; cur;) { + for (uint64_t cur = crashpad_info_->UserDataMinidumpStreamHead(); cur;) { internal::UserDataMinidumpStreamListEntry list_entry; if (!process_reader_->Memory()->Read( cur, sizeof(list_entry), &list_entry)) { diff --git a/snapshot/win/module_snapshot_win.h b/snapshot/win/module_snapshot_win.h index 693588db..f18a8809 100644 --- a/snapshot/win/module_snapshot_win.h +++ b/snapshot/win/module_snapshot_win.h @@ -25,6 +25,7 @@ #include "base/macros.h" #include "snapshot/crashpad_info_client_options.h" +#include "snapshot/crashpad_types/crashpad_info_reader.h" #include "snapshot/module_snapshot.h" #include "snapshot/win/process_reader_win.h" #include "util/misc/initialization_state.h" @@ -109,18 +110,19 @@ class ModuleSnapshotWin final : public ModuleSnapshot { std::wstring name_; std::string pdb_name_; UUID uuid_; - std::unique_ptr pe_image_reader_; - ProcessReaderWin* process_reader_; // weak - time_t timestamp_; - uint32_t age_; + ProcessMemoryRange memory_range_; // Too const-y: https://crashpad.chromium.org/bug/9. mutable std::vector> streams_; - InitializationStateDcheck initialized_; - // VSFixedFileInfo() is logically const, but updates these members on the // call. See https://crashpad.chromium.org/bug/9. mutable VS_FIXEDFILEINFO vs_fixed_file_info_; mutable InitializationState initialized_vs_fixed_file_info_; + ProcessReaderWin* process_reader_; // weak + std::unique_ptr pe_image_reader_; + std::unique_ptr crashpad_info_; + time_t timestamp_; + uint32_t age_; + InitializationStateDcheck initialized_; DISALLOW_COPY_AND_ASSIGN(ModuleSnapshotWin); }; diff --git a/snapshot/win/pe_image_reader.cc b/snapshot/win/pe_image_reader.cc index 094cf0fd..b4b1d169 100644 --- a/snapshot/win/pe_image_reader.cc +++ b/snapshot/win/pe_image_reader.cc @@ -72,6 +72,18 @@ bool PEImageReader::Initialize(ProcessReaderWin* process_reader, return true; } +bool PEImageReader::GetCrashpadInfoSection(WinVMAddress* address, + WinVMSize* size) const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + if (module_subrange_reader_.Is64Bit()) { + return GetCrashpadInfoSectionInternal( + address, size); + } else { + return GetCrashpadInfoSectionInternal( + address, size); + } +} + template bool PEImageReader::GetCrashpadInfo( process_types::CrashpadInfo* crashpad_info) const { @@ -294,6 +306,31 @@ bool PEImageReader::VSFixedFileInfo( return true; } +template +bool PEImageReader::GetCrashpadInfoSectionInternal(WinVMAddress* address, + WinVMSize* size) const { + IMAGE_SECTION_HEADER section; + if (!GetSectionByName::type>("CPADinfo", + §ion)) { + return false; + } + + process_types::CrashpadInfo crashpad_info; + if (section.Misc.VirtualSize < + offsetof(process_types::CrashpadInfo, size) + + sizeof(crashpad_info.size)) { + LOG(WARNING) << "small crashpad info section size " + << section.Misc.VirtualSize << ", " + << module_subrange_reader_.name(); + return false; + } + + *address = Address() + section.VirtualAddress; + *size = std::min(sizeof(crashpad_info), section.Misc.VirtualSize); + + return true; +} + template bool PEImageReader::ReadNtHeaders(NtHeadersType* nt_headers, WinVMAddress* nt_headers_address) const { diff --git a/snapshot/win/pe_image_reader.h b/snapshot/win/pe_image_reader.h index 56a991b8..ebdbe578 100644 --- a/snapshot/win/pe_image_reader.h +++ b/snapshot/win/pe_image_reader.h @@ -94,6 +94,16 @@ class PEImageReader { //! This is the value passed as \a size to Initialize(). WinVMSize Size() const { return module_subrange_reader_.Size(); } + //! \brief Obtains the module's CrashpadInfo structure address and size. + //! + //! \param[out] address The CrashpadInfo structure address. + //! \param[out] size The CrashpadInfo structure size. + //! + //! \return `true` on success, `false` on failure. If the module does not have + //! a `CPADinfo` section, this will return `false` without logging any + //! messages. Other failures will result in messages being logged. + bool GetCrashpadInfoSection(WinVMAddress* address, WinVMSize* size) const; + //! \brief Obtains the module's CrashpadInfo structure. //! //! \return `true` on success, `false` on failure. If the module does not have @@ -137,6 +147,13 @@ class PEImageReader { bool VSFixedFileInfo(VS_FIXEDFILEINFO* vs_fixed_file_info) const; private: + //! \brief Performs the internal logic for GetCrashpadInfoSection(). + //! + //! \sa GetCrashpadInfoSection + template + bool GetCrashpadInfoSectionInternal(WinVMAddress* address, + WinVMSize* size) const; + //! \brief Reads the `IMAGE_NT_HEADERS` from the beginning of the image. //! //! \param[out] nt_headers The contents of the templated NtHeadersType