1 //===- MinidumpTest.cpp - Tests for Minidump.cpp --------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/Object/Minidump.h"
10 #include "llvm/Support/MemoryBuffer.h"
11 #include "llvm/Testing/Support/Error.h"
12 #include "gtest/gtest.h"
13 
14 using namespace llvm;
15 using namespace llvm::object;
16 using namespace minidump;
17 
create(ArrayRef<uint8_t> Data)18 static Expected<std::unique_ptr<MinidumpFile>> create(ArrayRef<uint8_t> Data) {
19   return MinidumpFile::create(
20       MemoryBufferRef(toStringRef(Data), "Test buffer"));
21 }
22 
TEST(MinidumpFile,BasicInterface)23 TEST(MinidumpFile, BasicInterface) {
24   std::vector<uint8_t> Data{                        // Header
25                             'M', 'D', 'M', 'P',     // Signature
26                             0x93, 0xa7, 0, 0,       // Version
27                             1, 0, 0, 0,             // NumberOfStreams,
28                             0x20, 0, 0, 0,          // StreamDirectoryRVA
29                             0, 1, 2, 3, 4, 5, 6, 7, // Checksum, TimeDateStamp
30                             8, 9, 0, 1, 2, 3, 4, 5, // Flags
31                                                     // Stream Directory
32                             3, 0, 0x67, 0x47, 7, 0, 0, 0, // Type, DataSize,
33                             0x2c, 0, 0, 0,                // RVA
34                                                           // Stream
35                             'C', 'P', 'U', 'I', 'N', 'F', 'O'};
36   // A very simple minidump file which contains just a single stream.
37   auto ExpectedFile = create(Data);
38   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
39   const MinidumpFile &File = **ExpectedFile;
40   const Header &H = File.header();
41   EXPECT_EQ(Header::MagicSignature, H.Signature);
42   EXPECT_EQ(Header::MagicVersion, H.Version);
43   EXPECT_EQ(1u, H.NumberOfStreams);
44   EXPECT_EQ(0x20u, H.StreamDirectoryRVA);
45   EXPECT_EQ(0x03020100u, H.Checksum);
46   EXPECT_EQ(0x07060504u, H.TimeDateStamp);
47   EXPECT_EQ(uint64_t(0x0504030201000908), H.Flags);
48 
49   ASSERT_EQ(1u, File.streams().size());
50   const Directory &Stream0 = File.streams()[0];
51   EXPECT_EQ(StreamType::LinuxCPUInfo, Stream0.Type);
52   EXPECT_EQ(7u, Stream0.Location.DataSize);
53   EXPECT_EQ(0x2cu, Stream0.Location.RVA);
54 
55   EXPECT_EQ("CPUINFO", toStringRef(File.getRawStream(Stream0)));
56   EXPECT_EQ("CPUINFO",
57             toStringRef(*File.getRawStream(StreamType::LinuxCPUInfo)));
58 
59   EXPECT_THAT_EXPECTED(File.getSystemInfo(), Failed<BinaryError>());
60 }
61 
62 // Use the input from the previous test, but corrupt it in various ways
TEST(MinidumpFile,create_ErrorCases)63 TEST(MinidumpFile, create_ErrorCases) {
64   std::vector<uint8_t> FileTooShort{'M', 'D', 'M', 'P'};
65   EXPECT_THAT_EXPECTED(create(FileTooShort), Failed<BinaryError>());
66 
67   std::vector<uint8_t> WrongSignature{
68       // Header
69       '!', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
70       1, 0, 0, 0,                           // NumberOfStreams,
71       0x20, 0, 0, 0,                        // StreamDirectoryRVA
72       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
73       8, 9, 0, 1, 2, 3, 4, 5,               // Flags
74                                             // Stream Directory
75       3, 0, 0x67, 0x47, 7, 0, 0, 0,         // Type, DataSize,
76       0x2c, 0, 0, 0,                        // RVA
77                                             // Stream
78       'C', 'P', 'U', 'I', 'N', 'F', 'O'};
79   EXPECT_THAT_EXPECTED(create(WrongSignature), Failed<BinaryError>());
80 
81   std::vector<uint8_t> WrongVersion{
82       // Header
83       'M', 'D', 'M', 'P', 0x39, 0xa7, 0, 0, // Signature, Version
84       1, 0, 0, 0,                           // NumberOfStreams,
85       0x20, 0, 0, 0,                        // StreamDirectoryRVA
86       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
87       8, 9, 0, 1, 2, 3, 4, 5,               // Flags
88                                             // Stream Directory
89       3, 0, 0x67, 0x47, 7, 0, 0, 0,         // Type, DataSize,
90       0x2c, 0, 0, 0,                        // RVA
91                                             // Stream
92       'C', 'P', 'U', 'I', 'N', 'F', 'O'};
93   EXPECT_THAT_EXPECTED(create(WrongVersion), Failed<BinaryError>());
94 
95   std::vector<uint8_t> DirectoryAfterEOF{
96       // Header
97       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
98       1, 0, 0, 0,                           // NumberOfStreams,
99       0x20, 1, 0, 0,                        // StreamDirectoryRVA
100       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
101       8, 9, 0, 1, 2, 3, 4, 5,               // Flags
102                                             // Stream Directory
103       3, 0, 0x67, 0x47, 7, 0, 0, 0,         // Type, DataSize,
104       0x2c, 0, 0, 0,                        // RVA
105                                             // Stream
106       'C', 'P', 'U', 'I', 'N', 'F', 'O'};
107   EXPECT_THAT_EXPECTED(create(DirectoryAfterEOF), Failed<BinaryError>());
108 
109   std::vector<uint8_t> TruncatedDirectory{
110       // Header
111       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
112       1, 1, 0, 0,                           // NumberOfStreams,
113       0x20, 0, 0, 0,                        // StreamDirectoryRVA
114       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
115       8, 9, 0, 1, 2, 3, 4, 5,               // Flags
116                                             // Stream Directory
117       3, 0, 0x67, 0x47, 7, 0, 0, 0,         // Type, DataSize,
118       0x2c, 0, 0, 0,                        // RVA
119                                             // Stream
120       'C', 'P', 'U', 'I', 'N', 'F', 'O'};
121   EXPECT_THAT_EXPECTED(create(TruncatedDirectory), Failed<BinaryError>());
122 
123   std::vector<uint8_t> Stream0AfterEOF{
124       // Header
125       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
126       1, 0, 0, 0,                           // NumberOfStreams,
127       0x20, 0, 0, 0,                        // StreamDirectoryRVA
128       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
129       8, 9, 0, 1, 2, 3, 4, 5,               // Flags
130                                             // Stream Directory
131       3, 0, 0x67, 0x47, 7, 0, 0, 0,         // Type, DataSize,
132       0x2c, 1, 0, 0,                        // RVA
133                                             // Stream
134       'C', 'P', 'U', 'I', 'N', 'F', 'O'};
135   EXPECT_THAT_EXPECTED(create(Stream0AfterEOF), Failed<BinaryError>());
136 
137   std::vector<uint8_t> Stream0Truncated{
138       // Header
139       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
140       1, 0, 0, 0,                           // NumberOfStreams,
141       0x20, 0, 0, 0,                        // StreamDirectoryRVA
142       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
143       8, 9, 0, 1, 2, 3, 4, 5,               // Flags
144                                             // Stream Directory
145       3, 0, 0x67, 0x47, 8, 0, 0, 0,         // Type, DataSize,
146       0x2c, 0, 0, 0,                        // RVA
147                                             // Stream
148       'C', 'P', 'U', 'I', 'N', 'F', 'O'};
149   EXPECT_THAT_EXPECTED(create(Stream0Truncated), Failed<BinaryError>());
150 
151   std::vector<uint8_t> DuplicateStream{
152       // Header
153       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
154       2, 0, 0, 0,                           // NumberOfStreams,
155       0x20, 0, 0, 0,                        // StreamDirectoryRVA
156       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
157       8, 9, 0, 1, 2, 3, 4, 5,               // Flags
158                                             // Stream Directory
159       3, 0, 0x67, 0x47, 7, 0, 0, 0,         // Type, DataSize,
160       0x40, 0, 0, 0,                        // RVA
161                                             // Stream
162       3, 0, 0x67, 0x47, 7, 0, 0, 0,         // Type, DataSize,
163       0x40, 0, 0, 0,                        // RVA
164                                             // Stream
165       'C', 'P', 'U', 'I', 'N', 'F', 'O'};
166   EXPECT_THAT_EXPECTED(create(DuplicateStream), Failed<BinaryError>());
167 
168   std::vector<uint8_t> DenseMapInfoConflict{
169       // Header
170       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
171       1, 0, 0, 0,                           // NumberOfStreams,
172       0x20, 0, 0, 0,                        // StreamDirectoryRVA
173       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
174       8, 9, 0, 1, 2, 3, 4, 5,               // Flags
175                                             // Stream Directory
176       0xff, 0xff, 0xff, 0xff, 7, 0, 0, 0,   // Type, DataSize,
177       0x2c, 0, 0, 0,                        // RVA
178                                             // Stream
179       'C', 'P', 'U', 'I', 'N', 'F', 'O'};
180   EXPECT_THAT_EXPECTED(create(DenseMapInfoConflict), Failed<BinaryError>());
181 }
182 
TEST(MinidumpFile,IngoresDummyStreams)183 TEST(MinidumpFile, IngoresDummyStreams) {
184   std::vector<uint8_t> TwoDummyStreams{
185       // Header
186       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
187       2, 0, 0, 0,                           // NumberOfStreams,
188       0x20, 0, 0, 0,                        // StreamDirectoryRVA
189       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
190       8, 9, 0, 1, 2, 3, 4, 5,               // Flags
191                                             // Stream Directory
192       0, 0, 0, 0, 0, 0, 0, 0,               // Type, DataSize,
193       0x20, 0, 0, 0,                        // RVA
194       0, 0, 0, 0, 0, 0, 0, 0,               // Type, DataSize,
195       0x20, 0, 0, 0,                        // RVA
196   };
197   auto ExpectedFile = create(TwoDummyStreams);
198   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
199   const MinidumpFile &File = **ExpectedFile;
200   ASSERT_EQ(2u, File.streams().size());
201   EXPECT_EQ(StreamType::Unused, File.streams()[0].Type);
202   EXPECT_EQ(StreamType::Unused, File.streams()[1].Type);
203   EXPECT_EQ(None, File.getRawStream(StreamType::Unused));
204 }
205 
TEST(MinidumpFile,getSystemInfo)206 TEST(MinidumpFile, getSystemInfo) {
207   std::vector<uint8_t> Data{
208       // Header
209       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
210       1, 0, 0, 0,                           // NumberOfStreams,
211       0x20, 0, 0, 0,                        // StreamDirectoryRVA
212       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
213       8, 9, 0, 1, 2, 3, 4, 5,               // Flags
214                                             // Stream Directory
215       7, 0, 0, 0, 56, 0, 0, 0,              // Type, DataSize,
216       0x2c, 0, 0, 0,                        // RVA
217                                             // SystemInfo
218       0, 0, 1, 2,                           // ProcessorArch, ProcessorLevel
219       3, 4, 5, 6, // ProcessorRevision, NumberOfProcessors, ProductType
220       7, 8, 9, 0, 1, 2, 3, 4, // MajorVersion, MinorVersion
221       5, 6, 7, 8, 2, 0, 0, 0, // BuildNumber, PlatformId
222       1, 2, 3, 4, 5, 6, 7, 8, // CSDVersionRVA, SuiteMask, Reserved
223       'L', 'L', 'V', 'M', 'L', 'L', 'V', 'M', 'L', 'L', 'V', 'M', // VendorID
224       1, 2, 3, 4, 5, 6, 7, 8, // VersionInfo, FeatureInfo
225       9, 0, 1, 2,             // AMDExtendedFeatures
226   };
227   auto ExpectedFile = create(Data);
228   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
229   const MinidumpFile &File = **ExpectedFile;
230 
231   auto ExpectedInfo = File.getSystemInfo();
232   ASSERT_THAT_EXPECTED(ExpectedInfo, Succeeded());
233   const SystemInfo &Info = *ExpectedInfo;
234   EXPECT_EQ(ProcessorArchitecture::X86, Info.ProcessorArch);
235   EXPECT_EQ(0x0201, Info.ProcessorLevel);
236   EXPECT_EQ(0x0403, Info.ProcessorRevision);
237   EXPECT_EQ(5, Info.NumberOfProcessors);
238   EXPECT_EQ(6, Info.ProductType);
239   EXPECT_EQ(0x00090807u, Info.MajorVersion);
240   EXPECT_EQ(0x04030201u, Info.MinorVersion);
241   EXPECT_EQ(0x08070605u, Info.BuildNumber);
242   EXPECT_EQ(OSPlatform::Win32NT, Info.PlatformId);
243   EXPECT_EQ(0x04030201u, Info.CSDVersionRVA);
244   EXPECT_EQ(0x0605u, Info.SuiteMask);
245   EXPECT_EQ(0x0807u, Info.Reserved);
246   EXPECT_EQ("LLVMLLVMLLVM", llvm::StringRef(Info.CPU.X86.VendorID,
247                                             sizeof(Info.CPU.X86.VendorID)));
248   EXPECT_EQ(0x04030201u, Info.CPU.X86.VersionInfo);
249   EXPECT_EQ(0x08070605u, Info.CPU.X86.FeatureInfo);
250   EXPECT_EQ(0x02010009u, Info.CPU.X86.AMDExtendedFeatures);
251 }
252 
TEST(MinidumpFile,getString)253 TEST(MinidumpFile, getString) {
254   std::vector<uint8_t> ManyStrings{
255       // Header
256       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
257       2, 0, 0, 0,                           // NumberOfStreams,
258       0x20, 0, 0, 0,                        // StreamDirectoryRVA
259       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
260       8, 9, 0, 1, 2, 3, 4, 5,               // Flags
261                                             // Stream Directory
262       0, 0, 0, 0, 0, 0, 0, 0,               // Type, DataSize,
263       0x20, 0, 0, 0,                        // RVA
264       1, 0, 0, 0, 0, 0,                     // String1 - odd length
265       0, 0, 1, 0, 0, 0,                     // String2 - too long
266       2, 0, 0, 0, 0, 0xd8,                  // String3 - invalid utf16
267       0, 0, 0, 0, 0, 0,                     // String4 - ""
268       2, 0, 0, 0, 'a', 0,                   // String5 - "a"
269       0,                                    // Mis-align next string
270       2, 0, 0, 0, 'a', 0,                   // String6 - "a"
271 
272   };
273   auto ExpectedFile = create(ManyStrings);
274   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
275   const MinidumpFile &File = **ExpectedFile;
276   EXPECT_THAT_EXPECTED(File.getString(44), Failed<BinaryError>());
277   EXPECT_THAT_EXPECTED(File.getString(50), Failed<BinaryError>());
278   EXPECT_THAT_EXPECTED(File.getString(56), Failed<BinaryError>());
279   EXPECT_THAT_EXPECTED(File.getString(62), HasValue(""));
280   EXPECT_THAT_EXPECTED(File.getString(68), HasValue("a"));
281   EXPECT_THAT_EXPECTED(File.getString(75), HasValue("a"));
282 
283   // Check the case when the size field does not fit into the remaining data.
284   EXPECT_THAT_EXPECTED(File.getString(ManyStrings.size() - 2),
285                        Failed<BinaryError>());
286 }
287 
TEST(MinidumpFile,getModuleList)288 TEST(MinidumpFile, getModuleList) {
289   std::vector<uint8_t> OneModule{
290       // Header
291       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
292       1, 0, 0, 0,                           // NumberOfStreams,
293       32, 0, 0, 0,                          // StreamDirectoryRVA
294       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
295       0, 0, 0, 0, 0, 0, 0, 0,               // Flags
296                                             // Stream Directory
297       4, 0, 0, 0, 112, 0, 0, 0,             // Type, DataSize,
298       44, 0, 0, 0,                          // RVA
299       // ModuleList
300       1, 0, 0, 0,             // NumberOfModules
301       1, 2, 3, 4, 5, 6, 7, 8, // BaseOfImage
302       9, 0, 1, 2, 3, 4, 5, 6, // SizeOfImage, Checksum
303       7, 8, 9, 0, 1, 2, 3, 4, // TimeDateStamp, ModuleNameRVA
304       0, 0, 0, 0, 0, 0, 0, 0, // Signature, StructVersion
305       0, 0, 0, 0, 0, 0, 0, 0, // FileVersion
306       0, 0, 0, 0, 0, 0, 0, 0, // ProductVersion
307       0, 0, 0, 0, 0, 0, 0, 0, // FileFlagsMask, FileFlags
308       0, 0, 0, 0,             // FileOS
309       0, 0, 0, 0, 0, 0, 0, 0, // FileType, FileSubType
310       0, 0, 0, 0, 0, 0, 0, 0, // FileDate
311       1, 2, 3, 4, 5, 6, 7, 8, // CvRecord
312       9, 0, 1, 2, 3, 4, 5, 6, // MiscRecord
313       7, 8, 9, 0, 1, 2, 3, 4, // Reserved0
314       5, 6, 7, 8, 9, 0, 1, 2, // Reserved1
315   };
316   // Same as before, but with a padded module list.
317   std::vector<uint8_t> PaddedModule{
318       // Header
319       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
320       1, 0, 0, 0,                           // NumberOfStreams,
321       32, 0, 0, 0,                          // StreamDirectoryRVA
322       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
323       0, 0, 0, 0, 0, 0, 0, 0,               // Flags
324                                             // Stream Directory
325       4, 0, 0, 0, 116, 0, 0, 0,             // Type, DataSize,
326       44, 0, 0, 0,                          // RVA
327       // ModuleList
328       1, 0, 0, 0,             // NumberOfModules
329       0, 0, 0, 0,             // Padding
330       1, 2, 3, 4, 5, 6, 7, 8, // BaseOfImage
331       9, 0, 1, 2, 3, 4, 5, 6, // SizeOfImage, Checksum
332       7, 8, 9, 0, 1, 2, 3, 4, // TimeDateStamp, ModuleNameRVA
333       0, 0, 0, 0, 0, 0, 0, 0, // Signature, StructVersion
334       0, 0, 0, 0, 0, 0, 0, 0, // FileVersion
335       0, 0, 0, 0, 0, 0, 0, 0, // ProductVersion
336       0, 0, 0, 0, 0, 0, 0, 0, // FileFlagsMask, FileFlags
337       0, 0, 0, 0,             // FileOS
338       0, 0, 0, 0, 0, 0, 0, 0, // FileType, FileSubType
339       0, 0, 0, 0, 0, 0, 0, 0, // FileDate
340       1, 2, 3, 4, 5, 6, 7, 8, // CvRecord
341       9, 0, 1, 2, 3, 4, 5, 6, // MiscRecord
342       7, 8, 9, 0, 1, 2, 3, 4, // Reserved0
343       5, 6, 7, 8, 9, 0, 1, 2, // Reserved1
344   };
345 
346   for (ArrayRef<uint8_t> Data : {OneModule, PaddedModule}) {
347     auto ExpectedFile = create(Data);
348     ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
349     const MinidumpFile &File = **ExpectedFile;
350     Expected<ArrayRef<Module>> ExpectedModule = File.getModuleList();
351     ASSERT_THAT_EXPECTED(ExpectedModule, Succeeded());
352     ASSERT_EQ(1u, ExpectedModule->size());
353     const Module &M = ExpectedModule.get()[0];
354     EXPECT_EQ(0x0807060504030201u, M.BaseOfImage);
355     EXPECT_EQ(0x02010009u, M.SizeOfImage);
356     EXPECT_EQ(0x06050403u, M.Checksum);
357     EXPECT_EQ(0x00090807u, M.TimeDateStamp);
358     EXPECT_EQ(0x04030201u, M.ModuleNameRVA);
359     EXPECT_EQ(0x04030201u, M.CvRecord.DataSize);
360     EXPECT_EQ(0x08070605u, M.CvRecord.RVA);
361     EXPECT_EQ(0x02010009u, M.MiscRecord.DataSize);
362     EXPECT_EQ(0x06050403u, M.MiscRecord.RVA);
363     EXPECT_EQ(0x0403020100090807u, M.Reserved0);
364     EXPECT_EQ(0x0201000908070605u, M.Reserved1);
365   }
366 
367   std::vector<uint8_t> StreamTooShort{
368       // Header
369       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
370       1, 0, 0, 0,                           // NumberOfStreams,
371       32, 0, 0, 0,                          // StreamDirectoryRVA
372       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
373       0, 0, 0, 0, 0, 0, 0, 0,               // Flags
374                                             // Stream Directory
375       4, 0, 0, 0, 111, 0, 0, 0,             // Type, DataSize,
376       44, 0, 0, 0,                          // RVA
377       // ModuleList
378       1, 0, 0, 0,             // NumberOfModules
379       1, 2, 3, 4, 5, 6, 7, 8, // BaseOfImage
380       9, 0, 1, 2, 3, 4, 5, 6, // SizeOfImage, Checksum
381       7, 8, 9, 0, 1, 2, 3, 4, // TimeDateStamp, ModuleNameRVA
382       0, 0, 0, 0, 0, 0, 0, 0, // Signature, StructVersion
383       0, 0, 0, 0, 0, 0, 0, 0, // FileVersion
384       0, 0, 0, 0, 0, 0, 0, 0, // ProductVersion
385       0, 0, 0, 0, 0, 0, 0, 0, // FileFlagsMask, FileFlags
386       0, 0, 0, 0,             // FileOS
387       0, 0, 0, 0, 0, 0, 0, 0, // FileType, FileSubType
388       0, 0, 0, 0, 0, 0, 0, 0, // FileDate
389       1, 2, 3, 4, 5, 6, 7, 8, // CvRecord
390       9, 0, 1, 2, 3, 4, 5, 6, // MiscRecord
391       7, 8, 9, 0, 1, 2, 3, 4, // Reserved0
392       5, 6, 7, 8, 9, 0, 1, 2, // Reserved1
393   };
394   auto ExpectedFile = create(StreamTooShort);
395   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
396   const MinidumpFile &File = **ExpectedFile;
397   EXPECT_THAT_EXPECTED(File.getModuleList(), Failed<BinaryError>());
398 }
399 
TEST(MinidumpFile,getThreadList)400 TEST(MinidumpFile, getThreadList) {
401   std::vector<uint8_t> OneThread{
402       // Header
403       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
404       1, 0, 0, 0,                           // NumberOfStreams,
405       32, 0, 0, 0,                          // StreamDirectoryRVA
406       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
407       0, 0, 0, 0, 0, 0, 0, 0,               // Flags
408                                             // Stream Directory
409       3, 0, 0, 0, 52, 0, 0, 0,              // Type, DataSize,
410       44, 0, 0, 0,                          // RVA
411       // ThreadList
412       1, 0, 0, 0,             // NumberOfThreads
413       1, 2, 3, 4, 5, 6, 7, 8, // ThreadId, SuspendCount
414       9, 0, 1, 2, 3, 4, 5, 6, // PriorityClass, Priority
415       7, 8, 9, 0, 1, 2, 3, 4, // EnvironmentBlock
416       // Stack
417       5, 6, 7, 8, 9, 0, 1, 2, // StartOfMemoryRange
418       3, 4, 5, 6, 7, 8, 9, 0, // DataSize, RVA
419       // Context
420       1, 2, 3, 4, 5, 6, 7, 8, // DataSize, RVA
421   };
422   // Same as before, but with a padded thread list.
423   std::vector<uint8_t> PaddedThread{
424       // Header
425       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
426       1, 0, 0, 0,                           // NumberOfStreams,
427       32, 0, 0, 0,                          // StreamDirectoryRVA
428       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
429       0, 0, 0, 0, 0, 0, 0, 0,               // Flags
430                                             // Stream Directory
431       3, 0, 0, 0, 56, 0, 0, 0,              // Type, DataSize,
432       44, 0, 0, 0,                          // RVA
433       // ThreadList
434       1, 0, 0, 0,             // NumberOfThreads
435       0, 0, 0, 0,             // Padding
436       1, 2, 3, 4, 5, 6, 7, 8, // ThreadId, SuspendCount
437       9, 0, 1, 2, 3, 4, 5, 6, // PriorityClass, Priority
438       7, 8, 9, 0, 1, 2, 3, 4, // EnvironmentBlock
439       // Stack
440       5, 6, 7, 8, 9, 0, 1, 2, // StartOfMemoryRange
441       3, 4, 5, 6, 7, 8, 9, 0, // DataSize, RVA
442       // Context
443       1, 2, 3, 4, 5, 6, 7, 8, // DataSize, RVA
444   };
445 
446   for (ArrayRef<uint8_t> Data : {OneThread, PaddedThread}) {
447     auto ExpectedFile = create(Data);
448     ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
449     const MinidumpFile &File = **ExpectedFile;
450     Expected<ArrayRef<Thread>> ExpectedThread = File.getThreadList();
451     ASSERT_THAT_EXPECTED(ExpectedThread, Succeeded());
452     ASSERT_EQ(1u, ExpectedThread->size());
453     const Thread &T = ExpectedThread.get()[0];
454     EXPECT_EQ(0x04030201u, T.ThreadId);
455     EXPECT_EQ(0x08070605u, T.SuspendCount);
456     EXPECT_EQ(0x02010009u, T.PriorityClass);
457     EXPECT_EQ(0x06050403u, T.Priority);
458     EXPECT_EQ(0x0403020100090807u, T.EnvironmentBlock);
459     EXPECT_EQ(0x0201000908070605u, T.Stack.StartOfMemoryRange);
460     EXPECT_EQ(0x06050403u, T.Stack.Memory.DataSize);
461     EXPECT_EQ(0x00090807u, T.Stack.Memory.RVA);
462     EXPECT_EQ(0x04030201u, T.Context.DataSize);
463     EXPECT_EQ(0x08070605u, T.Context.RVA);
464   }
465 }
466 
TEST(MinidumpFile,getMemoryList)467 TEST(MinidumpFile, getMemoryList) {
468   std::vector<uint8_t> OneRange{
469       // Header
470       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
471       1, 0, 0, 0,                           // NumberOfStreams,
472       32, 0, 0, 0,                          // StreamDirectoryRVA
473       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
474       0, 0, 0, 0, 0, 0, 0, 0,               // Flags
475                                             // Stream Directory
476       5, 0, 0, 0, 20, 0, 0, 0,              // Type, DataSize,
477       44, 0, 0, 0,                          // RVA
478       // MemoryDescriptor
479       1, 0, 0, 0,             // NumberOfMemoryRanges
480       5, 6, 7, 8, 9, 0, 1, 2, // StartOfMemoryRange
481       3, 4, 5, 6, 7, 8, 9, 0, // DataSize, RVA
482   };
483   // Same as before, but with a padded memory list.
484   std::vector<uint8_t> PaddedRange{
485       // Header
486       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
487       1, 0, 0, 0,                           // NumberOfStreams,
488       32, 0, 0, 0,                          // StreamDirectoryRVA
489       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
490       0, 0, 0, 0, 0, 0, 0, 0,               // Flags
491                                             // Stream Directory
492       5, 0, 0, 0, 24, 0, 0, 0,              // Type, DataSize,
493       44, 0, 0, 0,                          // RVA
494       // MemoryDescriptor
495       1, 0, 0, 0,             // NumberOfMemoryRanges
496       0, 0, 0, 0,             // Padding
497       5, 6, 7, 8, 9, 0, 1, 2, // StartOfMemoryRange
498       3, 4, 5, 6, 7, 8, 9, 0, // DataSize, RVA
499   };
500 
501   for (ArrayRef<uint8_t> Data : {OneRange, PaddedRange}) {
502     auto ExpectedFile = create(Data);
503     ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
504     const MinidumpFile &File = **ExpectedFile;
505     Expected<ArrayRef<MemoryDescriptor>> ExpectedRanges = File.getMemoryList();
506     ASSERT_THAT_EXPECTED(ExpectedRanges, Succeeded());
507     ASSERT_EQ(1u, ExpectedRanges->size());
508     const MemoryDescriptor &MD = ExpectedRanges.get()[0];
509     EXPECT_EQ(0x0201000908070605u, MD.StartOfMemoryRange);
510     EXPECT_EQ(0x06050403u, MD.Memory.DataSize);
511     EXPECT_EQ(0x00090807u, MD.Memory.RVA);
512   }
513 }
514 
TEST(MinidumpFile,getMemoryInfoList)515 TEST(MinidumpFile, getMemoryInfoList) {
516   std::vector<uint8_t> OneEntry{
517       // Header
518       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
519       1, 0, 0, 0,                           // NumberOfStreams,
520       32, 0, 0, 0,                          // StreamDirectoryRVA
521       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
522       0, 0, 0, 0, 0, 0, 0, 0,               // Flags
523                                             // Stream Directory
524       16, 0, 0, 0, 64, 0, 0, 0,             // Type, DataSize,
525       44, 0, 0, 0,                          // RVA
526       // MemoryInfoListHeader
527       16, 0, 0, 0, 48, 0, 0, 0, // SizeOfHeader, SizeOfEntry
528       1, 0, 0, 0, 0, 0, 0, 0,   // NumberOfEntries
529       // MemoryInfo
530       0, 1, 2, 3, 4, 5, 6, 7,   // BaseAddress
531       8, 9, 0, 1, 2, 3, 4, 5,   // AllocationBase
532       16, 0, 0, 0, 6, 7, 8, 9,  // AllocationProtect, Reserved0
533       0, 1, 2, 3, 4, 5, 6, 7,   // RegionSize
534       0, 16, 0, 0, 32, 0, 0, 0, // State, Protect
535       0, 0, 2, 0, 8, 9, 0, 1,   // Type, Reserved1
536   };
537 
538   // Same as before, but the list header is larger.
539   std::vector<uint8_t> BiggerHeader{
540       // Header
541       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
542       1, 0, 0, 0,                           // NumberOfStreams,
543       32, 0, 0, 0,                          // StreamDirectoryRVA
544       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
545       0, 0, 0, 0, 0, 0, 0, 0,               // Flags
546                                             // Stream Directory
547       16, 0, 0, 0, 68, 0, 0, 0,             // Type, DataSize,
548       44, 0, 0, 0,                          // RVA
549       // MemoryInfoListHeader
550       20, 0, 0, 0, 48, 0, 0, 0, // SizeOfHeader, SizeOfEntry
551       1, 0, 0, 0, 0, 0, 0, 0,   // NumberOfEntries
552       0, 0, 0, 0,               // ???
553       // MemoryInfo
554       0, 1, 2, 3, 4, 5, 6, 7,   // BaseAddress
555       8, 9, 0, 1, 2, 3, 4, 5,   // AllocationBase
556       16, 0, 0, 0, 6, 7, 8, 9,  // AllocationProtect, Reserved0
557       0, 1, 2, 3, 4, 5, 6, 7,   // RegionSize
558       0, 16, 0, 0, 32, 0, 0, 0, // State, Protect
559       0, 0, 2, 0, 8, 9, 0, 1,   // Type, Reserved1
560   };
561 
562   // Same as before, but the entry is larger.
563   std::vector<uint8_t> BiggerEntry{
564       // Header
565       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
566       1, 0, 0, 0,                           // NumberOfStreams,
567       32, 0, 0, 0,                          // StreamDirectoryRVA
568       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
569       0, 0, 0, 0, 0, 0, 0, 0,               // Flags
570                                             // Stream Directory
571       16, 0, 0, 0, 68, 0, 0, 0,             // Type, DataSize,
572       44, 0, 0, 0,                          // RVA
573       // MemoryInfoListHeader
574       16, 0, 0, 0, 52, 0, 0, 0, // SizeOfHeader, SizeOfEntry
575       1, 0, 0, 0, 0, 0, 0, 0,   // NumberOfEntries
576       // MemoryInfo
577       0, 1, 2, 3, 4, 5, 6, 7,   // BaseAddress
578       8, 9, 0, 1, 2, 3, 4, 5,   // AllocationBase
579       16, 0, 0, 0, 6, 7, 8, 9,  // AllocationProtect, Reserved0
580       0, 1, 2, 3, 4, 5, 6, 7,   // RegionSize
581       0, 16, 0, 0, 32, 0, 0, 0, // State, Protect
582       0, 0, 2, 0, 8, 9, 0, 1,   // Type, Reserved1
583       0, 0, 0, 0,               // ???
584   };
585 
586   for (ArrayRef<uint8_t> Data : {OneEntry, BiggerHeader, BiggerEntry}) {
587     auto ExpectedFile = create(Data);
588     ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
589     const MinidumpFile &File = **ExpectedFile;
590     auto ExpectedInfo = File.getMemoryInfoList();
591     ASSERT_THAT_EXPECTED(ExpectedInfo, Succeeded());
592     ASSERT_EQ(1, std::distance(ExpectedInfo->begin(), ExpectedInfo->end()));
593     const MemoryInfo &Info = *ExpectedInfo.get().begin();
594     EXPECT_EQ(0x0706050403020100u, Info.BaseAddress);
595     EXPECT_EQ(0x0504030201000908u, Info.AllocationBase);
596     EXPECT_EQ(MemoryProtection::Execute, Info.AllocationProtect);
597     EXPECT_EQ(0x09080706u, Info.Reserved0);
598     EXPECT_EQ(0x0706050403020100u, Info.RegionSize);
599     EXPECT_EQ(MemoryState::Commit, Info.State);
600     EXPECT_EQ(MemoryProtection::ExecuteRead, Info.Protect);
601     EXPECT_EQ(MemoryType::Private, Info.Type);
602     EXPECT_EQ(0x01000908u, Info.Reserved1);
603   }
604 
605   // Header does not fit into the stream.
606   std::vector<uint8_t> HeaderTooBig{
607       // Header
608       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
609       1, 0, 0, 0,                           // NumberOfStreams,
610       32, 0, 0, 0,                          // StreamDirectoryRVA
611       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
612       0, 0, 0, 0, 0, 0, 0, 0,               // Flags
613                                             // Stream Directory
614       16, 0, 0, 0, 15, 0, 0, 0,             // Type, DataSize,
615       44, 0, 0, 0,                          // RVA
616       // MemoryInfoListHeader
617       16, 0, 0, 0, 48, 0, 0, 0, // SizeOfHeader, SizeOfEntry
618       1, 0, 0, 0, 0, 0, 0,      // ???
619   };
620   Expected<std::unique_ptr<MinidumpFile>> File = create(HeaderTooBig);
621   ASSERT_THAT_EXPECTED(File, Succeeded());
622   EXPECT_THAT_EXPECTED(File.get()->getMemoryInfoList(), Failed<BinaryError>());
623 
624   // Header fits into the stream, but it is too small to contain the required
625   // entries.
626   std::vector<uint8_t> HeaderTooSmall{
627       // Header
628       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
629       1, 0, 0, 0,                           // NumberOfStreams,
630       32, 0, 0, 0,                          // StreamDirectoryRVA
631       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
632       0, 0, 0, 0, 0, 0, 0, 0,               // Flags
633                                             // Stream Directory
634       16, 0, 0, 0, 15, 0, 0, 0,             // Type, DataSize,
635       44, 0, 0, 0,                          // RVA
636       // MemoryInfoListHeader
637       15, 0, 0, 0, 48, 0, 0, 0, // SizeOfHeader, SizeOfEntry
638       1, 0, 0, 0, 0, 0, 0,      // ???
639   };
640   File = create(HeaderTooSmall);
641   ASSERT_THAT_EXPECTED(File, Succeeded());
642   EXPECT_THAT_EXPECTED(File.get()->getMemoryInfoList(), Failed<BinaryError>());
643 
644   std::vector<uint8_t> EntryTooBig{
645       // Header
646       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
647       1, 0, 0, 0,                           // NumberOfStreams,
648       32, 0, 0, 0,                          // StreamDirectoryRVA
649       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
650       0, 0, 0, 0, 0, 0, 0, 0,               // Flags
651                                             // Stream Directory
652       16, 0, 0, 0, 64, 0, 0, 0,             // Type, DataSize,
653       44, 0, 0, 0,                          // RVA
654       // MemoryInfoListHeader
655       16, 0, 0, 0, 49, 0, 0, 0, // SizeOfHeader, SizeOfEntry
656       1, 0, 0, 0, 0, 0, 0, 0,   // NumberOfEntries
657       // MemoryInfo
658       0, 1, 2, 3, 4, 5, 6, 7,   // BaseAddress
659       8, 9, 0, 1, 2, 3, 4, 5,   // AllocationBase
660       16, 0, 0, 0, 6, 7, 8, 9,  // AllocationProtect, Reserved0
661       0, 1, 2, 3, 4, 5, 6, 7,   // RegionSize
662       0, 16, 0, 0, 32, 0, 0, 0, // State, Protect
663       0, 0, 2, 0, 8, 9, 0, 1,   // Type, Reserved1
664   };
665   File = create(EntryTooBig);
666   ASSERT_THAT_EXPECTED(File, Succeeded());
667   EXPECT_THAT_EXPECTED(File.get()->getMemoryInfoList(), Failed<BinaryError>());
668 
669   std::vector<uint8_t> ThreeEntries{
670       // Header
671       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
672       1, 0, 0, 0,                           // NumberOfStreams,
673       32, 0, 0, 0,                          // StreamDirectoryRVA
674       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
675       0, 0, 0, 0, 0, 0, 0, 0,               // Flags
676                                             // Stream Directory
677       16, 0, 0, 0, 160, 0, 0, 0,            // Type, DataSize,
678       44, 0, 0, 0,                          // RVA
679       // MemoryInfoListHeader
680       16, 0, 0, 0, 48, 0, 0, 0, // SizeOfHeader, SizeOfEntry
681       3, 0, 0, 0, 0, 0, 0, 0,   // NumberOfEntries
682       // MemoryInfo
683       0, 1, 2, 3, 0, 0, 0, 0, // BaseAddress
684       0, 0, 0, 0, 0, 0, 0, 0, // AllocationBase
685       0, 0, 0, 0, 0, 0, 0, 0, // AllocationProtect, Reserved0
686       0, 0, 0, 0, 0, 0, 0, 0, // RegionSize
687       0, 0, 0, 0, 0, 0, 0, 0, // State, Protect
688       0, 0, 0, 0, 0, 0, 0, 0, // Type, Reserved1
689       0, 0, 4, 5, 6, 7, 0, 0, // BaseAddress
690       0, 0, 0, 0, 0, 0, 0, 0, // AllocationBase
691       0, 0, 0, 0, 0, 0, 0, 0, // AllocationProtect, Reserved0
692       0, 0, 0, 0, 0, 0, 0, 0, // RegionSize
693       0, 0, 0, 0, 0, 0, 0, 0, // State, Protect
694       0, 0, 0, 0, 0, 0, 0, 0, // Type, Reserved1
695       0, 0, 0, 8, 9, 0, 1, 0, // BaseAddress
696       0, 0, 0, 0, 0, 0, 0, 0, // AllocationBase
697       0, 0, 0, 0, 0, 0, 0, 0, // AllocationProtect, Reserved0
698       0, 0, 0, 0, 0, 0, 0, 0, // RegionSize
699       0, 0, 0, 0, 0, 0, 0, 0, // State, Protect
700       0, 0, 0, 0, 0, 0, 0, 0, // Type, Reserved1
701   };
702   File = create(ThreeEntries);
703   ASSERT_THAT_EXPECTED(File, Succeeded());
704   auto ExpectedInfo = File.get()->getMemoryInfoList();
705   ASSERT_THAT_EXPECTED(ExpectedInfo, Succeeded());
706   EXPECT_THAT(to_vector<3>(map_range(*ExpectedInfo,
707                                      [](const MemoryInfo &Info) -> uint64_t {
708                                        return Info.BaseAddress;
709                                      })),
710               testing::ElementsAre(0x0000000003020100u, 0x0000070605040000u,
711                                    0x0001000908000000u));
712 }
713 
TEST(MinidumpFile,getExceptionStream)714 TEST(MinidumpFile, getExceptionStream) {
715   std::vector<uint8_t> Data{
716       // Header
717       'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
718       1, 0, 0, 0,                           // NumberOfStreams,
719       0x20, 0, 0, 0,                        // StreamDirectoryRVA
720       0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
721       8, 9, 0, 1, 2, 3, 4, 5,               // Flags
722       // Stream Directory
723       6, 0, 0, 0, 168, 0, 0, 0, // Type, DataSize,
724       0x2c, 0, 0, 0,            // RVA
725       // Exception Stream
726       1, 2, 3, 4, // Thread ID
727       0, 0, 0, 0, // Padding
728       // Exception Record
729       2, 3, 4, 2, 7, 8, 8, 9,  // Code, Flags
730       3, 4, 5, 6, 7, 8, 9, 10, // Inner exception record address
731       8, 7, 6, 5, 4, 3, 2, 1,  // Exception address
732       4, 0, 0, 0, 0, 0, 0, 0,  // Parameter count, padding
733       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // Parameter 0
734       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, // Parameter 1
735       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // Parameter 2
736       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, // Parameter 3
737       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, // Parameter 4
738       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, // Parameter 5
739       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, // Parameter 6
740       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, // Parameter 7
741       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, // Parameter 8
742       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, // Parameter 9
743       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, // Parameter 10
744       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, // Parameter 11
745       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, // Parameter 12
746       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, // Parameter 13
747       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, // Parameter 14
748       // Thread Context
749       0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, // DataSize, RVA
750   };
751   auto ExpectedFile = create(Data);
752   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
753   const MinidumpFile &File = **ExpectedFile;
754   Expected<const minidump::ExceptionStream &> ExpectedStream =
755       File.getExceptionStream();
756   ASSERT_THAT_EXPECTED(ExpectedStream, Succeeded());
757   EXPECT_EQ(0x04030201u, ExpectedStream->ThreadId);
758   const minidump::Exception &Exception = ExpectedStream->ExceptionRecord;
759   EXPECT_EQ(0x02040302u, Exception.ExceptionCode);
760   EXPECT_EQ(0x09080807u, Exception.ExceptionFlags);
761   EXPECT_EQ(0x0a09080706050403u, Exception.ExceptionRecord);
762   EXPECT_EQ(0x0102030405060708u, Exception.ExceptionAddress);
763   EXPECT_EQ(4u, Exception.NumberParameters);
764   for (uint64_t index = 0; index < Exception.MaxParameters; ++index) {
765     EXPECT_EQ(0x1716151413121110u + index * 0x1010101010101010u,
766               Exception.ExceptionInformation[index]);
767   }
768   EXPECT_EQ(0x84838281, ExpectedStream->ThreadContext.DataSize);
769   EXPECT_EQ(0x88878685, ExpectedStream->ThreadContext.RVA);
770 }
771