xref: /llvm-project/llvm/unittests/ObjectYAML/MinidumpYAMLTest.cpp (revision deba13409245aabf3fda8b82a873336ea5238d3a)
169de7a95SPavel Labath //===- MinidumpYAMLTest.cpp - Tests for Minidump<->YAML code --------------===//
269de7a95SPavel Labath //
369de7a95SPavel Labath // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
469de7a95SPavel Labath // See https://llvm.org/LICENSE.txt for license information.
569de7a95SPavel Labath // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
669de7a95SPavel Labath //
769de7a95SPavel Labath //===----------------------------------------------------------------------===//
869de7a95SPavel Labath 
969de7a95SPavel Labath #include "llvm/Object/Minidump.h"
1082275ec5SPavel Labath #include "llvm/ObjectYAML/yaml2obj.h"
1182275ec5SPavel Labath #include "llvm/Support/YAMLTraits.h"
1269de7a95SPavel Labath #include "llvm/Testing/Support/Error.h"
1369de7a95SPavel Labath #include "gtest/gtest.h"
1469de7a95SPavel Labath 
1569de7a95SPavel Labath using namespace llvm;
1669de7a95SPavel Labath using namespace llvm::minidump;
1769de7a95SPavel Labath 
1869de7a95SPavel Labath static Expected<std::unique_ptr<object::MinidumpFile>>
1969de7a95SPavel Labath toBinary(SmallVectorImpl<char> &Storage, StringRef Yaml) {
2069de7a95SPavel Labath   Storage.clear();
2169de7a95SPavel Labath   raw_svector_ostream OS(Storage);
2282275ec5SPavel Labath   yaml::Input YIn(Yaml);
2385011027SGeorge Rimar   if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {}))
2485011027SGeorge Rimar     return createStringError(std::errc::invalid_argument,
2585011027SGeorge Rimar                              "unable to convert YAML");
2669de7a95SPavel Labath 
2769de7a95SPavel Labath   return object::MinidumpFile::create(MemoryBufferRef(OS.str(), "Binary"));
2869de7a95SPavel Labath }
2969de7a95SPavel Labath 
3069de7a95SPavel Labath TEST(MinidumpYAML, Basic) {
3169de7a95SPavel Labath   SmallString<0> Storage;
3269de7a95SPavel Labath   auto ExpectedFile = toBinary(Storage, R"(
3369de7a95SPavel Labath --- !minidump
3469de7a95SPavel Labath Streams:
3569de7a95SPavel Labath   - Type:            SystemInfo
36e9430231SPavel Labath     Processor Arch:  ARM64
3769de7a95SPavel Labath     Platform ID:     Linux
3869de7a95SPavel Labath     CPU:
3969de7a95SPavel Labath       CPUID:           0x05060708
4069de7a95SPavel Labath   - Type:            LinuxMaps
4169de7a95SPavel Labath     Text:             |
4269de7a95SPavel Labath       400d9000-400db000 r-xp 00000000 b3:04 227        /system/bin/app_process
4369de7a95SPavel Labath       400db000-400dc000 r--p 00001000 b3:04 227        /system/bin/app_process
4469de7a95SPavel Labath 
4569de7a95SPavel Labath   - Type:            LinuxAuxv
4669de7a95SPavel Labath     Content:         DEADBEEFBAADF00D)");
4769de7a95SPavel Labath   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
4869de7a95SPavel Labath   object::MinidumpFile &File = **ExpectedFile;
4969de7a95SPavel Labath 
5069de7a95SPavel Labath   ASSERT_EQ(3u, File.streams().size());
5169de7a95SPavel Labath 
5269de7a95SPavel Labath   EXPECT_EQ(StreamType::SystemInfo, File.streams()[0].Type);
5369de7a95SPavel Labath   auto ExpectedSysInfo = File.getSystemInfo();
5469de7a95SPavel Labath   ASSERT_THAT_EXPECTED(ExpectedSysInfo, Succeeded());
5569de7a95SPavel Labath   const SystemInfo &SysInfo = *ExpectedSysInfo;
56e9430231SPavel Labath   EXPECT_EQ(ProcessorArchitecture::ARM64, SysInfo.ProcessorArch);
5769de7a95SPavel Labath   EXPECT_EQ(OSPlatform::Linux, SysInfo.PlatformId);
5869de7a95SPavel Labath   EXPECT_EQ(0x05060708u, SysInfo.CPU.Arm.CPUID);
5969de7a95SPavel Labath 
6069de7a95SPavel Labath   EXPECT_EQ(StreamType::LinuxMaps, File.streams()[1].Type);
6169de7a95SPavel Labath   EXPECT_EQ("400d9000-400db000 r-xp 00000000 b3:04 227        "
6269de7a95SPavel Labath             "/system/bin/app_process\n"
6369de7a95SPavel Labath             "400db000-400dc000 r--p 00001000 b3:04 227        "
6469de7a95SPavel Labath             "/system/bin/app_process\n",
6569de7a95SPavel Labath             toStringRef(*File.getRawStream(StreamType::LinuxMaps)));
6669de7a95SPavel Labath 
6769de7a95SPavel Labath   EXPECT_EQ(StreamType::LinuxAuxv, File.streams()[2].Type);
6869de7a95SPavel Labath   EXPECT_EQ((ArrayRef<uint8_t>{0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 0xF0, 0x0D}),
6969de7a95SPavel Labath             File.getRawStream(StreamType::LinuxAuxv));
7069de7a95SPavel Labath }
7169de7a95SPavel Labath 
7269de7a95SPavel Labath TEST(MinidumpYAML, RawContent) {
7369de7a95SPavel Labath   SmallString<0> Storage;
7469de7a95SPavel Labath   auto ExpectedFile = toBinary(Storage, R"(
7569de7a95SPavel Labath --- !minidump
7669de7a95SPavel Labath Streams:
7769de7a95SPavel Labath   - Type:            LinuxAuxv
7869de7a95SPavel Labath     Size:            9
7969de7a95SPavel Labath     Content:         DEADBEEFBAADF00D)");
8069de7a95SPavel Labath   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
8169de7a95SPavel Labath   object::MinidumpFile &File = **ExpectedFile;
8269de7a95SPavel Labath 
8369de7a95SPavel Labath   EXPECT_EQ(
8469de7a95SPavel Labath       (ArrayRef<uint8_t>{0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 0xF0, 0x0D, 0x00}),
8569de7a95SPavel Labath       File.getRawStream(StreamType::LinuxAuxv));
8669de7a95SPavel Labath }
8769de7a95SPavel Labath 
8869de7a95SPavel Labath TEST(MinidumpYAML, X86SystemInfo) {
8969de7a95SPavel Labath   SmallString<0> Storage;
9069de7a95SPavel Labath   auto ExpectedFile = toBinary(Storage, R"(
9169de7a95SPavel Labath --- !minidump
9269de7a95SPavel Labath Streams:
9369de7a95SPavel Labath   - Type:            SystemInfo
9469de7a95SPavel Labath     Processor Arch:  X86
9569de7a95SPavel Labath     Platform ID:     Linux
9669de7a95SPavel Labath     CPU:
9769de7a95SPavel Labath       Vendor ID:       LLVMLLVMLLVM
9869de7a95SPavel Labath       Version Info:    0x01020304
9969de7a95SPavel Labath       Feature Info:    0x05060708
10069de7a95SPavel Labath       AMD Extended Features: 0x09000102)");
10169de7a95SPavel Labath   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
10269de7a95SPavel Labath   object::MinidumpFile &File = **ExpectedFile;
10369de7a95SPavel Labath 
10469de7a95SPavel Labath   ASSERT_EQ(1u, File.streams().size());
10569de7a95SPavel Labath 
10669de7a95SPavel Labath   auto ExpectedSysInfo = File.getSystemInfo();
10769de7a95SPavel Labath   ASSERT_THAT_EXPECTED(ExpectedSysInfo, Succeeded());
10869de7a95SPavel Labath   const SystemInfo &SysInfo = *ExpectedSysInfo;
10969de7a95SPavel Labath   EXPECT_EQ(ProcessorArchitecture::X86, SysInfo.ProcessorArch);
11069de7a95SPavel Labath   EXPECT_EQ(OSPlatform::Linux, SysInfo.PlatformId);
11169de7a95SPavel Labath   EXPECT_EQ("LLVMLLVMLLVM", StringRef(SysInfo.CPU.X86.VendorID,
11269de7a95SPavel Labath                                       sizeof(SysInfo.CPU.X86.VendorID)));
11369de7a95SPavel Labath   EXPECT_EQ(0x01020304u, SysInfo.CPU.X86.VersionInfo);
11469de7a95SPavel Labath   EXPECT_EQ(0x05060708u, SysInfo.CPU.X86.FeatureInfo);
11569de7a95SPavel Labath   EXPECT_EQ(0x09000102u, SysInfo.CPU.X86.AMDExtendedFeatures);
11669de7a95SPavel Labath }
11769de7a95SPavel Labath 
11869de7a95SPavel Labath TEST(MinidumpYAML, OtherSystemInfo) {
11969de7a95SPavel Labath   SmallString<0> Storage;
12069de7a95SPavel Labath   auto ExpectedFile = toBinary(Storage, R"(
12169de7a95SPavel Labath --- !minidump
12269de7a95SPavel Labath Streams:
12369de7a95SPavel Labath   - Type:            SystemInfo
12469de7a95SPavel Labath     Processor Arch:  PPC
12569de7a95SPavel Labath     Platform ID:     Linux
12669de7a95SPavel Labath     CPU:
12769de7a95SPavel Labath       Features:        000102030405060708090a0b0c0d0e0f)");
12869de7a95SPavel Labath   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
12969de7a95SPavel Labath   object::MinidumpFile &File = **ExpectedFile;
13069de7a95SPavel Labath 
13169de7a95SPavel Labath   ASSERT_EQ(1u, File.streams().size());
13269de7a95SPavel Labath 
13369de7a95SPavel Labath   auto ExpectedSysInfo = File.getSystemInfo();
13469de7a95SPavel Labath   ASSERT_THAT_EXPECTED(ExpectedSysInfo, Succeeded());
13569de7a95SPavel Labath   const SystemInfo &SysInfo = *ExpectedSysInfo;
13669de7a95SPavel Labath   EXPECT_EQ(ProcessorArchitecture::PPC, SysInfo.ProcessorArch);
13769de7a95SPavel Labath   EXPECT_EQ(OSPlatform::Linux, SysInfo.PlatformId);
13869de7a95SPavel Labath   EXPECT_EQ(
13969de7a95SPavel Labath       (ArrayRef<uint8_t>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}),
14038818b60Sserge-sans-paille       ArrayRef(SysInfo.CPU.Other.ProcessorFeatures));
14169de7a95SPavel Labath }
142a50272f8SJoseph Tremoulet 
143a50272f8SJoseph Tremoulet // Test that we can parse a normal-looking ExceptionStream.
144a50272f8SJoseph Tremoulet TEST(MinidumpYAML, ExceptionStream) {
145a50272f8SJoseph Tremoulet   SmallString<0> Storage;
146a50272f8SJoseph Tremoulet   auto ExpectedFile = toBinary(Storage, R"(
147a50272f8SJoseph Tremoulet --- !minidump
148a50272f8SJoseph Tremoulet Streams:
149a50272f8SJoseph Tremoulet   - Type:            Exception
150a50272f8SJoseph Tremoulet     Thread ID:  0x7
151a50272f8SJoseph Tremoulet     Exception Record:
152a50272f8SJoseph Tremoulet       Exception Code:  0x23
153a50272f8SJoseph Tremoulet       Exception Flags: 0x5
154a50272f8SJoseph Tremoulet       Exception Record: 0x0102030405060708
155a50272f8SJoseph Tremoulet       Exception Address: 0x0a0b0c0d0e0f1011
156a50272f8SJoseph Tremoulet       Number of Parameters: 2
157a50272f8SJoseph Tremoulet       Parameter 0: 0x22
158a50272f8SJoseph Tremoulet       Parameter 1: 0x24
159a50272f8SJoseph Tremoulet     Thread Context:  3DeadBeefDefacedABadCafe)");
160a50272f8SJoseph Tremoulet   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
161a50272f8SJoseph Tremoulet   object::MinidumpFile &File = **ExpectedFile;
162a50272f8SJoseph Tremoulet 
163a50272f8SJoseph Tremoulet   ASSERT_EQ(1u, File.streams().size());
164a50272f8SJoseph Tremoulet 
165*deba1340SJacob Lalonde   auto ExceptionIterator = File.getExceptionStreams().begin();
166*deba1340SJacob Lalonde 
167*deba1340SJacob Lalonde   Expected<const ExceptionStream &> ExpectedStream = *ExceptionIterator;
168a50272f8SJoseph Tremoulet 
169a50272f8SJoseph Tremoulet   ASSERT_THAT_EXPECTED(ExpectedStream, Succeeded());
170a50272f8SJoseph Tremoulet 
171a50272f8SJoseph Tremoulet   const minidump::ExceptionStream &Stream = *ExpectedStream;
172a50272f8SJoseph Tremoulet   EXPECT_EQ(0x7u, Stream.ThreadId);
173a50272f8SJoseph Tremoulet   const minidump::Exception &Exception = Stream.ExceptionRecord;
174a50272f8SJoseph Tremoulet   EXPECT_EQ(0x23u, Exception.ExceptionCode);
175a50272f8SJoseph Tremoulet   EXPECT_EQ(0x5u, Exception.ExceptionFlags);
176a50272f8SJoseph Tremoulet   EXPECT_EQ(0x0102030405060708u, Exception.ExceptionRecord);
177a50272f8SJoseph Tremoulet   EXPECT_EQ(0x0a0b0c0d0e0f1011u, Exception.ExceptionAddress);
178a50272f8SJoseph Tremoulet   EXPECT_EQ(2u, Exception.NumberParameters);
179a50272f8SJoseph Tremoulet   EXPECT_EQ(0x22u, Exception.ExceptionInformation[0]);
180a50272f8SJoseph Tremoulet   EXPECT_EQ(0x24u, Exception.ExceptionInformation[1]);
181a50272f8SJoseph Tremoulet 
182a50272f8SJoseph Tremoulet   Expected<ArrayRef<uint8_t>> ExpectedContext =
183a50272f8SJoseph Tremoulet       File.getRawData(Stream.ThreadContext);
184a50272f8SJoseph Tremoulet   ASSERT_THAT_EXPECTED(ExpectedContext, Succeeded());
185a50272f8SJoseph Tremoulet   EXPECT_EQ((ArrayRef<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed,
186a50272f8SJoseph Tremoulet                                0xab, 0xad, 0xca, 0xfe}),
187a50272f8SJoseph Tremoulet             *ExpectedContext);
188a50272f8SJoseph Tremoulet }
189a50272f8SJoseph Tremoulet 
190a50272f8SJoseph Tremoulet // Test that we can parse an exception stream with no ExceptionInformation.
191a50272f8SJoseph Tremoulet TEST(MinidumpYAML, ExceptionStream_NoParameters) {
192a50272f8SJoseph Tremoulet   SmallString<0> Storage;
193a50272f8SJoseph Tremoulet   auto ExpectedFile = toBinary(Storage, R"(
194a50272f8SJoseph Tremoulet --- !minidump
195a50272f8SJoseph Tremoulet Streams:
196a50272f8SJoseph Tremoulet   - Type:            Exception
197a50272f8SJoseph Tremoulet     Thread ID:  0x7
198a50272f8SJoseph Tremoulet     Exception Record:
199a50272f8SJoseph Tremoulet       Exception Code:  0x23
200a50272f8SJoseph Tremoulet       Exception Flags: 0x5
201a50272f8SJoseph Tremoulet       Exception Record: 0x0102030405060708
202a50272f8SJoseph Tremoulet       Exception Address: 0x0a0b0c0d0e0f1011
203a50272f8SJoseph Tremoulet     Thread Context:  3DeadBeefDefacedABadCafe)");
204a50272f8SJoseph Tremoulet   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
205a50272f8SJoseph Tremoulet   object::MinidumpFile &File = **ExpectedFile;
206a50272f8SJoseph Tremoulet 
207a50272f8SJoseph Tremoulet   ASSERT_EQ(1u, File.streams().size());
208a50272f8SJoseph Tremoulet 
209*deba1340SJacob Lalonde   auto ExceptionIterator = File.getExceptionStreams().begin();
210a50272f8SJoseph Tremoulet 
211*deba1340SJacob Lalonde   Expected<const ExceptionStream &> ExpectedStream = *ExceptionIterator;
212a50272f8SJoseph Tremoulet   ASSERT_THAT_EXPECTED(ExpectedStream, Succeeded());
213a50272f8SJoseph Tremoulet 
214a50272f8SJoseph Tremoulet   const minidump::ExceptionStream &Stream = *ExpectedStream;
215a50272f8SJoseph Tremoulet   EXPECT_EQ(0x7u, Stream.ThreadId);
216a50272f8SJoseph Tremoulet   const minidump::Exception &Exception = Stream.ExceptionRecord;
217a50272f8SJoseph Tremoulet   EXPECT_EQ(0x23u, Exception.ExceptionCode);
218a50272f8SJoseph Tremoulet   EXPECT_EQ(0x5u, Exception.ExceptionFlags);
219a50272f8SJoseph Tremoulet   EXPECT_EQ(0x0102030405060708u, Exception.ExceptionRecord);
220a50272f8SJoseph Tremoulet   EXPECT_EQ(0x0a0b0c0d0e0f1011u, Exception.ExceptionAddress);
221a50272f8SJoseph Tremoulet   EXPECT_EQ(0u, Exception.NumberParameters);
222a50272f8SJoseph Tremoulet 
223a50272f8SJoseph Tremoulet   Expected<ArrayRef<uint8_t>> ExpectedContext =
224a50272f8SJoseph Tremoulet       File.getRawData(Stream.ThreadContext);
225a50272f8SJoseph Tremoulet   ASSERT_THAT_EXPECTED(ExpectedContext, Succeeded());
226a50272f8SJoseph Tremoulet   EXPECT_EQ((ArrayRef<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed,
227a50272f8SJoseph Tremoulet                                0xab, 0xad, 0xca, 0xfe}),
228a50272f8SJoseph Tremoulet             *ExpectedContext);
229a50272f8SJoseph Tremoulet }
230a50272f8SJoseph Tremoulet 
231a50272f8SJoseph Tremoulet // Test that we can parse an ExceptionStream where the stated number of
232a50272f8SJoseph Tremoulet // parameters is greater than the actual size of the ExceptionInformation
233a50272f8SJoseph Tremoulet // array.
234a50272f8SJoseph Tremoulet TEST(MinidumpYAML, ExceptionStream_TooManyParameters) {
235a50272f8SJoseph Tremoulet   SmallString<0> Storage;
236a50272f8SJoseph Tremoulet   auto ExpectedFile = toBinary(Storage, R"(
237a50272f8SJoseph Tremoulet --- !minidump
238a50272f8SJoseph Tremoulet Streams:
239a50272f8SJoseph Tremoulet   - Type:            Exception
240a50272f8SJoseph Tremoulet     Thread ID:  0x8
241a50272f8SJoseph Tremoulet     Exception Record:
242a50272f8SJoseph Tremoulet       Exception Code: 0
243a50272f8SJoseph Tremoulet       Number of Parameters: 16
244a50272f8SJoseph Tremoulet       Parameter 0: 0x0
245a50272f8SJoseph Tremoulet       Parameter 1: 0xff
246a50272f8SJoseph Tremoulet       Parameter 2: 0xee
247a50272f8SJoseph Tremoulet       Parameter 3: 0xdd
248a50272f8SJoseph Tremoulet       Parameter 4: 0xcc
249a50272f8SJoseph Tremoulet       Parameter 5: 0xbb
250a50272f8SJoseph Tremoulet       Parameter 6: 0xaa
251a50272f8SJoseph Tremoulet       Parameter 7: 0x99
252a50272f8SJoseph Tremoulet       Parameter 8: 0x88
253a50272f8SJoseph Tremoulet       Parameter 9: 0x77
254a50272f8SJoseph Tremoulet       Parameter 10: 0x66
255a50272f8SJoseph Tremoulet       Parameter 11: 0x55
256a50272f8SJoseph Tremoulet       Parameter 12: 0x44
257a50272f8SJoseph Tremoulet       Parameter 13: 0x33
258a50272f8SJoseph Tremoulet       Parameter 14: 0x22
259a50272f8SJoseph Tremoulet     Thread Context:  3DeadBeefDefacedABadCafe)");
260a50272f8SJoseph Tremoulet   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
261a50272f8SJoseph Tremoulet   object::MinidumpFile &File = **ExpectedFile;
262a50272f8SJoseph Tremoulet 
263a50272f8SJoseph Tremoulet   ASSERT_EQ(1u, File.streams().size());
264a50272f8SJoseph Tremoulet 
265*deba1340SJacob Lalonde   auto ExceptionIterator = File.getExceptionStreams().begin();
266*deba1340SJacob Lalonde 
267*deba1340SJacob Lalonde   Expected<const ExceptionStream &> ExpectedStream = *ExceptionIterator;
268a50272f8SJoseph Tremoulet 
269a50272f8SJoseph Tremoulet   ASSERT_THAT_EXPECTED(ExpectedStream, Succeeded());
270a50272f8SJoseph Tremoulet 
271a50272f8SJoseph Tremoulet   const minidump::ExceptionStream &Stream = *ExpectedStream;
272a50272f8SJoseph Tremoulet   EXPECT_EQ(0x8u, Stream.ThreadId);
273a50272f8SJoseph Tremoulet   const minidump::Exception &Exception = Stream.ExceptionRecord;
274a50272f8SJoseph Tremoulet   EXPECT_EQ(0x0u, Exception.ExceptionCode);
275a50272f8SJoseph Tremoulet   EXPECT_EQ(0x0u, Exception.ExceptionFlags);
276a50272f8SJoseph Tremoulet   EXPECT_EQ(0x00u, Exception.ExceptionRecord);
277a50272f8SJoseph Tremoulet   EXPECT_EQ(0x0u, Exception.ExceptionAddress);
278a50272f8SJoseph Tremoulet   EXPECT_EQ(16u, Exception.NumberParameters);
279a50272f8SJoseph Tremoulet   EXPECT_EQ(0x0u, Exception.ExceptionInformation[0]);
280a50272f8SJoseph Tremoulet   for (int Index = 1; Index < 15; ++Index) {
281a50272f8SJoseph Tremoulet     EXPECT_EQ(0x110u - Index * 0x11, Exception.ExceptionInformation[Index]);
282a50272f8SJoseph Tremoulet   }
283a50272f8SJoseph Tremoulet 
284a50272f8SJoseph Tremoulet   Expected<ArrayRef<uint8_t>> ExpectedContext =
285a50272f8SJoseph Tremoulet       File.getRawData(Stream.ThreadContext);
286a50272f8SJoseph Tremoulet   ASSERT_THAT_EXPECTED(ExpectedContext, Succeeded());
287a50272f8SJoseph Tremoulet   EXPECT_EQ((ArrayRef<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed,
288a50272f8SJoseph Tremoulet                                0xab, 0xad, 0xca, 0xfe}),
289a50272f8SJoseph Tremoulet             *ExpectedContext);
290a50272f8SJoseph Tremoulet }
291a50272f8SJoseph Tremoulet 
292a50272f8SJoseph Tremoulet // Test that we can parse an ExceptionStream where the number of
293a50272f8SJoseph Tremoulet // ExceptionInformation parameters provided is greater than the
294a50272f8SJoseph Tremoulet // specified Number of Parameters.
295a50272f8SJoseph Tremoulet TEST(MinidumpYAML, ExceptionStream_ExtraParameter) {
296a50272f8SJoseph Tremoulet   SmallString<0> Storage;
297a50272f8SJoseph Tremoulet   auto ExpectedFile = toBinary(Storage, R"(
298a50272f8SJoseph Tremoulet --- !minidump
299a50272f8SJoseph Tremoulet Streams:
300a50272f8SJoseph Tremoulet   - Type:            Exception
301a50272f8SJoseph Tremoulet     Thread ID:  0x7
302a50272f8SJoseph Tremoulet     Exception Record:
303a50272f8SJoseph Tremoulet       Exception Code:  0x23
304a50272f8SJoseph Tremoulet       Exception Flags: 0x5
305a50272f8SJoseph Tremoulet       Exception Record: 0x0102030405060708
306a50272f8SJoseph Tremoulet       Exception Address: 0x0a0b0c0d0e0f1011
307a50272f8SJoseph Tremoulet       Number of Parameters: 2
308a50272f8SJoseph Tremoulet       Parameter 0: 0x99
309a50272f8SJoseph Tremoulet       Parameter 1: 0x23
310a50272f8SJoseph Tremoulet       Parameter 2: 0x42
311a50272f8SJoseph Tremoulet     Thread Context:  3DeadBeefDefacedABadCafe)");
312a50272f8SJoseph Tremoulet   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
313a50272f8SJoseph Tremoulet   object::MinidumpFile &File = **ExpectedFile;
314a50272f8SJoseph Tremoulet 
315a50272f8SJoseph Tremoulet   ASSERT_EQ(1u, File.streams().size());
316a50272f8SJoseph Tremoulet 
317*deba1340SJacob Lalonde   auto ExceptionIterator = File.getExceptionStreams().begin();
318*deba1340SJacob Lalonde 
319*deba1340SJacob Lalonde   Expected<const ExceptionStream &> ExpectedStream = *ExceptionIterator;
320a50272f8SJoseph Tremoulet 
321a50272f8SJoseph Tremoulet   ASSERT_THAT_EXPECTED(ExpectedStream, Succeeded());
322a50272f8SJoseph Tremoulet 
323a50272f8SJoseph Tremoulet   const minidump::ExceptionStream &Stream = *ExpectedStream;
324a50272f8SJoseph Tremoulet   EXPECT_EQ(0x7u, Stream.ThreadId);
325a50272f8SJoseph Tremoulet   const minidump::Exception &Exception = Stream.ExceptionRecord;
326a50272f8SJoseph Tremoulet   EXPECT_EQ(0x23u, Exception.ExceptionCode);
327a50272f8SJoseph Tremoulet   EXPECT_EQ(0x5u, Exception.ExceptionFlags);
328a50272f8SJoseph Tremoulet   EXPECT_EQ(0x0102030405060708u, Exception.ExceptionRecord);
329a50272f8SJoseph Tremoulet   EXPECT_EQ(0x0a0b0c0d0e0f1011u, Exception.ExceptionAddress);
330a50272f8SJoseph Tremoulet   EXPECT_EQ(2u, Exception.NumberParameters);
331a50272f8SJoseph Tremoulet   EXPECT_EQ(0x99u, Exception.ExceptionInformation[0]);
332a50272f8SJoseph Tremoulet   EXPECT_EQ(0x23u, Exception.ExceptionInformation[1]);
333a50272f8SJoseph Tremoulet   EXPECT_EQ(0x42u, Exception.ExceptionInformation[2]);
334a50272f8SJoseph Tremoulet 
335a50272f8SJoseph Tremoulet   Expected<ArrayRef<uint8_t>> ExpectedContext =
336a50272f8SJoseph Tremoulet       File.getRawData(Stream.ThreadContext);
337a50272f8SJoseph Tremoulet   ASSERT_THAT_EXPECTED(ExpectedContext, Succeeded());
338a50272f8SJoseph Tremoulet   EXPECT_EQ((ArrayRef<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed,
339a50272f8SJoseph Tremoulet                                0xab, 0xad, 0xca, 0xfe}),
340a50272f8SJoseph Tremoulet             *ExpectedContext);
341a50272f8SJoseph Tremoulet }
342b1edac04SJacob Lalonde 
343b1edac04SJacob Lalonde TEST(MinidumpYAML, MemoryRegion_64bit) {
344b1edac04SJacob Lalonde   SmallString<0> Storage;
345b1edac04SJacob Lalonde   auto ExpectedFile = toBinary(Storage, R"(
346b1edac04SJacob Lalonde --- !minidump
347b1edac04SJacob Lalonde Streams:
348b1edac04SJacob Lalonde   - Type:            Memory64List
349b1edac04SJacob Lalonde     Memory Ranges:
350b1edac04SJacob Lalonde       - Start of Memory Range: 0x7FFFFFCF0818283
351b1edac04SJacob Lalonde         Content:               '68656c6c6f'
352b1edac04SJacob Lalonde       - Start of Memory Range: 0x7FFFFFFF0818283
353b1edac04SJacob Lalonde         Content:               '776f726c64'
354b1edac04SJacob Lalonde         )");
355b1edac04SJacob Lalonde 
356b1edac04SJacob Lalonde   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
357b1edac04SJacob Lalonde   object::MinidumpFile &File = **ExpectedFile;
358b1edac04SJacob Lalonde 
359b1edac04SJacob Lalonde   ASSERT_THAT(File.streams().size(), 1u);
360b1edac04SJacob Lalonde 
361b1edac04SJacob Lalonde   Error Err = Error::success();
362b1edac04SJacob Lalonde   iterator_range<object::MinidumpFile::FallibleMemory64Iterator> MemoryList =
363b1edac04SJacob Lalonde       File.getMemory64List(Err);
364b1edac04SJacob Lalonde 
365b1edac04SJacob Lalonde   ASSERT_THAT_ERROR(std::move(Err), Succeeded());
366b1edac04SJacob Lalonde   auto Iterator = MemoryList.begin();
367b1edac04SJacob Lalonde 
368b1edac04SJacob Lalonde   auto DescOnePair = *Iterator;
369b1edac04SJacob Lalonde   const minidump::MemoryDescriptor_64 &DescOne = DescOnePair.first;
370b1edac04SJacob Lalonde   ASSERT_THAT(DescOne.StartOfMemoryRange, 0x7FFFFFCF0818283u);
371b1edac04SJacob Lalonde   ASSERT_THAT(DescOne.DataSize, 5u);
372b1edac04SJacob Lalonde   ++Iterator;
373b1edac04SJacob Lalonde   ASSERT_THAT_ERROR(std::move(Err), Succeeded());
374b1edac04SJacob Lalonde 
375b1edac04SJacob Lalonde   auto DescTwoPair = *Iterator;
376b1edac04SJacob Lalonde   const minidump::MemoryDescriptor_64 &DescTwo = DescTwoPair.first;
377b1edac04SJacob Lalonde   ASSERT_THAT(DescTwo.StartOfMemoryRange, 0x7FFFFFFF0818283u);
378b1edac04SJacob Lalonde   ASSERT_THAT(DescTwo.DataSize, 5u);
379b1edac04SJacob Lalonde   ++Iterator;
380b1edac04SJacob Lalonde   ASSERT_THAT_ERROR(std::move(Err), Succeeded());
381b1edac04SJacob Lalonde 
382b1edac04SJacob Lalonde   const std::optional<ArrayRef<uint8_t>> ExpectedContent =
383b1edac04SJacob Lalonde       File.getRawStream(StreamType::Memory64List);
384b1edac04SJacob Lalonde   ASSERT_TRUE(ExpectedContent);
385b1edac04SJacob Lalonde   const size_t ExpectedStreamSize =
386b1edac04SJacob Lalonde       sizeof(Memory64ListHeader) + (sizeof(MemoryDescriptor_64) * 2);
387b1edac04SJacob Lalonde   ASSERT_THAT(ExpectedContent->size(), ExpectedStreamSize);
388b1edac04SJacob Lalonde 
389b1edac04SJacob Lalonde   Expected<minidump::Memory64ListHeader> ExpectedHeader =
390b1edac04SJacob Lalonde       File.getMemoryList64Header();
391b1edac04SJacob Lalonde   ASSERT_THAT_EXPECTED(ExpectedHeader, Succeeded());
392b1edac04SJacob Lalonde   ASSERT_THAT(ExpectedHeader->BaseRVA, 92u);
393b1edac04SJacob Lalonde 
394b1edac04SJacob Lalonde   Expected<ArrayRef<uint8_t>> DescOneExpectedContentSlice = DescOnePair.second;
395b1edac04SJacob Lalonde   ASSERT_THAT_EXPECTED(DescOneExpectedContentSlice, Succeeded());
396b1edac04SJacob Lalonde   ASSERT_THAT(DescOneExpectedContentSlice->size(), 5u);
397b1edac04SJacob Lalonde   ASSERT_THAT(*DescOneExpectedContentSlice, arrayRefFromStringRef("hello"));
398b1edac04SJacob Lalonde 
399b1edac04SJacob Lalonde   Expected<ArrayRef<uint8_t>> DescTwoExpectedContentSlice = DescTwoPair.second;
400b1edac04SJacob Lalonde   ASSERT_THAT_EXPECTED(DescTwoExpectedContentSlice, Succeeded());
401b1edac04SJacob Lalonde   ASSERT_THAT(*DescTwoExpectedContentSlice, arrayRefFromStringRef("world"));
402b1edac04SJacob Lalonde 
403b1edac04SJacob Lalonde   ASSERT_EQ(Iterator, MemoryList.end());
404b1edac04SJacob Lalonde }
405*deba1340SJacob Lalonde 
406*deba1340SJacob Lalonde // Test that we can parse multiple exception streams.
407*deba1340SJacob Lalonde TEST(MinidumpYAML, ExceptionStream_MultipleExceptions) {
408*deba1340SJacob Lalonde   SmallString<0> Storage;
409*deba1340SJacob Lalonde   auto ExpectedFile = toBinary(Storage, R"(
410*deba1340SJacob Lalonde --- !minidump
411*deba1340SJacob Lalonde Streams:
412*deba1340SJacob Lalonde   - Type:            Exception
413*deba1340SJacob Lalonde     Thread ID:  0x7
414*deba1340SJacob Lalonde     Exception Record:
415*deba1340SJacob Lalonde       Exception Code:  0x23
416*deba1340SJacob Lalonde       Exception Flags: 0x5
417*deba1340SJacob Lalonde       Exception Record: 0x0102030405060708
418*deba1340SJacob Lalonde       Exception Address: 0x0a0b0c0d0e0f1011
419*deba1340SJacob Lalonde       Number of Parameters: 2
420*deba1340SJacob Lalonde       Parameter 0: 0x99
421*deba1340SJacob Lalonde       Parameter 1: 0x23
422*deba1340SJacob Lalonde       Parameter 2: 0x42
423*deba1340SJacob Lalonde     Thread Context:  3DeadBeefDefacedABadCafe
424*deba1340SJacob Lalonde   - Type:            Exception
425*deba1340SJacob Lalonde     Thread ID:  0x5
426*deba1340SJacob Lalonde     Exception Record:
427*deba1340SJacob Lalonde       Exception Code:  0x23
428*deba1340SJacob Lalonde       Exception Flags: 0x5
429*deba1340SJacob Lalonde       Exception Record: 0x0102030405060708
430*deba1340SJacob Lalonde       Exception Address: 0x0a0b0c0d0e0f1011
431*deba1340SJacob Lalonde     Thread Context:  3DeadBeefDefacedABadCafe)");
432*deba1340SJacob Lalonde 
433*deba1340SJacob Lalonde   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
434*deba1340SJacob Lalonde   object::MinidumpFile &File = **ExpectedFile;
435*deba1340SJacob Lalonde 
436*deba1340SJacob Lalonde   ASSERT_EQ(2u, File.streams().size());
437*deba1340SJacob Lalonde 
438*deba1340SJacob Lalonde   size_t count = 0;
439*deba1340SJacob Lalonde   for (auto exception_stream : File.getExceptionStreams()) {
440*deba1340SJacob Lalonde     count++;
441*deba1340SJacob Lalonde     ASSERT_THAT_EXPECTED(exception_stream, Succeeded());
442*deba1340SJacob Lalonde     ASSERT_THAT(0x23u, exception_stream->ExceptionRecord.ExceptionCode);
443*deba1340SJacob Lalonde   }
444*deba1340SJacob Lalonde 
445*deba1340SJacob Lalonde   ASSERT_THAT(2u, count);
446*deba1340SJacob Lalonde }
447