OLD | NEW |
1 // Copyright 2015 The Crashpad Authors. All rights reserved. | 1 // Copyright 2015 The Crashpad Authors. All rights reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 #include "snapshot/minidump/process_snapshot_minidump.h" | 15 #include "snapshot/minidump/process_snapshot_minidump.h" |
16 | 16 |
17 #include <string.h> | 17 #include <string.h> |
18 #include <windows.h> | 18 #include <windows.h> |
19 #include <dbghelp.h> | 19 #include <dbghelp.h> |
20 | 20 |
21 #include "base/memory/scoped_ptr.h" | 21 #include "base/memory/scoped_ptr.h" |
22 #include "gtest/gtest.h" | 22 #include "gtest/gtest.h" |
| 23 #include "snapshot/module_snapshot.h" |
23 #include "util/file/string_file.h" | 24 #include "util/file/string_file.h" |
24 | 25 |
25 namespace crashpad { | 26 namespace crashpad { |
26 namespace test { | 27 namespace test { |
27 namespace { | 28 namespace { |
28 | 29 |
29 TEST(ProcessSnapshotMinidump, EmptyFile) { | 30 TEST(ProcessSnapshotMinidump, EmptyFile) { |
30 StringFile string_file; | 31 StringFile string_file; |
31 ProcessSnapshotMinidump process_snapshot; | 32 ProcessSnapshotMinidump process_snapshot; |
32 | 33 |
(...skipping 17 matching lines...) Expand all Loading... |
50 MINIDUMP_HEADER header = {}; | 51 MINIDUMP_HEADER header = {}; |
51 header.Signature = MINIDUMP_SIGNATURE; | 52 header.Signature = MINIDUMP_SIGNATURE; |
52 header.Version = MINIDUMP_VERSION; | 53 header.Version = MINIDUMP_VERSION; |
53 | 54 |
54 EXPECT_TRUE(string_file.Write(&header, sizeof(header))); | 55 EXPECT_TRUE(string_file.Write(&header, sizeof(header))); |
55 | 56 |
56 ProcessSnapshotMinidump process_snapshot; | 57 ProcessSnapshotMinidump process_snapshot; |
57 EXPECT_TRUE(process_snapshot.Initialize(&string_file)); | 58 EXPECT_TRUE(process_snapshot.Initialize(&string_file)); |
58 } | 59 } |
59 | 60 |
| 61 // Writes |string| to |writer| as a MinidumpUTF8String, and returns the file |
| 62 // offst of the beginning of the string. |
| 63 RVA WriteString(FileWriterInterface* writer, const std::string& string) { |
| 64 RVA rva = static_cast<RVA>(writer->SeekGet()); |
| 65 |
| 66 uint32_t string_size = string.size(); |
| 67 EXPECT_TRUE(writer->Write(&string_size, sizeof(string_size))); |
| 68 |
| 69 // Include the trailing NUL character. |
| 70 EXPECT_TRUE(writer->Write(string.c_str(), string.size() + 1)); |
| 71 |
| 72 return rva; |
| 73 } |
| 74 |
| 75 // Writes |dictionary| to |writer| as a MinidumpSimpleStringDictionary, and |
| 76 // populates |location| with a location descriptor identifying what was written. |
| 77 void WriteMinidumpSimpleStringDictionary( |
| 78 MINIDUMP_LOCATION_DESCRIPTOR* location, |
| 79 FileWriterInterface* writer, |
| 80 const std::map<std::string, std::string>& dictionary) { |
| 81 std::vector<MinidumpSimpleStringDictionaryEntry> entries; |
| 82 for (const auto& it : dictionary) { |
| 83 MinidumpSimpleStringDictionaryEntry entry; |
| 84 entry.key = WriteString(writer, it.first); |
| 85 entry.value = WriteString(writer, it.second); |
| 86 entries.push_back(entry); |
| 87 } |
| 88 |
| 89 location->Rva = static_cast<RVA>(writer->SeekGet()); |
| 90 |
| 91 const uint32_t simple_string_dictionary_entries = entries.size(); |
| 92 EXPECT_TRUE(writer->Write(&simple_string_dictionary_entries, |
| 93 sizeof(simple_string_dictionary_entries))); |
| 94 for (const MinidumpSimpleStringDictionaryEntry& entry : entries) { |
| 95 EXPECT_TRUE(writer->Write(&entry, sizeof(entry))); |
| 96 } |
| 97 |
| 98 location->DataSize = |
| 99 sizeof(simple_string_dictionary_entries) + |
| 100 entries.size() * sizeof(MinidumpSimpleStringDictionaryEntry); |
| 101 } |
| 102 |
| 103 // Writes |strings| to |writer| as a MinidumpRVAList referencing |
| 104 // MinidumpUTF8String objects, and populates |location| with a location |
| 105 // descriptor identifying what was written. |
| 106 void WriteMinidumpStringList(MINIDUMP_LOCATION_DESCRIPTOR* location, |
| 107 FileWriterInterface* writer, |
| 108 const std::vector<std::string>& strings) { |
| 109 std::vector<RVA> rvas; |
| 110 for (const std::string& string : strings) { |
| 111 rvas.push_back(WriteString(writer, string)); |
| 112 } |
| 113 |
| 114 location->Rva = static_cast<RVA>(writer->SeekGet()); |
| 115 |
| 116 const uint32_t string_list_entries = rvas.size(); |
| 117 EXPECT_TRUE(writer->Write(&string_list_entries, sizeof(string_list_entries))); |
| 118 for (RVA rva : rvas) { |
| 119 EXPECT_TRUE(writer->Write(&rva, sizeof(rva))); |
| 120 } |
| 121 |
| 122 location->DataSize = sizeof(string_list_entries) + rvas.size() * sizeof(RVA); |
| 123 } |
| 124 |
60 TEST(ProcessSnapshotMinidump, AnnotationsSimpleMap) { | 125 TEST(ProcessSnapshotMinidump, AnnotationsSimpleMap) { |
61 StringFile string_file; | 126 StringFile string_file; |
62 | 127 |
63 MINIDUMP_HEADER header = {}; | 128 MINIDUMP_HEADER header = {}; |
64 EXPECT_TRUE(string_file.Write(&header, sizeof(header))); | 129 EXPECT_TRUE(string_file.Write(&header, sizeof(header))); |
65 | 130 |
66 MinidumpSimpleStringDictionaryEntry entry0 = {}; | |
67 entry0.key = static_cast<RVA>(string_file.SeekGet()); | |
68 const char kKey0[] = "the first key"; | |
69 uint32_t string_size = strlen(kKey0); | |
70 EXPECT_TRUE(string_file.Write(&string_size, sizeof(string_size))); | |
71 EXPECT_TRUE(string_file.Write(kKey0, sizeof(kKey0))); | |
72 | |
73 entry0.value = static_cast<RVA>(string_file.SeekGet()); | |
74 const char kValue0[] = "THE FIRST VALUE EVER!"; | |
75 string_size = strlen(kValue0); | |
76 EXPECT_TRUE(string_file.Write(&string_size, sizeof(string_size))); | |
77 EXPECT_TRUE(string_file.Write(kValue0, sizeof(kValue0))); | |
78 | |
79 MinidumpSimpleStringDictionaryEntry entry1 = {}; | |
80 entry1.key = static_cast<RVA>(string_file.SeekGet()); | |
81 const char kKey1[] = "2key"; | |
82 string_size = strlen(kKey1); | |
83 EXPECT_TRUE(string_file.Write(&string_size, sizeof(string_size))); | |
84 EXPECT_TRUE(string_file.Write(kKey1, sizeof(kKey1))); | |
85 | |
86 entry1.value = static_cast<RVA>(string_file.SeekGet()); | |
87 const char kValue1[] = "a lowly second value"; | |
88 string_size = strlen(kValue1); | |
89 EXPECT_TRUE(string_file.Write(&string_size, sizeof(string_size))); | |
90 EXPECT_TRUE(string_file.Write(kValue1, sizeof(kValue1))); | |
91 | |
92 MinidumpCrashpadInfo crashpad_info = {}; | 131 MinidumpCrashpadInfo crashpad_info = {}; |
93 crashpad_info.version = MinidumpCrashpadInfo::kVersion; | 132 crashpad_info.version = MinidumpCrashpadInfo::kVersion; |
94 | 133 |
95 crashpad_info.simple_annotations.Rva = | 134 std::map<std::string, std::string> dictionary; |
96 static_cast<RVA>(string_file.SeekGet()); | 135 dictionary["the first key"] = "THE FIRST VALUE EVER!"; |
97 uint32_t simple_string_dictionary_entries = 2; | 136 dictionary["2key"] = "a lowly second value"; |
98 EXPECT_TRUE(string_file.Write(&simple_string_dictionary_entries, | 137 WriteMinidumpSimpleStringDictionary( |
99 sizeof(simple_string_dictionary_entries))); | 138 &crashpad_info.simple_annotations, &string_file, dictionary); |
100 EXPECT_TRUE(string_file.Write(&entry0, sizeof(entry0))); | |
101 EXPECT_TRUE(string_file.Write(&entry1, sizeof(entry1))); | |
102 crashpad_info.simple_annotations.DataSize = | |
103 simple_string_dictionary_entries * | |
104 sizeof(MinidumpSimpleStringDictionaryEntry); | |
105 | 139 |
106 MINIDUMP_DIRECTORY crashpad_info_directory = {}; | 140 MINIDUMP_DIRECTORY crashpad_info_directory = {}; |
107 crashpad_info_directory.StreamType = kMinidumpStreamTypeCrashpadInfo; | 141 crashpad_info_directory.StreamType = kMinidumpStreamTypeCrashpadInfo; |
108 crashpad_info_directory.Location.Rva = | 142 crashpad_info_directory.Location.Rva = |
109 static_cast<RVA>(string_file.SeekGet()); | 143 static_cast<RVA>(string_file.SeekGet()); |
110 EXPECT_TRUE(string_file.Write(&crashpad_info, sizeof(crashpad_info))); | 144 EXPECT_TRUE(string_file.Write(&crashpad_info, sizeof(crashpad_info))); |
111 crashpad_info_directory.Location.DataSize = sizeof(crashpad_info); | 145 crashpad_info_directory.Location.DataSize = sizeof(crashpad_info); |
112 | 146 |
113 header.StreamDirectoryRva = static_cast<RVA>(string_file.SeekGet()); | 147 header.StreamDirectoryRva = static_cast<RVA>(string_file.SeekGet()); |
114 EXPECT_TRUE(string_file.Write(&crashpad_info_directory, | 148 EXPECT_TRUE(string_file.Write(&crashpad_info_directory, |
115 sizeof(crashpad_info_directory))); | 149 sizeof(crashpad_info_directory))); |
116 | 150 |
117 header.Signature = MINIDUMP_SIGNATURE; | 151 header.Signature = MINIDUMP_SIGNATURE; |
118 header.Version = MINIDUMP_VERSION; | 152 header.Version = MINIDUMP_VERSION; |
119 header.NumberOfStreams = 1; | 153 header.NumberOfStreams = 1; |
120 EXPECT_TRUE(string_file.SeekSet(0)); | 154 EXPECT_TRUE(string_file.SeekSet(0)); |
121 EXPECT_TRUE(string_file.Write(&header, sizeof(header))); | 155 EXPECT_TRUE(string_file.Write(&header, sizeof(header))); |
122 | 156 |
123 ProcessSnapshotMinidump process_snapshot; | 157 ProcessSnapshotMinidump process_snapshot; |
124 EXPECT_TRUE(process_snapshot.Initialize(&string_file)); | 158 EXPECT_TRUE(process_snapshot.Initialize(&string_file)); |
125 | 159 |
126 const auto annotations_simple_map = process_snapshot.AnnotationsSimpleMap(); | 160 const auto annotations_simple_map = process_snapshot.AnnotationsSimpleMap(); |
127 EXPECT_EQ(2u, annotations_simple_map.size()); | 161 EXPECT_EQ(dictionary, annotations_simple_map); |
| 162 } |
128 | 163 |
129 auto it = annotations_simple_map.find(kKey0); | 164 TEST(ProcessSnapshotMinidump, Modules) { |
130 ASSERT_NE(it, annotations_simple_map.end()); | 165 StringFile string_file; |
131 EXPECT_EQ(kValue0, it->second); | |
132 | 166 |
133 it = annotations_simple_map.find(kKey1); | 167 MINIDUMP_HEADER header = {}; |
134 ASSERT_NE(it, annotations_simple_map.end()); | 168 EXPECT_TRUE(string_file.Write(&header, sizeof(header))); |
135 EXPECT_EQ(kValue1, it->second); | 169 |
| 170 MINIDUMP_MODULE minidump_module = {}; |
| 171 uint32_t minidump_module_count = 3; |
| 172 |
| 173 MINIDUMP_DIRECTORY minidump_module_list_directory = {}; |
| 174 minidump_module_list_directory.StreamType = kMinidumpStreamTypeModuleList; |
| 175 minidump_module_list_directory.Location.DataSize = |
| 176 sizeof(MINIDUMP_MODULE_LIST) + |
| 177 minidump_module_count * sizeof(MINIDUMP_MODULE); |
| 178 minidump_module_list_directory.Location.Rva = |
| 179 static_cast<RVA>(string_file.SeekGet()); |
| 180 |
| 181 EXPECT_TRUE( |
| 182 string_file.Write(&minidump_module_count, sizeof(minidump_module_count))); |
| 183 for (uint32_t minidump_module_index = 0; |
| 184 minidump_module_index < minidump_module_count; |
| 185 ++minidump_module_index) { |
| 186 EXPECT_TRUE(string_file.Write(&minidump_module, sizeof(minidump_module))); |
| 187 } |
| 188 |
| 189 MinidumpModuleCrashpadInfo crashpad_module_0 = {}; |
| 190 crashpad_module_0.version = MinidumpModuleCrashpadInfo::kVersion; |
| 191 std::map<std::string, std::string> dictionary_0; |
| 192 dictionary_0["ptype"] = "browser"; |
| 193 dictionary_0["pid"] = "12345"; |
| 194 WriteMinidumpSimpleStringDictionary( |
| 195 &crashpad_module_0.simple_annotations, &string_file, dictionary_0); |
| 196 |
| 197 MinidumpModuleCrashpadInfoLink crashpad_module_0_link = {}; |
| 198 crashpad_module_0_link.minidump_module_list_index = 0; |
| 199 crashpad_module_0_link.location.DataSize = sizeof(crashpad_module_0); |
| 200 crashpad_module_0_link.location.Rva = static_cast<RVA>(string_file.SeekGet()); |
| 201 EXPECT_TRUE(string_file.Write(&crashpad_module_0, sizeof(crashpad_module_0))); |
| 202 |
| 203 MinidumpModuleCrashpadInfo crashpad_module_2 = {}; |
| 204 crashpad_module_2.version = MinidumpModuleCrashpadInfo::kVersion; |
| 205 std::map<std::string, std::string> dictionary_2; |
| 206 dictionary_2["fakemodule"] = "yes"; |
| 207 WriteMinidumpSimpleStringDictionary( |
| 208 &crashpad_module_2.simple_annotations, &string_file, dictionary_2); |
| 209 |
| 210 std::vector<std::string> list_annotations_2; |
| 211 list_annotations_2.push_back("first string"); |
| 212 list_annotations_2.push_back("last string"); |
| 213 WriteMinidumpStringList( |
| 214 &crashpad_module_2.list_annotations, &string_file, list_annotations_2); |
| 215 |
| 216 MinidumpModuleCrashpadInfoLink crashpad_module_2_link = {}; |
| 217 crashpad_module_2_link.minidump_module_list_index = 2; |
| 218 crashpad_module_2_link.location.DataSize = sizeof(crashpad_module_2); |
| 219 crashpad_module_2_link.location.Rva = static_cast<RVA>(string_file.SeekGet()); |
| 220 EXPECT_TRUE(string_file.Write(&crashpad_module_2, sizeof(crashpad_module_2))); |
| 221 |
| 222 MinidumpCrashpadInfo crashpad_info = {}; |
| 223 crashpad_info.version = MinidumpCrashpadInfo::kVersion; |
| 224 |
| 225 uint32_t crashpad_module_count = 2; |
| 226 |
| 227 crashpad_info.module_list.DataSize = |
| 228 sizeof(MinidumpModuleCrashpadInfoList) + |
| 229 crashpad_module_count * sizeof(MinidumpModuleCrashpadInfoLink); |
| 230 crashpad_info.module_list.Rva = static_cast<RVA>(string_file.SeekGet()); |
| 231 |
| 232 EXPECT_TRUE( |
| 233 string_file.Write(&crashpad_module_count, sizeof(crashpad_module_count))); |
| 234 EXPECT_TRUE(string_file.Write(&crashpad_module_0_link, |
| 235 sizeof(crashpad_module_0_link))); |
| 236 EXPECT_TRUE(string_file.Write(&crashpad_module_2_link, |
| 237 sizeof(crashpad_module_2_link))); |
| 238 |
| 239 MINIDUMP_DIRECTORY crashpad_info_directory = {}; |
| 240 crashpad_info_directory.StreamType = kMinidumpStreamTypeCrashpadInfo; |
| 241 crashpad_info_directory.Location.DataSize = sizeof(crashpad_info); |
| 242 crashpad_info_directory.Location.Rva = |
| 243 static_cast<RVA>(string_file.SeekGet()); |
| 244 EXPECT_TRUE(string_file.Write(&crashpad_info, sizeof(crashpad_info))); |
| 245 |
| 246 header.StreamDirectoryRva = static_cast<RVA>(string_file.SeekGet()); |
| 247 EXPECT_TRUE(string_file.Write(&minidump_module_list_directory, |
| 248 sizeof(minidump_module_list_directory))); |
| 249 EXPECT_TRUE(string_file.Write(&crashpad_info_directory, |
| 250 sizeof(crashpad_info_directory))); |
| 251 |
| 252 header.Signature = MINIDUMP_SIGNATURE; |
| 253 header.Version = MINIDUMP_VERSION; |
| 254 header.NumberOfStreams = 2; |
| 255 EXPECT_TRUE(string_file.SeekSet(0)); |
| 256 EXPECT_TRUE(string_file.Write(&header, sizeof(header))); |
| 257 |
| 258 ProcessSnapshotMinidump process_snapshot; |
| 259 EXPECT_TRUE(process_snapshot.Initialize(&string_file)); |
| 260 |
| 261 std::vector<const ModuleSnapshot*> modules = process_snapshot.Modules(); |
| 262 ASSERT_EQ(minidump_module_count, modules.size()); |
| 263 |
| 264 auto annotations_simple_map = modules[0]->AnnotationsSimpleMap(); |
| 265 EXPECT_EQ(dictionary_0, annotations_simple_map); |
| 266 |
| 267 auto annotations_vector = modules[0]->AnnotationsVector(); |
| 268 EXPECT_TRUE(annotations_vector.empty()); |
| 269 |
| 270 annotations_simple_map = modules[1]->AnnotationsSimpleMap(); |
| 271 EXPECT_TRUE(annotations_simple_map.empty()); |
| 272 |
| 273 annotations_vector = modules[1]->AnnotationsVector(); |
| 274 EXPECT_TRUE(annotations_vector.empty()); |
| 275 |
| 276 annotations_simple_map = modules[2]->AnnotationsSimpleMap(); |
| 277 EXPECT_EQ(dictionary_2, annotations_simple_map); |
| 278 |
| 279 annotations_vector = modules[2]->AnnotationsVector(); |
| 280 EXPECT_EQ(list_annotations_2, annotations_vector); |
136 } | 281 } |
137 | 282 |
138 } // namespace | 283 } // namespace |
139 } // namespace test | 284 } // namespace test |
140 } // namespace crashpad | 285 } // namespace crashpad |
OLD | NEW |