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 EXPECT_TRUE(writer->Write(string.c_str(), string.size() + 1)); // include NUL | |
Robert Sesek
2015/03/04 01:52:25
nit: punctuation and capitalization (yes I know th
Mark Mentovai
2015/03/04 16:24:24
Robert Sesek wrote:
| |
69 | |
70 return rva; | |
71 } | |
72 | |
73 // Writes |dictionary| to |writer| as a MinidumpSimpleStringDictionary, and | |
74 // populates |location| with a location descriptor identifying what was written. | |
75 void WriteMinidumpSimpleStringDictionary( | |
76 MINIDUMP_LOCATION_DESCRIPTOR* location, | |
77 FileWriterInterface* writer, | |
78 const std::map<std::string, std::string>& dictionary) { | |
79 std::vector<MinidumpSimpleStringDictionaryEntry> entries; | |
80 for (const auto& it : dictionary) { | |
81 MinidumpSimpleStringDictionaryEntry entry; | |
82 entry.key = WriteString(writer, it.first); | |
83 entry.value = WriteString(writer, it.second); | |
84 entries.push_back(entry); | |
85 } | |
86 | |
87 location->Rva = static_cast<RVA>(writer->SeekGet()); | |
88 | |
89 const uint32_t simple_string_dictionary_entries = entries.size(); | |
90 EXPECT_TRUE(writer->Write(&simple_string_dictionary_entries, | |
91 sizeof(simple_string_dictionary_entries))); | |
92 for (const MinidumpSimpleStringDictionaryEntry& entry : entries) { | |
93 EXPECT_TRUE(writer->Write(&entry, sizeof(entry))); | |
94 } | |
95 | |
96 location->DataSize = | |
97 sizeof(simple_string_dictionary_entries) + | |
98 entries.size() * sizeof(MinidumpSimpleStringDictionaryEntry); | |
99 } | |
100 | |
101 // Writes |strings| to |writer| as a MinidumpRVAList referencing | |
102 // MinidumpUTF8String objects, and populates |location| with a location | |
103 // descriptor identifying what was written. | |
104 void WriteMinidumpStringList(MINIDUMP_LOCATION_DESCRIPTOR* location, | |
105 FileWriterInterface* writer, | |
106 const std::vector<std::string>& strings) { | |
107 std::vector<RVA> rvas; | |
108 for (const std::string& string : strings) { | |
109 rvas.push_back(WriteString(writer, string)); | |
110 } | |
111 | |
112 location->Rva = static_cast<RVA>(writer->SeekGet()); | |
113 | |
114 const uint32_t string_list_entries = rvas.size(); | |
115 EXPECT_TRUE(writer->Write(&string_list_entries, sizeof(string_list_entries))); | |
116 for (RVA rva : rvas) { | |
117 EXPECT_TRUE(writer->Write(&rva, sizeof(rva))); | |
118 } | |
119 | |
120 location->DataSize = sizeof(string_list_entries) + rvas.size() * sizeof(RVA); | |
121 } | |
122 | |
60 TEST(ProcessSnapshotMinidump, AnnotationsSimpleMap) { | 123 TEST(ProcessSnapshotMinidump, AnnotationsSimpleMap) { |
61 StringFile string_file; | 124 StringFile string_file; |
62 | 125 |
63 MINIDUMP_HEADER header = {}; | 126 MINIDUMP_HEADER header = {}; |
64 EXPECT_TRUE(string_file.Write(&header, sizeof(header))); | 127 EXPECT_TRUE(string_file.Write(&header, sizeof(header))); |
65 | 128 |
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 = {}; | 129 MinidumpCrashpadInfo crashpad_info = {}; |
93 crashpad_info.version = MinidumpCrashpadInfo::kVersion; | 130 crashpad_info.version = MinidumpCrashpadInfo::kVersion; |
94 | 131 |
95 crashpad_info.simple_annotations.Rva = | 132 std::map<std::string, std::string> dictionary; |
96 static_cast<RVA>(string_file.SeekGet()); | 133 dictionary["the first key"] = "THE FIRST VALUE EVER!"; |
97 uint32_t simple_string_dictionary_entries = 2; | 134 dictionary["2key"] = "a lowly second value"; |
98 EXPECT_TRUE(string_file.Write(&simple_string_dictionary_entries, | 135 WriteMinidumpSimpleStringDictionary( |
99 sizeof(simple_string_dictionary_entries))); | 136 &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 | 137 |
106 MINIDUMP_DIRECTORY crashpad_info_directory = {}; | 138 MINIDUMP_DIRECTORY crashpad_info_directory = {}; |
107 crashpad_info_directory.StreamType = kMinidumpStreamTypeCrashpadInfo; | 139 crashpad_info_directory.StreamType = kMinidumpStreamTypeCrashpadInfo; |
108 crashpad_info_directory.Location.Rva = | 140 crashpad_info_directory.Location.Rva = |
109 static_cast<RVA>(string_file.SeekGet()); | 141 static_cast<RVA>(string_file.SeekGet()); |
110 EXPECT_TRUE(string_file.Write(&crashpad_info, sizeof(crashpad_info))); | 142 EXPECT_TRUE(string_file.Write(&crashpad_info, sizeof(crashpad_info))); |
111 crashpad_info_directory.Location.DataSize = sizeof(crashpad_info); | 143 crashpad_info_directory.Location.DataSize = sizeof(crashpad_info); |
112 | 144 |
113 header.StreamDirectoryRva = static_cast<RVA>(string_file.SeekGet()); | 145 header.StreamDirectoryRva = static_cast<RVA>(string_file.SeekGet()); |
114 EXPECT_TRUE(string_file.Write(&crashpad_info_directory, | 146 EXPECT_TRUE(string_file.Write(&crashpad_info_directory, |
115 sizeof(crashpad_info_directory))); | 147 sizeof(crashpad_info_directory))); |
116 | 148 |
117 header.Signature = MINIDUMP_SIGNATURE; | 149 header.Signature = MINIDUMP_SIGNATURE; |
118 header.Version = MINIDUMP_VERSION; | 150 header.Version = MINIDUMP_VERSION; |
119 header.NumberOfStreams = 1; | 151 header.NumberOfStreams = 1; |
120 EXPECT_TRUE(string_file.SeekSet(0)); | 152 EXPECT_TRUE(string_file.SeekSet(0)); |
121 EXPECT_TRUE(string_file.Write(&header, sizeof(header))); | 153 EXPECT_TRUE(string_file.Write(&header, sizeof(header))); |
122 | 154 |
123 ProcessSnapshotMinidump process_snapshot; | 155 ProcessSnapshotMinidump process_snapshot; |
124 EXPECT_TRUE(process_snapshot.Initialize(&string_file)); | 156 EXPECT_TRUE(process_snapshot.Initialize(&string_file)); |
125 | 157 |
126 const auto annotations_simple_map = process_snapshot.AnnotationsSimpleMap(); | 158 const auto annotations_simple_map = process_snapshot.AnnotationsSimpleMap(); |
127 EXPECT_EQ(2u, annotations_simple_map.size()); | 159 EXPECT_EQ(dictionary, annotations_simple_map); |
160 } | |
128 | 161 |
129 auto it = annotations_simple_map.find(kKey0); | 162 TEST(ProcessSnapshotMinidump, Modules) { |
130 ASSERT_NE(it, annotations_simple_map.end()); | 163 StringFile string_file; |
131 EXPECT_EQ(kValue0, it->second); | |
132 | 164 |
133 it = annotations_simple_map.find(kKey1); | 165 MINIDUMP_HEADER header = {}; |
134 ASSERT_NE(it, annotations_simple_map.end()); | 166 EXPECT_TRUE(string_file.Write(&header, sizeof(header))); |
135 EXPECT_EQ(kValue1, it->second); | 167 |
168 MINIDUMP_MODULE minidump_module = {}; | |
169 uint32_t minidump_module_count = 3; | |
170 | |
171 MINIDUMP_DIRECTORY minidump_module_list_directory = {}; | |
172 minidump_module_list_directory.StreamType = kMinidumpStreamTypeModuleList; | |
173 minidump_module_list_directory.Location.DataSize = | |
174 sizeof(MINIDUMP_MODULE_LIST) + | |
175 minidump_module_count * sizeof(MINIDUMP_MODULE); | |
176 minidump_module_list_directory.Location.Rva = | |
177 static_cast<RVA>(string_file.SeekGet()); | |
178 | |
179 EXPECT_TRUE( | |
180 string_file.Write(&minidump_module_count, sizeof(minidump_module_count))); | |
181 for (uint32_t minidump_module_index = 0; | |
182 minidump_module_index < minidump_module_count; | |
183 ++minidump_module_index) { | |
184 EXPECT_TRUE(string_file.Write(&minidump_module, sizeof(minidump_module))); | |
185 } | |
186 | |
187 MinidumpModuleCrashpadInfo crashpad_module_0 = {}; | |
188 crashpad_module_0.version = MinidumpModuleCrashpadInfo::kVersion; | |
189 std::map<std::string, std::string> dictionary_0; | |
190 dictionary_0["ptype"] = "browser"; | |
191 dictionary_0["pid"] = "12345"; | |
192 WriteMinidumpSimpleStringDictionary( | |
193 &crashpad_module_0.simple_annotations, &string_file, dictionary_0); | |
194 | |
195 MinidumpModuleCrashpadInfoLink crashpad_module_0_link = {}; | |
196 crashpad_module_0_link.minidump_module_list_index = 0; | |
197 crashpad_module_0_link.location.DataSize = sizeof(crashpad_module_0); | |
198 crashpad_module_0_link.location.Rva = static_cast<RVA>(string_file.SeekGet()); | |
199 EXPECT_TRUE(string_file.Write(&crashpad_module_0, sizeof(crashpad_module_0))); | |
200 | |
201 MinidumpModuleCrashpadInfo crashpad_module_2 = {}; | |
202 crashpad_module_2.version = MinidumpModuleCrashpadInfo::kVersion; | |
203 std::map<std::string, std::string> dictionary_2; | |
204 dictionary_2["fakemodule"] = "yes"; | |
205 WriteMinidumpSimpleStringDictionary( | |
206 &crashpad_module_2.simple_annotations, &string_file, dictionary_2); | |
207 | |
208 std::vector<std::string> list_annotations_2; | |
209 list_annotations_2.push_back("first string"); | |
210 list_annotations_2.push_back("last string"); | |
211 WriteMinidumpStringList( | |
212 &crashpad_module_2.list_annotations, &string_file, list_annotations_2); | |
213 | |
214 MinidumpModuleCrashpadInfoLink crashpad_module_2_link = {}; | |
215 crashpad_module_2_link.minidump_module_list_index = 2; | |
216 crashpad_module_2_link.location.DataSize = sizeof(crashpad_module_2); | |
217 crashpad_module_2_link.location.Rva = static_cast<RVA>(string_file.SeekGet()); | |
218 EXPECT_TRUE(string_file.Write(&crashpad_module_2, sizeof(crashpad_module_2))); | |
219 | |
220 MinidumpCrashpadInfo crashpad_info = {}; | |
221 crashpad_info.version = MinidumpCrashpadInfo::kVersion; | |
222 | |
223 uint32_t crashpad_module_count = 2; | |
224 | |
225 crashpad_info.module_list.DataSize = | |
226 sizeof(MinidumpModuleCrashpadInfoList) + | |
227 crashpad_module_count * sizeof(MinidumpModuleCrashpadInfoLink); | |
228 crashpad_info.module_list.Rva = static_cast<RVA>(string_file.SeekGet()); | |
229 | |
230 EXPECT_TRUE( | |
231 string_file.Write(&crashpad_module_count, sizeof(crashpad_module_count))); | |
232 EXPECT_TRUE(string_file.Write(&crashpad_module_0_link, | |
233 sizeof(crashpad_module_0_link))); | |
234 EXPECT_TRUE(string_file.Write(&crashpad_module_2_link, | |
235 sizeof(crashpad_module_2_link))); | |
236 | |
237 MINIDUMP_DIRECTORY crashpad_info_directory = {}; | |
238 crashpad_info_directory.StreamType = kMinidumpStreamTypeCrashpadInfo; | |
239 crashpad_info_directory.Location.DataSize = sizeof(crashpad_info); | |
240 crashpad_info_directory.Location.Rva = | |
241 static_cast<RVA>(string_file.SeekGet()); | |
242 EXPECT_TRUE(string_file.Write(&crashpad_info, sizeof(crashpad_info))); | |
243 | |
244 header.StreamDirectoryRva = static_cast<RVA>(string_file.SeekGet()); | |
245 EXPECT_TRUE(string_file.Write(&minidump_module_list_directory, | |
246 sizeof(minidump_module_list_directory))); | |
247 EXPECT_TRUE(string_file.Write(&crashpad_info_directory, | |
248 sizeof(crashpad_info_directory))); | |
249 | |
250 header.Signature = MINIDUMP_SIGNATURE; | |
251 header.Version = MINIDUMP_VERSION; | |
252 header.NumberOfStreams = 2; | |
253 EXPECT_TRUE(string_file.SeekSet(0)); | |
254 EXPECT_TRUE(string_file.Write(&header, sizeof(header))); | |
255 | |
256 ProcessSnapshotMinidump process_snapshot; | |
257 EXPECT_TRUE(process_snapshot.Initialize(&string_file)); | |
258 | |
259 std::vector<const ModuleSnapshot*> modules = process_snapshot.Modules(); | |
260 ASSERT_EQ(minidump_module_count, modules.size()); | |
261 | |
262 auto annotations_simple_map = modules[0]->AnnotationsSimpleMap(); | |
263 EXPECT_EQ(dictionary_0, annotations_simple_map); | |
264 | |
265 auto annotations_vector = modules[0]->AnnotationsVector(); | |
266 EXPECT_TRUE(annotations_vector.empty()); | |
267 | |
268 annotations_simple_map = modules[1]->AnnotationsSimpleMap(); | |
269 EXPECT_TRUE(annotations_simple_map.empty()); | |
270 | |
271 annotations_vector = modules[1]->AnnotationsVector(); | |
272 EXPECT_TRUE(annotations_vector.empty()); | |
273 | |
274 annotations_simple_map = modules[2]->AnnotationsSimpleMap(); | |
275 EXPECT_EQ(dictionary_2, annotations_simple_map); | |
276 | |
277 annotations_vector = modules[2]->AnnotationsVector(); | |
278 EXPECT_EQ(list_annotations_2, annotations_vector); | |
136 } | 279 } |
137 | 280 |
138 } // namespace | 281 } // namespace |
139 } // namespace test | 282 } // namespace test |
140 } // namespace crashpad | 283 } // namespace crashpad |
OLD | NEW |