// Copyright 2015 The Crashpad Authors // // 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 #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) { constexpr size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER); constexpr 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); constexpr size_t kDirectoryIndex = 0; ASSERT_EQ(directory[kDirectoryIndex].StreamType, kMinidumpStreamTypeMemoryInfoList); EXPECT_EQ(directory[kDirectoryIndex].Location.Rva, kMemoryInfoListStreamOffset); *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 = std::make_unique(); ASSERT_TRUE( minidump_file_writer.AddStream(std::move(memory_info_list_writer))); StringFile string_file; ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file)); ASSERT_EQ(string_file.string().size(), sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + sizeof(MINIDUMP_MEMORY_INFO_LIST)); const MINIDUMP_MEMORY_INFO_LIST* memory_info_list = nullptr; ASSERT_NO_FATAL_FAILURE( GetMemoryInfoListStream(string_file.string(), &memory_info_list)); uint64_t number_of_entries; memcpy(&number_of_entries, &memory_info_list->NumberOfEntries, sizeof(number_of_entries)); EXPECT_EQ(number_of_entries, 0u); } TEST(MinidumpMemoryInfoWriter, OneRegion) { MinidumpFileWriter minidump_file_writer; auto memory_info_list_writer = std::make_unique(); auto memory_map_region = std::make_unique(); MINIDUMP_MEMORY_INFO mmi; mmi.BaseAddress = 0x12340000; mmi.AllocationBase = 0x12000000; mmi.AllocationProtect = PAGE_READWRITE; mmi.__alignment1 = 0; mmi.RegionSize = 0x6000; mmi.State = MEM_COMMIT; mmi.Protect = PAGE_NOACCESS; mmi.Type = MEM_PRIVATE; mmi.__alignment2 = 0; memory_map_region->SetMindumpMemoryInfo(mmi); std::vector memory_map; memory_map.push_back(memory_map_region.get()); memory_info_list_writer->InitializeFromSnapshot(memory_map); ASSERT_TRUE( minidump_file_writer.AddStream(std::move(memory_info_list_writer))); StringFile string_file; ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file)); ASSERT_EQ(string_file.string().size(), sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + sizeof(MINIDUMP_MEMORY_INFO_LIST) + sizeof(MINIDUMP_MEMORY_INFO)); const MINIDUMP_MEMORY_INFO_LIST* memory_info_list = nullptr; ASSERT_NO_FATAL_FAILURE( GetMemoryInfoListStream(string_file.string(), &memory_info_list)); uint64_t number_of_entries; memcpy(&number_of_entries, &memory_info_list->NumberOfEntries, sizeof(number_of_entries)); EXPECT_EQ(number_of_entries, 1u); MINIDUMP_MEMORY_INFO memory_info; memcpy(&memory_info, &memory_info_list[1], sizeof(memory_info)); EXPECT_EQ(memory_info.BaseAddress, mmi.BaseAddress); EXPECT_EQ(memory_info.AllocationBase, mmi.AllocationBase); EXPECT_EQ(memory_info.AllocationProtect, mmi.AllocationProtect); EXPECT_EQ(memory_info.RegionSize, mmi.RegionSize); EXPECT_EQ(memory_info.State, mmi.State); EXPECT_EQ(memory_info.Protect, mmi.Protect); EXPECT_EQ(memory_info.Type, mmi.Type); } } // namespace } // namespace test } // namespace crashpad