1 //===- MinidumpYAMLTest.cpp - Tests for Minidump<->YAML code --------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Object/Minidump.h"
10 #include "llvm/ObjectYAML/yaml2obj.h"
11 #include "llvm/Support/YAMLTraits.h"
12 #include "llvm/Testing/Support/Error.h"
13 #include "gtest/gtest.h"
16 using namespace llvm::minidump
;
18 static Expected
<std::unique_ptr
<object::MinidumpFile
>>
19 toBinary(SmallVectorImpl
<char> &Storage
, StringRef Yaml
) {
21 raw_svector_ostream
OS(Storage
);
22 yaml::Input
YIn(Yaml
);
23 if (!yaml::convertYAML(YIn
, OS
, [](const Twine
&Msg
) {}))
24 return createStringError(std::errc::invalid_argument
,
25 "unable to convert YAML");
27 return object::MinidumpFile::create(MemoryBufferRef(OS
.str(), "Binary"));
30 TEST(MinidumpYAML
, Basic
) {
31 SmallString
<0> Storage
;
32 auto ExpectedFile
= toBinary(Storage
, R
"(
42 400d9000-400db000 r-xp 00000000 b3:04 227 /system/bin/app_process
43 400db000-400dc000 r--p 00001000 b3:04 227 /system/bin/app_process
46 Content: DEADBEEFBAADF00D)");
47 ASSERT_THAT_EXPECTED(ExpectedFile
, Succeeded());
48 object::MinidumpFile
&File
= **ExpectedFile
;
50 ASSERT_EQ(3u, File
.streams().size());
52 EXPECT_EQ(StreamType::SystemInfo
, File
.streams()[0].Type
);
53 auto ExpectedSysInfo
= File
.getSystemInfo();
54 ASSERT_THAT_EXPECTED(ExpectedSysInfo
, Succeeded());
55 const SystemInfo
&SysInfo
= *ExpectedSysInfo
;
56 EXPECT_EQ(ProcessorArchitecture::ARM64
, SysInfo
.ProcessorArch
);
57 EXPECT_EQ(OSPlatform::Linux
, SysInfo
.PlatformId
);
58 EXPECT_EQ(0x05060708u
, SysInfo
.CPU
.Arm
.CPUID
);
60 EXPECT_EQ(StreamType::LinuxMaps
, File
.streams()[1].Type
);
61 EXPECT_EQ("400d9000-400db000 r-xp 00000000 b3:04 227 "
62 "/system/bin/app_process\n"
63 "400db000-400dc000 r--p 00001000 b3:04 227 "
64 "/system/bin/app_process\n",
65 toStringRef(*File
.getRawStream(StreamType::LinuxMaps
)));
67 EXPECT_EQ(StreamType::LinuxAuxv
, File
.streams()[2].Type
);
68 EXPECT_EQ((ArrayRef
<uint8_t>{0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 0xF0, 0x0D}),
69 File
.getRawStream(StreamType::LinuxAuxv
));
72 TEST(MinidumpYAML
, RawContent
) {
73 SmallString
<0> Storage
;
74 auto ExpectedFile
= toBinary(Storage
, R
"(
79 Content: DEADBEEFBAADF00D)");
80 ASSERT_THAT_EXPECTED(ExpectedFile
, Succeeded());
81 object::MinidumpFile
&File
= **ExpectedFile
;
84 (ArrayRef
<uint8_t>{0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 0xF0, 0x0D, 0x00}),
85 File
.getRawStream(StreamType::LinuxAuxv
));
88 TEST(MinidumpYAML
, X86SystemInfo
) {
89 SmallString
<0> Storage
;
90 auto ExpectedFile
= toBinary(Storage
, R
"(
97 Vendor ID: LLVMLLVMLLVM
98 Version Info: 0x01020304
99 Feature Info: 0x05060708
100 AMD Extended Features: 0x09000102)");
101 ASSERT_THAT_EXPECTED(ExpectedFile
, Succeeded());
102 object::MinidumpFile
&File
= **ExpectedFile
;
104 ASSERT_EQ(1u, File
.streams().size());
106 auto ExpectedSysInfo
= File
.getSystemInfo();
107 ASSERT_THAT_EXPECTED(ExpectedSysInfo
, Succeeded());
108 const SystemInfo
&SysInfo
= *ExpectedSysInfo
;
109 EXPECT_EQ(ProcessorArchitecture::X86
, SysInfo
.ProcessorArch
);
110 EXPECT_EQ(OSPlatform::Linux
, SysInfo
.PlatformId
);
111 EXPECT_EQ("LLVMLLVMLLVM", StringRef(SysInfo
.CPU
.X86
.VendorID
,
112 sizeof(SysInfo
.CPU
.X86
.VendorID
)));
113 EXPECT_EQ(0x01020304u
, SysInfo
.CPU
.X86
.VersionInfo
);
114 EXPECT_EQ(0x05060708u
, SysInfo
.CPU
.X86
.FeatureInfo
);
115 EXPECT_EQ(0x09000102u
, SysInfo
.CPU
.X86
.AMDExtendedFeatures
);
118 TEST(MinidumpYAML
, OtherSystemInfo
) {
119 SmallString
<0> Storage
;
120 auto ExpectedFile
= toBinary(Storage
, R
"(
127 Features: 000102030405060708090a0b0c0d0e0f)");
128 ASSERT_THAT_EXPECTED(ExpectedFile
, Succeeded());
129 object::MinidumpFile
&File
= **ExpectedFile
;
131 ASSERT_EQ(1u, File
.streams().size());
133 auto ExpectedSysInfo
= File
.getSystemInfo();
134 ASSERT_THAT_EXPECTED(ExpectedSysInfo
, Succeeded());
135 const SystemInfo
&SysInfo
= *ExpectedSysInfo
;
136 EXPECT_EQ(ProcessorArchitecture::PPC
, SysInfo
.ProcessorArch
);
137 EXPECT_EQ(OSPlatform::Linux
, SysInfo
.PlatformId
);
139 (ArrayRef
<uint8_t>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}),
140 makeArrayRef(SysInfo
.CPU
.Other
.ProcessorFeatures
));
143 // Test that we can parse a normal-looking ExceptionStream.
144 TEST(MinidumpYAML
, ExceptionStream
) {
145 SmallString
<0> Storage
;
146 auto ExpectedFile
= toBinary(Storage
, R
"(
154 Exception Record: 0x0102030405060708
155 Exception Address: 0x0a0b0c0d0e0f1011
156 Number of Parameters: 2
159 Thread Context: 3DeadBeefDefacedABadCafe)");
160 ASSERT_THAT_EXPECTED(ExpectedFile
, Succeeded());
161 object::MinidumpFile
&File
= **ExpectedFile
;
163 ASSERT_EQ(1u, File
.streams().size());
165 Expected
<const minidump::ExceptionStream
&> ExpectedStream
=
166 File
.getExceptionStream();
168 ASSERT_THAT_EXPECTED(ExpectedStream
, Succeeded());
170 const minidump::ExceptionStream
&Stream
= *ExpectedStream
;
171 EXPECT_EQ(0x7u
, Stream
.ThreadId
);
172 const minidump::Exception
&Exception
= Stream
.ExceptionRecord
;
173 EXPECT_EQ(0x23u
, Exception
.ExceptionCode
);
174 EXPECT_EQ(0x5u
, Exception
.ExceptionFlags
);
175 EXPECT_EQ(0x0102030405060708u
, Exception
.ExceptionRecord
);
176 EXPECT_EQ(0x0a0b0c0d0e0f1011u
, Exception
.ExceptionAddress
);
177 EXPECT_EQ(2u, Exception
.NumberParameters
);
178 EXPECT_EQ(0x22u
, Exception
.ExceptionInformation
[0]);
179 EXPECT_EQ(0x24u
, Exception
.ExceptionInformation
[1]);
181 Expected
<ArrayRef
<uint8_t>> ExpectedContext
=
182 File
.getRawData(Stream
.ThreadContext
);
183 ASSERT_THAT_EXPECTED(ExpectedContext
, Succeeded());
184 EXPECT_EQ((ArrayRef
<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed,
185 0xab, 0xad, 0xca, 0xfe}),
189 // Test that we can parse an exception stream with no ExceptionInformation.
190 TEST(MinidumpYAML
, ExceptionStream_NoParameters
) {
191 SmallString
<0> Storage
;
192 auto ExpectedFile
= toBinary(Storage
, R
"(
200 Exception Record: 0x0102030405060708
201 Exception Address: 0x0a0b0c0d0e0f1011
202 Thread Context: 3DeadBeefDefacedABadCafe)");
203 ASSERT_THAT_EXPECTED(ExpectedFile
, Succeeded());
204 object::MinidumpFile
&File
= **ExpectedFile
;
206 ASSERT_EQ(1u, File
.streams().size());
208 Expected
<const minidump::ExceptionStream
&> ExpectedStream
=
209 File
.getExceptionStream();
211 ASSERT_THAT_EXPECTED(ExpectedStream
, Succeeded());
213 const minidump::ExceptionStream
&Stream
= *ExpectedStream
;
214 EXPECT_EQ(0x7u
, Stream
.ThreadId
);
215 const minidump::Exception
&Exception
= Stream
.ExceptionRecord
;
216 EXPECT_EQ(0x23u
, Exception
.ExceptionCode
);
217 EXPECT_EQ(0x5u
, Exception
.ExceptionFlags
);
218 EXPECT_EQ(0x0102030405060708u
, Exception
.ExceptionRecord
);
219 EXPECT_EQ(0x0a0b0c0d0e0f1011u
, Exception
.ExceptionAddress
);
220 EXPECT_EQ(0u, Exception
.NumberParameters
);
222 Expected
<ArrayRef
<uint8_t>> ExpectedContext
=
223 File
.getRawData(Stream
.ThreadContext
);
224 ASSERT_THAT_EXPECTED(ExpectedContext
, Succeeded());
225 EXPECT_EQ((ArrayRef
<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed,
226 0xab, 0xad, 0xca, 0xfe}),
230 // Test that we can parse an ExceptionStream where the stated number of
231 // parameters is greater than the actual size of the ExceptionInformation
233 TEST(MinidumpYAML
, ExceptionStream_TooManyParameters
) {
234 SmallString
<0> Storage
;
235 auto ExpectedFile
= toBinary(Storage
, R
"(
242 Number of Parameters: 16
258 Thread Context: 3DeadBeefDefacedABadCafe)");
259 ASSERT_THAT_EXPECTED(ExpectedFile
, Succeeded());
260 object::MinidumpFile
&File
= **ExpectedFile
;
262 ASSERT_EQ(1u, File
.streams().size());
264 Expected
<const minidump::ExceptionStream
&> ExpectedStream
=
265 File
.getExceptionStream();
267 ASSERT_THAT_EXPECTED(ExpectedStream
, Succeeded());
269 const minidump::ExceptionStream
&Stream
= *ExpectedStream
;
270 EXPECT_EQ(0x8u
, Stream
.ThreadId
);
271 const minidump::Exception
&Exception
= Stream
.ExceptionRecord
;
272 EXPECT_EQ(0x0u
, Exception
.ExceptionCode
);
273 EXPECT_EQ(0x0u
, Exception
.ExceptionFlags
);
274 EXPECT_EQ(0x00u
, Exception
.ExceptionRecord
);
275 EXPECT_EQ(0x0u
, Exception
.ExceptionAddress
);
276 EXPECT_EQ(16u, Exception
.NumberParameters
);
277 EXPECT_EQ(0x0u
, Exception
.ExceptionInformation
[0]);
278 for (int Index
= 1; Index
< 15; ++Index
) {
279 EXPECT_EQ(0x110u
- Index
* 0x11, Exception
.ExceptionInformation
[Index
]);
282 Expected
<ArrayRef
<uint8_t>> ExpectedContext
=
283 File
.getRawData(Stream
.ThreadContext
);
284 ASSERT_THAT_EXPECTED(ExpectedContext
, Succeeded());
285 EXPECT_EQ((ArrayRef
<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed,
286 0xab, 0xad, 0xca, 0xfe}),
290 // Test that we can parse an ExceptionStream where the number of
291 // ExceptionInformation parameters provided is greater than the
292 // specified Number of Parameters.
293 TEST(MinidumpYAML
, ExceptionStream_ExtraParameter
) {
294 SmallString
<0> Storage
;
295 auto ExpectedFile
= toBinary(Storage
, R
"(
303 Exception Record: 0x0102030405060708
304 Exception Address: 0x0a0b0c0d0e0f1011
305 Number of Parameters: 2
309 Thread Context: 3DeadBeefDefacedABadCafe)");
310 ASSERT_THAT_EXPECTED(ExpectedFile
, Succeeded());
311 object::MinidumpFile
&File
= **ExpectedFile
;
313 ASSERT_EQ(1u, File
.streams().size());
315 Expected
<const minidump::ExceptionStream
&> ExpectedStream
=
316 File
.getExceptionStream();
318 ASSERT_THAT_EXPECTED(ExpectedStream
, Succeeded());
320 const minidump::ExceptionStream
&Stream
= *ExpectedStream
;
321 EXPECT_EQ(0x7u
, Stream
.ThreadId
);
322 const minidump::Exception
&Exception
= Stream
.ExceptionRecord
;
323 EXPECT_EQ(0x23u
, Exception
.ExceptionCode
);
324 EXPECT_EQ(0x5u
, Exception
.ExceptionFlags
);
325 EXPECT_EQ(0x0102030405060708u
, Exception
.ExceptionRecord
);
326 EXPECT_EQ(0x0a0b0c0d0e0f1011u
, Exception
.ExceptionAddress
);
327 EXPECT_EQ(2u, Exception
.NumberParameters
);
328 EXPECT_EQ(0x99u
, Exception
.ExceptionInformation
[0]);
329 EXPECT_EQ(0x23u
, Exception
.ExceptionInformation
[1]);
330 EXPECT_EQ(0x42u
, Exception
.ExceptionInformation
[2]);
332 Expected
<ArrayRef
<uint8_t>> ExpectedContext
=
333 File
.getRawData(Stream
.ThreadContext
);
334 ASSERT_THAT_EXPECTED(ExpectedContext
, Succeeded());
335 EXPECT_EQ((ArrayRef
<uint8_t>{0x3d, 0xea, 0xdb, 0xee, 0xfd, 0xef, 0xac, 0xed,
336 0xab, 0xad, 0xca, 0xfe}),