diff --git a/compat/non_win/dbghelp.h b/compat/non_win/dbghelp.h index 4fcd796b..6fed86bd 100644 --- a/compat/non_win/dbghelp.h +++ b/compat/non_win/dbghelp.h @@ -167,6 +167,9 @@ enum MINIDUMP_STREAM_TYPE { //! MINIDUMP_MISC_INFO::Flags1, that indicates which data is present and //! valid. MiscInfoStream = 15, + + //! \brief The stream type for MINIDUMP_MEMORY_INFO_LIST. + MemoryInfoListStream = 16, }; //! \brief Information about the CPU (or CPUs) that ran the process that the @@ -847,8 +850,8 @@ struct __attribute__((packed, aligned(4))) MINIDUMP_MEMORY_INFO { //! \brief The memory protection when the region was initially allocated. This //! member can be one of the memory protection options (such as - //! `PAGE_EXECUTE`, `PAGE_NOACCESS`, etc.), along with `PAGE_GUARD` or - //! `PAGE_NOCACHE`, as needed. + //! \ref PAGE_x PAGE_EXECUTE, \ref PAGE_x PAGE_NOACCESS, etc.), along with + //! \ref PAGE_x PAGE_GUARD or \ref PAGE_x PAGE_NOCACHE, as needed. uint32_t AllocationProtect; uint32_t __alignment1; @@ -858,20 +861,35 @@ struct __attribute__((packed, aligned(4))) MINIDUMP_MEMORY_INFO { uint64_t RegionSize; //! \brief The state of the pages in the region. This can be one of - //! `MEM_COMMIT`, `MEM_FREE`, or `MEM_RESERVE`. + //! \ref MEM_x MEM_COMMIT, \ref MEM_x MEM_FREE, or \ref MEM_x MEM_RESERVE. uint32_t State; //! \brief The access protection of the pages in the region. This member is //! one of the values listed for the #AllocationProtect member. uint32_t Protect; - //! \brief The type of pages in the region. This can be one of `MEM_IMAGE`, - //! `MEM_MAPPED`, or `MEM_PRIVATE`. + //! \brief The type of pages in the region. This can be one of \ref MEM_x + //! MEM_IMAGE, \ref MEM_x MEM_MAPPED, or \ref MEM_x MEM_PRIVATE. uint32_t Type; uint32_t __alignment2; }; +//! \brief Contains a list of memory regions. +struct __attribute__((packed, aligned(4))) MINIDUMP_MEMORY_INFO_LIST { + //! \brief The size of the header data for the stream, in bytes. This is + //! generally sizeof(MINIDUMP_MEMORY_INFO_LIST). + uint32_t SizeOfHeader; + + //! \brief The size of each entry following the header, in bytes. This is + //! generally sizeof(MINIDUMP_MEMORY_INFO). + uint32_t SizeOfEntry; + + //! \brief The number of entries in the stream. These are generally + //! MINIDUMP_MEMORY_INFO structures. The entries follow the header. + uint64_t NumberOfEntries; +}; + //! \brief Minidump file type values for MINIDUMP_HEADER::Flags. These bits //! describe the types of data carried within a minidump file. enum MINIDUMP_TYPE { diff --git a/compat/non_win/winnt.h b/compat/non_win/winnt.h index d61504c0..03167aa5 100644 --- a/compat/non_win/winnt.h +++ b/compat/non_win/winnt.h @@ -179,4 +179,39 @@ struct IMAGE_DEBUG_MISC { #define VER_PLATFORM_WIN32_NT 2 //! \} +//! \anchor PAGE_x +//! \name PAGE_* +//! +//! \brief Memory protection constants for MINIDUMP_MEMORY_INFO::Protect and +//! MINIDUMP_MEMORY_INFO::AllocationProtect. +//! \{ +#define PAGE_NOACCESS 0x1 +#define PAGE_READONLY 0x2 +#define PAGE_READWRITE 0x4 +#define PAGE_WRITECOPY 0x8 +#define PAGE_EXECUTE 0x10 +#define PAGE_EXECUTE_READ 0x20 +#define PAGE_EXECUTE_READWRITE 0x40 +#define PAGE_EXECUTE_WRITECOPY 0x80 +#define PAGE_GUARD 0x100 +#define PAGE_NOCACHE 0x200 +#define PAGE_WRITECOMBINE 0x400 +//! \} + +//! \anchor MEM_x +//! \name MEM_* +//! +//! \brief Memory state and type constants for MINIDUMP_MEMORY_INFO::State and +//! MINIDUMP_MEMORY_INFO::Type. +//! \{ +#define MEM_COMMIT 0x1000 +#define MEM_RESERVE 0x2000 +#define MEM_DECOMMIT 0x4000 +#define MEM_RELEASE 0x8000 +#define MEM_FREE 0x10000 +#define MEM_PRIVATE 0x20000 +#define MEM_MAPPED 0x40000 +#define MEM_RESET 0x80000 +//! \} + #endif // CRASHPAD_COMPAT_NON_WIN_WINNT_H_ diff --git a/handler/win/crashy_test_program.cc b/handler/win/crashy_test_program.cc index 622a5e5d..638098a6 100644 --- a/handler/win/crashy_test_program.cc +++ b/handler/win/crashy_test_program.cc @@ -20,6 +20,7 @@ #define STATUS_NO_SUCH_FILE static_cast(0xC000000F) #endif +#include "base/basictypes.h" #include "base/logging.h" #include "client/crashpad_client.h" #include "tools/tool_support.h" @@ -35,6 +36,45 @@ ULONG RtlNtStatusToDosError(NTSTATUS status) { return rtl_nt_status_to_dos_error(status); } +void AllocateMemoryOfVariousProtections() { + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + + const size_t kPageSize = system_info.dwPageSize; + + const uint32_t kPageTypes[] = { + PAGE_NOACCESS, + PAGE_READONLY, + PAGE_READWRITE, + PAGE_EXECUTE, + PAGE_EXECUTE_READ, + PAGE_EXECUTE_READWRITE, + + // PAGE_NOACCESS is invalid with PAGE_GUARD. + PAGE_READONLY | PAGE_GUARD, + PAGE_READWRITE | PAGE_GUARD, + PAGE_EXECUTE | PAGE_GUARD, + PAGE_EXECUTE_READ | PAGE_GUARD, + PAGE_EXECUTE_READWRITE | PAGE_GUARD, + }; + + // All of these allocations are leaked, we want to view them in windbg via + // !vprot. + void* reserve = VirtualAlloc( + nullptr, arraysize(kPageTypes) * kPageSize, MEM_RESERVE, PAGE_READWRITE); + PCHECK(reserve) << "VirtualAlloc MEM_RESERVE"; + uintptr_t reserve_as_int = reinterpret_cast(reserve); + + for (size_t i = 0; i < arraysize(kPageTypes); ++i) { + void* result = + VirtualAlloc(reinterpret_cast(reserve_as_int + (kPageSize * i)), + kPageSize, + MEM_COMMIT, + kPageTypes[i]); + PCHECK(result) << "VirtualAlloc MEM_COMMIT " << i; + } +} + void SomeCrashyFunction() { // SetLastError and NTSTATUS so that we have something to view in !gle in // windbg. RtlNtStatusToDosError() stores STATUS_NO_SUCH_FILE into the @@ -61,6 +101,8 @@ int CrashyMain(int argc, char* argv[]) { return 1; } + AllocateMemoryOfVariousProtections(); + SomeCrashyFunction(); return 0; diff --git a/minidump/minidump.gyp b/minidump/minidump.gyp index f7da929c..21041a9e 100644 --- a/minidump/minidump.gyp +++ b/minidump/minidump.gyp @@ -44,6 +44,8 @@ 'minidump_extensions.h', 'minidump_file_writer.cc', 'minidump_file_writer.h', + 'minidump_memory_info_writer.cc', + 'minidump_memory_info_writer.h', 'minidump_memory_writer.cc', 'minidump_memory_writer.h', 'minidump_misc_info_writer.cc', diff --git a/minidump/minidump_extensions.h b/minidump/minidump_extensions.h index 95fdbddf..3cb39dc2 100644 --- a/minidump/minidump_extensions.h +++ b/minidump/minidump_extensions.h @@ -77,6 +77,11 @@ enum MinidumpStreamType : uint32_t { //! \sa MiscInfoStream kMinidumpStreamTypeMiscInfo = MiscInfoStream, + //! \brief The stream type for MINIDUMP_MEMORY_INFO_LIST. + //! + //! \sa MemoryInfoListStream + kMinidumpStreamTypeMemoryInfoList = MemoryInfoListStream, + // 0x4350 = "CP" //! \brief The stream type for MinidumpCrashpadInfo. diff --git a/minidump/minidump_file_writer.cc b/minidump/minidump_file_writer.cc index f0c8d4b8..88986561 100644 --- a/minidump/minidump_file_writer.cc +++ b/minidump/minidump_file_writer.cc @@ -17,6 +17,7 @@ #include "base/logging.h" #include "minidump/minidump_crashpad_info_writer.h" #include "minidump/minidump_exception_writer.h" +#include "minidump/minidump_memory_info_writer.h" #include "minidump/minidump_memory_writer.h" #include "minidump/minidump_misc_info_writer.h" #include "minidump/minidump_module_writer.h" @@ -99,6 +100,14 @@ void MinidumpFileWriter::InitializeFromSnapshot( AddStream(crashpad_info.Pass()); } + std::vector memory_map_snapshot = + process_snapshot->MemoryMap(); + if (!memory_map_snapshot.empty()) { + auto memory_info_list = make_scoped_ptr(new MinidumpMemoryInfoListWriter()); + memory_info_list->InitializeFromSnapshot(memory_map_snapshot); + AddStream(memory_info_list.Pass()); + } + memory_list->AddFromSnapshot(process_snapshot->ExtraMemory()); AddStream(memory_list.Pass()); diff --git a/minidump/minidump_memory_info_writer.cc b/minidump/minidump_memory_info_writer.cc new file mode 100644 index 00000000..8b6bdc8c --- /dev/null +++ b/minidump/minidump_memory_info_writer.cc @@ -0,0 +1,85 @@ +// Copyright 2015 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "minidump/minidump_memory_info_writer.h" + +#include "base/logging.h" +#include "snapshot/memory_map_region_snapshot.h" +#include "util/file/file_writer.h" + +namespace crashpad { + +MinidumpMemoryInfoListWriter::MinidumpMemoryInfoListWriter() + : memory_info_list_base_(), items_() { +} + +MinidumpMemoryInfoListWriter::~MinidumpMemoryInfoListWriter() { +} + +void MinidumpMemoryInfoListWriter::InitializeFromSnapshot( + const std::vector& memory_map) { + DCHECK_EQ(state(), kStateMutable); + + DCHECK(items_.empty()); + for (const auto& region : memory_map) + items_.push_back(region->AsMinidumpMemoryInfo()); +} + +bool MinidumpMemoryInfoListWriter::Freeze() { + DCHECK_EQ(state(), kStateMutable); + + if (!MinidumpStreamWriter::Freeze()) + return false; + + memory_info_list_base_.SizeOfHeader = sizeof(MINIDUMP_MEMORY_INFO_LIST); + memory_info_list_base_.SizeOfEntry = sizeof(MINIDUMP_MEMORY_INFO); + memory_info_list_base_.NumberOfEntries = items_.size(); + + return true; +} + +size_t MinidumpMemoryInfoListWriter::SizeOfObject() { + DCHECK_GE(state(), kStateFrozen); + return sizeof(memory_info_list_base_) + sizeof(items_[0]) * items_.size(); +} + +std::vector +MinidumpMemoryInfoListWriter::Children() { + DCHECK_GE(state(), kStateFrozen); + return std::vector(); +} + +bool MinidumpMemoryInfoListWriter::WriteObject( + FileWriterInterface* file_writer) { + DCHECK_EQ(state(), kStateWritable); + + WritableIoVec iov; + iov.iov_base = &memory_info_list_base_; + iov.iov_len = sizeof(memory_info_list_base_); + std::vector iovecs(1, iov); + + for (const auto& minidump_memory_info : items_) { + iov.iov_base = &minidump_memory_info; + iov.iov_len = sizeof(minidump_memory_info); + iovecs.push_back(iov); + } + + return file_writer->WriteIoVec(&iovecs); +} + +MinidumpStreamType MinidumpMemoryInfoListWriter::StreamType() const { + return kMinidumpStreamTypeMemoryInfoList; +} + +} // namespace crashpad diff --git a/minidump/minidump_memory_info_writer.h b/minidump/minidump_memory_info_writer.h new file mode 100644 index 00000000..6f6ea59b --- /dev/null +++ b/minidump/minidump_memory_info_writer.h @@ -0,0 +1,71 @@ +// Copyright 2015 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_MINIDUMP_MINIDUMP_MEMORY_INFO_WRITER_H_ +#define CRASHPAD_MINIDUMP_MINIDUMP_MEMORY_INFO_WRITER_H_ + +#include +#include +#include + +#include + +#include "base/basictypes.h" +#include "minidump/minidump_stream_writer.h" +#include "minidump/minidump_writable.h" + +namespace crashpad { + +class MemoryMapRegionSnapshot; +class MinidumpContextWriter; +class MinidumpMemoryListWriter; +class MinidumpMemoryWriter; + +//! \brief The writer for a MINIDUMP_MEMORY_INFO_LIST stream in a minidump file, +//! containing a list of MINIDUMP_MEMORY_INFO objects. +class MinidumpMemoryInfoListWriter final + : public internal::MinidumpStreamWriter { + public: + MinidumpMemoryInfoListWriter(); + ~MinidumpMemoryInfoListWriter() override; + + //! \brief Initializes a MINIDUMP_MEMORY_INFO_LIST based on \a memory_map. + //! + //! \param[in] memory_map The vector of memory map region snapshots to use as + //! source data. + //! + //! \note Valid in #kStateMutable. + void InitializeFromSnapshot( + const std::vector& memory_map); + + protected: + // MinidumpWritable: + bool Freeze() override; + size_t SizeOfObject() override; + std::vector Children() override; + bool WriteObject(FileWriterInterface* file_writer) override; + + // MinidumpStreamWriter: + MinidumpStreamType StreamType() const override; + + private: + MINIDUMP_MEMORY_INFO_LIST memory_info_list_base_; + std::vector items_; + + DISALLOW_COPY_AND_ASSIGN(MinidumpMemoryInfoListWriter); +}; + +} // namespace crashpad + +#endif // CRASHPAD_MINIDUMP_MINIDUMP_MEMORY_INFO_WRITER_H_ diff --git a/minidump/minidump_memory_info_writer_test.cc b/minidump/minidump_memory_info_writer_test.cc new file mode 100644 index 00000000..21081d53 --- /dev/null +++ b/minidump/minidump_memory_info_writer_test.cc @@ -0,0 +1,126 @@ +// Copyright 2015 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "minidump/minidump_memory_info_writer.h" + +#include + +#include "gtest/gtest.h" +#include "minidump/minidump_file_writer.h" +#include "minidump/test/minidump_file_writer_test_util.h" +#include "minidump/test/minidump_writable_test_util.h" +#include "snapshot/test/test_memory_map_region_snapshot.h" +#include "util/file/string_file.h" + +namespace crashpad { +namespace test { +namespace { + +// The memory info list is expected to be the only stream. +void GetMemoryInfoListStream( + const std::string& file_contents, + const MINIDUMP_MEMORY_INFO_LIST** memory_info_list) { + const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER); + const size_t kMemoryInfoListStreamOffset = + kDirectoryOffset + sizeof(MINIDUMP_DIRECTORY); + + const MINIDUMP_DIRECTORY* directory; + const MINIDUMP_HEADER* header = + MinidumpHeaderAtStart(file_contents, &directory); + ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, 1, 0)); + ASSERT_TRUE(directory); + + const size_t kDirectoryIndex = 0; + + ASSERT_EQ(kMinidumpStreamTypeMemoryInfoList, + directory[kDirectoryIndex].StreamType); + EXPECT_EQ(kMemoryInfoListStreamOffset, + directory[kDirectoryIndex].Location.Rva); + + *memory_info_list = + MinidumpWritableAtLocationDescriptor( + file_contents, directory[kDirectoryIndex].Location); + ASSERT_TRUE(memory_info_list); +} + +TEST(MinidumpMemoryInfoWriter, Empty) { + MinidumpFileWriter minidump_file_writer; + auto memory_info_list_writer = + make_scoped_ptr(new MinidumpMemoryInfoListWriter()); + minidump_file_writer.AddStream(memory_info_list_writer.Pass()); + + StringFile string_file; + ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file)); + + ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + + sizeof(MINIDUMP_MEMORY_INFO_LIST), + string_file.string().size()); + + const MINIDUMP_MEMORY_INFO_LIST* memory_info_list = nullptr; + ASSERT_NO_FATAL_FAILURE( + GetMemoryInfoListStream(string_file.string(), &memory_info_list)); + + EXPECT_EQ(0u, memory_info_list->NumberOfEntries); +} + +TEST(MinidumpMemoryInfoWriter, OneRegion) { + MinidumpFileWriter minidump_file_writer; + auto memory_info_list_writer = + make_scoped_ptr(new MinidumpMemoryInfoListWriter()); + + auto memory_map_region = make_scoped_ptr(new TestMemoryMapRegionSnapshot()); + + MINIDUMP_MEMORY_INFO mmi = {0}; + mmi.BaseAddress = 0x12340000; + mmi.AllocationBase = 0x12000000; + mmi.AllocationProtect = PAGE_READWRITE; + mmi.RegionSize = 0x6000; + mmi.State = MEM_COMMIT; + mmi.Protect = PAGE_NOACCESS; + mmi.Type = MEM_PRIVATE; + memory_map_region->SetMindumpMemoryInfo(mmi); + + std::vector memory_map; + memory_map.push_back(memory_map_region.get()); + memory_info_list_writer->InitializeFromSnapshot(memory_map); + + minidump_file_writer.AddStream(memory_info_list_writer.Pass()); + + StringFile string_file; + ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file)); + + ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + + sizeof(MINIDUMP_MEMORY_INFO_LIST) + + sizeof(MINIDUMP_MEMORY_INFO), + string_file.string().size()); + + const MINIDUMP_MEMORY_INFO_LIST* memory_info_list = nullptr; + ASSERT_NO_FATAL_FAILURE( + GetMemoryInfoListStream(string_file.string(), &memory_info_list)); + + EXPECT_EQ(1u, memory_info_list->NumberOfEntries); + const MINIDUMP_MEMORY_INFO* memory_info = + reinterpret_cast(&memory_info_list[1]); + EXPECT_EQ(mmi.BaseAddress, memory_info->BaseAddress); + EXPECT_EQ(mmi.AllocationBase, memory_info->AllocationBase); + EXPECT_EQ(mmi.AllocationProtect, memory_info->AllocationProtect); + EXPECT_EQ(mmi.RegionSize, memory_info->RegionSize); + EXPECT_EQ(mmi.State, memory_info->State); + EXPECT_EQ(mmi.Protect, memory_info->Protect); + EXPECT_EQ(mmi.Type, memory_info->Type); +} + +} // namespace +} // namespace test +} // namespace crashpad diff --git a/minidump/minidump_test.gyp b/minidump/minidump_test.gyp index 35b7d1a9..09b80cc2 100644 --- a/minidump/minidump_test.gyp +++ b/minidump/minidump_test.gyp @@ -37,6 +37,7 @@ 'minidump_crashpad_info_writer_test.cc', 'minidump_exception_writer_test.cc', 'minidump_file_writer_test.cc', + 'minidump_memory_info_writer_test.cc', 'minidump_memory_writer_test.cc', 'minidump_misc_info_writer_test.cc', 'minidump_module_crashpad_info_writer_test.cc', diff --git a/minidump/test/minidump_writable_test_util.cc b/minidump/test/minidump_writable_test_util.cc index d16aed94..ef00f40a 100644 --- a/minidump/test/minidump_writable_test_util.cc +++ b/minidump/test/minidump_writable_test_util.cc @@ -181,6 +181,14 @@ struct MinidumpThreadListTraits { } }; +struct MinidumpMemoryInfoListTraits { + using ListType = MINIDUMP_MEMORY_INFO_LIST; + enum : size_t { kElementSize = sizeof(MINIDUMP_MEMORY_INFO) }; + static size_t ElementCount(const ListType* list) { + return static_cast(list->NumberOfEntries); + } +}; + struct MinidumpModuleCrashpadInfoListTraits { using ListType = MinidumpModuleCrashpadInfoList; enum : size_t { kElementSize = sizeof(MinidumpModuleCrashpadInfoLink) }; @@ -244,6 +252,14 @@ const MINIDUMP_THREAD_LIST* MinidumpWritableAtLocationDescriptor< file_contents, location); } +template <> +const MINIDUMP_MEMORY_INFO_LIST* MinidumpWritableAtLocationDescriptor< + MINIDUMP_MEMORY_INFO_LIST>(const std::string& file_contents, + const MINIDUMP_LOCATION_DESCRIPTOR& location) { + return MinidumpListAtLocationDescriptor( + file_contents, location); +} + template <> const MinidumpModuleCrashpadInfoList* MinidumpWritableAtLocationDescriptor( diff --git a/minidump/test/minidump_writable_test_util.h b/minidump/test/minidump_writable_test_util.h index ce489686..9cba8be0 100644 --- a/minidump/test/minidump_writable_test_util.h +++ b/minidump/test/minidump_writable_test_util.h @@ -90,6 +90,7 @@ MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_DIRECTORY); MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_MEMORY_LIST); MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_MODULE_LIST); MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_THREAD_LIST); +MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_MEMORY_INFO_LIST); MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpModuleCrashpadInfoList); MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpRVAList); MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpSimpleStringDictionary); @@ -138,10 +139,10 @@ const T* TMinidumpWritableAtLocationDescriptor( //! - With a MINIDUMP_HEADER template parameter, a template specialization //! ensures that the structure’s magic number and version fields are correct. //! - With a MINIDUMP_MEMORY_LIST, MINIDUMP_THREAD_LIST, MINIDUMP_MODULE_LIST, -//! or MinidumpSimpleStringDictionary template parameter, template -//! specializations ensure that the size given by \a location matches the -//! size expected of a stream containing the number of elements it claims to -//! have. +//! MINIDUMP_MEMORY_INFO_LIST, or MinidumpSimpleStringDictionary template +//! parameter, template specializations ensure that the size given by \a +//! location matches the size expected of a stream containing the number of +//! elements it claims to have. //! - With an IMAGE_DEBUG_MISC, CodeViewRecordPDB20, or CodeViewRecordPDB70 //! template parameter, template specializations ensure that the structure //! has the expected format including any magic number and the `NUL`- @@ -189,6 +190,11 @@ const MINIDUMP_THREAD_LIST* MinidumpWritableAtLocationDescriptor< MINIDUMP_THREAD_LIST>(const std::string& file_contents, const MINIDUMP_LOCATION_DESCRIPTOR& location); +template <> +const MINIDUMP_MEMORY_INFO_LIST* MinidumpWritableAtLocationDescriptor< + MINIDUMP_MEMORY_INFO_LIST>(const std::string& file_contents, + const MINIDUMP_LOCATION_DESCRIPTOR& location); + template <> const CodeViewRecordPDB20* MinidumpWritableAtLocationDescriptor< CodeViewRecordPDB20>(const std::string& file_contents, diff --git a/snapshot/snapshot_test.gyp b/snapshot/snapshot_test.gyp index fd7aaefe..51274e6c 100644 --- a/snapshot/snapshot_test.gyp +++ b/snapshot/snapshot_test.gyp @@ -34,6 +34,8 @@ 'test/test_cpu_context.h', 'test/test_exception_snapshot.cc', 'test/test_exception_snapshot.h', + 'test/test_memory_map_region_snapshot.cc', + 'test/test_memory_map_region_snapshot.h', 'test/test_memory_snapshot.cc', 'test/test_memory_snapshot.h', 'test/test_module_snapshot.cc', diff --git a/snapshot/test/test_memory_map_region_snapshot.cc b/snapshot/test/test_memory_map_region_snapshot.cc new file mode 100644 index 00000000..53500c64 --- /dev/null +++ b/snapshot/test/test_memory_map_region_snapshot.cc @@ -0,0 +1,37 @@ +// Copyright 2015 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "snapshot/test/test_memory_map_region_snapshot.h" + +namespace crashpad { +namespace test { + +TestMemoryMapRegionSnapshot::TestMemoryMapRegionSnapshot() : memory_info_() { +} + +TestMemoryMapRegionSnapshot::~TestMemoryMapRegionSnapshot() { +} + +void TestMemoryMapRegionSnapshot::SetMindumpMemoryInfo( + const MINIDUMP_MEMORY_INFO& mmi) { + memory_info_ = mmi; +} + +const MINIDUMP_MEMORY_INFO& TestMemoryMapRegionSnapshot::AsMinidumpMemoryInfo() + const { + return memory_info_; +} + +} // namespace test +} // namespace crashpad diff --git a/snapshot/test/test_memory_map_region_snapshot.h b/snapshot/test/test_memory_map_region_snapshot.h new file mode 100644 index 00000000..e9edc5ca --- /dev/null +++ b/snapshot/test/test_memory_map_region_snapshot.h @@ -0,0 +1,47 @@ +// Copyright 2015 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_SNAPSHOT_TEST_TEST_MEMORY_MAP_REGION_SNAPSHOT_H_ +#define CRASHPAD_SNAPSHOT_TEST_TEST_MEMORY_MAP_REGION_SNAPSHOT_H_ + +#include + +#include "base/basictypes.h" +#include "snapshot/memory_map_region_snapshot.h" + +namespace crashpad { +namespace test { + +//! \brief A test MemoryMapRegionSnapshot that can carry arbitrary data for +//! testing purposes. +class TestMemoryMapRegionSnapshot final : public MemoryMapRegionSnapshot { + public: + TestMemoryMapRegionSnapshot(); + ~TestMemoryMapRegionSnapshot() override; + + void SetMindumpMemoryInfo(const MINIDUMP_MEMORY_INFO& mmi); + + // MemoryMapRegionSnapshot: + const MINIDUMP_MEMORY_INFO& AsMinidumpMemoryInfo() const override; + + private: + MINIDUMP_MEMORY_INFO memory_info_; + + DISALLOW_COPY_AND_ASSIGN(TestMemoryMapRegionSnapshot); +}; + +} // namespace test +} // namespace crashpad + +#endif // CRASHPAD_SNAPSHOT_TEST_TEST_MEMORY_MAP_REGION_SNAPSHOT_H_