1 //===- DXContainerTest.cpp - Tests for DXContainerFile --------------------===//
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/DXContainer.h"
10 #include "llvm/ADT/StringRef.h"
11 #include "llvm/BinaryFormat/Magic.h"
12 #include "llvm/ObjectYAML/DXContainerYAML.h"
13 #include "llvm/ObjectYAML/yaml2obj.h"
14 #include "llvm/Support/MemoryBufferRef.h"
15 #include "llvm/Testing/Support/Error.h"
16 #include "gtest/gtest.h"
19 using namespace llvm::object
;
21 template <std::size_t X
> MemoryBufferRef
getMemoryBuffer(uint8_t Data
[X
]) {
22 StringRef
Obj(reinterpret_cast<char *>(&Data
[0]), X
);
23 return MemoryBufferRef(Obj
, "");
26 TEST(DXCFile
, IdentifyMagic
) {
28 StringRef
Buffer("DXBC");
29 EXPECT_EQ(identify_magic(Buffer
), file_magic::dxcontainer_object
);
32 StringRef
Buffer("DXBCBlahBlahBlah");
33 EXPECT_EQ(identify_magic(Buffer
), file_magic::dxcontainer_object
);
37 TEST(DXCFile
, ParseHeaderErrors
) {
38 uint8_t Buffer
[] = {0x44, 0x58, 0x42, 0x43};
40 DXContainer::create(getMemoryBuffer
<4>(Buffer
)),
41 FailedWithMessage("Reading structure out of file bounds"));
44 TEST(DXCFile
, EmptyFile
) {
46 DXContainer::create(MemoryBufferRef(StringRef("", 0), "")),
47 FailedWithMessage("Reading structure out of file bounds"));
50 TEST(DXCFile
, ParseHeader
) {
51 uint8_t Buffer
[] = {0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
54 0x70, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
56 llvm::cantFail(DXContainer::create(getMemoryBuffer
<32>(Buffer
)));
57 EXPECT_TRUE(memcmp(C
.getHeader().Magic
, "DXBC", 4) == 0);
58 EXPECT_TRUE(memcmp(C
.getHeader().FileHash
.Digest
,
59 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0);
60 EXPECT_EQ(C
.getHeader().Version
.Major
, 1u);
61 EXPECT_EQ(C
.getHeader().Version
.Minor
, 0u);
64 TEST(DXCFile
, ParsePartMissingOffsets
) {
66 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
68 0x00, 0x00, 0x70, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
71 DXContainer::create(getMemoryBuffer
<32>(Buffer
)),
72 FailedWithMessage("Reading structure out of file bounds"));
75 TEST(DXCFile
, ParsePartInvalidOffsets
) {
76 // This test covers a case where the part offset is beyond the buffer size.
78 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
80 0x70, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
83 DXContainer::create(getMemoryBuffer
<36>(Buffer
)),
84 FailedWithMessage("Part offset points beyond boundary of the file"));
87 TEST(DXCFile
, ParsePartTooSmallBuffer
) {
88 // This test covers a case where there is insufficent space to read a full
89 // part name, but the offset for the part is inside the buffer.
90 uint8_t Buffer
[] = {0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
93 0x26, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
94 0x24, 0x00, 0x00, 0x00, 0x46, 0x4B};
96 DXContainer::create(getMemoryBuffer
<38>(Buffer
)),
97 FailedWithMessage("File not large enough to read part name"));
100 TEST(DXCFile
, ParsePartNoSize
) {
101 // This test covers a case where the part's header is readable, but the size
102 // the part extends beyond the boundaries of the file.
103 uint8_t Buffer
[] = {0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00,
104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x0D, 0x00,
106 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
107 0x46, 0x4B, 0x45, 0x30, 0x00, 0x00};
108 EXPECT_THAT_EXPECTED(
109 DXContainer::create(getMemoryBuffer
<42>(Buffer
)),
110 FailedWithMessage("Reading part size out of file bounds"));
113 TEST(DXCFile
, ParseOverlappingParts
) {
114 // This test covers a case where a part's offset is inside the size range
115 // covered by the previous part.
117 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
119 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
120 0x2C, 0x00, 0x00, 0x00, 0x46, 0x4B, 0x45, 0x30, 0x08, 0x00, 0x00, 0x00,
121 0x46, 0x4B, 0x45, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123 EXPECT_THAT_EXPECTED(
124 DXContainer::create(getMemoryBuffer
<60>(Buffer
)),
126 "Part offset for part 1 begins before the previous part ends"));
129 TEST(DXCFile
, ParseEmptyParts
) {
131 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
133 0x70, 0x0D, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00,
134 0x44, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
135 0x5C, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00,
136 0x46, 0x4B, 0x45, 0x30, 0x00, 0x00, 0x00, 0x00, 0x46, 0x4B, 0x45, 0x31,
137 0x00, 0x00, 0x00, 0x00, 0x46, 0x4B, 0x45, 0x32, 0x00, 0x00, 0x00, 0x00,
138 0x46, 0x4B, 0x45, 0x33, 0x00, 0x00, 0x00, 0x00, 0x46, 0x4B, 0x45, 0x34,
139 0x00, 0x00, 0x00, 0x00, 0x46, 0x4B, 0x45, 0x35, 0x00, 0x00, 0x00, 0x00,
140 0x46, 0x4B, 0x45, 0x36, 0x00, 0x00, 0x00, 0x00,
143 llvm::cantFail(DXContainer::create(getMemoryBuffer
<116>(Buffer
)));
144 EXPECT_EQ(C
.getHeader().PartCount
, 7u);
146 // All the part sizes are 0, which makes a nice test of the range based for
147 int ElementsVisited
= 0;
148 for (auto Part
: C
) {
149 EXPECT_EQ(Part
.Part
.Size
, 0u);
150 EXPECT_EQ(Part
.Data
.size(), 0u);
153 EXPECT_EQ(ElementsVisited
, 7);
156 // These are all intended to be fake part names so that the parser doesn't
157 // try to parse the part data.
159 EXPECT_TRUE(memcmp(It
->Part
.Name
, "FKE0", 4) == 0);
161 EXPECT_TRUE(memcmp(It
->Part
.Name
, "FKE1", 4) == 0);
163 EXPECT_TRUE(memcmp(It
->Part
.Name
, "FKE2", 4) == 0);
165 EXPECT_TRUE(memcmp(It
->Part
.Name
, "FKE3", 4) == 0);
167 EXPECT_TRUE(memcmp(It
->Part
.Name
, "FKE4", 4) == 0);
169 EXPECT_TRUE(memcmp(It
->Part
.Name
, "FKE5", 4) == 0);
171 EXPECT_TRUE(memcmp(It
->Part
.Name
, "FKE6", 4) == 0);
172 ++It
; // Don't increment past the end
173 EXPECT_TRUE(memcmp(It
->Part
.Name
, "FKE6", 4) == 0);
177 static Expected
<DXContainer
>
178 generateDXContainer(StringRef Yaml
, SmallVectorImpl
<char> &BinaryData
) {
179 DXContainerYAML::Object Obj
;
180 SMDiagnostic GenerateDiag
;
182 Yaml
, /*Ctxt=*/nullptr,
183 [](const SMDiagnostic
&Diag
, void *DiagContext
) {
184 *static_cast<SMDiagnostic
*>(DiagContext
) = Diag
;
190 return createStringError(YIn
.error(), GenerateDiag
.getMessage());
192 raw_svector_ostream
OS(BinaryData
);
193 std::string ErrorMsg
;
194 if (!yaml::yaml2dxcontainer(
195 Obj
, OS
, [&ErrorMsg
](const Twine
&Msg
) { ErrorMsg
= Msg
.str(); }))
196 return createStringError(YIn
.error(), ErrorMsg
);
198 MemoryBufferRef BinaryDataRef
= MemoryBufferRef(OS
.str(), "");
200 return DXContainer::create(BinaryDataRef
);
203 TEST(DXCFile
, PSVResourceIterators
) {
204 const char *Yaml
= R
"(
207 Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
208 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
219 PayloadSizeInBytes: 4092
220 MinimumWaveLaneCount: 0
221 MaximumWaveLaneCount: 4294967295
249 SmallVector
<char, 256> BinaryData
;
250 auto C
= generateDXContainer(Yaml
, BinaryData
);
252 ASSERT_THAT_EXPECTED(C
, Succeeded());
254 const auto &PSVInfo
= C
->getPSVInfo();
255 ASSERT_TRUE(PSVInfo
.has_value());
257 EXPECT_EQ(PSVInfo
->getResourceCount(), 3u);
259 auto It
= PSVInfo
->getResources().begin();
261 EXPECT_TRUE(It
== PSVInfo
->getResources().begin());
263 dxbc::PSV::v2::ResourceBindInfo Binding
;
266 EXPECT_EQ(Binding
.Type
, 1u);
267 EXPECT_EQ(Binding
.Flags
, 0u);
272 EXPECT_EQ(Binding
.Type
, 2u);
273 EXPECT_EQ(Binding
.Flags
, 0u);
278 EXPECT_TRUE(It
== PSVInfo
->getResources().begin());
280 EXPECT_EQ(Binding
.Type
, 1u);
281 EXPECT_EQ(Binding
.Flags
, 0u);
286 EXPECT_EQ(Binding
.Type
, 1u);
287 EXPECT_EQ(Binding
.Flags
, 0u);
292 EXPECT_EQ(Binding
.Type
, 2u);
293 EXPECT_EQ(Binding
.Flags
, 0u);
298 EXPECT_EQ(Binding
.Type
, 3u);
299 EXPECT_EQ(Binding
.Flags
, 0u);
301 EXPECT_FALSE(It
== PSVInfo
->getResources().end());
306 EXPECT_TRUE(It
== PSVInfo
->getResources().end());
307 EXPECT_FALSE(It
!= PSVInfo
->getResources().end());
309 EXPECT_EQ(Binding
.Type
, 0u);
310 EXPECT_EQ(Binding
.Flags
, 0u);
316 EXPECT_TRUE(Old
== PSVInfo
->getResources().end());
317 EXPECT_FALSE(Old
!= PSVInfo
->getResources().end());
319 EXPECT_EQ(Binding
.Type
, 0u);
320 EXPECT_EQ(Binding
.Flags
, 0u);
325 EXPECT_TRUE(It
== PSVInfo
->getResources().end());
327 EXPECT_EQ(Binding
.Type
, 0u);
328 EXPECT_EQ(Binding
.Flags
, 0u);
333 EXPECT_TRUE(Old
== PSVInfo
->getResources().end());
335 EXPECT_EQ(Binding
.Type
, 0u);
336 EXPECT_EQ(Binding
.Flags
, 0u);
341 EXPECT_EQ(Binding
.Type
, 3u);
342 EXPECT_EQ(Binding
.Flags
, 0u);
345 // The malicious file bits in these tests are mutations of the binary produced
346 // by the following YAML:
350 // Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
351 // 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
364 // DXILMajorVersion: 0
365 // DXILMinorVersion: 1
372 // MinimumWaveLaneCount: 0
373 // MaximumWaveLaneCount: 0
374 // ResourceStride: 16
380 TEST(DXCFile
, MaliciousFiles
) {
382 // In this file blob, the file size is specified as 96 bytes (0x60), and the
383 // PSV0 data is specified as 24 bytes (0x18) which extends beyond the size of
387 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
389 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
390 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00,
391 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,
392 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
393 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
396 EXPECT_THAT_EXPECTED(
397 DXContainer::create(getMemoryBuffer
<96>(Buffer
)),
399 "Pipeline state data extends beyond the bounds of the part"));
402 // PSV extends beyond part, but in file range. In this blob the file size is
403 // 144 bytes (0x90), and the PSV part is 36 bytes (0x24), and the PSV data is
407 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
408 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
409 0x90, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00,
410 0x4C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,
411 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00,
412 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
413 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00,
414 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
417 0x42, 0x4C, 0x45, 0x48, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
418 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420 EXPECT_THAT_EXPECTED(
421 DXContainer::create(getMemoryBuffer
<144>(Buffer
)),
423 "Pipeline state data extends beyond the bounds of the part"));
426 // In this file blob, the file is 116 bytes (0x74). The file structure is
427 // valid except that it specifies 1 16 byte resource binding which would
428 // extend beyond the range of the part and file.
431 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
433 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
434 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00,
435 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,
436 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
437 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
442 EXPECT_THAT_EXPECTED(
443 DXContainer::create(getMemoryBuffer
<116>(Buffer
)),
445 "Resource binding data extends beyond the bounds of the part"));
448 // In this file blob, the file is 116 bytes (0x74). The file structure is
449 // valid except that it specifies 1 16 byte resource binding which would
450 // extend beyond the range of the part and into the `BLEH` part.
453 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
455 0x90, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00,
456 0x4C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C,
457 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00,
458 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
459 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x24, 0x00, 0x00, 0x00,
460 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
462 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
463 0x42, 0x4C, 0x45, 0x48, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466 EXPECT_THAT_EXPECTED(
467 DXContainer::create(getMemoryBuffer
<144>(Buffer
)),
469 "Resource binding data extends beyond the bounds of the part"));
473 // This test verifies that the resource iterator follows the stride even if the
474 // stride doesn't match an expected or known value. In this test, the resource
475 // data is structured validly, with 32 bytes per resource. This test is based on
476 // editing the binary output constructed from this yaml.
480 // Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
481 // 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
494 // DXILMajorVersion: 0
495 // DXILMinorVersion: 1
502 // MinimumWaveLaneCount: 0
503 // MaximumWaveLaneCount: 0
504 // ResourceStride: 16
515 TEST(DXCFile
, PSVResourceIteratorsStride
) {
517 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
519 0x28, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x18, 0x00, 0x00, 0x00,
520 0x60, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4C, 0x00, 0x01, 0x00, 0x00,
521 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x64, 0x00, 0x00, 0x00,
522 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
524 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
525 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
527 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528 0x00, 0x00, 0x00, 0x00,
531 llvm::cantFail(DXContainer::create(getMemoryBuffer
<180>(Buffer
)));
533 const auto &PSVInfo
= C
.getPSVInfo();
534 ASSERT_TRUE(PSVInfo
.has_value());
536 ASSERT_EQ(PSVInfo
->getResourceCount(), 2u);
538 auto It
= PSVInfo
->getResources().begin();
540 EXPECT_TRUE(It
== PSVInfo
->getResources().begin());
542 dxbc::PSV::v2::ResourceBindInfo Binding
;
545 EXPECT_EQ(Binding
.Type
, 1u);
546 EXPECT_EQ(Binding
.Space
, 2u);
547 EXPECT_EQ(Binding
.LowerBound
, 3u);
548 EXPECT_EQ(Binding
.UpperBound
, 4u);
553 EXPECT_EQ(Binding
.Type
, 5u);
554 EXPECT_EQ(Binding
.Space
, 6u);
555 EXPECT_EQ(Binding
.LowerBound
, 7u);
556 EXPECT_EQ(Binding
.UpperBound
, 8u);
561 EXPECT_TRUE(It
== PSVInfo
->getResources().begin());
563 EXPECT_EQ(Binding
.Type
, 1u);
564 EXPECT_EQ(Binding
.Space
, 2u);
565 EXPECT_EQ(Binding
.LowerBound
, 3u);
566 EXPECT_EQ(Binding
.UpperBound
, 4u);
571 EXPECT_EQ(Binding
.Type
, 1u);
572 EXPECT_EQ(Binding
.Space
, 2u);
573 EXPECT_EQ(Binding
.LowerBound
, 3u);
574 EXPECT_EQ(Binding
.UpperBound
, 4u);
579 EXPECT_EQ(Binding
.Type
, 5u);
580 EXPECT_EQ(Binding
.Space
, 6u);
581 EXPECT_EQ(Binding
.LowerBound
, 7u);
582 EXPECT_EQ(Binding
.UpperBound
, 8u);;
585 EXPECT_FALSE(It
== PSVInfo
->getResources().end());
590 EXPECT_TRUE(It
== PSVInfo
->getResources().end());
591 EXPECT_FALSE(It
!= PSVInfo
->getResources().end());
593 EXPECT_EQ(Binding
.Type
, 0u);
594 EXPECT_EQ(Binding
.Flags
, 0u);
597 // This test binary is created using mutations of the yaml in the SigElements
598 // test found under test/ObjectYAML/DXContainer/SigElements.yaml.
600 TEST(DXCFile
, MisalignedStringTable
) {
602 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
604 0xb4, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
605 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x18, 0x00, 0x00, 0x00,
606 0x60, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c,
607 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608 0x50, 0x53, 0x56, 0x30, 0x68, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
611 0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x10, 0x20, 0x40,
612 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
616 EXPECT_THAT_EXPECTED(DXContainer::create(getMemoryBuffer
<168>(Buffer
)),
617 FailedWithMessage("String table misaligned"));
620 // This test binary is created using mutations of the yaml in the SigElements
621 // test found under test/ObjectYAML/DXContainer/SigElements.yaml.
622 TEST(DXCFile
, SigElementsExtendBeyondPart
) {
624 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
626 0xb4, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
627 0x48, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x18, 0x00, 0x00, 0x00,
628 0x60, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c,
629 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 0x50, 0x53, 0x56, 0x30, 0x54, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
633 0x05, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0x08, 0x10, 0x20, 0x40,
634 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x49, 0x4e, 0x00,
635 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
636 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x02, 0x00, 0x42, 0x00, 0x02, 0x00, 0x03, 0x00};
638 EXPECT_THAT_EXPECTED(
639 DXContainer::create(getMemoryBuffer
<164>(Buffer
)),
641 "Signature elements extend beyond the size of the part"));
644 TEST(DXCFile
, MalformedSignature
) {
646 The tests here exercise the DXContainer Signature section parser. These tests
647 are based on modifying the binary described by the following yaml:
651 Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
652 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
667 SystemValue: Undefined
672 MinPrecision: Default
675 The unmodified hex sequence is:
678 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80,
680 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
681 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08,
684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
685 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
686 0x00, 0x07, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00,
687 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
694 // This binary says the signature has 10 parameters, but the part data is
695 // only big enough for 1.
697 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
699 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
702 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00,
703 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
704 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00,
706 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00,
707 0x00, 0x00, 0x00, 0x00};
708 EXPECT_THAT_EXPECTED(
709 DXContainer::create(getMemoryBuffer
<164>(Buffer
)),
711 "Signature parameters extend beyond the part boundary"));
716 // This binary only has one parameter, but the start offset is beyond the
719 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
721 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
723 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
724 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00,
725 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
726 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
727 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00,
728 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00,
729 0x00, 0x00, 0x00, 0x00};
730 EXPECT_THAT_EXPECTED(
731 DXContainer::create(getMemoryBuffer
<164>(Buffer
)),
733 "Signature parameters extend beyond the part boundary"));
738 // This parameter has a name offset of 3, which is before the start of the
741 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
743 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
744 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
745 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
746 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00,
747 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
748 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
749 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00,
750 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00,
751 0x00, 0x00, 0x00, 0x00};
752 EXPECT_THAT_EXPECTED(
753 DXContainer::create(getMemoryBuffer
<164>(Buffer
)),
754 FailedWithMessage("Invalid parameter name offset: name starts before "
755 "the first name offset"));
759 // This parameter has a name offset of 255, which is after the end of the
762 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
763 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
764 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
765 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
767 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00,
768 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00,
771 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00,
772 0x00, 0x00, 0x00, 0x00};
773 EXPECT_THAT_EXPECTED(
774 DXContainer::create(getMemoryBuffer
<164>(Buffer
)),
775 FailedWithMessage("Invalid parameter name offset: name starts after "
776 "the end of the part data"));