Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(284)

Side by Side Diff: minidump/minidump_memory_writer_test.cc

Issue 459973002: Add MinidumpMemoryWriter, MinidumpMemoryListWriter, and their test (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (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
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "minidump/minidump_memory_writer.h"
16
17 #include <dbghelp.h>
18 #include <stdint.h>
19
20 #include "base/basictypes.h"
21 #include "gtest/gtest.h"
22 #include "minidump/minidump_file_writer.h"
23 #include "minidump/minidump_stream_writer.h"
24 #include "util/file/string_file_writer.h"
25
26 namespace {
27
28 using namespace crashpad;
29
30 const MinidumpStreamType kBogusStreamType = static_cast<MinidumpStreamType>(1234 );
31
32 // expected_streams is the expected number of streams in the file. The memory
33 // list must be the last stream. If there is another stream, it must come first,
34 // have stream type kBogusStreamType, and have zero-length data.
35 void GetMemoryListStream(const std::string& file_contents,
36 const MINIDUMP_MEMORY_LIST** memory_list,
37 const uint32_t expected_streams) {
38 const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER);
39 const size_t kMemoryListStreamOffset =
40 kDirectoryOffset + expected_streams * sizeof(MINIDUMP_DIRECTORY);
41 const size_t kMemoryDescriptorsOffset =
42 kMemoryListStreamOffset + sizeof(MINIDUMP_MEMORY_LIST);
43
44 ASSERT_GE(file_contents.size(), kMemoryDescriptorsOffset);
45
46 const MINIDUMP_HEADER* header =
47 reinterpret_cast<const MINIDUMP_HEADER*>(&file_contents[0]);
48
49 EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_SIGNATURE), header->Signature);
Robert Sesek 2014/08/11 22:23:59 This code gets repeated a lot in other tests. Perh
50 EXPECT_EQ(static_cast<uint32_t>(MINIDUMP_VERSION), header->Version);
51 ASSERT_EQ(expected_streams, header->NumberOfStreams);
52 ASSERT_EQ(kDirectoryOffset, header->StreamDirectoryRva);
53 EXPECT_EQ(0u, header->CheckSum);
54 EXPECT_EQ(0u, header->TimeDateStamp);
55 EXPECT_EQ(MiniDumpNormal, header->Flags);
56
57 const MINIDUMP_DIRECTORY* directory =
58 reinterpret_cast<const MINIDUMP_DIRECTORY*>(
59 &file_contents[kDirectoryOffset]);
60
61 if (expected_streams > 1) {
62 ASSERT_EQ(kBogusStreamType, directory->StreamType);
63 ASSERT_EQ(0u, directory->Location.DataSize);
64 ASSERT_EQ(kMemoryListStreamOffset, directory->Location.Rva);
65 ++directory;
66 }
67
68 ASSERT_EQ(kMinidumpStreamTypeMemoryList, directory->StreamType);
69 ASSERT_GE(directory->Location.DataSize, sizeof(MINIDUMP_MEMORY_LIST));
70 ASSERT_EQ(kMemoryListStreamOffset, directory->Location.Rva);
71
72 *memory_list = reinterpret_cast<const MINIDUMP_MEMORY_LIST*>(
73 &file_contents[kMemoryListStreamOffset]);
74
75 ASSERT_EQ(sizeof(MINIDUMP_MEMORY_LIST) +
76 (*memory_list)->NumberOfMemoryRanges *
77 sizeof(MINIDUMP_MEMORY_DESCRIPTOR),
78 directory->Location.DataSize);
79 }
80
81 TEST(MinidumpMemoryWriter, EmptyMemoryList) {
82 MinidumpFileWriter minidump_file_writer;
83 MinidumpMemoryListWriter memory_list_writer;
84
85 minidump_file_writer.AddStream(&memory_list_writer);
86
87 StringFileWriter file_writer;
88 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
89
90 ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
91 sizeof(MINIDUMP_MEMORY_LIST),
92 file_writer.string().size());
93
94 const MINIDUMP_MEMORY_LIST* memory_list;
95 GetMemoryListStream(file_writer.string(), &memory_list, 1);
96 if (Test::HasFatalFailure()) {
97 return;
98 }
99
100 EXPECT_EQ(0u, memory_list->NumberOfMemoryRanges);
101 }
102
103 class TestMemoryWriter final : public MinidumpMemoryWriter {
104 public:
105 TestMemoryWriter(uint64_t base_address, size_t size, uint8_t value)
106 : MinidumpMemoryWriter(),
107 base_address_(base_address),
108 expected_offset_(-1),
109 size_(size),
110 value_(value) {}
111
112 ~TestMemoryWriter() {}
113
114 protected:
115 // MinidumpWritable:
116 virtual bool WillWriteAtOffsetImpl(off_t offset) override {
117 EXPECT_EQ(state(), kStateFrozen);
118 expected_offset_ = offset;
119 bool rv = MinidumpMemoryWriter::WillWriteAtOffsetImpl(offset);
120 EXPECT_TRUE(rv);
121 return rv;
122 }
123
124 virtual bool WriteObject(FileWriterInterface* file_writer) override {
125 EXPECT_EQ(state(), kStateWritable);
126 EXPECT_EQ(expected_offset_, file_writer->Seek(0, SEEK_CUR));
127
128 bool rv = true;
129 if (size_ > 0) {
130 std::string data(size_, value_);
131 rv = file_writer->Write(&data[0], size_);
132 EXPECT_TRUE(rv);
133 }
134
135 return true;
Robert Sesek 2014/08/11 22:23:59 return rv?
136 }
137
138 // MinidumpMemoryWriter:
139 virtual uint64_t MemoryRangeBaseAddress() const override {
140 EXPECT_EQ(state(), kStateFrozen);
141 return base_address_;
142 }
143
144 virtual size_t MemoryRangeSize() const override {
145 EXPECT_GE(state(), kStateFrozen);
146 return size_;
147 }
148
149 private:
150 uint64_t base_address_;
151 off_t expected_offset_;
152 size_t size_;
153 uint8_t value_;
154
155 DISALLOW_COPY_AND_ASSIGN(TestMemoryWriter);
156 };
157
158 TEST(MinidumpMemoryWriter, OneMemoryRegion) {
159 MinidumpFileWriter minidump_file_writer;
160 MinidumpMemoryListWriter memory_list_writer;
161
162 const uint64_t kBaseAddress = 0xfedcba9876543210ull;
163 const uint64_t kSize = 0x1000;
164 const uint8_t kValue = 'm';
165
166 TestMemoryWriter memory_writer(kBaseAddress, kSize, kValue);
167 memory_list_writer.AddMemory(&memory_writer);
168
169 minidump_file_writer.AddStream(&memory_list_writer);
170
171 StringFileWriter file_writer;
172 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
173
174 const MINIDUMP_MEMORY_LIST* memory_list;
175 GetMemoryListStream(file_writer.string(), &memory_list, 1);
176 if (Test::HasFatalFailure()) {
177 return;
178 }
179
180 EXPECT_EQ(1u, memory_list->NumberOfMemoryRanges);
181 EXPECT_EQ(kBaseAddress, memory_list->MemoryRanges[0].StartOfMemoryRange);
182 EXPECT_EQ(kSize, memory_list->MemoryRanges[0].Memory.DataSize);
183 EXPECT_LT(memory_list->MemoryRanges[0].Memory.Rva -
184 (sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
185 sizeof(MINIDUMP_MEMORY_LIST) +
186 memory_list->NumberOfMemoryRanges *
187 sizeof(MINIDUMP_MEMORY_DESCRIPTOR)),
188 16u);
189 EXPECT_EQ(0u, memory_list->MemoryRanges[0].Memory.Rva % 16);
190 EXPECT_EQ(file_writer.string().size(),
191 memory_list->MemoryRanges[0].Memory.Rva +
192 memory_list->MemoryRanges[0].Memory.DataSize);
193
194 std::string expected_data(kSize, kValue);
195 std::string observed_data(
196 &file_writer.string()[memory_list->MemoryRanges[0].Memory.Rva],
197 memory_list->MemoryRanges[0].Memory.DataSize);
198 EXPECT_EQ(expected_data, observed_data);
199 }
200
201 TEST(MinidumpMemoryWriter, TwoMemoryRegions) {
202 MinidumpFileWriter minidump_file_writer;
203 MinidumpMemoryListWriter memory_list_writer;
204
205 const uint64_t kBaseAddress1 = 0x00c0ffeeull;
206 const uint64_t kSize1 = 0x0100;
207 const uint8_t kValue1 = '6';
208 const uint64_t kBaseAddress2 = 0xfac00facull;
209 const uint64_t kSize2 = 0x0200;
210 const uint8_t kValue2 = '!';
211
212 TestMemoryWriter memory_writer_1(kBaseAddress1, kSize1, kValue1);
213 memory_list_writer.AddMemory(&memory_writer_1);
214 TestMemoryWriter memory_writer_2(kBaseAddress2, kSize2, kValue2);
215 memory_list_writer.AddMemory(&memory_writer_2);
216
217 minidump_file_writer.AddStream(&memory_list_writer);
218
219 StringFileWriter file_writer;
220 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
221
222 const MINIDUMP_MEMORY_LIST* memory_list;
223 GetMemoryListStream(file_writer.string(), &memory_list, 1);
224 if (Test::HasFatalFailure()) {
225 return;
226 }
227
228 EXPECT_EQ(2u, memory_list->NumberOfMemoryRanges);
229
230 EXPECT_EQ(kBaseAddress1, memory_list->MemoryRanges[0].StartOfMemoryRange);
231 EXPECT_EQ(kSize1, memory_list->MemoryRanges[0].Memory.DataSize);
232 EXPECT_LT(memory_list->MemoryRanges[0].Memory.Rva -
233 (sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) +
234 sizeof(MINIDUMP_MEMORY_LIST) +
235 memory_list->NumberOfMemoryRanges *
236 sizeof(MINIDUMP_MEMORY_DESCRIPTOR)),
237 16u);
238 EXPECT_EQ(0u, memory_list->MemoryRanges[0].Memory.Rva % 16);
239 EXPECT_LE(memory_list->MemoryRanges[0].Memory.Rva +
240 memory_list->MemoryRanges[0].Memory.DataSize,
241 file_writer.string().size());
242
243 std::string expected_data(kSize1, kValue1);
244 std::string observed_data(
245 &file_writer.string()[memory_list->MemoryRanges[0].Memory.Rva],
246 memory_list->MemoryRanges[0].Memory.DataSize);
247 EXPECT_EQ(expected_data, observed_data);
248
249 EXPECT_EQ(kBaseAddress2, memory_list->MemoryRanges[1].StartOfMemoryRange);
250 EXPECT_EQ(kSize2, memory_list->MemoryRanges[1].Memory.DataSize);
251 EXPECT_LT(memory_list->MemoryRanges[1].Memory.Rva -
252 (memory_list->MemoryRanges[0].Memory.Rva +
253 memory_list->MemoryRanges[0].Memory.DataSize),
254 16u);
255 EXPECT_EQ(0u, memory_list->MemoryRanges[1].Memory.Rva % 16);
256 EXPECT_EQ(file_writer.string().size(),
257 memory_list->MemoryRanges[1].Memory.Rva +
258 memory_list->MemoryRanges[1].Memory.DataSize);
259
260 expected_data.assign(kSize2, kValue2);
261 observed_data.assign(
262 &file_writer.string()[memory_list->MemoryRanges[1].Memory.Rva],
263 memory_list->MemoryRanges[1].Memory.DataSize);
264 EXPECT_EQ(expected_data, observed_data);
265 }
266
267 class TestMemoryStream final : public internal::MinidumpStreamWriter {
268 public:
269 TestMemoryStream(uint64_t base_address, size_t size, uint8_t value)
270 : MinidumpStreamWriter(),
271 memory_(base_address, size, value) {
272 }
273
274 ~TestMemoryStream() {
275 }
276
277 TestMemoryWriter* memory() { return &memory_; }
278
279 // MinidumpStreamWriter:
280 virtual MinidumpStreamType StreamType() const override {
281 return kBogusStreamType;
282 }
283
284 protected:
285 // MinidumpWritable:
286 virtual size_t SizeOfObject() override {
287 EXPECT_GE(state(), kStateFrozen);
288 return 0;
289 }
290
291 virtual std::vector<MinidumpWritable*> Children() override {
292 EXPECT_GE(state(), kStateFrozen);
293 std::vector<MinidumpWritable*> children(1, memory());
294 return children;
295 }
296
297 virtual bool WriteObject(FileWriterInterface* file_writer) override {
298 EXPECT_EQ(kStateWritable, state());
299 return true;
300 }
301
302 private:
303 TestMemoryWriter memory_;
304
305 DISALLOW_COPY_AND_ASSIGN(TestMemoryStream);
306 };
307
308 TEST(MinidumpMemoryWriter, ExtraMemory) {
309 // This tests MinidumpMemoryListWriter::AddExtraMemory(). That method adds
310 // a MinidumpMemoryWriter to the MinidumpMemoryListWriter without making the
311 // memory writer a child of the memory list writer.
312 MinidumpFileWriter minidump_file_writer;
313
314 const uint64_t kBaseAddress1 = 0x0000000000001000ull;
315 const uint64_t kSize1 = 0x0400;
316 const uint8_t kValue1 = '1';
317 TestMemoryStream test_memory_stream(kBaseAddress1, kSize1, kValue1);
318
319 MinidumpMemoryListWriter memory_list_writer;
320 memory_list_writer.AddExtraMemory(test_memory_stream.memory());
321
322 minidump_file_writer.AddStream(&test_memory_stream);
323
324 const uint64_t kBaseAddress2 = 0x0000000000002000ull;
325 const uint64_t kSize2 = 0x0400;
326 const uint8_t kValue2 = 'm';
327
328 TestMemoryWriter memory_writer(kBaseAddress2, kSize2, kValue2);
329 memory_list_writer.AddMemory(&memory_writer);
330
331 minidump_file_writer.AddStream(&memory_list_writer);
332
333 StringFileWriter file_writer;
334 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
335
336 const MINIDUMP_MEMORY_LIST* memory_list;
337 GetMemoryListStream(file_writer.string(), &memory_list, 2);
338 if (Test::HasFatalFailure()) {
339 return;
340 }
341
342 EXPECT_EQ(2u, memory_list->NumberOfMemoryRanges);
343
344 EXPECT_EQ(kBaseAddress1, memory_list->MemoryRanges[0].StartOfMemoryRange);
345 EXPECT_EQ(kSize1, memory_list->MemoryRanges[0].Memory.DataSize);
346 EXPECT_LT(memory_list->MemoryRanges[0].Memory.Rva -
347 (sizeof(MINIDUMP_HEADER) + 2 * sizeof(MINIDUMP_DIRECTORY) +
348 sizeof(MINIDUMP_MEMORY_LIST) +
349 memory_list->NumberOfMemoryRanges *
350 sizeof(MINIDUMP_MEMORY_DESCRIPTOR)),
351 16u);
352 EXPECT_EQ(0u, memory_list->MemoryRanges[0].Memory.Rva % 16);
353 EXPECT_LE(memory_list->MemoryRanges[0].Memory.Rva +
354 memory_list->MemoryRanges[0].Memory.DataSize,
355 file_writer.string().size());
356
357 std::string expected_data(kSize1, kValue1);
358 std::string observed_data(
359 &file_writer.string()[memory_list->MemoryRanges[0].Memory.Rva],
360 memory_list->MemoryRanges[0].Memory.DataSize);
361 EXPECT_EQ(expected_data, observed_data);
362
363 EXPECT_EQ(kBaseAddress2, memory_list->MemoryRanges[1].StartOfMemoryRange);
364 EXPECT_EQ(kSize2, memory_list->MemoryRanges[1].Memory.DataSize);
365 EXPECT_LT(memory_list->MemoryRanges[1].Memory.Rva -
366 (memory_list->MemoryRanges[0].Memory.Rva +
367 memory_list->MemoryRanges[0].Memory.DataSize),
368 16u);
369 EXPECT_EQ(0u, memory_list->MemoryRanges[1].Memory.Rva % 16);
Robert Sesek 2014/08/11 22:23:59 A small helper to verify that a MemoryRange is val
370 EXPECT_EQ(file_writer.string().size(),
371 memory_list->MemoryRanges[1].Memory.Rva +
372 memory_list->MemoryRanges[1].Memory.DataSize);
373
374 expected_data.assign(kSize2, kValue2);
375 observed_data.assign(
376 &file_writer.string()[memory_list->MemoryRanges[1].Memory.Rva],
377 memory_list->MemoryRanges[1].Memory.DataSize);
378 EXPECT_EQ(expected_data, observed_data);
379 }
380
381 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698