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 llvm::minidump::ExceptionStream *exception_stream =
256       parser->GetExceptionStream();
257   ASSERT_NE(nullptr, exception_stream);
258   ASSERT_EQ(11UL, exception_stream->ExceptionRecord.ExceptionCode);
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 constexpr auto yes = MemoryRegionInfo::eYes;
336 constexpr auto no = MemoryRegionInfo::eNo;
337 constexpr auto unknown = MemoryRegionInfo::eDontKnow;
338 
339 TEST_F(MinidumpParserTest, GetMemoryRegionInfo) {
340   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
341 --- !minidump
342 Streams:
343   - Type:            MemoryInfoList
344     Memory Ranges:
345       - Base Address:    0x0000000000000000
346         Allocation Protect: [  ]
347         Region Size:     0x0000000000010000
348         State:           [ MEM_FREE ]
349         Protect:         [ PAGE_NO_ACCESS ]
350         Type:            [  ]
351       - Base Address:    0x0000000000010000
352         Allocation Protect: [ PAGE_READ_WRITE ]
353         Region Size:     0x0000000000021000
354         State:           [ MEM_COMMIT ]
355         Type:            [ MEM_MAPPED ]
356       - Base Address:    0x0000000000040000
357         Allocation Protect: [ PAGE_EXECUTE_WRITE_COPY ]
358         Region Size:     0x0000000000001000
359         State:           [ MEM_COMMIT ]
360         Protect:         [ PAGE_READ_ONLY ]
361         Type:            [ MEM_IMAGE ]
362       - Base Address:    0x000000007FFE0000
363         Allocation Protect: [ PAGE_READ_ONLY ]
364         Region Size:     0x0000000000001000
365         State:           [ MEM_COMMIT ]
366         Type:            [ MEM_PRIVATE ]
367       - Base Address:    0x000000007FFE1000
368         Allocation Base: 0x000000007FFE0000
369         Allocation Protect: [ PAGE_READ_ONLY ]
370         Region Size:     0x000000000000F000
371         State:           [ MEM_RESERVE ]
372         Protect:         [ PAGE_NO_ACCESS ]
373         Type:            [ MEM_PRIVATE ]
374 ...
375 )"),
376                     llvm::Succeeded());
377 
378   EXPECT_THAT(
379       parser->BuildMemoryRegions(),
380       testing::Pair(testing::ElementsAre(
381                         MemoryRegionInfo({0x0, 0x10000}, no, no, no, no,
382                                          ConstString(), unknown, 0),
383                         MemoryRegionInfo({0x10000, 0x21000}, yes, yes, no, yes,
384                                          ConstString(), unknown, 0),
385                         MemoryRegionInfo({0x40000, 0x1000}, yes, no, no, yes,
386                                          ConstString(), unknown, 0),
387                         MemoryRegionInfo({0x7ffe0000, 0x1000}, yes, no, no, yes,
388                                          ConstString(), unknown, 0),
389                         MemoryRegionInfo({0x7ffe1000, 0xf000}, no, no, no, yes,
390                                          ConstString(), unknown, 0)),
391                     true));
392 }
393 
394 TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemoryList) {
395   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
396 --- !minidump
397 Streams:
398   - Type:            MemoryList
399     Memory Ranges:
400       - Start of Memory Range: 0x0000000000001000
401         Content:         '31313131313131313131313131313131'
402       - Start of Memory Range: 0x0000000000002000
403         Content:         '3333333333333333333333333333333333333333333333333333333333333333'
404 ...
405 )"),
406                     llvm::Succeeded());
407 
408   // Test we can get memory regions from the MINIDUMP_MEMORY_LIST stream when
409   // we don't have a MemoryInfoListStream.
410 
411   EXPECT_THAT(
412       parser->BuildMemoryRegions(),
413       testing::Pair(testing::ElementsAre(
414                         MemoryRegionInfo({0x1000, 0x10}, yes, unknown, unknown,
415                                          yes, ConstString(), unknown, 0),
416                         MemoryRegionInfo({0x2000, 0x20}, yes, unknown, unknown,
417                                          yes, ConstString(), unknown, 0)),
418                     false));
419 }
420 
421 TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemory64List) {
422   SetUpData("regions-memlist64.dmp");
423 
424   // Test we can get memory regions from the MINIDUMP_MEMORY64_LIST stream when
425   // we don't have a MemoryInfoListStream.
426   EXPECT_THAT(
427       parser->BuildMemoryRegions(),
428       testing::Pair(testing::ElementsAre(
429                         MemoryRegionInfo({0x1000, 0x10}, yes, unknown, unknown,
430                                          yes, ConstString(), unknown, 0),
431                         MemoryRegionInfo({0x2000, 0x20}, yes, unknown, unknown,
432                                          yes, ConstString(), unknown, 0)),
433                     false));
434 }
435 
436 TEST_F(MinidumpParserTest, GetMemoryRegionInfoLinuxMaps) {
437   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
438 --- !minidump
439 Streams:
440   - Type:            LinuxMaps
441     Text:             |
442       400d9000-400db000 r-xp 00000000 b3:04 227        /system/bin/app_process
443       400db000-400dc000 r--p 00001000 b3:04 227        /system/bin/app_process
444       400dc000-400dd000 rw-p 00000000 00:00 0
445       400ec000-400ed000 r--p 00000000 00:00 0
446       400ee000-400ef000 rw-p 00010000 b3:04 300        /system/bin/linker
447       400fc000-400fd000 rwxp 00001000 b3:04 1096       /system/lib/liblog.so
448 
449 ...
450 )"),
451                     llvm::Succeeded());
452   // Test we can get memory regions from the linux /proc/<pid>/maps stream when
453   // we don't have a MemoryInfoListStream.
454   ConstString app_process("/system/bin/app_process");
455   ConstString linker("/system/bin/linker");
456   ConstString liblog("/system/lib/liblog.so");
457   EXPECT_THAT(
458       parser->BuildMemoryRegions(),
459       testing::Pair(testing::ElementsAre(
460                         MemoryRegionInfo({0x400d9000, 0x2000}, yes, no, yes,
461                                          yes, app_process, unknown, 0),
462                         MemoryRegionInfo({0x400db000, 0x1000}, yes, no, no, yes,
463                                          app_process, unknown, 0),
464                         MemoryRegionInfo({0x400dc000, 0x1000}, yes, yes, no,
465                                          yes, ConstString(), unknown, 0),
466                         MemoryRegionInfo({0x400ec000, 0x1000}, yes, no, no, yes,
467                                          ConstString(), unknown, 0),
468                         MemoryRegionInfo({0x400ee000, 0x1000}, yes, yes, no,
469                                          yes, linker, unknown, 0),
470                         MemoryRegionInfo({0x400fc000, 0x1000}, yes, yes, yes,
471                                          yes, liblog, unknown, 0)),
472                     true));
473 }
474 
475 // Windows Minidump tests
476 TEST_F(MinidumpParserTest, GetArchitectureWindows) {
477   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
478 --- !minidump
479 Streams:
480   - Type:            SystemInfo
481     Processor Arch:  X86
482     Processor Level: 6
483     Processor Revision: 15876
484     Number of Processors: 32
485     Product type:    1
486     Major Version:   6
487     Minor Version:   1
488     Build Number:    7601
489     Platform ID:     Win32NT
490     CSD Version:     Service Pack 1
491     Suite Mask:      0x0100
492     CPU:
493       Vendor ID:       GenuineIntel
494       Version Info:    0x000306E4
495       Feature Info:    0xBFEBFBFF
496       AMD Extended Features: 0x771EEC80
497 ...
498 )"),
499                     llvm::Succeeded());
500   ASSERT_EQ(llvm::Triple::ArchType::x86,
501             parser->GetArchitecture().GetMachine());
502   ASSERT_EQ(llvm::Triple::OSType::Win32,
503             parser->GetArchitecture().GetTriple().getOS());
504 }
505 
506 TEST_F(MinidumpParserTest, GetLinuxProcStatus_no_stream) {
507   // Test that GetLinuxProcStatus returns nullptr when the minidump does not
508   // contain this stream.
509   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
510 --- !minidump
511 Streams:
512 ...
513 )"),
514                     llvm::Succeeded());
515   EXPECT_EQ(llvm::None, parser->GetLinuxProcStatus());
516 }
517 
518 TEST_F(MinidumpParserTest, GetMiscInfoWindows) {
519   SetUpData("fizzbuzz_no_heap.dmp");
520   const MinidumpMiscInfo *misc_info = parser->GetMiscInfo();
521   ASSERT_NE(nullptr, misc_info);
522   llvm::Optional<lldb::pid_t> pid = misc_info->GetPid();
523   ASSERT_TRUE(pid.hasValue());
524   ASSERT_EQ(4440UL, pid.getValue());
525 }
526 
527 TEST_F(MinidumpParserTest, GetPidWindows) {
528   SetUpData("fizzbuzz_no_heap.dmp");
529   llvm::Optional<lldb::pid_t> pid = parser->GetPid();
530   ASSERT_TRUE(pid.hasValue());
531   ASSERT_EQ(4440UL, pid.getValue());
532 }
533 
534 // wow64
535 TEST_F(MinidumpParserTest, GetPidWow64) {
536   SetUpData("fizzbuzz_wow64.dmp");
537   llvm::Optional<lldb::pid_t> pid = parser->GetPid();
538   ASSERT_TRUE(pid.hasValue());
539   ASSERT_EQ(7836UL, pid.getValue());
540 }
541 
542 // Register tests
543 #define REG_VAL32(x) *(reinterpret_cast<uint32_t *>(x))
544 #define REG_VAL64(x) *(reinterpret_cast<uint64_t *>(x))
545 
546 TEST_F(MinidumpParserTest, GetThreadContext_x86_32) {
547   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
548 --- !minidump
549 Streams:
550   - Type:            ThreadList
551     Threads:
552       - Thread Id:       0x00026804
553         Stack:
554           Start of Memory Range: 0x00000000FF9DD000
555           Content:         68D39DFF
556         Context:         0F0001000000000000000000000000000000000000000000000000007F03FFFF0000FFFFFFFFFFFF09DC62F72300000088E36CF72B00FFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063000000000000002B0000002B000000A88204085CD59DFF008077F7A3D49DFF01000000000000003CD59DFFA082040823000000820201002CD59DFF2B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
557 )"),
558                     llvm::Succeeded());
559 
560   llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads();
561   const minidump::Thread &thread = thread_list[0];
562   llvm::ArrayRef<uint8_t> registers(parser->GetThreadContext(thread));
563   const MinidumpContext_x86_32 *context;
564   EXPECT_TRUE(consumeObject(registers, context).Success());
565 
566   EXPECT_EQ(MinidumpContext_x86_32_Flags(uint32_t(context->context_flags)),
567             MinidumpContext_x86_32_Flags::x86_32_Flag |
568                 MinidumpContext_x86_32_Flags::Full |
569                 MinidumpContext_x86_32_Flags::FloatingPoint);
570 
571   EXPECT_EQ(0x00000000u, context->eax);
572   EXPECT_EQ(0xf7778000u, context->ebx);
573   EXPECT_EQ(0x00000001u, context->ecx);
574   EXPECT_EQ(0xff9dd4a3u, context->edx);
575   EXPECT_EQ(0x080482a8u, context->edi);
576   EXPECT_EQ(0xff9dd55cu, context->esi);
577   EXPECT_EQ(0xff9dd53cu, context->ebp);
578   EXPECT_EQ(0xff9dd52cu, context->esp);
579   EXPECT_EQ(0x080482a0u, context->eip);
580   EXPECT_EQ(0x00010282u, context->eflags);
581   EXPECT_EQ(0x0023u, context->cs);
582   EXPECT_EQ(0x0000u, context->fs);
583   EXPECT_EQ(0x0063u, context->gs);
584   EXPECT_EQ(0x002bu, context->ss);
585   EXPECT_EQ(0x002bu, context->ds);
586   EXPECT_EQ(0x002bu, context->es);
587 }
588 
589 TEST_F(MinidumpParserTest, GetThreadContext_x86_64) {
590   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
591 --- !minidump
592 Streams:
593   - Type:            ThreadList
594     Threads:
595       - Thread Id:       0x00003E81
596         Stack:
597           Start of Memory Range: 0x00007FFCEB34A000
598           Content:         C84D04BCE97F00
599         Context:         0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B0010000000000033000000000000000000000006020100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000010A234EBFC7F000010A234EBFC7F00000000000000000000F09C34EBFC7F0000C0A91ABCE97F00000000000000000000A0163FBCE97F00004602000000000000921C40000000000030A434EBFC7F000000000000000000000000000000000000C61D4000000000007F0300000000000000000000000000000000000000000000801F0000FFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF25252525252525252525252525252525000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
600 ...
601 )"),
602                     llvm::Succeeded());
603   llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads();
604   const minidump::Thread &thread = thread_list[0];
605   llvm::ArrayRef<uint8_t> registers(parser->GetThreadContext(thread));
606   const MinidumpContext_x86_64 *context;
607   EXPECT_TRUE(consumeObject(registers, context).Success());
608 
609   EXPECT_EQ(MinidumpContext_x86_64_Flags(uint32_t(context->context_flags)),
610             MinidumpContext_x86_64_Flags::x86_64_Flag |
611                 MinidumpContext_x86_64_Flags::Control |
612                 MinidumpContext_x86_64_Flags::FloatingPoint |
613                 MinidumpContext_x86_64_Flags::Integer);
614   EXPECT_EQ(0x0000000000000000u, context->rax);
615   EXPECT_EQ(0x0000000000000000u, context->rbx);
616   EXPECT_EQ(0x0000000000000010u, context->rcx);
617   EXPECT_EQ(0x0000000000000000u, context->rdx);
618   EXPECT_EQ(0x00007ffceb349cf0u, context->rdi);
619   EXPECT_EQ(0x0000000000000000u, context->rsi);
620   EXPECT_EQ(0x00007ffceb34a210u, context->rbp);
621   EXPECT_EQ(0x00007ffceb34a210u, context->rsp);
622   EXPECT_EQ(0x00007fe9bc1aa9c0u, context->r8);
623   EXPECT_EQ(0x0000000000000000u, context->r9);
624   EXPECT_EQ(0x00007fe9bc3f16a0u, context->r10);
625   EXPECT_EQ(0x0000000000000246u, context->r11);
626   EXPECT_EQ(0x0000000000401c92u, context->r12);
627   EXPECT_EQ(0x00007ffceb34a430u, context->r13);
628   EXPECT_EQ(0x0000000000000000u, context->r14);
629   EXPECT_EQ(0x0000000000000000u, context->r15);
630   EXPECT_EQ(0x0000000000401dc6u, context->rip);
631   EXPECT_EQ(0x00010206u, context->eflags);
632   EXPECT_EQ(0x0033u, context->cs);
633   EXPECT_EQ(0x0000u, context->ss);
634 }
635 
636 TEST_F(MinidumpParserTest, GetThreadContext_x86_32_wow64) {
637   SetUpData("fizzbuzz_wow64.dmp");
638   llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads();
639   const minidump::Thread &thread = thread_list[0];
640   llvm::ArrayRef<uint8_t> registers(parser->GetThreadContextWow64(thread));
641   const MinidumpContext_x86_32 *context;
642   EXPECT_TRUE(consumeObject(registers, context).Success());
643 
644   EXPECT_EQ(MinidumpContext_x86_32_Flags(uint32_t(context->context_flags)),
645             MinidumpContext_x86_32_Flags::x86_32_Flag |
646                 MinidumpContext_x86_32_Flags::Full |
647                 MinidumpContext_x86_32_Flags::FloatingPoint |
648                 MinidumpContext_x86_32_Flags::ExtendedRegisters);
649 
650   EXPECT_EQ(0x00000000u, context->eax);
651   EXPECT_EQ(0x0037f608u, context->ebx);
652   EXPECT_EQ(0x00e61578u, context->ecx);
653   EXPECT_EQ(0x00000008u, context->edx);
654   EXPECT_EQ(0x00000000u, context->edi);
655   EXPECT_EQ(0x00000002u, context->esi);
656   EXPECT_EQ(0x0037f654u, context->ebp);
657   EXPECT_EQ(0x0037f5b8u, context->esp);
658   EXPECT_EQ(0x77ce01fdu, context->eip);
659   EXPECT_EQ(0x00000246u, context->eflags);
660   EXPECT_EQ(0x0023u, context->cs);
661   EXPECT_EQ(0x0053u, context->fs);
662   EXPECT_EQ(0x002bu, context->gs);
663   EXPECT_EQ(0x002bu, context->ss);
664   EXPECT_EQ(0x002bu, context->ds);
665   EXPECT_EQ(0x002bu, context->es);
666 }
667 
668 TEST_F(MinidumpParserTest, MinidumpDuplicateModuleMinAddress) {
669   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
670 --- !minidump
671 Streams:
672   - Type:            ModuleList
673     Modules:
674       - Base of Image:   0x0000000000002000
675         Size of Image:   0x00001000
676         Module Name:     '/tmp/a'
677         CodeView Record: ''
678       - Base of Image:   0x0000000000001000
679         Size of Image:   0x00001000
680         Module Name:     '/tmp/a'
681         CodeView Record: ''
682 ...
683 )"),
684                     llvm::Succeeded());
685   // If we have a module mentioned twice in the module list, the filtered
686   // module list should contain the instance with the lowest BaseOfImage.
687   std::vector<const minidump::Module *> filtered_modules =
688       parser->GetFilteredModuleList();
689   ASSERT_EQ(1u, filtered_modules.size());
690   EXPECT_EQ(0x0000000000001000u, filtered_modules[0]->BaseOfImage);
691 }
692 
693 TEST_F(MinidumpParserTest, MinidumpModuleOrder) {
694   ASSERT_THAT_ERROR(SetUpFromYaml(R"(
695 --- !minidump
696 Streams:
697   - Type:            ModuleList
698     Modules:
699       - Base of Image:   0x0000000000002000
700         Size of Image:   0x00001000
701         Module Name:     '/tmp/a'
702         CodeView Record: ''
703       - Base of Image:   0x0000000000001000
704         Size of Image:   0x00001000
705         Module Name:     '/tmp/b'
706         CodeView Record: ''
707 ...
708 )"),
709                     llvm::Succeeded());
710   // Test module filtering does not affect the overall module order.  Previous
711   // versions of the MinidumpParser::GetFilteredModuleList() function would sort
712   // all images by address and modify the order of the modules.
713   std::vector<const minidump::Module *> filtered_modules =
714       parser->GetFilteredModuleList();
715   ASSERT_EQ(2u, filtered_modules.size());
716   EXPECT_EQ(0x0000000000002000u, filtered_modules[0]->BaseOfImage);
717   EXPECT_THAT_EXPECTED(
718       parser->GetMinidumpFile().getString(filtered_modules[0]->ModuleNameRVA),
719       llvm::HasValue("/tmp/a"));
720   EXPECT_EQ(0x0000000000001000u, filtered_modules[1]->BaseOfImage);
721   EXPECT_THAT_EXPECTED(
722       parser->GetMinidumpFile().getString(filtered_modules[1]->ModuleNameRVA),
723       llvm::HasValue("/tmp/b"));
724 }
725 
726