1 //===-- MinidumpTypesTest.cpp -----------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
11 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
12 #include "Plugins/Process/minidump/MinidumpParser.h"
13 #include "Plugins/Process/minidump/MinidumpTypes.h"
14 #include "Plugins/Process/minidump/RegisterContextMinidump_x86_32.h"
15 #include "Plugins/Process/minidump/RegisterContextMinidump_x86_64.h"
16 
17 #include "TestingSupport/TestUtilities.h"
18 #include "lldb/Host/FileSystem.h"
19 #include "lldb/Target/MemoryRegionInfo.h"
20 #include "lldb/Utility/ArchSpec.h"
21 #include "lldb/Utility/DataExtractor.h"
22 #include "lldb/Utility/FileSpec.h"
23 #include "llvm/ADT/ArrayRef.h"
24 #include "llvm/ADT/Optional.h"
25 #include "llvm/Support/FileSystem.h"
26 #include "llvm/Support/MemoryBuffer.h"
27 #include "llvm/Support/Path.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::Optional<MinidumpParser> optional_parser =
49         MinidumpParser::Create(BufferPtr);
50     ASSERT_TRUE(optional_parser.hasValue());
51     parser.reset(new MinidumpParser(optional_parser.getValue()));
52     ASSERT_GT(parser->GetData().size(), 0UL);
53     auto result = parser->Initialize();
54     ASSERT_TRUE(result.Success()) << result.AsCString();
55   }
56 
57   void InvalidMinidump(const char *minidump_filename, uint64_t load_size) {
58     std::string filename = GetInputFilePath(minidump_filename);
59     auto BufferPtr =
60         FileSystem::Instance().CreateDataBuffer(filename, load_size, 0);
61     ASSERT_NE(BufferPtr, nullptr);
62 
63     llvm::Optional<MinidumpParser> optional_parser =
64         MinidumpParser::Create(BufferPtr);
65     ASSERT_TRUE(optional_parser.hasValue());
66     parser.reset(new MinidumpParser(optional_parser.getValue()));
67     ASSERT_GT(parser->GetData().size(), 0UL);
68     auto result = parser->Initialize();
69     ASSERT_TRUE(result.Fail());
70   }
71 
72   std::unique_ptr<MinidumpParser> parser;
73 };
74 
75 TEST_F(MinidumpParserTest, GetThreadsAndGetThreadContext) {
76   SetUpData("linux-x86_64.dmp");
77   llvm::ArrayRef<MinidumpThread> thread_list;
78 
79   thread_list = parser->GetThreads();
80   ASSERT_EQ(1UL, thread_list.size());
81 
82   const MinidumpThread thread = thread_list[0];
83 
84   EXPECT_EQ(16001UL, thread.thread_id);
85 
86   llvm::ArrayRef<uint8_t> context = parser->GetThreadContext(thread);
87   EXPECT_EQ(1232UL, context.size());
88 }
89 
90 TEST_F(MinidumpParserTest, GetThreadListNotPadded) {
91   // Verify that we can load a thread list that doesn't have 4 bytes of padding
92   // after the thread count.
93   SetUpData("thread-list-not-padded.dmp");
94   llvm::ArrayRef<MinidumpThread> thread_list;
95 
96   thread_list = parser->GetThreads();
97   ASSERT_EQ(2UL, thread_list.size());
98   EXPECT_EQ(0x11223344UL, thread_list[0].thread_id);
99   EXPECT_EQ(0x55667788UL, thread_list[1].thread_id);
100 }
101 
102 TEST_F(MinidumpParserTest, GetThreadListPadded) {
103   // Verify that we can load a thread list that has 4 bytes of padding
104   // after the thread count as found in breakpad minidump files.
105   SetUpData("thread-list-padded.dmp");
106   auto thread_list = parser->GetThreads();
107   ASSERT_EQ(2UL, thread_list.size());
108   EXPECT_EQ(0x11223344UL, thread_list[0].thread_id);
109   EXPECT_EQ(0x55667788UL, thread_list[1].thread_id);
110 }
111 
112 TEST_F(MinidumpParserTest, GetModuleListNotPadded) {
113   // Verify that we can load a module list that doesn't have 4 bytes of padding
114   // after the module count.
115   SetUpData("module-list-not-padded.dmp");
116   auto module_list = parser->GetModuleList();
117   ASSERT_EQ(2UL, module_list.size());
118   EXPECT_EQ(0x1000UL, module_list[0].base_of_image);
119   EXPECT_EQ(0x2000UL, module_list[0].size_of_image);
120   EXPECT_EQ(0x5000UL, module_list[1].base_of_image);
121   EXPECT_EQ(0x3000UL, module_list[1].size_of_image);
122 }
123 
124 TEST_F(MinidumpParserTest, GetModuleListPadded) {
125   // Verify that we can load a module list that has 4 bytes of padding
126   // after the module count as found in breakpad minidump files.
127   SetUpData("module-list-padded.dmp");
128   auto module_list = parser->GetModuleList();
129   ASSERT_EQ(2UL, module_list.size());
130   EXPECT_EQ(0x1000UL, module_list[0].base_of_image);
131   EXPECT_EQ(0x2000UL, module_list[0].size_of_image);
132   EXPECT_EQ(0x5000UL, module_list[1].base_of_image);
133   EXPECT_EQ(0x3000UL, module_list[1].size_of_image);
134 }
135 
136 TEST_F(MinidumpParserTest, GetMemoryListNotPadded) {
137   // Verify that we can load a memory list that doesn't have 4 bytes of padding
138   // after the memory range count.
139   SetUpData("memory-list-not-padded.dmp");
140   auto mem = parser->FindMemoryRange(0x8000);
141   ASSERT_TRUE(mem.hasValue());
142   EXPECT_EQ((lldb::addr_t)0x8000, mem->start);
143   mem = parser->FindMemoryRange(0x8010);
144   ASSERT_TRUE(mem.hasValue());
145   EXPECT_EQ((lldb::addr_t)0x8010, mem->start);
146 }
147 
148 TEST_F(MinidumpParserTest, GetMemoryListPadded) {
149   // Verify that we can load a memory list that has 4 bytes of padding
150   // after the memory range count as found in breakpad minidump files.
151   SetUpData("memory-list-padded.dmp");
152   auto mem = parser->FindMemoryRange(0x8000);
153   ASSERT_TRUE(mem.hasValue());
154   EXPECT_EQ((lldb::addr_t)0x8000, mem->start);
155   mem = parser->FindMemoryRange(0x8010);
156   ASSERT_TRUE(mem.hasValue());
157   EXPECT_EQ((lldb::addr_t)0x8010, mem->start);
158 }
159 
160 TEST_F(MinidumpParserTest, TruncatedMinidumps) {
161   InvalidMinidump("linux-x86_64.dmp", 32);
162   InvalidMinidump("linux-x86_64.dmp", 100);
163   InvalidMinidump("linux-x86_64.dmp", 20 * 1024);
164 }
165 
166 TEST_F(MinidumpParserTest, IllFormedMinidumps) {
167   InvalidMinidump("bad_duplicate_streams.dmp", -1);
168   InvalidMinidump("bad_overlapping_streams.dmp", -1);
169 }
170 
171 TEST_F(MinidumpParserTest, GetArchitecture) {
172   SetUpData("linux-x86_64.dmp");
173   ASSERT_EQ(llvm::Triple::ArchType::x86_64,
174             parser->GetArchitecture().GetMachine());
175   ASSERT_EQ(llvm::Triple::OSType::Linux,
176             parser->GetArchitecture().GetTriple().getOS());
177 }
178 
179 TEST_F(MinidumpParserTest, GetMiscInfo) {
180   SetUpData("linux-x86_64.dmp");
181   const MinidumpMiscInfo *misc_info = parser->GetMiscInfo();
182   ASSERT_EQ(nullptr, misc_info);
183 }
184 
185 TEST_F(MinidumpParserTest, GetLinuxProcStatus) {
186   SetUpData("linux-x86_64.dmp");
187   llvm::Optional<LinuxProcStatus> proc_status = parser->GetLinuxProcStatus();
188   ASSERT_TRUE(proc_status.hasValue());
189   lldb::pid_t pid = proc_status->GetPid();
190   ASSERT_EQ(16001UL, pid);
191 }
192 
193 TEST_F(MinidumpParserTest, GetPid) {
194   SetUpData("linux-x86_64.dmp");
195   llvm::Optional<lldb::pid_t> pid = parser->GetPid();
196   ASSERT_TRUE(pid.hasValue());
197   ASSERT_EQ(16001UL, pid.getValue());
198 }
199 
200 TEST_F(MinidumpParserTest, GetModuleList) {
201   SetUpData("linux-x86_64.dmp");
202   llvm::ArrayRef<MinidumpModule> modules = parser->GetModuleList();
203   ASSERT_EQ(8UL, modules.size());
204   std::string module_names[8] = {
205       "/usr/local/google/home/dvlahovski/projects/test_breakpad/a.out",
206       "/lib/x86_64-linux-gnu/libm-2.19.so",
207       "/lib/x86_64-linux-gnu/libc-2.19.so",
208       "/lib/x86_64-linux-gnu/libgcc_s.so.1",
209       "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19",
210       "/lib/x86_64-linux-gnu/libpthread-2.19.so",
211       "/lib/x86_64-linux-gnu/ld-2.19.so",
212       "linux-gate.so",
213   };
214 
215   for (int i = 0; i < 8; ++i) {
216     llvm::Optional<std::string> name =
217         parser->GetMinidumpString(modules[i].module_name_rva);
218     ASSERT_TRUE(name.hasValue());
219     EXPECT_EQ(module_names[i], name.getValue());
220   }
221 }
222 
223 TEST_F(MinidumpParserTest, GetFilteredModuleList) {
224   SetUpData("linux-x86_64_not_crashed.dmp");
225   llvm::ArrayRef<MinidumpModule> modules = parser->GetModuleList();
226   std::vector<const MinidumpModule *> filtered_modules =
227       parser->GetFilteredModuleList();
228   EXPECT_EQ(10UL, modules.size());
229   EXPECT_EQ(9UL, filtered_modules.size());
230   // EXPECT_GT(modules.size(), filtered_modules.size());
231   bool found = false;
232   for (size_t i = 0; i < filtered_modules.size(); ++i) {
233     llvm::Optional<std::string> name =
234         parser->GetMinidumpString(filtered_modules[i]->module_name_rva);
235     ASSERT_TRUE(name.hasValue());
236     if (name.getValue() == "/tmp/test/linux-x86_64_not_crashed") {
237       ASSERT_FALSE(found) << "There should be only one module with this name "
238                              "in the filtered module list";
239       found = true;
240       ASSERT_EQ(0x400000UL, filtered_modules[i]->base_of_image);
241     }
242   }
243 }
244 
245 TEST_F(MinidumpParserTest, GetExceptionStream) {
246   SetUpData("linux-x86_64.dmp");
247   const MinidumpExceptionStream *exception_stream =
248       parser->GetExceptionStream();
249   ASSERT_NE(nullptr, exception_stream);
250   ASSERT_EQ(11UL, exception_stream->exception_record.exception_code);
251 }
252 
253 void check_mem_range_exists(std::unique_ptr<MinidumpParser> &parser,
254                             const uint64_t range_start,
255                             const uint64_t range_size) {
256   llvm::Optional<minidump::Range> range = parser->FindMemoryRange(range_start);
257   ASSERT_TRUE(range.hasValue()) << "There is no range containing this address";
258   EXPECT_EQ(range_start, range->start);
259   EXPECT_EQ(range_start + range_size, range->start + range->range_ref.size());
260 }
261 
262 TEST_F(MinidumpParserTest, FindMemoryRange) {
263   SetUpData("linux-x86_64.dmp");
264   // There are two memory ranges in the file (size is in bytes, decimal):
265   // 1) 0x401d46 256
266   // 2) 0x7ffceb34a000 12288
267   EXPECT_FALSE(parser->FindMemoryRange(0x00).hasValue());
268   EXPECT_FALSE(parser->FindMemoryRange(0x2a).hasValue());
269 
270   check_mem_range_exists(parser, 0x401d46, 256);
271   EXPECT_FALSE(parser->FindMemoryRange(0x401d46 + 256).hasValue());
272 
273   check_mem_range_exists(parser, 0x7ffceb34a000, 12288);
274   EXPECT_FALSE(parser->FindMemoryRange(0x7ffceb34a000 + 12288).hasValue());
275 }
276 
277 TEST_F(MinidumpParserTest, GetMemory) {
278   SetUpData("linux-x86_64.dmp");
279 
280   EXPECT_EQ(128UL, parser->GetMemory(0x401d46, 128).size());
281   EXPECT_EQ(256UL, parser->GetMemory(0x401d46, 512).size());
282 
283   EXPECT_EQ(12288UL, parser->GetMemory(0x7ffceb34a000, 12288).size());
284   EXPECT_EQ(1024UL, parser->GetMemory(0x7ffceb34a000, 1024).size());
285 
286   EXPECT_TRUE(parser->GetMemory(0x500000, 512).empty());
287 }
288 
289 TEST_F(MinidumpParserTest, FindMemoryRangeWithFullMemoryMinidump) {
290   SetUpData("fizzbuzz_wow64.dmp");
291 
292   // There are a lot of ranges in the file, just testing with some of them
293   EXPECT_FALSE(parser->FindMemoryRange(0x00).hasValue());
294   EXPECT_FALSE(parser->FindMemoryRange(0x2a).hasValue());
295   check_mem_range_exists(parser, 0x10000, 65536); // first range
296   check_mem_range_exists(parser, 0x40000, 4096);
297   EXPECT_FALSE(parser->FindMemoryRange(0x40000 + 4096).hasValue());
298   check_mem_range_exists(parser, 0x77c12000, 8192);
299   check_mem_range_exists(parser, 0x7ffe0000, 4096); // last range
300   EXPECT_FALSE(parser->FindMemoryRange(0x7ffe0000 + 4096).hasValue());
301 }
302 
303 void check_region(std::unique_ptr<MinidumpParser> &parser,
304                   lldb::addr_t addr, lldb::addr_t start, lldb::addr_t end,
305                   MemoryRegionInfo::OptionalBool read,
306                   MemoryRegionInfo::OptionalBool write,
307                   MemoryRegionInfo::OptionalBool exec,
308                   MemoryRegionInfo::OptionalBool mapped,
309                   ConstString name = ConstString()) {
310   auto range_info = parser->GetMemoryRegionInfo(addr);
311   EXPECT_EQ(start, range_info.GetRange().GetRangeBase());
312   EXPECT_EQ(end, range_info.GetRange().GetRangeEnd());
313   EXPECT_EQ(read, range_info.GetReadable());
314   EXPECT_EQ(write, range_info.GetWritable());
315   EXPECT_EQ(exec, range_info.GetExecutable());
316   EXPECT_EQ(mapped, range_info.GetMapped());
317   EXPECT_EQ(name, range_info.GetName());
318 }
319 
320 // Same as above function where addr == start
321 void check_region(std::unique_ptr<MinidumpParser> &parser,
322                   lldb::addr_t start, lldb::addr_t end,
323                   MemoryRegionInfo::OptionalBool read,
324                   MemoryRegionInfo::OptionalBool write,
325                   MemoryRegionInfo::OptionalBool exec,
326                   MemoryRegionInfo::OptionalBool mapped,
327                   ConstString name = ConstString()) {
328   check_region(parser, start, start, end, read, write, exec, mapped, name);
329 }
330 
331 
332 constexpr auto yes = MemoryRegionInfo::eYes;
333 constexpr auto no = MemoryRegionInfo::eNo;
334 constexpr auto unknown = MemoryRegionInfo::eDontKnow;
335 
336 TEST_F(MinidumpParserTest, GetMemoryRegionInfo) {
337   SetUpData("fizzbuzz_wow64.dmp");
338 
339   check_region(parser, 0x00000000, 0x00010000, no, no, no, no);
340   check_region(parser, 0x00010000, 0x00020000, yes, yes, no, yes);
341   check_region(parser, 0x00020000, 0x00030000, yes, yes, no, yes);
342   check_region(parser, 0x00030000, 0x00031000, yes, yes, no, yes);
343   check_region(parser, 0x00031000, 0x00040000, no, no, no, no);
344   check_region(parser, 0x00040000, 0x00041000, yes, no, no, yes);
345 
346   // Check addresses contained inside ranges
347   check_region(parser, 0x00000001, 0x00000000, 0x00010000, no, no, no, no);
348   check_region(parser, 0x0000ffff, 0x00000000, 0x00010000, no, no, no, no);
349   check_region(parser, 0x00010001, 0x00010000, 0x00020000, yes, yes, no, yes);
350   check_region(parser, 0x0001ffff, 0x00010000, 0x00020000, yes, yes, no, yes);
351 
352   // Test that an address after the last entry maps to rest of the memory space
353   check_region(parser, 0x7fff0000, 0x7fff0000, UINT64_MAX, no, no, no, no);
354 }
355 
356 TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemoryList) {
357   SetUpData("regions-memlist.dmp");
358   // Test we can get memory regions from the MINIDUMP_MEMORY_LIST stream when
359   // we don't have a MemoryInfoListStream.
360 
361   // Test addres before the first entry comes back with nothing mapped up
362   // to first valid region info
363   check_region(parser, 0x00000000, 0x00001000, no, no, no, no);
364   check_region(parser, 0x00001000, 0x00001010, yes, unknown, unknown, yes);
365   check_region(parser, 0x00001010, 0x00002000, no, no, no, no);
366   check_region(parser, 0x00002000, 0x00002020, yes, unknown, unknown, yes);
367   check_region(parser, 0x00002020, UINT64_MAX, no, no, no, no);
368 }
369 
370 TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemory64List) {
371   SetUpData("regions-memlist64.dmp");
372   // Test we can get memory regions from the MINIDUMP_MEMORY64_LIST stream when
373   // we don't have a MemoryInfoListStream.
374 
375   // Test addres before the first entry comes back with nothing mapped up
376   // to first valid region info
377   check_region(parser, 0x00000000, 0x00001000, no, no, no, no);
378   check_region(parser, 0x00001000, 0x00001010, yes, unknown, unknown, yes);
379   check_region(parser, 0x00001010, 0x00002000, no, no, no, no);
380   check_region(parser, 0x00002000, 0x00002020, yes, unknown, unknown, yes);
381   check_region(parser, 0x00002020, UINT64_MAX, no, no, no, no);
382 }
383 
384 TEST_F(MinidumpParserTest, GetMemoryRegionInfoLinuxMaps) {
385   SetUpData("regions-linux-map.dmp");
386   // Test we can get memory regions from the linux /proc/<pid>/maps stream when
387   // we don't have a MemoryInfoListStream.
388 
389   // Test addres before the first entry comes back with nothing mapped up
390   // to first valid region info
391   ConstString a("/system/bin/app_process");
392   ConstString b("/system/bin/linker");
393   ConstString c("/system/lib/liblog.so");
394   ConstString d("/system/lib/libc.so");
395   ConstString n;
396   check_region(parser, 0x00000000, 0x400d9000, no , no , no , no , n);
397   check_region(parser, 0x400d9000, 0x400db000, yes, no , yes, yes, a);
398   check_region(parser, 0x400db000, 0x400dc000, yes, no , no , yes, a);
399   check_region(parser, 0x400dc000, 0x400dd000, yes, yes, no , yes, n);
400   check_region(parser, 0x400dd000, 0x400ec000, yes, no , yes, yes, b);
401   check_region(parser, 0x400ec000, 0x400ed000, yes, no , no , yes, n);
402   check_region(parser, 0x400ed000, 0x400ee000, yes, no , no , yes, b);
403   check_region(parser, 0x400ee000, 0x400ef000, yes, yes, no , yes, b);
404   check_region(parser, 0x400ef000, 0x400fb000, yes, yes, no , yes, n);
405   check_region(parser, 0x400fb000, 0x400fc000, yes, no , yes, yes, c);
406   check_region(parser, 0x400fc000, 0x400fd000, yes, yes, yes, yes, c);
407   check_region(parser, 0x400fd000, 0x400ff000, yes, no , yes, yes, c);
408   check_region(parser, 0x400ff000, 0x40100000, yes, no , no , yes, c);
409   check_region(parser, 0x40100000, 0x40101000, yes, yes, no , yes, c);
410   check_region(parser, 0x40101000, 0x40122000, yes, no , yes, yes, d);
411   check_region(parser, 0x40122000, 0x40123000, yes, yes, yes, yes, d);
412   check_region(parser, 0x40123000, 0x40167000, yes, no , yes, yes, d);
413   check_region(parser, 0x40167000, 0x40169000, yes, no , no , yes, d);
414   check_region(parser, 0x40169000, 0x4016b000, yes, yes, no , yes, d);
415   check_region(parser, 0x4016b000, 0x40176000, yes, yes, no , yes, n);
416   check_region(parser, 0x40176000, UINT64_MAX, no , no , no , no , n);
417 }
418 
419 // Windows Minidump tests
420 // fizzbuzz_no_heap.dmp is copied from the WinMiniDump tests
421 TEST_F(MinidumpParserTest, GetArchitectureWindows) {
422   SetUpData("fizzbuzz_no_heap.dmp");
423   ASSERT_EQ(llvm::Triple::ArchType::x86,
424             parser->GetArchitecture().GetMachine());
425   ASSERT_EQ(llvm::Triple::OSType::Win32,
426             parser->GetArchitecture().GetTriple().getOS());
427 }
428 
429 TEST_F(MinidumpParserTest, GetLinuxProcStatusWindows) {
430   SetUpData("fizzbuzz_no_heap.dmp");
431   llvm::Optional<LinuxProcStatus> proc_status = parser->GetLinuxProcStatus();
432   ASSERT_FALSE(proc_status.hasValue());
433 }
434 
435 TEST_F(MinidumpParserTest, GetMiscInfoWindows) {
436   SetUpData("fizzbuzz_no_heap.dmp");
437   const MinidumpMiscInfo *misc_info = parser->GetMiscInfo();
438   ASSERT_NE(nullptr, misc_info);
439   llvm::Optional<lldb::pid_t> pid = misc_info->GetPid();
440   ASSERT_TRUE(pid.hasValue());
441   ASSERT_EQ(4440UL, pid.getValue());
442 }
443 
444 TEST_F(MinidumpParserTest, GetPidWindows) {
445   SetUpData("fizzbuzz_no_heap.dmp");
446   llvm::Optional<lldb::pid_t> pid = parser->GetPid();
447   ASSERT_TRUE(pid.hasValue());
448   ASSERT_EQ(4440UL, pid.getValue());
449 }
450 
451 // wow64
452 TEST_F(MinidumpParserTest, GetPidWow64) {
453   SetUpData("fizzbuzz_wow64.dmp");
454   llvm::Optional<lldb::pid_t> pid = parser->GetPid();
455   ASSERT_TRUE(pid.hasValue());
456   ASSERT_EQ(7836UL, pid.getValue());
457 }
458 
459 TEST_F(MinidumpParserTest, GetModuleListWow64) {
460   SetUpData("fizzbuzz_wow64.dmp");
461   llvm::ArrayRef<MinidumpModule> modules = parser->GetModuleList();
462   ASSERT_EQ(16UL, modules.size());
463   std::string module_names[16] = {
464       R"(D:\src\llvm\llvm\tools\lldb\packages\Python\lldbsuite\test\functionalities\postmortem\wow64_minidump\fizzbuzz.exe)",
465       R"(C:\Windows\System32\ntdll.dll)",
466       R"(C:\Windows\System32\wow64.dll)",
467       R"(C:\Windows\System32\wow64win.dll)",
468       R"(C:\Windows\System32\wow64cpu.dll)",
469       R"(D:\src\llvm\llvm\tools\lldb\packages\Python\lldbsuite\test\functionalities\postmortem\wow64_minidump\fizzbuzz.exe)",
470       R"(C:\Windows\SysWOW64\ntdll.dll)",
471       R"(C:\Windows\SysWOW64\kernel32.dll)",
472       R"(C:\Windows\SysWOW64\KERNELBASE.dll)",
473       R"(C:\Windows\SysWOW64\advapi32.dll)",
474       R"(C:\Windows\SysWOW64\msvcrt.dll)",
475       R"(C:\Windows\SysWOW64\sechost.dll)",
476       R"(C:\Windows\SysWOW64\rpcrt4.dll)",
477       R"(C:\Windows\SysWOW64\sspicli.dll)",
478       R"(C:\Windows\SysWOW64\CRYPTBASE.dll)",
479       R"(C:\Windows\System32\api-ms-win-core-synch-l1-2-0.DLL)",
480   };
481 
482   for (int i = 0; i < 16; ++i) {
483     llvm::Optional<std::string> name =
484         parser->GetMinidumpString(modules[i].module_name_rva);
485     ASSERT_TRUE(name.hasValue());
486     EXPECT_EQ(module_names[i], name.getValue());
487   }
488 }
489 
490 // Register tests
491 #define REG_VAL32(x) *(reinterpret_cast<uint32_t *>(x))
492 #define REG_VAL64(x) *(reinterpret_cast<uint64_t *>(x))
493 
494 TEST_F(MinidumpParserTest, ConvertMinidumpContext_x86_32) {
495   SetUpData("linux-i386.dmp");
496   llvm::ArrayRef<MinidumpThread> thread_list = parser->GetThreads();
497   const MinidumpThread thread = thread_list[0];
498   llvm::ArrayRef<uint8_t> registers(parser->GetThreadContext(thread));
499 
500   ArchSpec arch = parser->GetArchitecture();
501   auto reg_interface = llvm::make_unique<RegisterContextLinux_i386>(arch);
502   lldb::DataBufferSP buf =
503       ConvertMinidumpContext_x86_32(registers, reg_interface.get());
504   ASSERT_EQ(reg_interface->GetGPRSize(), buf->GetByteSize());
505 
506   const RegisterInfo *reg_info = reg_interface->GetRegisterInfo();
507 
508   std::map<uint64_t, uint32_t> reg_values;
509 
510   reg_values[lldb_eax_i386] = 0x00000000;
511   reg_values[lldb_ebx_i386] = 0xf7778000;
512   reg_values[lldb_ecx_i386] = 0x00000001;
513   reg_values[lldb_edx_i386] = 0xff9dd4a3;
514   reg_values[lldb_edi_i386] = 0x080482a8;
515   reg_values[lldb_esi_i386] = 0xff9dd55c;
516   reg_values[lldb_ebp_i386] = 0xff9dd53c;
517   reg_values[lldb_esp_i386] = 0xff9dd52c;
518   reg_values[lldb_eip_i386] = 0x080482a0;
519   reg_values[lldb_eflags_i386] = 0x00010282;
520   reg_values[lldb_cs_i386] = 0x00000023;
521   reg_values[lldb_fs_i386] = 0x00000000;
522   reg_values[lldb_gs_i386] = 0x00000063;
523   reg_values[lldb_ss_i386] = 0x0000002b;
524   reg_values[lldb_ds_i386] = 0x0000002b;
525   reg_values[lldb_es_i386] = 0x0000002b;
526 
527   for (uint32_t reg_index = 0; reg_index < reg_interface->GetRegisterCount();
528        ++reg_index) {
529     if (reg_values.find(reg_index) != reg_values.end()) {
530       EXPECT_EQ(reg_values[reg_index],
531                 REG_VAL32(buf->GetBytes() + reg_info[reg_index].byte_offset));
532     }
533   }
534 }
535 
536 TEST_F(MinidumpParserTest, ConvertMinidumpContext_x86_64) {
537   SetUpData("linux-x86_64.dmp");
538   llvm::ArrayRef<MinidumpThread> thread_list = parser->GetThreads();
539   const MinidumpThread thread = thread_list[0];
540   llvm::ArrayRef<uint8_t> registers(parser->GetThreadContext(thread));
541 
542   ArchSpec arch = parser->GetArchitecture();
543   auto reg_interface = llvm::make_unique<RegisterContextLinux_x86_64>(arch);
544   lldb::DataBufferSP buf =
545       ConvertMinidumpContext_x86_64(registers, reg_interface.get());
546   ASSERT_EQ(reg_interface->GetGPRSize(), buf->GetByteSize());
547 
548   const RegisterInfo *reg_info = reg_interface->GetRegisterInfo();
549 
550   std::map<uint64_t, uint64_t> reg_values;
551 
552   reg_values[lldb_rax_x86_64] = 0x0000000000000000;
553   reg_values[lldb_rbx_x86_64] = 0x0000000000000000;
554   reg_values[lldb_rcx_x86_64] = 0x0000000000000010;
555   reg_values[lldb_rdx_x86_64] = 0x0000000000000000;
556   reg_values[lldb_rdi_x86_64] = 0x00007ffceb349cf0;
557   reg_values[lldb_rsi_x86_64] = 0x0000000000000000;
558   reg_values[lldb_rbp_x86_64] = 0x00007ffceb34a210;
559   reg_values[lldb_rsp_x86_64] = 0x00007ffceb34a210;
560   reg_values[lldb_r8_x86_64] = 0x00007fe9bc1aa9c0;
561   reg_values[lldb_r9_x86_64] = 0x0000000000000000;
562   reg_values[lldb_r10_x86_64] = 0x00007fe9bc3f16a0;
563   reg_values[lldb_r11_x86_64] = 0x0000000000000246;
564   reg_values[lldb_r12_x86_64] = 0x0000000000401c92;
565   reg_values[lldb_r13_x86_64] = 0x00007ffceb34a430;
566   reg_values[lldb_r14_x86_64] = 0x0000000000000000;
567   reg_values[lldb_r15_x86_64] = 0x0000000000000000;
568   reg_values[lldb_rip_x86_64] = 0x0000000000401dc6;
569   reg_values[lldb_rflags_x86_64] = 0x0000000000010206;
570   reg_values[lldb_cs_x86_64] = 0x0000000000000033;
571   reg_values[lldb_fs_x86_64] = 0x0000000000000000;
572   reg_values[lldb_gs_x86_64] = 0x0000000000000000;
573   reg_values[lldb_ss_x86_64] = 0x0000000000000000;
574   reg_values[lldb_ds_x86_64] = 0x0000000000000000;
575   reg_values[lldb_es_x86_64] = 0x0000000000000000;
576 
577   for (uint32_t reg_index = 0; reg_index < reg_interface->GetRegisterCount();
578        ++reg_index) {
579     if (reg_values.find(reg_index) != reg_values.end()) {
580       EXPECT_EQ(reg_values[reg_index],
581                 REG_VAL64(buf->GetBytes() + reg_info[reg_index].byte_offset));
582     }
583   }
584 }
585 
586 TEST_F(MinidumpParserTest, ConvertMinidumpContext_x86_32_wow64) {
587   SetUpData("fizzbuzz_wow64.dmp");
588   llvm::ArrayRef<MinidumpThread> thread_list = parser->GetThreads();
589   const MinidumpThread thread = thread_list[0];
590   llvm::ArrayRef<uint8_t> registers(parser->GetThreadContextWow64(thread));
591 
592   ArchSpec arch = parser->GetArchitecture();
593   auto reg_interface = llvm::make_unique<RegisterContextLinux_i386>(arch);
594   lldb::DataBufferSP buf =
595       ConvertMinidumpContext_x86_32(registers, reg_interface.get());
596   ASSERT_EQ(reg_interface->GetGPRSize(), buf->GetByteSize());
597 
598   const RegisterInfo *reg_info = reg_interface->GetRegisterInfo();
599 
600   std::map<uint64_t, uint32_t> reg_values;
601 
602   reg_values[lldb_eax_i386] = 0x00000000;
603   reg_values[lldb_ebx_i386] = 0x0037f608;
604   reg_values[lldb_ecx_i386] = 0x00e61578;
605   reg_values[lldb_edx_i386] = 0x00000008;
606   reg_values[lldb_edi_i386] = 0x00000000;
607   reg_values[lldb_esi_i386] = 0x00000002;
608   reg_values[lldb_ebp_i386] = 0x0037f654;
609   reg_values[lldb_esp_i386] = 0x0037f5b8;
610   reg_values[lldb_eip_i386] = 0x77ce01fd;
611   reg_values[lldb_eflags_i386] = 0x00000246;
612   reg_values[lldb_cs_i386] = 0x00000023;
613   reg_values[lldb_fs_i386] = 0x00000053;
614   reg_values[lldb_gs_i386] = 0x0000002b;
615   reg_values[lldb_ss_i386] = 0x0000002b;
616   reg_values[lldb_ds_i386] = 0x0000002b;
617   reg_values[lldb_es_i386] = 0x0000002b;
618 
619   for (uint32_t reg_index = 0; reg_index < reg_interface->GetRegisterCount();
620        ++reg_index) {
621     if (reg_values.find(reg_index) != reg_values.end()) {
622       EXPECT_EQ(reg_values[reg_index],
623                 REG_VAL32(buf->GetBytes() + reg_info[reg_index].byte_offset));
624     }
625   }
626 }
627 
628 TEST_F(MinidumpParserTest, MinidumpDuplicateModuleMinAddress) {
629   SetUpData("modules-dup-min-addr.dmp");
630   // Test that if we have two modules in the module list:
631   //    /tmp/a with range [0x2000-0x3000)
632   //    /tmp/a with range [0x1000-0x2000)
633   // That we end up with one module in the filtered list with the
634   // range [0x1000-0x2000). MinidumpParser::GetFilteredModuleList() is
635   // trying to ensure that if we have the same module mentioned more than
636   // one time, we pick the one with the lowest base_of_image.
637   std::vector<const MinidumpModule *> filtered_modules =
638       parser->GetFilteredModuleList();
639   EXPECT_EQ(1u, filtered_modules.size());
640   EXPECT_EQ(0x0000000000001000u, filtered_modules[0]->base_of_image);
641 }
642 
643 TEST_F(MinidumpParserTest, MinidumpModuleOrder) {
644   SetUpData("modules-order.dmp");
645   // Test that if we have two modules in the module list:
646   //    /tmp/a with range [0x2000-0x3000)
647   //    /tmp/b with range [0x1000-0x2000)
648   // That we end up with two modules in the filtered list with the same ranges
649   // and in the same order. Previous versions of the
650   // MinidumpParser::GetFilteredModuleList() function would sort all images
651   // by address and modify the order of the modules.
652   std::vector<const MinidumpModule *> filtered_modules =
653       parser->GetFilteredModuleList();
654   llvm::Optional<std::string> name;
655   EXPECT_EQ(2u, filtered_modules.size());
656   EXPECT_EQ(0x0000000000002000u, filtered_modules[0]->base_of_image);
657   name = parser->GetMinidumpString(filtered_modules[0]->module_name_rva);
658   ASSERT_TRUE((bool)name);
659   EXPECT_EQ(std::string("/tmp/a"), *name);
660   EXPECT_EQ(0x0000000000001000u, filtered_modules[1]->base_of_image);
661   name = parser->GetMinidumpString(filtered_modules[1]->module_name_rva);
662   ASSERT_TRUE((bool)name);
663   EXPECT_EQ(std::string("/tmp/b"), *name);
664 }
665 
666