702 lines · cpp
1//===- DXContainer.cpp - DXContainer object file implementation -----------===//2//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Object/DXContainer.h"10#include "llvm/BinaryFormat/DXContainer.h"11#include "llvm/Object/Error.h"12#include "llvm/Support/Endian.h"13#include "llvm/Support/FormatVariadic.h"14#include "llvm/TargetParser/SubtargetFeature.h"15 16using namespace llvm;17using namespace llvm::object;18 19static Error parseFailed(const Twine &Msg) {20 return make_error<GenericBinaryError>(Msg.str(), object_error::parse_failed);21}22 23template <typename T>24static Error readStruct(StringRef Buffer, const char *Src, T &Struct) {25 // Don't read before the beginning or past the end of the file26 if (Src < Buffer.begin() || Src + sizeof(T) > Buffer.end())27 return parseFailed("Reading structure out of file bounds");28 29 memcpy(&Struct, Src, sizeof(T));30 // DXContainer is always little endian31 if (sys::IsBigEndianHost)32 Struct.swapBytes();33 return Error::success();34}35 36template <typename T>37static Error readInteger(StringRef Buffer, const char *Src, T &Val,38 Twine Str = "structure") {39 static_assert(std::is_integral_v<T>,40 "Cannot call readInteger on non-integral type.");41 // Don't read before the beginning or past the end of the file42 if (Src < Buffer.begin() || Src + sizeof(T) > Buffer.end())43 return parseFailed(Twine("Reading ") + Str + " out of file bounds");44 45 // The DXContainer offset table is comprised of uint32_t values but not padded46 // to a 64-bit boundary. So Parts may start unaligned if there is an odd47 // number of parts and part data itself is not required to be padded.48 if (reinterpret_cast<uintptr_t>(Src) % alignof(T) != 0)49 memcpy(reinterpret_cast<char *>(&Val), Src, sizeof(T));50 else51 Val = *reinterpret_cast<const T *>(Src);52 // DXContainer is always little endian53 if (sys::IsBigEndianHost)54 sys::swapByteOrder(Val);55 return Error::success();56}57 58DXContainer::DXContainer(MemoryBufferRef O) : Data(O) {}59 60Error DXContainer::parseHeader() {61 return readStruct(Data.getBuffer(), Data.getBuffer().data(), Header);62}63 64Error DXContainer::parseDXILHeader(StringRef Part) {65 if (DXIL)66 return parseFailed("More than one DXIL part is present in the file");67 const char *Current = Part.begin();68 dxbc::ProgramHeader Header;69 if (Error Err = readStruct(Part, Current, Header))70 return Err;71 Current += offsetof(dxbc::ProgramHeader, Bitcode) + Header.Bitcode.Offset;72 DXIL.emplace(std::make_pair(Header, Current));73 return Error::success();74}75 76Error DXContainer::parseShaderFeatureFlags(StringRef Part) {77 if (ShaderFeatureFlags)78 return parseFailed("More than one SFI0 part is present in the file");79 uint64_t FlagValue = 0;80 if (Error Err = readInteger(Part, Part.begin(), FlagValue))81 return Err;82 ShaderFeatureFlags = FlagValue;83 return Error::success();84}85 86Error DXContainer::parseHash(StringRef Part) {87 if (Hash)88 return parseFailed("More than one HASH part is present in the file");89 dxbc::ShaderHash ReadHash;90 if (Error Err = readStruct(Part, Part.begin(), ReadHash))91 return Err;92 Hash = ReadHash;93 return Error::success();94}95 96Error DXContainer::parseRootSignature(StringRef Part) {97 if (RootSignature)98 return parseFailed("More than one RTS0 part is present in the file");99 RootSignature = DirectX::RootSignature(Part);100 if (Error Err = RootSignature->parse())101 return Err;102 return Error::success();103}104 105Error DXContainer::parsePSVInfo(StringRef Part) {106 if (PSVInfo)107 return parseFailed("More than one PSV0 part is present in the file");108 PSVInfo = DirectX::PSVRuntimeInfo(Part);109 // Parsing the PSVRuntime info occurs late because we need to read data from110 // other parts first.111 return Error::success();112}113 114Error DirectX::Signature::initialize(StringRef Part) {115 dxbc::ProgramSignatureHeader SigHeader;116 if (Error Err = readStruct(Part, Part.begin(), SigHeader))117 return Err;118 size_t Size = sizeof(dxbc::ProgramSignatureElement) * SigHeader.ParamCount;119 120 if (Part.size() < Size + SigHeader.FirstParamOffset)121 return parseFailed("Signature parameters extend beyond the part boundary");122 123 Parameters.Data = Part.substr(SigHeader.FirstParamOffset, Size);124 125 StringTableOffset = SigHeader.FirstParamOffset + static_cast<uint32_t>(Size);126 StringTable = Part.substr(SigHeader.FirstParamOffset + Size);127 128 for (const auto &Param : Parameters) {129 if (Param.NameOffset < StringTableOffset)130 return parseFailed("Invalid parameter name offset: name starts before "131 "the first name offset");132 if (Param.NameOffset - StringTableOffset > StringTable.size())133 return parseFailed("Invalid parameter name offset: name starts after the "134 "end of the part data");135 }136 return Error::success();137}138 139Error DXContainer::parsePartOffsets() {140 uint32_t LastOffset =141 sizeof(dxbc::Header) + (Header.PartCount * sizeof(uint32_t));142 const char *Current = Data.getBuffer().data() + sizeof(dxbc::Header);143 for (uint32_t Part = 0; Part < Header.PartCount; ++Part) {144 uint32_t PartOffset;145 if (Error Err = readInteger(Data.getBuffer(), Current, PartOffset))146 return Err;147 if (PartOffset < LastOffset)148 return parseFailed(149 formatv(150 "Part offset for part {0} begins before the previous part ends",151 Part)152 .str());153 Current += sizeof(uint32_t);154 if (PartOffset >= Data.getBufferSize())155 return parseFailed("Part offset points beyond boundary of the file");156 // To prevent overflow when reading the part name, we subtract the part name157 // size from the buffer size, rather than adding to the offset. Since the158 // file header is larger than the part header we can't reach this code159 // unless the buffer is at least as large as a part header, so this160 // subtraction can't underflow.161 if (PartOffset >= Data.getBufferSize() - sizeof(dxbc::PartHeader::Name))162 return parseFailed("File not large enough to read part name");163 PartOffsets.push_back(PartOffset);164 165 dxbc::PartType PT =166 dxbc::parsePartType(Data.getBuffer().substr(PartOffset, 4));167 uint32_t PartDataStart = PartOffset + sizeof(dxbc::PartHeader);168 uint32_t PartSize;169 if (Error Err = readInteger(Data.getBuffer(),170 Data.getBufferStart() + PartOffset + 4,171 PartSize, "part size"))172 return Err;173 StringRef PartData = Data.getBuffer().substr(PartDataStart, PartSize);174 LastOffset = PartOffset + PartSize;175 switch (PT) {176 case dxbc::PartType::DXIL:177 if (Error Err = parseDXILHeader(PartData))178 return Err;179 break;180 case dxbc::PartType::SFI0:181 if (Error Err = parseShaderFeatureFlags(PartData))182 return Err;183 break;184 case dxbc::PartType::HASH:185 if (Error Err = parseHash(PartData))186 return Err;187 break;188 case dxbc::PartType::PSV0:189 if (Error Err = parsePSVInfo(PartData))190 return Err;191 break;192 case dxbc::PartType::ISG1:193 if (Error Err = InputSignature.initialize(PartData))194 return Err;195 break;196 case dxbc::PartType::OSG1:197 if (Error Err = OutputSignature.initialize(PartData))198 return Err;199 break;200 case dxbc::PartType::PSG1:201 if (Error Err = PatchConstantSignature.initialize(PartData))202 return Err;203 break;204 case dxbc::PartType::Unknown:205 break;206 case dxbc::PartType::RTS0:207 if (Error Err = parseRootSignature(PartData))208 return Err;209 break;210 }211 }212 213 // Fully parsing the PSVInfo requires knowing the shader kind which we read214 // out of the program header in the DXIL part.215 if (PSVInfo) {216 if (!DXIL)217 return parseFailed("Cannot fully parse pipeline state validation "218 "information without DXIL part.");219 if (Error Err = PSVInfo->parse(DXIL->first.ShaderKind))220 return Err;221 }222 return Error::success();223}224 225Expected<DXContainer> DXContainer::create(MemoryBufferRef Object) {226 DXContainer Container(Object);227 if (Error Err = Container.parseHeader())228 return std::move(Err);229 if (Error Err = Container.parsePartOffsets())230 return std::move(Err);231 return Container;232}233 234void DXContainer::PartIterator::updateIteratorImpl(const uint32_t Offset) {235 StringRef Buffer = Container.Data.getBuffer();236 const char *Current = Buffer.data() + Offset;237 // Offsets are validated during parsing, so all offsets in the container are238 // valid and contain enough readable data to read a header.239 cantFail(readStruct(Buffer, Current, IteratorState.Part));240 IteratorState.Data =241 StringRef(Current + sizeof(dxbc::PartHeader), IteratorState.Part.Size);242 IteratorState.Offset = Offset;243}244 245Error DirectX::RootSignature::parse() {246 const char *Current = PartData.begin();247 248 // Root Signature headers expects 6 integers to be present.249 if (PartData.size() < 6 * sizeof(uint32_t))250 return parseFailed(251 "Invalid root signature, insufficient space for header.");252 253 Version = support::endian::read<uint32_t, llvm::endianness::little>(Current);254 Current += sizeof(uint32_t);255 256 NumParameters =257 support::endian::read<uint32_t, llvm::endianness::little>(Current);258 Current += sizeof(uint32_t);259 260 RootParametersOffset =261 support::endian::read<uint32_t, llvm::endianness::little>(Current);262 Current += sizeof(uint32_t);263 264 NumStaticSamplers =265 support::endian::read<uint32_t, llvm::endianness::little>(Current);266 Current += sizeof(uint32_t);267 268 StaticSamplersOffset =269 support::endian::read<uint32_t, llvm::endianness::little>(Current);270 Current += sizeof(uint32_t);271 272 Flags = support::endian::read<uint32_t, llvm::endianness::little>(Current);273 Current += sizeof(uint32_t);274 275 ParametersHeaders.Data = PartData.substr(276 RootParametersOffset,277 NumParameters * sizeof(dxbc::RTS0::v1::RootParameterHeader));278 279 StaticSamplers.Stride = (Version <= 2)280 ? sizeof(dxbc::RTS0::v1::StaticSampler)281 : sizeof(dxbc::RTS0::v3::StaticSampler);282 283 StaticSamplers.Data = PartData.substr(StaticSamplersOffset,284 static_cast<size_t>(NumStaticSamplers) *285 StaticSamplers.Stride);286 287 return Error::success();288}289 290Error DirectX::PSVRuntimeInfo::parse(uint16_t ShaderKind) {291 Triple::EnvironmentType ShaderStage = dxbc::getShaderStage(ShaderKind);292 293 const char *Current = Data.begin();294 if (Error Err = readInteger(Data, Current, Size))295 return Err;296 Current += sizeof(uint32_t);297 298 StringRef PSVInfoData = Data.substr(sizeof(uint32_t), Size);299 300 if (PSVInfoData.size() < Size)301 return parseFailed(302 "Pipeline state data extends beyond the bounds of the part");303 304 using namespace dxbc::PSV;305 306 const uint32_t PSVVersion = getVersion();307 308 // Detect the PSVVersion by looking at the size field.309 if (PSVVersion == 3) {310 v3::RuntimeInfo Info;311 if (Error Err = readStruct(PSVInfoData, Current, Info))312 return Err;313 if (sys::IsBigEndianHost)314 Info.swapBytes(ShaderStage);315 BasicInfo = Info;316 } else if (PSVVersion == 2) {317 v2::RuntimeInfo Info;318 if (Error Err = readStruct(PSVInfoData, Current, Info))319 return Err;320 if (sys::IsBigEndianHost)321 Info.swapBytes(ShaderStage);322 BasicInfo = Info;323 } else if (PSVVersion == 1) {324 v1::RuntimeInfo Info;325 if (Error Err = readStruct(PSVInfoData, Current, Info))326 return Err;327 if (sys::IsBigEndianHost)328 Info.swapBytes(ShaderStage);329 BasicInfo = Info;330 } else if (PSVVersion == 0) {331 v0::RuntimeInfo Info;332 if (Error Err = readStruct(PSVInfoData, Current, Info))333 return Err;334 if (sys::IsBigEndianHost)335 Info.swapBytes(ShaderStage);336 BasicInfo = Info;337 } else338 return parseFailed(339 "Cannot read PSV Runtime Info, unsupported PSV version.");340 341 Current += Size;342 343 uint32_t ResourceCount = 0;344 if (Error Err = readInteger(Data, Current, ResourceCount))345 return Err;346 Current += sizeof(uint32_t);347 348 if (ResourceCount > 0) {349 if (Error Err = readInteger(Data, Current, Resources.Stride))350 return Err;351 Current += sizeof(uint32_t);352 353 size_t BindingDataSize = Resources.Stride * ResourceCount;354 Resources.Data = Data.substr(Current - Data.begin(), BindingDataSize);355 356 if (Resources.Data.size() < BindingDataSize)357 return parseFailed(358 "Resource binding data extends beyond the bounds of the part");359 360 Current += BindingDataSize;361 } else362 Resources.Stride = sizeof(v2::ResourceBindInfo);363 364 // PSV version 0 ends after the resource bindings.365 if (PSVVersion == 0)366 return Error::success();367 368 // String table starts at a 4-byte offset.369 Current = reinterpret_cast<const char *>(370 alignTo<4>(reinterpret_cast<uintptr_t>(Current)));371 372 uint32_t StringTableSize = 0;373 if (Error Err = readInteger(Data, Current, StringTableSize))374 return Err;375 if (StringTableSize % 4 != 0)376 return parseFailed("String table misaligned");377 Current += sizeof(uint32_t);378 StringTable = StringRef(Current, StringTableSize);379 380 Current += StringTableSize;381 382 uint32_t SemanticIndexTableSize = 0;383 if (Error Err = readInteger(Data, Current, SemanticIndexTableSize))384 return Err;385 Current += sizeof(uint32_t);386 387 SemanticIndexTable.reserve(SemanticIndexTableSize);388 for (uint32_t I = 0; I < SemanticIndexTableSize; ++I) {389 uint32_t Index = 0;390 if (Error Err = readInteger(Data, Current, Index))391 return Err;392 Current += sizeof(uint32_t);393 SemanticIndexTable.push_back(Index);394 }395 396 uint8_t InputCount = getSigInputCount();397 uint8_t OutputCount = getSigOutputCount();398 uint8_t PatchOrPrimCount = getSigPatchOrPrimCount();399 400 uint32_t ElementCount = InputCount + OutputCount + PatchOrPrimCount;401 402 if (ElementCount > 0) {403 if (Error Err = readInteger(Data, Current, SigInputElements.Stride))404 return Err;405 Current += sizeof(uint32_t);406 // Assign the stride to all the arrays.407 SigOutputElements.Stride = SigPatchOrPrimElements.Stride =408 SigInputElements.Stride;409 410 if (Data.end() - Current <411 (ptrdiff_t)(ElementCount * SigInputElements.Stride))412 return parseFailed(413 "Signature elements extend beyond the size of the part");414 415 size_t InputSize = SigInputElements.Stride * InputCount;416 SigInputElements.Data = Data.substr(Current - Data.begin(), InputSize);417 Current += InputSize;418 419 size_t OutputSize = SigOutputElements.Stride * OutputCount;420 SigOutputElements.Data = Data.substr(Current - Data.begin(), OutputSize);421 Current += OutputSize;422 423 size_t PSize = SigPatchOrPrimElements.Stride * PatchOrPrimCount;424 SigPatchOrPrimElements.Data = Data.substr(Current - Data.begin(), PSize);425 Current += PSize;426 }427 428 ArrayRef<uint8_t> OutputVectorCounts = getOutputVectorCounts();429 uint8_t PatchConstOrPrimVectorCount = getPatchConstOrPrimVectorCount();430 uint8_t InputVectorCount = getInputVectorCount();431 432 auto maskDwordSize = [](uint8_t Vector) {433 return (static_cast<uint32_t>(Vector) + 7) >> 3;434 };435 436 auto mapTableSize = [maskDwordSize](uint8_t X, uint8_t Y) {437 return maskDwordSize(Y) * X * 4;438 };439 440 if (usesViewID()) {441 for (uint32_t I = 0; I < OutputVectorCounts.size(); ++I) {442 // The vector mask is one bit per component and 4 components per vector.443 // We can compute the number of dwords required by rounding up to the next444 // multiple of 8.445 uint32_t NumDwords =446 maskDwordSize(static_cast<uint32_t>(OutputVectorCounts[I]));447 size_t NumBytes = NumDwords * sizeof(uint32_t);448 OutputVectorMasks[I].Data = Data.substr(Current - Data.begin(), NumBytes);449 Current += NumBytes;450 }451 452 if (ShaderStage == Triple::Hull && PatchConstOrPrimVectorCount > 0) {453 uint32_t NumDwords = maskDwordSize(PatchConstOrPrimVectorCount);454 size_t NumBytes = NumDwords * sizeof(uint32_t);455 PatchOrPrimMasks.Data = Data.substr(Current - Data.begin(), NumBytes);456 Current += NumBytes;457 }458 }459 460 // Input/Output mapping table461 for (uint32_t I = 0; I < OutputVectorCounts.size(); ++I) {462 if (InputVectorCount == 0 || OutputVectorCounts[I] == 0)463 continue;464 uint32_t NumDwords = mapTableSize(InputVectorCount, OutputVectorCounts[I]);465 size_t NumBytes = NumDwords * sizeof(uint32_t);466 InputOutputMap[I].Data = Data.substr(Current - Data.begin(), NumBytes);467 Current += NumBytes;468 }469 470 // Hull shader: Input/Patch mapping table471 if (ShaderStage == Triple::Hull && PatchConstOrPrimVectorCount > 0 &&472 InputVectorCount > 0) {473 uint32_t NumDwords =474 mapTableSize(InputVectorCount, PatchConstOrPrimVectorCount);475 size_t NumBytes = NumDwords * sizeof(uint32_t);476 InputPatchMap.Data = Data.substr(Current - Data.begin(), NumBytes);477 Current += NumBytes;478 }479 480 // Domain Shader: Patch/Output mapping table481 if (ShaderStage == Triple::Domain && PatchConstOrPrimVectorCount > 0 &&482 OutputVectorCounts[0] > 0) {483 uint32_t NumDwords =484 mapTableSize(PatchConstOrPrimVectorCount, OutputVectorCounts[0]);485 size_t NumBytes = NumDwords * sizeof(uint32_t);486 PatchOutputMap.Data = Data.substr(Current - Data.begin(), NumBytes);487 Current += NumBytes;488 }489 490 return Error::success();491}492 493uint8_t DirectX::PSVRuntimeInfo::getSigInputCount() const {494 if (const auto *P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo))495 return P->SigInputElements;496 if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo))497 return P->SigInputElements;498 if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo))499 return P->SigInputElements;500 return 0;501}502 503uint8_t DirectX::PSVRuntimeInfo::getSigOutputCount() const {504 if (const auto *P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo))505 return P->SigOutputElements;506 if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo))507 return P->SigOutputElements;508 if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo))509 return P->SigOutputElements;510 return 0;511}512 513uint8_t DirectX::PSVRuntimeInfo::getSigPatchOrPrimCount() const {514 if (const auto *P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo))515 return P->SigPatchOrPrimElements;516 if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo))517 return P->SigPatchOrPrimElements;518 if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo))519 return P->SigPatchOrPrimElements;520 return 0;521}522 523class DXNotSupportedError : public ErrorInfo<DXNotSupportedError> {524public:525 static char ID;526 527 DXNotSupportedError(StringRef S) : FeatureString(S) {}528 529 void log(raw_ostream &OS) const override {530 OS << "DXContainer does not support " << FeatureString;531 }532 533 std::error_code convertToErrorCode() const override {534 return inconvertibleErrorCode();535 }536 537private:538 StringRef FeatureString;539};540 541char DXNotSupportedError::ID = 0;542 543Expected<section_iterator>544DXContainerObjectFile::getSymbolSection(DataRefImpl Symb) const {545 return make_error<DXNotSupportedError>("Symbol sections");546}547 548Expected<StringRef> DXContainerObjectFile::getSymbolName(DataRefImpl) const {549 return make_error<DXNotSupportedError>("Symbol names");550}551 552Expected<uint64_t>553DXContainerObjectFile::getSymbolAddress(DataRefImpl Symb) const {554 return make_error<DXNotSupportedError>("Symbol addresses");555}556 557uint64_t DXContainerObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {558 llvm_unreachable("DXContainer does not support symbols");559}560uint64_t561DXContainerObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {562 llvm_unreachable("DXContainer does not support symbols");563}564 565Expected<SymbolRef::Type>566DXContainerObjectFile::getSymbolType(DataRefImpl Symb) const {567 return make_error<DXNotSupportedError>("Symbol types");568}569 570void DXContainerObjectFile::moveSectionNext(DataRefImpl &Sec) const {571 PartIterator It = reinterpret_cast<PartIterator>(Sec.p);572 if (It == Parts.end())573 return;574 575 ++It;576 Sec.p = reinterpret_cast<uintptr_t>(It);577}578 579Expected<StringRef>580DXContainerObjectFile::getSectionName(DataRefImpl Sec) const {581 PartIterator It = reinterpret_cast<PartIterator>(Sec.p);582 return StringRef(It->Part.getName());583}584 585uint64_t DXContainerObjectFile::getSectionAddress(DataRefImpl Sec) const {586 PartIterator It = reinterpret_cast<PartIterator>(Sec.p);587 return It->Offset;588}589 590uint64_t DXContainerObjectFile::getSectionIndex(DataRefImpl Sec) const {591 return (Sec.p - reinterpret_cast<uintptr_t>(Parts.begin())) /592 sizeof(PartIterator);593}594 595uint64_t DXContainerObjectFile::getSectionSize(DataRefImpl Sec) const {596 PartIterator It = reinterpret_cast<PartIterator>(Sec.p);597 return It->Data.size();598}599Expected<ArrayRef<uint8_t>>600DXContainerObjectFile::getSectionContents(DataRefImpl Sec) const {601 PartIterator It = reinterpret_cast<PartIterator>(Sec.p);602 return ArrayRef<uint8_t>(It->Data.bytes_begin(), It->Data.size());603}604 605uint64_t DXContainerObjectFile::getSectionAlignment(DataRefImpl Sec) const {606 return 1;607}608 609bool DXContainerObjectFile::isSectionCompressed(DataRefImpl Sec) const {610 return false;611}612 613bool DXContainerObjectFile::isSectionText(DataRefImpl Sec) const {614 return false;615}616 617bool DXContainerObjectFile::isSectionData(DataRefImpl Sec) const {618 return false;619}620 621bool DXContainerObjectFile::isSectionBSS(DataRefImpl Sec) const {622 return false;623}624 625bool DXContainerObjectFile::isSectionVirtual(DataRefImpl Sec) const {626 return false;627}628 629relocation_iterator630DXContainerObjectFile::section_rel_begin(DataRefImpl Sec) const {631 return relocation_iterator(RelocationRef());632}633 634relocation_iterator635DXContainerObjectFile::section_rel_end(DataRefImpl Sec) const {636 return relocation_iterator(RelocationRef());637}638 639void DXContainerObjectFile::moveRelocationNext(DataRefImpl &Rel) const {640 llvm_unreachable("DXContainer does not support relocations");641}642 643uint64_t DXContainerObjectFile::getRelocationOffset(DataRefImpl Rel) const {644 llvm_unreachable("DXContainer does not support relocations");645}646 647symbol_iterator648DXContainerObjectFile::getRelocationSymbol(DataRefImpl Rel) const {649 return symbol_iterator(SymbolRef());650}651 652uint64_t DXContainerObjectFile::getRelocationType(DataRefImpl Rel) const {653 llvm_unreachable("DXContainer does not support relocations");654}655 656void DXContainerObjectFile::getRelocationTypeName(657 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {658 llvm_unreachable("DXContainer does not support relocations");659}660 661section_iterator DXContainerObjectFile::section_begin() const {662 DataRefImpl Sec;663 Sec.p = reinterpret_cast<uintptr_t>(Parts.begin());664 return section_iterator(SectionRef(Sec, this));665}666section_iterator DXContainerObjectFile::section_end() const {667 DataRefImpl Sec;668 Sec.p = reinterpret_cast<uintptr_t>(Parts.end());669 return section_iterator(SectionRef(Sec, this));670}671 672uint8_t DXContainerObjectFile::getBytesInAddress() const { return 4; }673 674StringRef DXContainerObjectFile::getFileFormatName() const {675 return "DirectX Container";676}677 678Triple::ArchType DXContainerObjectFile::getArch() const { return Triple::dxil; }679 680Expected<SubtargetFeatures> DXContainerObjectFile::getFeatures() const {681 return SubtargetFeatures();682}683 684Error DXContainerObjectFile::printSymbolName(raw_ostream &OS,685 DataRefImpl Symb) const {686 return make_error<DXNotSupportedError>("Symbol names");687}688 689Expected<uint32_t>690DXContainerObjectFile::getSymbolFlags(DataRefImpl Symb) const {691 return make_error<DXNotSupportedError>("Symbol flags");692}693 694Expected<std::unique_ptr<DXContainerObjectFile>>695ObjectFile::createDXContainerObjectFile(MemoryBufferRef Object) {696 auto ExC = DXContainer::create(Object);697 if (!ExC)698 return ExC.takeError();699 std::unique_ptr<DXContainerObjectFile> Obj(new DXContainerObjectFile(*ExC));700 return std::move(Obj);701}702