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