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