1 //===-- MinidumpTypesTest.cpp -----------------------------------*- C++ -*-===//
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 "Plugins/Process/minidump/MinidumpParser.h"
10 #include "Plugins/Process/minidump/MinidumpTypes.h"
11 #include "Plugins/Process/minidump/RegisterContextMinidump_x86_32.h"
12 #include "Plugins/Process/minidump/RegisterContextMinidump_x86_64.h"
13 #include "TestingSupport/TestUtilities.h"
14 #include "lldb/Host/FileSystem.h"
15 #include "lldb/Target/MemoryRegionInfo.h"
16 #include "lldb/Utility/ArchSpec.h"
17 #include "lldb/Utility/DataBufferHeap.h"
18 #include "lldb/Utility/DataExtractor.h"
19 #include "lldb/Utility/FileSpec.h"
20 #include "llvm/ADT/ArrayRef.h"
21 #include "llvm/ADT/Optional.h"
22 #include "llvm/ObjectYAML/MinidumpYAML.h"
23 #include "llvm/Support/FileSystem.h"
24 #include "llvm/Support/MemoryBuffer.h"
25 #include "llvm/Support/Path.h"
26 #include "llvm/Testing/Support/Error.h"
27 #include "gtest/gtest.h"
28 
29 // C includes
30 
31 // C++ includes
32 #include <memory>
33 
34 using namespace lldb_private;
35 using namespace minidump;
36 
37 class MinidumpParserTest : public testing::Test {
38 public:
39   void SetUp() override { FileSystem::Initialize(); }
40 
41   void TearDown() override { FileSystem::Terminate(); }
42 
43   void SetUpData(const char *minidump_filename) {
44     std::string filename = GetInputFilePath(minidump_filename);
45     auto BufferPtr = FileSystem::Instance().CreateDataBuffer(filename, -1, 0);
46     ASSERT_NE(BufferPtr, nullptr);
47     llvm::Expected<MinidumpParser> expected_parser =
48         MinidumpParser::Create(BufferPtr);
49     ASSERT_THAT_EXPECTED(expected_parser, llvm::Succeeded());
50     parser = std::move(*expected_parser);
51     ASSERT_GT(parser->GetData().size(), 0UL);
52   }
53 
54   llvm::Error SetUpFromYaml(llvm::StringRef yaml) {
55     std::string data;
56     llvm::raw_string_ostream os(data);
57     if (llvm::Error E = llvm::MinidumpYAML::writeAsBinary(yaml, os))
58       return E;
59 
60     os.flush();
61     auto data_buffer_sp =
62         std::make_shared<DataBufferHeap>(data.data(), data.size());
63     auto expected_parser = MinidumpParser::Create(std::move(data_buffer_sp));
64     if (!expected_parser)
65       return expected_parser.takeError();
66     parser = std::move(*expected_parser);
67     return llvm::Error::success();
68   }
69 
70   llvm::Optional<MinidumpParser> parser;
71 };
72 
73 TEST_F(MinidumpParserTest, InvalidMinidump) {
74   std::string duplicate_streams;
75   llvm::raw_string_ostream os(duplicate_streams);
76   ASSERT_THAT_ERROR(llvm::MinidumpYAML::writeAsBinary(R"(
77 --- !minidump
78 Streams:
79   - Type:            LinuxAuxv
80     Content:         DEADBEEFBAADF00D
81   - Type:            LinuxAuxv
82     Content:         DEADBEEFBAADF00D
83   )",
84                                                       os),
85                     llvm::Succeeded());
86   os.flush();
87   auto data_buffer_sp = std::make_shared<DataBufferHeap>(
88       duplicate_streams.data(), duplicate_streams.size());
89   ASSERT_THAT_EXPECTED(MinidumpParser::Create(data_buffer_sp), llvm::Failed());
90 }
91 
92 TEST_F(MinidumpParserTest, GetThreadsAndGetThreadContext) {
93   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
94 --- !minidump
95 Streams:
96   - Type:            ThreadList
97     Threads:
98       - Thread Id:       0x00003E81
99         Stack:
100           Start of Memory Range: 0x00007FFCEB34A000
101           Content:         C84D04BCE97F00
102         Context:         00000000000000
103 ...
104 )"),
105                     llvm::Succeeded());
106   llvm::ArrayRef<minidump::Thread> thread_list;
107 
108   thread_list = parser->GetThreads();
109   ASSERT_EQ(1UL, thread_list.size());
110 
111   const minidump::Thread &thread = thread_list[0];
112 
113   EXPECT_EQ(0x3e81u, thread.ThreadId);
114 
115   llvm::ArrayRef<uint8_t> context = parser->GetThreadContext(thread);
116   EXPECT_EQ(7u, context.size());
117 }
118 
119 TEST_F(MinidumpParserTest, GetArchitecture) {
120   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
121 --- !minidump
122 Streams:
123   - Type:            SystemInfo
124     Processor Arch:  AMD64
125     Processor Level: 6
126     Processor Revision: 16130
127     Number of Processors: 1
128     Platform ID:     Linux
129     CPU:
130       Vendor ID:       GenuineIntel
131       Version Info:    0x00000000
132       Feature Info:    0x00000000
133 ...
134 )"),
135                     llvm::Succeeded());
136   ASSERT_EQ(llvm::Triple::ArchType::x86_64,
137             parser->GetArchitecture().GetMachine());
138   ASSERT_EQ(llvm::Triple::OSType::Linux,
139             parser->GetArchitecture().GetTriple().getOS());
140 }
141 
142 TEST_F(MinidumpParserTest, GetMiscInfo_no_stream) {
143   // Test that GetMiscInfo returns nullptr when the minidump does not contain
144   // this stream.
145   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
146 --- !minidump
147 Streams:
148 ...
149 )"),
150                     llvm::Succeeded());
151   EXPECT_EQ(nullptr, parser->GetMiscInfo());
152 }
153 
154 TEST_F(MinidumpParserTest, GetLinuxProcStatus) {
155   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
156 --- !minidump
157 Streams:
158   - Type:            SystemInfo
159     Processor Arch:  AMD64
160     Processor Level: 6
161     Processor Revision: 16130
162     Number of Processors: 1
163     Platform ID:     Linux
164     CSD Version:     'Linux 3.13.0-91-generic'
165     CPU:
166       Vendor ID:       GenuineIntel
167       Version Info:    0x00000000
168       Feature Info:    0x00000000
169   - Type:            LinuxProcStatus
170     Text:             |
171       Name:	a.out
172       State:	t (tracing stop)
173       Tgid:	16001
174       Ngid:	0
175       Pid:	16001
176       PPid:	13243
177       TracerPid:	16002
178       Uid:	404696	404696	404696	404696
179       Gid:	5762	5762	5762	5762
180 ...
181 )"),
182                     llvm::Succeeded());
183   llvm::Optional<LinuxProcStatus> proc_status = parser->GetLinuxProcStatus();
184   ASSERT_TRUE(proc_status.hasValue());
185   lldb::pid_t pid = proc_status->GetPid();
186   ASSERT_EQ(16001UL, pid);
187 }
188 
189 TEST_F(MinidumpParserTest, GetPid) {
190   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
191 --- !minidump
192 Streams:
193   - Type:            SystemInfo
194     Processor Arch:  AMD64
195     Processor Level: 6
196     Processor Revision: 16130
197     Number of Processors: 1
198     Platform ID:     Linux
199     CSD Version:     'Linux 3.13.0-91-generic'
200     CPU:
201       Vendor ID:       GenuineIntel
202       Version Info:    0x00000000
203       Feature Info:    0x00000000
204   - Type:            LinuxProcStatus
205     Text:             |
206       Name:	a.out
207       State:	t (tracing stop)
208       Tgid:	16001
209       Ngid:	0
210       Pid:	16001
211       PPid:	13243
212       TracerPid:	16002
213       Uid:	404696	404696	404696	404696
214       Gid:	5762	5762	5762	5762
215 ...
216 )"),
217                     llvm::Succeeded());
218   llvm::Optional<lldb::pid_t> pid = parser->GetPid();
219   ASSERT_TRUE(pid.hasValue());
220   ASSERT_EQ(16001UL, pid.getValue());
221 }
222 
223 TEST_F(MinidumpParserTest, GetFilteredModuleList) {
224   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
225 --- !minidump
226 Streams:
227   - Type:            ModuleList
228     Modules:
229       - Base of Image:   0x0000000000400000
230         Size of Image:   0x00001000
231         Module Name:     '/tmp/test/linux-x86_64_not_crashed'
232         CodeView Record: 4C4570426CCF3F60FFA7CC4B86AE8FF44DB2576A68983611
233       - Base of Image:   0x0000000000600000
234         Size of Image:   0x00002000
235         Module Name:     '/tmp/test/linux-x86_64_not_crashed'
236         CodeView Record: 4C4570426CCF3F60FFA7CC4B86AE8FF44DB2576A68983611
237 ...
238 )"),
239                     llvm::Succeeded());
240   llvm::ArrayRef<minidump::Module> modules = parser->GetModuleList();
241   std::vector<const minidump::Module *> filtered_modules =
242       parser->GetFilteredModuleList();
243   EXPECT_EQ(2u, modules.size());
244   ASSERT_EQ(1u, filtered_modules.size());
245   const minidump::Module &M = *filtered_modules[0];
246   EXPECT_THAT_EXPECTED(parser->GetMinidumpFile().getString(M.ModuleNameRVA),
247                        llvm::HasValue("/tmp/test/linux-x86_64_not_crashed"));
248 }
249 
250 TEST_F(MinidumpParserTest, GetExceptionStream) {
251   SetUpData("linux-x86_64.dmp");
252   const MinidumpExceptionStream *exception_stream =
253       parser->GetExceptionStream();
254   ASSERT_NE(nullptr, exception_stream);
255   ASSERT_EQ(11UL, exception_stream->exception_record.exception_code);
256 }
257 
258 void check_mem_range_exists(MinidumpParser &parser, const uint64_t range_start,
259                             const uint64_t range_size) {
260   llvm::Optional<minidump::Range> range = parser.FindMemoryRange(range_start);
261   ASSERT_TRUE(range.hasValue()) << "There is no range containing this address";
262   EXPECT_EQ(range_start, range->start);
263   EXPECT_EQ(range_start + range_size, range->start + range->range_ref.size());
264 }
265 
266 TEST_F(MinidumpParserTest, FindMemoryRange) {
267   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
268 --- !minidump
269 Streams:
270   - Type:            MemoryList
271     Memory Ranges:
272       - Start of Memory Range: 0x00007FFCEB34A000
273         Content:         C84D04BCE9
274       - Start of Memory Range: 0x0000000000401D46
275         Content:         5421
276 ...
277 )"),
278                     llvm::Succeeded());
279   EXPECT_EQ(llvm::None, parser->FindMemoryRange(0x00));
280   EXPECT_EQ(llvm::None, parser->FindMemoryRange(0x2a));
281   EXPECT_EQ((minidump::Range{0x401d46, llvm::ArrayRef<uint8_t>{0x54, 0x21}}),
282             parser->FindMemoryRange(0x401d46));
283   EXPECT_EQ(llvm::None, parser->FindMemoryRange(0x401d46 + 2));
284 
285   EXPECT_EQ(
286       (minidump::Range{0x7ffceb34a000,
287                        llvm::ArrayRef<uint8_t>{0xc8, 0x4d, 0x04, 0xbc, 0xe9}}),
288       parser->FindMemoryRange(0x7ffceb34a000 + 2));
289   EXPECT_EQ(llvm::None, parser->FindMemoryRange(0x7ffceb34a000 + 5));
290 }
291 
292 TEST_F(MinidumpParserTest, GetMemory) {
293   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
294 --- !minidump
295 Streams:
296   - Type:            MemoryList
297     Memory Ranges:
298       - Start of Memory Range: 0x00007FFCEB34A000
299         Content:         C84D04BCE9
300       - Start of Memory Range: 0x0000000000401D46
301         Content:         5421
302 ...
303 )"),
304                     llvm::Succeeded());
305 
306   EXPECT_EQ((llvm::ArrayRef<uint8_t>{0x54}), parser->GetMemory(0x401d46, 1));
307   EXPECT_EQ((llvm::ArrayRef<uint8_t>{0x54, 0x21}),
308             parser->GetMemory(0x401d46, 4));
309 
310   EXPECT_EQ((llvm::ArrayRef<uint8_t>{0xc8, 0x4d, 0x04, 0xbc, 0xe9}),
311             parser->GetMemory(0x7ffceb34a000, 5));
312   EXPECT_EQ((llvm::ArrayRef<uint8_t>{0xc8, 0x4d, 0x04}),
313             parser->GetMemory(0x7ffceb34a000, 3));
314 
315   EXPECT_EQ(llvm::ArrayRef<uint8_t>(), parser->GetMemory(0x500000, 512));
316 }
317 
318 TEST_F(MinidumpParserTest, FindMemoryRangeWithFullMemoryMinidump) {
319   SetUpData("fizzbuzz_wow64.dmp");
320 
321   // There are a lot of ranges in the file, just testing with some of them
322   EXPECT_FALSE(parser->FindMemoryRange(0x00).hasValue());
323   EXPECT_FALSE(parser->FindMemoryRange(0x2a).hasValue());
324   check_mem_range_exists(*parser, 0x10000, 65536); // first range
325   check_mem_range_exists(*parser, 0x40000, 4096);
326   EXPECT_FALSE(parser->FindMemoryRange(0x40000 + 4096).hasValue());
327   check_mem_range_exists(*parser, 0x77c12000, 8192);
328   check_mem_range_exists(*parser, 0x7ffe0000, 4096); // last range
329   EXPECT_FALSE(parser->FindMemoryRange(0x7ffe0000 + 4096).hasValue());
330 }
331 
332 void check_region(MinidumpParser &parser, lldb::addr_t addr, lldb::addr_t start,
333                   lldb::addr_t end, MemoryRegionInfo::OptionalBool read,
334                   MemoryRegionInfo::OptionalBool write,
335                   MemoryRegionInfo::OptionalBool exec,
336                   MemoryRegionInfo::OptionalBool mapped,
337                   ConstString name = ConstString()) {
338   auto range_info = parser.GetMemoryRegionInfo(addr);
339   EXPECT_EQ(start, range_info.GetRange().GetRangeBase());
340   EXPECT_EQ(end, range_info.GetRange().GetRangeEnd());
341   EXPECT_EQ(read, range_info.GetReadable());
342   EXPECT_EQ(write, range_info.GetWritable());
343   EXPECT_EQ(exec, range_info.GetExecutable());
344   EXPECT_EQ(mapped, range_info.GetMapped());
345   EXPECT_EQ(name, range_info.GetName());
346 }
347 
348 // Same as above function where addr == start
349 void check_region(MinidumpParser &parser, lldb::addr_t start, lldb::addr_t end,
350                   MemoryRegionInfo::OptionalBool read,
351                   MemoryRegionInfo::OptionalBool write,
352                   MemoryRegionInfo::OptionalBool exec,
353                   MemoryRegionInfo::OptionalBool mapped,
354                   ConstString name = ConstString()) {
355   check_region(parser, start, start, end, read, write, exec, mapped, name);
356 }
357 
358 
359 constexpr auto yes = MemoryRegionInfo::eYes;
360 constexpr auto no = MemoryRegionInfo::eNo;
361 constexpr auto unknown = MemoryRegionInfo::eDontKnow;
362 
363 TEST_F(MinidumpParserTest, GetMemoryRegionInfo) {
364   SetUpData("fizzbuzz_wow64.dmp");
365 
366   check_region(*parser, 0x00000000, 0x00010000, no, no, no, no);
367   check_region(*parser, 0x00010000, 0x00020000, yes, yes, no, yes);
368   check_region(*parser, 0x00020000, 0x00030000, yes, yes, no, yes);
369   check_region(*parser, 0x00030000, 0x00031000, yes, yes, no, yes);
370   check_region(*parser, 0x00031000, 0x00040000, no, no, no, no);
371   check_region(*parser, 0x00040000, 0x00041000, yes, no, no, yes);
372 
373   // Check addresses contained inside ranges
374   check_region(*parser, 0x00000001, 0x00000000, 0x00010000, no, no, no, no);
375   check_region(*parser, 0x0000ffff, 0x00000000, 0x00010000, no, no, no, no);
376   check_region(*parser, 0x00010001, 0x00010000, 0x00020000, yes, yes, no, yes);
377   check_region(*parser, 0x0001ffff, 0x00010000, 0x00020000, yes, yes, no, yes);
378 
379   // Test that an address after the last entry maps to rest of the memory space
380   check_region(*parser, 0x7fff0000, 0x7fff0000, UINT64_MAX, no, no, no, no);
381 }
382 
383 TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemoryList) {
384   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
385 --- !minidump
386 Streams:
387   - Type:            MemoryList
388     Memory Ranges:
389       - Start of Memory Range: 0x0000000000001000
390         Content:         '31313131313131313131313131313131'
391       - Start of Memory Range: 0x0000000000002000
392         Content:         '3333333333333333333333333333333333333333333333333333333333333333'
393 ...
394 )"),
395                     llvm::Succeeded());
396   // Test we can get memory regions from the MINIDUMP_MEMORY_LIST stream when
397   // we don't have a MemoryInfoListStream.
398 
399   // Test addres before the first entry comes back with nothing mapped up
400   // to first valid region info
401   check_region(*parser, 0x00000000, 0x00001000, no, no, no, no);
402   check_region(*parser, 0x00001000, 0x00001010, yes, unknown, unknown, yes);
403   check_region(*parser, 0x00001010, 0x00002000, no, no, no, no);
404   check_region(*parser, 0x00002000, 0x00002020, yes, unknown, unknown, yes);
405   check_region(*parser, 0x00002020, UINT64_MAX, no, no, no, no);
406 }
407 
408 TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemory64List) {
409   SetUpData("regions-memlist64.dmp");
410   // Test we can get memory regions from the MINIDUMP_MEMORY64_LIST stream when
411   // we don't have a MemoryInfoListStream.
412 
413   // Test addres before the first entry comes back with nothing mapped up
414   // to first valid region info
415   check_region(*parser, 0x00000000, 0x00001000, no, no, no, no);
416   check_region(*parser, 0x00001000, 0x00001010, yes, unknown, unknown, yes);
417   check_region(*parser, 0x00001010, 0x00002000, no, no, no, no);
418   check_region(*parser, 0x00002000, 0x00002020, yes, unknown, unknown, yes);
419   check_region(*parser, 0x00002020, UINT64_MAX, no, no, no, no);
420 }
421 
422 TEST_F(MinidumpParserTest, GetMemoryRegionInfoLinuxMaps) {
423   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
424 --- !minidump
425 Streams:
426   - Type:            LinuxMaps
427     Text:             |
428       400d9000-400db000 r-xp 00000000 b3:04 227        /system/bin/app_process
429       400db000-400dc000 r--p 00001000 b3:04 227        /system/bin/app_process
430       400dc000-400dd000 rw-p 00000000 00:00 0
431       400dd000-400ec000 r-xp 00000000 b3:04 300        /system/bin/linker
432       400ec000-400ed000 r--p 00000000 00:00 0
433       400ed000-400ee000 r--p 0000f000 b3:04 300        /system/bin/linker
434       400ee000-400ef000 rw-p 00010000 b3:04 300        /system/bin/linker
435       400ef000-400fb000 rw-p 00000000 00:00 0
436       400fb000-400fc000 r-xp 00000000 b3:04 1096       /system/lib/liblog.so
437       400fc000-400fd000 rwxp 00001000 b3:04 1096       /system/lib/liblog.so
438       400fd000-400ff000 r-xp 00002000 b3:04 1096       /system/lib/liblog.so
439       400ff000-40100000 r--p 00003000 b3:04 1096       /system/lib/liblog.so
440       40100000-40101000 rw-p 00004000 b3:04 1096       /system/lib/liblog.so
441       40101000-40122000 r-xp 00000000 b3:04 955        /system/lib/libc.so
442       40122000-40123000 rwxp 00021000 b3:04 955        /system/lib/libc.so
443       40123000-40167000 r-xp 00022000 b3:04 955        /system/lib/libc.so
444       40167000-40169000 r--p 00065000 b3:04 955        /system/lib/libc.so
445       40169000-4016b000 rw-p 00067000 b3:04 955        /system/lib/libc.so
446       4016b000-40176000 rw-p 00000000 00:00 0
447 
448 ...
449 )"),
450                     llvm::Succeeded());
451   // Test we can get memory regions from the linux /proc/<pid>/maps stream when
452   // we don't have a MemoryInfoListStream.
453 
454   // Test addres before the first entry comes back with nothing mapped up
455   // to first valid region info
456   ConstString a("/system/bin/app_process");
457   ConstString b("/system/bin/linker");
458   ConstString c("/system/lib/liblog.so");
459   ConstString d("/system/lib/libc.so");
460   ConstString n;
461   check_region(*parser, 0x00000000, 0x400d9000, no, no, no, no, n);
462   check_region(*parser, 0x400d9000, 0x400db000, yes, no, yes, yes, a);
463   check_region(*parser, 0x400db000, 0x400dc000, yes, no, no, yes, a);
464   check_region(*parser, 0x400dc000, 0x400dd000, yes, yes, no, yes, n);
465   check_region(*parser, 0x400dd000, 0x400ec000, yes, no, yes, yes, b);
466   check_region(*parser, 0x400ec000, 0x400ed000, yes, no, no, yes, n);
467   check_region(*parser, 0x400ed000, 0x400ee000, yes, no, no, yes, b);
468   check_region(*parser, 0x400ee000, 0x400ef000, yes, yes, no, yes, b);
469   check_region(*parser, 0x400ef000, 0x400fb000, yes, yes, no, yes, n);
470   check_region(*parser, 0x400fb000, 0x400fc000, yes, no, yes, yes, c);
471   check_region(*parser, 0x400fc000, 0x400fd000, yes, yes, yes, yes, c);
472   check_region(*parser, 0x400fd000, 0x400ff000, yes, no, yes, yes, c);
473   check_region(*parser, 0x400ff000, 0x40100000, yes, no, no, yes, c);
474   check_region(*parser, 0x40100000, 0x40101000, yes, yes, no, yes, c);
475   check_region(*parser, 0x40101000, 0x40122000, yes, no, yes, yes, d);
476   check_region(*parser, 0x40122000, 0x40123000, yes, yes, yes, yes, d);
477   check_region(*parser, 0x40123000, 0x40167000, yes, no, yes, yes, d);
478   check_region(*parser, 0x40167000, 0x40169000, yes, no, no, yes, d);
479   check_region(*parser, 0x40169000, 0x4016b000, yes, yes, no, yes, d);
480   check_region(*parser, 0x4016b000, 0x40176000, yes, yes, no, yes, n);
481   check_region(*parser, 0x40176000, UINT64_MAX, no, no, no, no, n);
482 }
483 
484 // Windows Minidump tests
485 TEST_F(MinidumpParserTest, GetArchitectureWindows) {
486   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
487 --- !minidump
488 Streams:
489   - Type:            SystemInfo
490     Processor Arch:  X86
491     Processor Level: 6
492     Processor Revision: 15876
493     Number of Processors: 32
494     Product type:    1
495     Major Version:   6
496     Minor Version:   1
497     Build Number:    7601
498     Platform ID:     Win32NT
499     CSD Version:     Service Pack 1
500     Suite Mask:      0x0100
501     CPU:
502       Vendor ID:       GenuineIntel
503       Version Info:    0x000306E4
504       Feature Info:    0xBFEBFBFF
505       AMD Extended Features: 0x771EEC80
506 ...
507 )"),
508                     llvm::Succeeded());
509   ASSERT_EQ(llvm::Triple::ArchType::x86,
510             parser->GetArchitecture().GetMachine());
511   ASSERT_EQ(llvm::Triple::OSType::Win32,
512             parser->GetArchitecture().GetTriple().getOS());
513 }
514 
515 TEST_F(MinidumpParserTest, GetLinuxProcStatus_no_stream) {
516   // Test that GetLinuxProcStatus returns nullptr when the minidump does not
517   // contain this stream.
518   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
519 --- !minidump
520 Streams:
521 ...
522 )"),
523                     llvm::Succeeded());
524   EXPECT_EQ(llvm::None, parser->GetLinuxProcStatus());
525 }
526 
527 TEST_F(MinidumpParserTest, GetMiscInfoWindows) {
528   SetUpData("fizzbuzz_no_heap.dmp");
529   const MinidumpMiscInfo *misc_info = parser->GetMiscInfo();
530   ASSERT_NE(nullptr, misc_info);
531   llvm::Optional<lldb::pid_t> pid = misc_info->GetPid();
532   ASSERT_TRUE(pid.hasValue());
533   ASSERT_EQ(4440UL, pid.getValue());
534 }
535 
536 TEST_F(MinidumpParserTest, GetPidWindows) {
537   SetUpData("fizzbuzz_no_heap.dmp");
538   llvm::Optional<lldb::pid_t> pid = parser->GetPid();
539   ASSERT_TRUE(pid.hasValue());
540   ASSERT_EQ(4440UL, pid.getValue());
541 }
542 
543 // wow64
544 TEST_F(MinidumpParserTest, GetPidWow64) {
545   SetUpData("fizzbuzz_wow64.dmp");
546   llvm::Optional<lldb::pid_t> pid = parser->GetPid();
547   ASSERT_TRUE(pid.hasValue());
548   ASSERT_EQ(7836UL, pid.getValue());
549 }
550 
551 // Register tests
552 #define REG_VAL32(x) *(reinterpret_cast<uint32_t *>(x))
553 #define REG_VAL64(x) *(reinterpret_cast<uint64_t *>(x))
554 
555 TEST_F(MinidumpParserTest, GetThreadContext_x86_32) {
556   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
557 --- !minidump
558 Streams:
559   - Type:            ThreadList
560     Threads:
561       - Thread Id:       0x00026804
562         Stack:
563           Start of Memory Range: 0x00000000FF9DD000
564           Content:         68D39DFF
565         Context:         0F0001000000000000000000000000000000000000000000000000007F03FFFF0000FFFFFFFFFFFF09DC62F72300000088E36CF72B00FFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063000000000000002B0000002B000000A88204085CD59DFF008077F7A3D49DFF01000000000000003CD59DFFA082040823000000820201002CD59DFF2B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
566 )"),
567                     llvm::Succeeded());
568 
569   llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads();
570   const minidump::Thread &thread = thread_list[0];
571   llvm::ArrayRef<uint8_t> registers(parser->GetThreadContext(thread));
572   const MinidumpContext_x86_32 *context;
573   EXPECT_TRUE(consumeObject(registers, context).Success());
574 
575   EXPECT_EQ(MinidumpContext_x86_32_Flags(uint32_t(context->context_flags)),
576             MinidumpContext_x86_32_Flags::x86_32_Flag |
577                 MinidumpContext_x86_32_Flags::Full |
578                 MinidumpContext_x86_32_Flags::FloatingPoint);
579 
580   EXPECT_EQ(0x00000000u, context->eax);
581   EXPECT_EQ(0xf7778000u, context->ebx);
582   EXPECT_EQ(0x00000001u, context->ecx);
583   EXPECT_EQ(0xff9dd4a3u, context->edx);
584   EXPECT_EQ(0x080482a8u, context->edi);
585   EXPECT_EQ(0xff9dd55cu, context->esi);
586   EXPECT_EQ(0xff9dd53cu, context->ebp);
587   EXPECT_EQ(0xff9dd52cu, context->esp);
588   EXPECT_EQ(0x080482a0u, context->eip);
589   EXPECT_EQ(0x00010282u, context->eflags);
590   EXPECT_EQ(0x0023u, context->cs);
591   EXPECT_EQ(0x0000u, context->fs);
592   EXPECT_EQ(0x0063u, context->gs);
593   EXPECT_EQ(0x002bu, context->ss);
594   EXPECT_EQ(0x002bu, context->ds);
595   EXPECT_EQ(0x002bu, context->es);
596 }
597 
598 TEST_F(MinidumpParserTest, GetThreadContext_x86_64) {
599   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
600 --- !minidump
601 Streams:
602   - Type:            ThreadList
603     Threads:
604       - Thread Id:       0x00003E81
605         Stack:
606           Start of Memory Range: 0x00007FFCEB34A000
607           Content:         C84D04BCE97F00
608         Context:         0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B0010000000000033000000000000000000000006020100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000010A234EBFC7F000010A234EBFC7F00000000000000000000F09C34EBFC7F0000C0A91ABCE97F00000000000000000000A0163FBCE97F00004602000000000000921C40000000000030A434EBFC7F000000000000000000000000000000000000C61D4000000000007F0300000000000000000000000000000000000000000000801F0000FFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF25252525252525252525252525252525000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
609 ...
610 )"),
611                     llvm::Succeeded());
612   llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads();
613   const minidump::Thread &thread = thread_list[0];
614   llvm::ArrayRef<uint8_t> registers(parser->GetThreadContext(thread));
615   const MinidumpContext_x86_64 *context;
616   EXPECT_TRUE(consumeObject(registers, context).Success());
617 
618   EXPECT_EQ(MinidumpContext_x86_64_Flags(uint32_t(context->context_flags)),
619             MinidumpContext_x86_64_Flags::x86_64_Flag |
620                 MinidumpContext_x86_64_Flags::Control |
621                 MinidumpContext_x86_64_Flags::FloatingPoint |
622                 MinidumpContext_x86_64_Flags::Integer);
623   EXPECT_EQ(0x0000000000000000u, context->rax);
624   EXPECT_EQ(0x0000000000000000u, context->rbx);
625   EXPECT_EQ(0x0000000000000010u, context->rcx);
626   EXPECT_EQ(0x0000000000000000u, context->rdx);
627   EXPECT_EQ(0x00007ffceb349cf0u, context->rdi);
628   EXPECT_EQ(0x0000000000000000u, context->rsi);
629   EXPECT_EQ(0x00007ffceb34a210u, context->rbp);
630   EXPECT_EQ(0x00007ffceb34a210u, context->rsp);
631   EXPECT_EQ(0x00007fe9bc1aa9c0u, context->r8);
632   EXPECT_EQ(0x0000000000000000u, context->r9);
633   EXPECT_EQ(0x00007fe9bc3f16a0u, context->r10);
634   EXPECT_EQ(0x0000000000000246u, context->r11);
635   EXPECT_EQ(0x0000000000401c92u, context->r12);
636   EXPECT_EQ(0x00007ffceb34a430u, context->r13);
637   EXPECT_EQ(0x0000000000000000u, context->r14);
638   EXPECT_EQ(0x0000000000000000u, context->r15);
639   EXPECT_EQ(0x0000000000401dc6u, context->rip);
640   EXPECT_EQ(0x00010206u, context->eflags);
641   EXPECT_EQ(0x0033u, context->cs);
642   EXPECT_EQ(0x0000u, context->ss);
643 }
644 
645 TEST_F(MinidumpParserTest, GetThreadContext_x86_32_wow64) {
646   SetUpData("fizzbuzz_wow64.dmp");
647   llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads();
648   const minidump::Thread &thread = thread_list[0];
649   llvm::ArrayRef<uint8_t> registers(parser->GetThreadContextWow64(thread));
650   const MinidumpContext_x86_32 *context;
651   EXPECT_TRUE(consumeObject(registers, context).Success());
652 
653   EXPECT_EQ(MinidumpContext_x86_32_Flags(uint32_t(context->context_flags)),
654             MinidumpContext_x86_32_Flags::x86_32_Flag |
655                 MinidumpContext_x86_32_Flags::Full |
656                 MinidumpContext_x86_32_Flags::FloatingPoint |
657                 MinidumpContext_x86_32_Flags::ExtendedRegisters);
658 
659   EXPECT_EQ(0x00000000u, context->eax);
660   EXPECT_EQ(0x0037f608u, context->ebx);
661   EXPECT_EQ(0x00e61578u, context->ecx);
662   EXPECT_EQ(0x00000008u, context->edx);
663   EXPECT_EQ(0x00000000u, context->edi);
664   EXPECT_EQ(0x00000002u, context->esi);
665   EXPECT_EQ(0x0037f654u, context->ebp);
666   EXPECT_EQ(0x0037f5b8u, context->esp);
667   EXPECT_EQ(0x77ce01fdu, context->eip);
668   EXPECT_EQ(0x00000246u, context->eflags);
669   EXPECT_EQ(0x0023u, context->cs);
670   EXPECT_EQ(0x0053u, context->fs);
671   EXPECT_EQ(0x002bu, context->gs);
672   EXPECT_EQ(0x002bu, context->ss);
673   EXPECT_EQ(0x002bu, context->ds);
674   EXPECT_EQ(0x002bu, context->es);
675 }
676 
677 TEST_F(MinidumpParserTest, MinidumpDuplicateModuleMinAddress) {
678   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
679 --- !minidump
680 Streams:
681   - Type:            ModuleList
682     Modules:
683       - Base of Image:   0x0000000000002000
684         Size of Image:   0x00001000
685         Module Name:     '/tmp/a'
686         CodeView Record: ''
687       - Base of Image:   0x0000000000001000
688         Size of Image:   0x00001000
689         Module Name:     '/tmp/a'
690         CodeView Record: ''
691 ...
692 )"),
693                     llvm::Succeeded());
694   // If we have a module mentioned twice in the module list, the filtered
695   // module list should contain the instance with the lowest BaseOfImage.
696   std::vector<const minidump::Module *> filtered_modules =
697       parser->GetFilteredModuleList();
698   ASSERT_EQ(1u, filtered_modules.size());
699   EXPECT_EQ(0x0000000000001000u, filtered_modules[0]->BaseOfImage);
700 }
701 
702 TEST_F(MinidumpParserTest, MinidumpModuleOrder) {
703   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
704 --- !minidump
705 Streams:
706   - Type:            ModuleList
707     Modules:
708       - Base of Image:   0x0000000000002000
709         Size of Image:   0x00001000
710         Module Name:     '/tmp/a'
711         CodeView Record: ''
712       - Base of Image:   0x0000000000001000
713         Size of Image:   0x00001000
714         Module Name:     '/tmp/b'
715         CodeView Record: ''
716 ...
717 )"),
718                     llvm::Succeeded());
719   // Test module filtering does not affect the overall module order.  Previous
720   // versions of the MinidumpParser::GetFilteredModuleList() function would sort
721   // all images by address and modify the order of the modules.
722   std::vector<const minidump::Module *> filtered_modules =
723       parser->GetFilteredModuleList();
724   ASSERT_EQ(2u, filtered_modules.size());
725   EXPECT_EQ(0x0000000000002000u, filtered_modules[0]->BaseOfImage);
726   EXPECT_THAT_EXPECTED(
727       parser->GetMinidumpFile().getString(filtered_modules[0]->ModuleNameRVA),
728       llvm::HasValue("/tmp/a"));
729   EXPECT_EQ(0x0000000000001000u, filtered_modules[1]->BaseOfImage);
730   EXPECT_THAT_EXPECTED(
731       parser->GetMinidumpFile().getString(filtered_modules[1]->ModuleNameRVA),
732       llvm::HasValue("/tmp/b"));
733 }
734 
735