Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 9f87522

Browse files
authoredOct 5, 2023
[DX] Add support for program signatures (#67346)
For DirectX, program signatures are encoded into three different binary sections depending on if the signature is for inputs, outputs, or patches. All three signature types use the same data structure encoding so they can share a lot of logic. This patch adds support for reading and writing program signature data as both yaml and binary data. Fixes #57743 and #57744
1 parent 7e28234 commit 9f87522

File tree

13 files changed

+859
-65
lines changed

13 files changed

+859
-65
lines changed
 

‎llvm/include/llvm/BinaryFormat/DXContainer.h

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,74 @@ struct ResourceBindInfo : public v0::ResourceBindInfo {
426426
} // namespace v2
427427
} // namespace PSV
428428

429+
#define COMPONENT_PRECISION(Val, Enum) Enum = Val,
430+
enum class SigMinPrecision : uint32_t {
431+
#include "DXContainerConstants.def"
432+
};
433+
434+
ArrayRef<EnumEntry<SigMinPrecision>> getSigMinPrecisions();
435+
436+
#define D3D_SYSTEM_VALUE(Val, Enum) Enum = Val,
437+
enum class D3DSystemValue : uint32_t {
438+
#include "DXContainerConstants.def"
439+
};
440+
441+
ArrayRef<EnumEntry<D3DSystemValue>> getD3DSystemValues();
442+
443+
#define COMPONENT_TYPE(Val, Enum) Enum = Val,
444+
enum class SigComponentType : uint32_t {
445+
#include "DXContainerConstants.def"
446+
};
447+
448+
ArrayRef<EnumEntry<SigComponentType>> getSigComponentTypes();
449+
450+
struct ProgramSignatureHeader {
451+
uint32_t ParamCount;
452+
uint32_t FirstParamOffset;
453+
454+
void swapBytes() {
455+
sys::swapByteOrder(ParamCount);
456+
sys::swapByteOrder(ParamCount);
457+
}
458+
};
459+
460+
struct ProgramSignatureElement {
461+
uint32_t Stream; // Stream index (parameters must appear in non-decreasing
462+
// stream order)
463+
uint32_t NameOffset; // Offset from the start of the ProgramSignatureHeader to
464+
// the start of the null terminated string for the name.
465+
uint32_t Index; // Semantic Index
466+
D3DSystemValue SystemValue; // Semantic type. Similar to PSV::SemanticKind.
467+
SigComponentType CompType; // Type of bits.
468+
uint32_t Register; // Register Index (row index)
469+
uint8_t Mask; // Mask (column allocation)
470+
471+
// The ExclusiveMask has a different meaning for input and output signatures.
472+
// For an output signature, masked components of the output register are never
473+
// written to.
474+
// For an input signature, masked components of the input register are always
475+
// read.
476+
uint8_t ExclusiveMask;
477+
478+
uint16_t Unused;
479+
SigMinPrecision MinPrecision; // Minimum precision of input/output data
480+
481+
void swapBytes() {
482+
sys::swapByteOrder(Stream);
483+
sys::swapByteOrder(NameOffset);
484+
sys::swapByteOrder(Index);
485+
sys::swapByteOrder(SystemValue);
486+
sys::swapByteOrder(CompType);
487+
sys::swapByteOrder(Register);
488+
sys::swapByteOrder(Mask);
489+
sys::swapByteOrder(ExclusiveMask);
490+
sys::swapByteOrder(MinPrecision);
491+
}
492+
};
493+
494+
static_assert(sizeof(ProgramSignatureElement) == 32,
495+
"ProgramSignatureElement is misaligned");
496+
429497
} // namespace dxbc
430498
} // namespace llvm
431499

‎llvm/include/llvm/BinaryFormat/DXContainerConstants.def

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ CONTAINER_PART(DXIL)
44
CONTAINER_PART(SFI0)
55
CONTAINER_PART(HASH)
66
CONTAINER_PART(PSV0)
7+
CONTAINER_PART(ISG1)
8+
CONTAINER_PART(OSG1)
9+
CONTAINER_PART(PSG1)
710

811
#undef CONTAINER_PART
912
#endif
@@ -101,6 +104,20 @@ COMPONENT_TYPE(9, Float64)
101104
#undef COMPONENT_TYPE
102105
#endif
103106

107+
#ifdef COMPONENT_PRECISION
108+
109+
COMPONENT_PRECISION(0, Default)
110+
COMPONENT_PRECISION(1, Float16)
111+
COMPONENT_PRECISION(2, Float2_8)
112+
COMPONENT_PRECISION(3, Reserved)
113+
COMPONENT_PRECISION(4, SInt16)
114+
COMPONENT_PRECISION(5, UInt16)
115+
COMPONENT_PRECISION(0xf0, Any16)
116+
COMPONENT_PRECISION(0xf1, Any10)
117+
118+
#undef COMPONENT_PRECISION
119+
#endif
120+
104121
#ifdef INTERPOLATION_MODE
105122

106123
INTERPOLATION_MODE(0, Undefined)
@@ -115,3 +132,37 @@ INTERPOLATION_MODE(8, Invalid)
115132

116133
#undef INTERPOLATION_MODE
117134
#endif
135+
136+
#ifdef D3D_SYSTEM_VALUE
137+
138+
D3D_SYSTEM_VALUE(0, Undefined)
139+
D3D_SYSTEM_VALUE(1, Position)
140+
D3D_SYSTEM_VALUE(2, ClipDistance)
141+
D3D_SYSTEM_VALUE(3, CullDistance)
142+
D3D_SYSTEM_VALUE(4, RenderTargetArrayIndex)
143+
D3D_SYSTEM_VALUE(5, ViewPortArrayIndex)
144+
D3D_SYSTEM_VALUE(6, VertexID)
145+
D3D_SYSTEM_VALUE(7, PrimitiveID)
146+
D3D_SYSTEM_VALUE(8, InstanceID)
147+
D3D_SYSTEM_VALUE(9, IsFrontFace)
148+
D3D_SYSTEM_VALUE(10, SampleIndex)
149+
D3D_SYSTEM_VALUE(11, FinalQuadEdgeTessfactor)
150+
D3D_SYSTEM_VALUE(12, FinalQuadInsideTessfactor)
151+
D3D_SYSTEM_VALUE(13, FinalTriEdgeTessfactor)
152+
D3D_SYSTEM_VALUE(14, FinalTriInsideTessfactor)
153+
D3D_SYSTEM_VALUE(15, FinalLineDetailTessfactor)
154+
D3D_SYSTEM_VALUE(16, FinalLineDensityTessfactor)
155+
D3D_SYSTEM_VALUE(23, Barycentrics)
156+
D3D_SYSTEM_VALUE(24, ShadingRate)
157+
D3D_SYSTEM_VALUE(25, CullPrimitive)
158+
D3D_SYSTEM_VALUE(64, Target)
159+
D3D_SYSTEM_VALUE(65, Depth)
160+
D3D_SYSTEM_VALUE(66, Coverage)
161+
D3D_SYSTEM_VALUE(67, DepthGE)
162+
D3D_SYSTEM_VALUE(68, DepthLE)
163+
D3D_SYSTEM_VALUE(69, StencilRef)
164+
D3D_SYSTEM_VALUE(70, InnerCoverage)
165+
166+
#undef D3D_SYSTEM_VALUE
167+
168+
#endif

‎llvm/include/llvm/MC/DXContainerPSVInfo.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,34 @@ struct PSVRuntimeInfo {
8686
}
8787
};
8888

89+
class Signature {
90+
struct Parameter {
91+
uint32_t Stream;
92+
StringRef Name;
93+
uint32_t Index;
94+
dxbc::D3DSystemValue SystemValue;
95+
dxbc::SigComponentType CompType;
96+
uint32_t Register;
97+
uint8_t Mask;
98+
uint8_t ExclusiveMask;
99+
dxbc::SigMinPrecision MinPrecision;
100+
};
101+
102+
SmallVector<Parameter> Params;
103+
104+
public:
105+
void addParam(uint32_t Stream, StringRef Name, uint32_t Index,
106+
dxbc::D3DSystemValue SystemValue,
107+
dxbc::SigComponentType CompType, uint32_t Register,
108+
uint8_t Mask, uint8_t ExclusiveMask,
109+
dxbc::SigMinPrecision MinPrecision) {
110+
Params.push_back(Parameter{Stream, Name, Index, SystemValue, CompType,
111+
Register, Mask, ExclusiveMask, MinPrecision});
112+
}
113+
114+
void write(raw_ostream &OS);
115+
};
116+
89117
} // namespace mcdxbc
90118
} // namespace llvm
91119

‎llvm/include/llvm/Object/DXContainer.h

Lines changed: 108 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
namespace llvm {
2828
namespace object {
2929

30-
namespace DirectX {
31-
3230
namespace detail {
3331
template <typename T>
3432
std::enable_if_t<std::is_arithmetic<T>::value, void> swapBytes(T &value) {
@@ -40,82 +38,85 @@ std::enable_if_t<std::is_class<T>::value, void> swapBytes(T &value) {
4038
value.swapBytes();
4139
}
4240
} // namespace detail
43-
class PSVRuntimeInfo {
4441

45-
// This class provides a view into the underlying resource array. The Resource
46-
// data is little-endian encoded and may not be properly aligned to read
47-
// directly from. The dereference operator creates a copy of the data and byte
48-
// swaps it as appropriate.
49-
template <typename T> struct ViewArray {
50-
StringRef Data;
51-
uint32_t Stride = sizeof(T); // size of each element in the list.
42+
// This class provides a view into the underlying resource array. The Resource
43+
// data is little-endian encoded and may not be properly aligned to read
44+
// directly from. The dereference operator creates a copy of the data and byte
45+
// swaps it as appropriate.
46+
template <typename T> struct ViewArray {
47+
StringRef Data;
48+
uint32_t Stride = sizeof(T); // size of each element in the list.
5249

53-
ViewArray() = default;
54-
ViewArray(StringRef D, size_t S) : Data(D), Stride(S) {}
50+
ViewArray() = default;
51+
ViewArray(StringRef D, size_t S) : Data(D), Stride(S) {}
5552

56-
using value_type = T;
57-
static constexpr uint32_t MaxStride() {
58-
return static_cast<uint32_t>(sizeof(value_type));
59-
}
53+
using value_type = T;
54+
static constexpr uint32_t MaxStride() {
55+
return static_cast<uint32_t>(sizeof(value_type));
56+
}
6057

61-
struct iterator {
62-
StringRef Data;
63-
uint32_t Stride; // size of each element in the list.
64-
const char *Current;
65-
66-
iterator(const ViewArray &A, const char *C)
67-
: Data(A.Data), Stride(A.Stride), Current(C) {}
68-
iterator(const iterator &) = default;
69-
70-
value_type operator*() {
71-
// Explicitly zero the structure so that unused fields are zeroed. It is
72-
// up to the user to know if the fields are used by verifying the PSV
73-
// version.
74-
value_type Val;
75-
std::memset(&Val, 0, sizeof(value_type));
76-
if (Current >= Data.end())
77-
return Val;
78-
memcpy(static_cast<void *>(&Val), Current,
79-
std::min(Stride, MaxStride()));
80-
if (sys::IsBigEndianHost)
81-
detail::swapBytes(Val);
58+
struct iterator {
59+
StringRef Data;
60+
uint32_t Stride; // size of each element in the list.
61+
const char *Current;
62+
63+
iterator(const ViewArray &A, const char *C)
64+
: Data(A.Data), Stride(A.Stride), Current(C) {}
65+
iterator(const iterator &) = default;
66+
67+
value_type operator*() {
68+
// Explicitly zero the structure so that unused fields are zeroed. It is
69+
// up to the user to know if the fields are used by verifying the PSV
70+
// version.
71+
value_type Val;
72+
std::memset(&Val, 0, sizeof(value_type));
73+
if (Current >= Data.end())
8274
return Val;
83-
}
75+
memcpy(static_cast<void *>(&Val), Current, std::min(Stride, MaxStride()));
76+
if (sys::IsBigEndianHost)
77+
detail::swapBytes(Val);
78+
return Val;
79+
}
8480

85-
iterator operator++() {
86-
if (Current < Data.end())
87-
Current += Stride;
88-
return *this;
89-
}
81+
iterator operator++() {
82+
if (Current < Data.end())
83+
Current += Stride;
84+
return *this;
85+
}
9086

91-
iterator operator++(int) {
92-
iterator Tmp = *this;
93-
++*this;
94-
return Tmp;
95-
}
87+
iterator operator++(int) {
88+
iterator Tmp = *this;
89+
++*this;
90+
return Tmp;
91+
}
9692

97-
iterator operator--() {
98-
if (Current > Data.begin())
99-
Current -= Stride;
100-
return *this;
101-
}
93+
iterator operator--() {
94+
if (Current > Data.begin())
95+
Current -= Stride;
96+
return *this;
97+
}
98+
99+
iterator operator--(int) {
100+
iterator Tmp = *this;
101+
--*this;
102+
return Tmp;
103+
}
102104

103-
iterator operator--(int) {
104-
iterator Tmp = *this;
105-
--*this;
106-
return Tmp;
107-
}
105+
bool operator==(const iterator I) { return I.Current == Current; }
106+
bool operator!=(const iterator I) { return !(*this == I); }
107+
};
108108

109-
bool operator==(const iterator I) { return I.Current == Current; }
110-
bool operator!=(const iterator I) { return !(*this == I); }
111-
};
109+
iterator begin() const { return iterator(*this, Data.begin()); }
112110

113-
iterator begin() const { return iterator(*this, Data.begin()); }
111+
iterator end() const { return iterator(*this, Data.end()); }
114112

115-
iterator end() const { return iterator(*this, Data.end()); }
113+
size_t size() const { return Data.size() / Stride; }
116114

117-
size_t size() const { return Data.size() / Stride; }
118-
};
115+
bool isEmpty() const { return Data.empty(); }
116+
};
117+
118+
namespace DirectX {
119+
class PSVRuntimeInfo {
119120

120121
using ResourceArray = ViewArray<dxbc::PSV::v2::ResourceBindInfo>;
121122
using SigElementArray = ViewArray<dxbc::PSV::v0::SignatureElement>;
@@ -232,6 +233,36 @@ class PSVRuntimeInfo {
232233
}
233234
};
234235

236+
class Signature {
237+
ViewArray<dxbc::ProgramSignatureElement> Parameters;
238+
uint32_t StringTableOffset;
239+
StringRef StringTable;
240+
241+
public:
242+
ViewArray<dxbc::ProgramSignatureElement>::iterator begin() const {
243+
return Parameters.begin();
244+
}
245+
246+
ViewArray<dxbc::ProgramSignatureElement>::iterator end() const {
247+
return Parameters.end();
248+
}
249+
250+
StringRef getName(uint32_t Offset) const {
251+
assert(Offset >= StringTableOffset &&
252+
Offset < StringTableOffset + StringTable.size() &&
253+
"Offset out of range.");
254+
// Name offsets are from the start of the signature data, not from the start
255+
// of the string table. The header encodes the start offset of the sting
256+
// table, so we convert the offset here.
257+
uint32_t TableOffset = Offset - StringTableOffset;
258+
return StringTable.slice(TableOffset, StringTable.find('\0', TableOffset));
259+
}
260+
261+
bool isEmpty() const { return Parameters.isEmpty(); }
262+
263+
Error initialize(StringRef Part);
264+
};
265+
235266
} // namespace DirectX
236267

237268
class DXContainer {
@@ -248,13 +279,17 @@ class DXContainer {
248279
std::optional<uint64_t> ShaderFlags;
249280
std::optional<dxbc::ShaderHash> Hash;
250281
std::optional<DirectX::PSVRuntimeInfo> PSVInfo;
282+
DirectX::Signature InputSignature;
283+
DirectX::Signature OutputSignature;
284+
DirectX::Signature PatchConstantSignature;
251285

252286
Error parseHeader();
253287
Error parsePartOffsets();
254288
Error parseDXILHeader(StringRef Part);
255289
Error parseShaderFlags(StringRef Part);
256290
Error parseHash(StringRef Part);
257291
Error parsePSVInfo(StringRef Part);
292+
Error parseSignature(StringRef Part, DirectX::Signature &Array);
258293
friend class PartIterator;
259294

260295
public:
@@ -340,6 +375,14 @@ class DXContainer {
340375
const std::optional<DirectX::PSVRuntimeInfo> &getPSVInfo() const {
341376
return PSVInfo;
342377
};
378+
379+
const DirectX::Signature &getInputSignature() const { return InputSignature; }
380+
const DirectX::Signature &getOutputSignature() const {
381+
return OutputSignature;
382+
}
383+
const DirectX::Signature &getPatchConstantSignature() const {
384+
return PatchConstantSignature;
385+
}
343386
};
344387

345388
} // namespace object

‎llvm/include/llvm/ObjectYAML/DXContainerYAML.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,22 @@ struct PSVInfo {
129129
PSVInfo(const dxbc::PSV::v2::RuntimeInfo *P);
130130
};
131131

132+
struct SignatureParameter {
133+
uint32_t Stream;
134+
std::string Name;
135+
uint32_t Index;
136+
dxbc::D3DSystemValue SystemValue;
137+
dxbc::SigComponentType CompType;
138+
uint32_t Register;
139+
uint8_t Mask;
140+
uint8_t ExclusiveMask;
141+
dxbc::SigMinPrecision MinPrecision;
142+
};
143+
144+
struct Signature {
145+
llvm::SmallVector<SignatureParameter> Parameters;
146+
};
147+
132148
struct Part {
133149
Part() = default;
134150
Part(std::string N, uint32_t S) : Name(N), Size(S) {}
@@ -138,6 +154,7 @@ struct Part {
138154
std::optional<ShaderFlags> Flags;
139155
std::optional<ShaderHash> Hash;
140156
std::optional<PSVInfo> Info;
157+
std::optional<Signature> Signature;
141158
};
142159

143160
struct Object {
@@ -152,9 +169,13 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::Part)
152169
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::ResourceBindInfo)
153170
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::SignatureElement)
154171
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::PSVInfo::MaskVector)
172+
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::SignatureParameter)
155173
LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::SemanticKind)
156174
LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::ComponentType)
157175
LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::InterpolationMode)
176+
LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::D3DSystemValue)
177+
LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::SigComponentType)
178+
LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::SigMinPrecision)
158179

159180
namespace llvm {
160181

@@ -202,6 +223,14 @@ template <> struct MappingTraits<DXContainerYAML::SignatureElement> {
202223
static void mapping(IO &IO, llvm::DXContainerYAML::SignatureElement &El);
203224
};
204225

226+
template <> struct MappingTraits<DXContainerYAML::SignatureParameter> {
227+
static void mapping(IO &IO, llvm::DXContainerYAML::SignatureParameter &El);
228+
};
229+
230+
template <> struct MappingTraits<DXContainerYAML::Signature> {
231+
static void mapping(IO &IO, llvm::DXContainerYAML::Signature &El);
232+
};
233+
205234
} // namespace yaml
206235

207236
} // namespace llvm

‎llvm/lib/BinaryFormat/DXContainer.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,36 @@ bool ShaderHash::isPopulated() {
3030
return Flags > 0 || 0 != memcmp(&Digest, &Zeros, 16);
3131
}
3232

33+
#define COMPONENT_PRECISION(Val, Enum) {#Enum, SigMinPrecision::Enum},
34+
35+
static const EnumEntry<SigMinPrecision> SigMinPrecisionNames[] = {
36+
#include "llvm/BinaryFormat/DXContainerConstants.def"
37+
};
38+
39+
ArrayRef<EnumEntry<SigMinPrecision>> dxbc::getSigMinPrecisions() {
40+
return ArrayRef(SigMinPrecisionNames);
41+
}
42+
43+
#define D3D_SYSTEM_VALUE(Val, Enum) {#Enum, D3DSystemValue::Enum},
44+
45+
static const EnumEntry<D3DSystemValue> D3DSystemValueNames[] = {
46+
#include "llvm/BinaryFormat/DXContainerConstants.def"
47+
};
48+
49+
ArrayRef<EnumEntry<D3DSystemValue>> dxbc::getD3DSystemValues() {
50+
return ArrayRef(D3DSystemValueNames);
51+
}
52+
53+
#define COMPONENT_TYPE(Val, Enum) {#Enum, SigComponentType::Enum},
54+
55+
static const EnumEntry<SigComponentType> SigComponentTypes[] = {
56+
#include "llvm/BinaryFormat/DXContainerConstants.def"
57+
};
58+
59+
ArrayRef<EnumEntry<SigComponentType>> dxbc::getSigComponentTypes() {
60+
return ArrayRef(SigComponentTypes);
61+
}
62+
3363
#define SEMANTIC_KIND(Val, Enum) {#Enum, PSV::SemanticKind::Enum},
3464

3565
static const EnumEntry<PSV::SemanticKind> SemanticKindNames[] = {

‎llvm/lib/MC/DXContainerPSVInfo.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,51 @@ void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const {
161161
support::endian::write_array(OS, ArrayRef<uint32_t>(PatchOutputMap),
162162
support::little);
163163
}
164+
165+
void Signature::write(raw_ostream &OS) {
166+
SmallVector<dxbc::ProgramSignatureElement> SigParams;
167+
SigParams.reserve(Params.size());
168+
StringTableBuilder StrTabBuilder((StringTableBuilder::DWARF));
169+
170+
// Name offsets are from the start of the part. Pre-calculate the offset to
171+
// the start of the string table so that it can be added to the table offset.
172+
uint32_t TableStart = sizeof(dxbc::ProgramSignatureHeader) +
173+
(sizeof(dxbc::ProgramSignatureElement) * Params.size());
174+
175+
for (const auto &P : Params) {
176+
// zero out the data
177+
dxbc::ProgramSignatureElement FinalElement;
178+
memset(&FinalElement, 0, sizeof(dxbc::ProgramSignatureElement));
179+
FinalElement.Stream = P.Stream;
180+
FinalElement.NameOffset =
181+
static_cast<uint32_t>(StrTabBuilder.add(P.Name)) + TableStart;
182+
FinalElement.Index = P.Index;
183+
FinalElement.SystemValue = P.SystemValue;
184+
FinalElement.CompType = P.CompType;
185+
FinalElement.Register = P.Register;
186+
FinalElement.Mask = P.Mask;
187+
FinalElement.ExclusiveMask = P.ExclusiveMask;
188+
FinalElement.MinPrecision = P.MinPrecision;
189+
SigParams.push_back(FinalElement);
190+
}
191+
192+
StrTabBuilder.finalizeInOrder();
193+
stable_sort(SigParams, [&](const dxbc::ProgramSignatureElement &L,
194+
const dxbc::ProgramSignatureElement R) {
195+
return std::tie(L.Stream, L.Register, L.NameOffset) <
196+
std::tie(R.Stream, R.Register, R.NameOffset);
197+
});
198+
if (sys::IsBigEndianHost)
199+
for (auto &El : SigParams)
200+
El.swapBytes();
201+
202+
dxbc::ProgramSignatureHeader Header = {static_cast<uint32_t>(Params.size()),
203+
sizeof(dxbc::ProgramSignatureHeader)};
204+
if (sys::IsBigEndianHost)
205+
Header.swapBytes();
206+
OS.write(reinterpret_cast<const char *>(&Header),
207+
sizeof(dxbc::ProgramSignatureHeader));
208+
OS.write(reinterpret_cast<const char *>(SigParams.data()),
209+
sizeof(dxbc::ProgramSignatureElement) * SigParams.size());
210+
StrTabBuilder.write(OS);
211+
}

‎llvm/lib/Object/DXContainer.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,31 @@ Error DXContainer::parsePSVInfo(StringRef Part) {
101101
return Error::success();
102102
}
103103

104+
Error DirectX::Signature::initialize(StringRef Part) {
105+
dxbc::ProgramSignatureHeader SigHeader;
106+
if (Error Err = readStruct(Part, Part.begin(), SigHeader))
107+
return Err;
108+
size_t Size = sizeof(dxbc::ProgramSignatureElement) * SigHeader.ParamCount;
109+
110+
if (Part.size() < Size + SigHeader.FirstParamOffset)
111+
return parseFailed("Signature parameters extend beyond the part boundary");
112+
113+
Parameters.Data = Part.substr(SigHeader.FirstParamOffset, Size);
114+
115+
StringTableOffset = SigHeader.FirstParamOffset + static_cast<uint32_t>(Size);
116+
StringTable = Part.substr(SigHeader.FirstParamOffset + Size);
117+
118+
for (const auto &Param : Parameters) {
119+
if (Param.NameOffset < StringTableOffset)
120+
return parseFailed("Invalid parameter name offset: name starts before "
121+
"the first name offset");
122+
if (Param.NameOffset - StringTableOffset > StringTable.size())
123+
return parseFailed("Invalid parameter name offset: name starts after the "
124+
"end of the part data");
125+
}
126+
return Error::success();
127+
}
128+
104129
Error DXContainer::parsePartOffsets() {
105130
uint32_t LastOffset =
106131
sizeof(dxbc::Header) + (Header.PartCount * sizeof(uint32_t));
@@ -154,6 +179,18 @@ Error DXContainer::parsePartOffsets() {
154179
if (Error Err = parsePSVInfo(PartData))
155180
return Err;
156181
break;
182+
case dxbc::PartType::ISG1:
183+
if (Error Err = InputSignature.initialize(PartData))
184+
return Err;
185+
break;
186+
case dxbc::PartType::OSG1:
187+
if (Error Err = OutputSignature.initialize(PartData))
188+
return Err;
189+
break;
190+
case dxbc::PartType::PSG1:
191+
if (Error Err = PatchConstantSignature.initialize(PartData))
192+
return Err;
193+
break;
157194
case dxbc::PartType::Unknown:
158195
break;
159196
}

‎llvm/lib/ObjectYAML/DXContainerEmitter.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,20 @@ void DXContainerWriter::writeParts(raw_ostream &OS) {
244244
PSV.write(OS, P.Info->Version);
245245
break;
246246
}
247+
case dxbc::PartType::ISG1:
248+
case dxbc::PartType::OSG1:
249+
case dxbc::PartType::PSG1: {
250+
mcdxbc::Signature Sig;
251+
if (P.Signature.has_value()) {
252+
for (const auto &Param : P.Signature->Parameters) {
253+
Sig.addParam(Param.Stream, Param.Name, Param.Index, Param.SystemValue,
254+
Param.CompType, Param.Register, Param.Mask,
255+
Param.ExclusiveMask, Param.MinPrecision);
256+
}
257+
}
258+
Sig.write(OS);
259+
break;
260+
}
247261
case dxbc::PartType::Unknown:
248262
break; // Skip any handling for unrecognized parts.
249263
}

‎llvm/lib/ObjectYAML/DXContainerYAML.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,24 @@ void MappingTraits<DXContainerYAML::PSVInfo>::mapping(
159159
IO.mapRequired("PatchOutputMap", PSV.PatchOutputMap);
160160
}
161161

162+
void MappingTraits<DXContainerYAML::SignatureParameter>::mapping(
163+
IO &IO, DXContainerYAML::SignatureParameter &S) {
164+
IO.mapRequired("Stream", S.Stream);
165+
IO.mapRequired("Name", S.Name);
166+
IO.mapRequired("Index", S.Index);
167+
IO.mapRequired("SystemValue", S.SystemValue);
168+
IO.mapRequired("CompType", S.CompType);
169+
IO.mapRequired("Register", S.Register);
170+
IO.mapRequired("Mask", S.Mask);
171+
IO.mapRequired("ExclusiveMask", S.ExclusiveMask);
172+
IO.mapRequired("MinPrecision", S.MinPrecision);
173+
}
174+
175+
void MappingTraits<DXContainerYAML::Signature>::mapping(
176+
IO &IO, DXContainerYAML::Signature &S) {
177+
IO.mapRequired("Parameters", S.Parameters);
178+
}
179+
162180
void MappingTraits<DXContainerYAML::Part>::mapping(IO &IO,
163181
DXContainerYAML::Part &P) {
164182
IO.mapRequired("Name", P.Name);
@@ -167,6 +185,7 @@ void MappingTraits<DXContainerYAML::Part>::mapping(IO &IO,
167185
IO.mapOptional("Flags", P.Flags);
168186
IO.mapOptional("Hash", P.Hash);
169187
IO.mapOptional("PSVInfo", P.Info);
188+
IO.mapOptional("Signature", P.Signature);
170189
}
171190

172191
void MappingTraits<DXContainerYAML::Object>::mapping(
@@ -224,6 +243,24 @@ void ScalarEnumerationTraits<dxbc::PSV::InterpolationMode>::enumeration(
224243
IO.enumCase(Value, E.Name.str().c_str(), E.Value);
225244
}
226245

246+
void ScalarEnumerationTraits<dxbc::D3DSystemValue>::enumeration(
247+
IO &IO, dxbc::D3DSystemValue &Value) {
248+
for (const auto &E : dxbc::getD3DSystemValues())
249+
IO.enumCase(Value, E.Name.str().c_str(), E.Value);
250+
}
251+
252+
void ScalarEnumerationTraits<dxbc::SigMinPrecision>::enumeration(
253+
IO &IO, dxbc::SigMinPrecision &Value) {
254+
for (const auto &E : dxbc::getSigMinPrecisions())
255+
IO.enumCase(Value, E.Name.str().c_str(), E.Value);
256+
}
257+
258+
void ScalarEnumerationTraits<dxbc::SigComponentType>::enumeration(
259+
IO &IO, dxbc::SigComponentType &Value) {
260+
for (const auto &E : dxbc::getSigComponentTypes())
261+
IO.enumCase(Value, E.Name.str().c_str(), E.Value);
262+
}
263+
227264
} // namespace yaml
228265

229266
void DXContainerYAML::PSVInfo::mapInfoForVersion(yaml::IO &IO) {
Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
# RUN: yaml2obj %s | obj2yaml | FileCheck %s
2+
--- !dxcontainer
3+
Header:
4+
Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
5+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
6+
Version:
7+
Major: 1
8+
Minor: 0
9+
FileSize: 600
10+
PartCount: 3
11+
PartOffsets: [ 64, 124, 184 ]
12+
Parts:
13+
- Name: ISG1
14+
Size: 52
15+
Signature:
16+
Parameters:
17+
- Stream: 0
18+
Name: AAA_HSFoo
19+
Index: 0
20+
SystemValue: Undefined
21+
CompType: Float32
22+
Register: 0
23+
Mask: 7
24+
ExclusiveMask: 2
25+
MinPrecision: Default
26+
- Name: OSG1
27+
Size: 52
28+
Signature:
29+
Parameters:
30+
- Stream: 0
31+
Name: SV_Position
32+
Index: 0
33+
SystemValue: Position
34+
CompType: Float32
35+
Register: 0
36+
Mask: 15
37+
ExclusiveMask: 0
38+
MinPrecision: Default
39+
- Name: PSG1
40+
Size: 372
41+
Signature:
42+
Parameters:
43+
- Stream: 0
44+
Name: SV_TessFactor
45+
Index: 0
46+
SystemValue: FinalQuadEdgeTessfactor
47+
CompType: Float32
48+
Register: 0
49+
Mask: 8
50+
ExclusiveMask: 8
51+
MinPrecision: Default
52+
- Stream: 0
53+
Name: BBB
54+
Index: 0
55+
SystemValue: Undefined
56+
CompType: Float32
57+
Register: 0
58+
Mask: 7
59+
ExclusiveMask: 0
60+
MinPrecision: Default
61+
- Stream: 0
62+
Name: SV_TessFactor
63+
Index: 1
64+
SystemValue: FinalQuadEdgeTessfactor
65+
CompType: Float32
66+
Register: 1
67+
Mask: 8
68+
ExclusiveMask: 8
69+
MinPrecision: Default
70+
- Stream: 0
71+
Name: BBB
72+
Index: 1
73+
SystemValue: Undefined
74+
CompType: Float32
75+
Register: 1
76+
Mask: 7
77+
ExclusiveMask: 0
78+
MinPrecision: Default
79+
- Stream: 0
80+
Name: SV_TessFactor
81+
Index: 2
82+
SystemValue: FinalQuadEdgeTessfactor
83+
CompType: Float32
84+
Register: 2
85+
Mask: 8
86+
ExclusiveMask: 8
87+
MinPrecision: Default
88+
- Stream: 0
89+
Name: BBB
90+
Index: 2
91+
SystemValue: Undefined
92+
CompType: Float32
93+
Register: 2
94+
Mask: 7
95+
ExclusiveMask: 0
96+
MinPrecision: Default
97+
- Stream: 0
98+
Name: SV_TessFactor
99+
Index: 3
100+
SystemValue: FinalQuadEdgeTessfactor
101+
CompType: Float32
102+
Register: 3
103+
Mask: 8
104+
ExclusiveMask: 8
105+
MinPrecision: Default
106+
- Stream: 0
107+
Name: SV_InsideTessFactor
108+
Index: 0
109+
SystemValue: FinalQuadInsideTessfactor
110+
CompType: Float32
111+
Register: 4
112+
Mask: 8
113+
ExclusiveMask: 0
114+
MinPrecision: Default
115+
- Stream: 0
116+
Name: SV_InsideTessFactor
117+
Index: 1
118+
SystemValue: FinalQuadInsideTessfactor
119+
CompType: Float32
120+
Register: 5
121+
Mask: 8
122+
ExclusiveMask: 0
123+
MinPrecision: Default
124+
- Stream: 0
125+
Name: AAA
126+
Index: 0
127+
SystemValue: Undefined
128+
CompType: Float32
129+
Register: 6
130+
Mask: 15
131+
ExclusiveMask: 4
132+
MinPrecision: Default
133+
...
134+
135+
# CHECK: - Name: ISG1
136+
# CHECK-NEXT: Size: 52
137+
# CHECK-NEXT: Signature:
138+
# CHECK-NEXT: Parameters:
139+
# CHECK-NEXT: - Stream: 0
140+
# CHECK-NEXT: Name: AAA_HSFoo
141+
# CHECK-NEXT: Index: 0
142+
# CHECK-NEXT: SystemValue: Undefined
143+
# CHECK-NEXT: CompType: Float32
144+
# CHECK-NEXT: Register: 0
145+
# CHECK-NEXT: Mask: 7
146+
# CHECK-NEXT: ExclusiveMask: 2
147+
# CHECK-NEXT: MinPrecision: Default
148+
# CHECK-NEXT: - Name: OSG1
149+
# CHECK-NEXT: Size: 52
150+
# CHECK-NEXT: Signature:
151+
# CHECK-NEXT: Parameters:
152+
# CHECK-NEXT: - Stream: 0
153+
# CHECK-NEXT: Name: SV_Position
154+
# CHECK-NEXT: Index: 0
155+
# CHECK-NEXT: SystemValue: Position
156+
# CHECK-NEXT: CompType: Float32
157+
# CHECK-NEXT: Register: 0
158+
# CHECK-NEXT: Mask: 15
159+
# CHECK-NEXT: ExclusiveMask: 0
160+
# CHECK-NEXT: MinPrecision: Default
161+
# CHECK-NEXT: - Name: PSG1
162+
# CHECK-NEXT: Size: 372
163+
# CHECK-NEXT: Signature:
164+
# CHECK-NEXT: Parameters:
165+
# CHECK-NEXT: - Stream: 0
166+
# CHECK-NEXT: Name: SV_TessFactor
167+
# CHECK-NEXT: Index: 0
168+
# CHECK-NEXT: SystemValue: FinalQuadEdgeTessfactor
169+
# CHECK-NEXT: CompType: Float32
170+
# CHECK-NEXT: Register: 0
171+
# CHECK-NEXT: Mask: 8
172+
# CHECK-NEXT: ExclusiveMask: 8
173+
# CHECK-NEXT: MinPrecision: Default
174+
# CHECK-NEXT: - Stream: 0
175+
# CHECK-NEXT: Name: BBB
176+
# CHECK-NEXT: Index: 0
177+
# CHECK-NEXT: SystemValue: Undefined
178+
# CHECK-NEXT: CompType: Float32
179+
# CHECK-NEXT: Register: 0
180+
# CHECK-NEXT: Mask: 7
181+
# CHECK-NEXT: ExclusiveMask: 0
182+
# CHECK-NEXT: MinPrecision: Default
183+
# CHECK-NEXT: - Stream: 0
184+
# CHECK-NEXT: Name: SV_TessFactor
185+
# CHECK-NEXT: Index: 1
186+
# CHECK-NEXT: SystemValue: FinalQuadEdgeTessfactor
187+
# CHECK-NEXT: CompType: Float32
188+
# CHECK-NEXT: Register: 1
189+
# CHECK-NEXT: Mask: 8
190+
# CHECK-NEXT: ExclusiveMask: 8
191+
# CHECK-NEXT: MinPrecision: Default
192+
# CHECK-NEXT: - Stream: 0
193+
# CHECK-NEXT: Name: BBB
194+
# CHECK-NEXT: Index: 1
195+
# CHECK-NEXT: SystemValue: Undefined
196+
# CHECK-NEXT: CompType: Float32
197+
# CHECK-NEXT: Register: 1
198+
# CHECK-NEXT: Mask: 7
199+
# CHECK-NEXT: ExclusiveMask: 0
200+
# CHECK-NEXT: MinPrecision: Default
201+
# CHECK-NEXT: - Stream: 0
202+
# CHECK-NEXT: Name: SV_TessFactor
203+
# CHECK-NEXT: Index: 2
204+
# CHECK-NEXT: SystemValue: FinalQuadEdgeTessfactor
205+
# CHECK-NEXT: CompType: Float32
206+
# CHECK-NEXT: Register: 2
207+
# CHECK-NEXT: Mask: 8
208+
# CHECK-NEXT: ExclusiveMask: 8
209+
# CHECK-NEXT: MinPrecision: Default
210+
# CHECK-NEXT: - Stream: 0
211+
# CHECK-NEXT: Name: BBB
212+
# CHECK-NEXT: Index: 2
213+
# CHECK-NEXT: SystemValue: Undefined
214+
# CHECK-NEXT: CompType: Float32
215+
# CHECK-NEXT: Register: 2
216+
# CHECK-NEXT: Mask: 7
217+
# CHECK-NEXT: ExclusiveMask: 0
218+
# CHECK-NEXT: MinPrecision: Default
219+
# CHECK-NEXT: - Stream: 0
220+
# CHECK-NEXT: Name: SV_TessFactor
221+
# CHECK-NEXT: Index: 3
222+
# CHECK-NEXT: SystemValue: FinalQuadEdgeTessfactor
223+
# CHECK-NEXT: CompType: Float32
224+
# CHECK-NEXT: Register: 3
225+
# CHECK-NEXT: Mask: 8
226+
# CHECK-NEXT: ExclusiveMask: 8
227+
# CHECK-NEXT: MinPrecision: Default
228+
# CHECK-NEXT: - Stream: 0
229+
# CHECK-NEXT: Name: SV_InsideTessFactor
230+
# CHECK-NEXT: Index: 0
231+
# CHECK-NEXT: SystemValue: FinalQuadInsideTessfactor
232+
# CHECK-NEXT: CompType: Float32
233+
# CHECK-NEXT: Register: 4
234+
# CHECK-NEXT: Mask: 8
235+
# CHECK-NEXT: ExclusiveMask: 0
236+
# CHECK-NEXT: MinPrecision: Default
237+
# CHECK-NEXT: - Stream: 0
238+
# CHECK-NEXT: Name: SV_InsideTessFactor
239+
# CHECK-NEXT: Index: 1
240+
# CHECK-NEXT: SystemValue: FinalQuadInsideTessfactor
241+
# CHECK-NEXT: CompType: Float32
242+
# CHECK-NEXT: Register: 5
243+
# CHECK-NEXT: Mask: 8
244+
# CHECK-NEXT: ExclusiveMask: 0
245+
# CHECK-NEXT: MinPrecision: Default
246+
# CHECK-NEXT: - Stream: 0
247+
# CHECK-NEXT: Name: AAA
248+
# CHECK-NEXT: Index: 0
249+
# CHECK-NEXT: SystemValue: Undefined
250+
# CHECK-NEXT: CompType: Float32
251+
# CHECK-NEXT: Register: 6
252+
# CHECK-NEXT: Mask: 15
253+
# CHECK-NEXT: ExclusiveMask: 4
254+
# CHECK-NEXT: MinPrecision: Default

‎llvm/tools/obj2yaml/dxcontainer2yaml.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@
1616
using namespace llvm;
1717
using namespace llvm::object;
1818

19+
static DXContainerYAML::Signature dumpSignature(const DirectX::Signature &Sig) {
20+
DXContainerYAML::Signature YAML;
21+
for (auto Param : Sig)
22+
YAML.Parameters.push_back(DXContainerYAML::SignatureParameter{
23+
Param.Stream, Sig.getName(Param.NameOffset).str(), Param.Index,
24+
Param.SystemValue, Param.CompType, Param.Register, Param.Mask,
25+
Param.ExclusiveMask, Param.MinPrecision});
26+
return YAML;
27+
}
28+
1929
static Expected<DXContainerYAML::Object *>
2030
dumpDXContainer(MemoryBufferRef Source) {
2131
assert(file_magic::dxcontainer_object == identify_magic(Source.getBuffer()));
@@ -129,6 +139,15 @@ dumpDXContainer(MemoryBufferRef Source) {
129139

130140
break;
131141
}
142+
case dxbc::PartType::ISG1:
143+
NewPart.Signature = dumpSignature(Container.getInputSignature());
144+
break;
145+
case dxbc::PartType::OSG1:
146+
NewPart.Signature = dumpSignature(Container.getOutputSignature());
147+
break;
148+
case dxbc::PartType::PSG1:
149+
NewPart.Signature = dumpSignature(Container.getPatchConstantSignature());
150+
break;
132151
case dxbc::PartType::Unknown:
133152
break;
134153
}

‎llvm/unittests/Object/DXContainerTest.cpp

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,3 +640,139 @@ TEST(DXCFile, SigElementsExtendBeyondPart) {
640640
FailedWithMessage(
641641
"Signature elements extend beyond the size of the part"));
642642
}
643+
644+
TEST(DXCFile, MalformedSignature) {
645+
/*
646+
The tests here exercise the DXContainer Signature section parser. These tests
647+
are based on modifying the binary described by the following yaml:
648+
649+
--- !dxcontainer
650+
Header:
651+
Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
652+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
653+
Version:
654+
Major: 1
655+
Minor: 0
656+
FileSize: 128
657+
PartCount: 1
658+
PartOffsets: [ 64 ]
659+
Parts:
660+
- Name: ISG1
661+
Size: 52
662+
Signature:
663+
Parameters:
664+
- Stream: 0
665+
Name: AAA
666+
Index: 0
667+
SystemValue: Undefined
668+
CompType: Float32
669+
Register: 0
670+
Mask: 7
671+
ExclusiveMask: 2
672+
MinPrecision: Default
673+
...
674+
675+
The unmodified hex sequence is:
676+
677+
uint8_t Buffer[] = {
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
688+
};
689+
690+
*/
691+
692+
{
693+
694+
// This binary says the signature has 10 parameters, but the part data is
695+
// only big enough for 1.
696+
uint8_t Buffer[] = {
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)),
710+
FailedWithMessage(
711+
"Signature parameters extend beyond the part boundary"));
712+
}
713+
714+
{
715+
716+
// This binary only has one parameter, but the start offset is beyond the
717+
// size of the part.
718+
uint8_t Buffer[] = {
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)),
732+
FailedWithMessage(
733+
"Signature parameters extend beyond the part boundary"));
734+
}
735+
736+
{
737+
738+
// This parameter has a name offset of 3, which is before the start of the
739+
// string table.
740+
uint8_t Buffer[] = {
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"));
756+
}
757+
758+
{
759+
// This parameter has a name offset of 255, which is after the end of the
760+
// part.
761+
uint8_t Buffer[] = {
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"));
777+
}
778+
}

0 commit comments

Comments
 (0)
Please sign in to comment.