DxilContainer.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilContainer.cpp //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. // Provides support for manipulating DXIL container structures. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "dxc/DxilContainer/DxilContainer.h"
  12. #include <algorithm>
  13. namespace hlsl {
  14. DxilPartIterator begin(const DxilContainerHeader *pHeader) {
  15. return{ pHeader, 0 };
  16. }
  17. DxilPartIterator end(const DxilContainerHeader *pHeader) {
  18. return{ pHeader, pHeader->PartCount };
  19. }
  20. void InitDxilContainer(_Out_ DxilContainerHeader *pHeader, uint32_t partCount,
  21. uint32_t containerSizeInBytes) {
  22. memset(pHeader, 0, sizeof(*pHeader));
  23. pHeader->HeaderFourCC = DFCC_Container;
  24. pHeader->Version.Major = DxilContainerVersionMajor;
  25. pHeader->Version.Minor = DxilContainerVersionMinor;
  26. pHeader->PartCount = partCount;
  27. pHeader->ContainerSizeInBytes = containerSizeInBytes;
  28. }
  29. const DxilContainerHeader *IsDxilContainerLike(const void *ptr, size_t length) {
  30. if (ptr == nullptr || length < sizeof(DxilContainerHeader))
  31. return nullptr;
  32. if (DFCC_Container != *reinterpret_cast<const uint32_t *>(ptr))
  33. return nullptr;
  34. return reinterpret_cast<const DxilContainerHeader *>(ptr);
  35. }
  36. DxilContainerHeader *IsDxilContainerLike(void *ptr, size_t length) {
  37. return const_cast<DxilContainerHeader *>(IsDxilContainerLike(
  38. static_cast<const void *>(ptr), length));
  39. }
  40. bool IsValidDxilContainer(const DxilContainerHeader *pHeader, size_t length) {
  41. // Validate that the header is where it's supposed to be.
  42. if (pHeader == nullptr) return false;
  43. if (length < sizeof(DxilContainerHeader)) return false;
  44. // Validate the header values.
  45. if (pHeader->HeaderFourCC != DFCC_Container) return false;
  46. if (pHeader->Version.Major != DxilContainerVersionMajor) return false;
  47. if (pHeader->ContainerSizeInBytes > length) return false;
  48. if (pHeader->ContainerSizeInBytes > DxilContainerMaxSize) return false;
  49. // Make sure that the count of offsets fits.
  50. size_t partOffsetTableBytes = sizeof(uint32_t) * pHeader->PartCount;
  51. if (partOffsetTableBytes + sizeof(DxilContainerHeader) >
  52. pHeader->ContainerSizeInBytes)
  53. return false;
  54. // Make sure that each part is within the bounds.
  55. const uint8_t *pLinearContainer = reinterpret_cast<const uint8_t *>(pHeader);
  56. const uint32_t *pPartOffsetTable =
  57. reinterpret_cast<const uint32_t *>(pHeader + 1);
  58. for (uint32_t i = 0; i < pHeader->PartCount; ++i) {
  59. // The part header should fit.
  60. if (pPartOffsetTable[i] >
  61. (pHeader->ContainerSizeInBytes - sizeof(DxilPartHeader)))
  62. return false;
  63. // The contents of the part should fit.
  64. const DxilPartHeader *pPartHeader =
  65. reinterpret_cast<const DxilPartHeader *>(pLinearContainer +
  66. pPartOffsetTable[i]);
  67. if (pPartOffsetTable[i] + sizeof(DxilPartHeader) + pPartHeader->PartSize >
  68. pHeader->ContainerSizeInBytes) {
  69. return false;
  70. }
  71. }
  72. // Note: the container parts may overlap and there may be holes
  73. // based on this validation
  74. return true;
  75. }
  76. const DxilPartHeader *GetDxilPartByType(const DxilContainerHeader *pHeader, DxilFourCC fourCC) {
  77. if (!IsDxilContainerLike(pHeader, pHeader->ContainerSizeInBytes)) {
  78. return nullptr;
  79. }
  80. const DxilPartIterator partIter =
  81. find_if(begin(pHeader), end(pHeader), DxilPartIsType(fourCC));
  82. if (partIter == end(pHeader)) {
  83. return nullptr;
  84. }
  85. return *partIter;
  86. }
  87. DxilPartHeader *GetDxilPartByType(DxilContainerHeader *pHeader,
  88. DxilFourCC fourCC) {
  89. return const_cast<DxilPartHeader *>(GetDxilPartByType(
  90. static_cast<const DxilContainerHeader *>(pHeader), fourCC));
  91. }
  92. const DxilProgramHeader *GetDxilProgramHeader(const DxilContainerHeader *pHeader, DxilFourCC fourCC) {
  93. if (!IsDxilContainerLike(pHeader, pHeader->ContainerSizeInBytes)) {
  94. return nullptr;
  95. }
  96. const DxilPartHeader *PartHeader = GetDxilPartByType(pHeader, fourCC);
  97. if (!PartHeader) {
  98. return nullptr;
  99. }
  100. const DxilProgramHeader *ProgramHeader =
  101. reinterpret_cast<const DxilProgramHeader *>(GetDxilPartData(PartHeader));
  102. return IsValidDxilProgramHeader(ProgramHeader,
  103. ProgramHeader->SizeInUint32 * 4)
  104. ? ProgramHeader
  105. : nullptr;
  106. }
  107. DxilProgramHeader *GetDxilProgramHeader(DxilContainerHeader *pHeader, DxilFourCC fourCC) {
  108. return const_cast<DxilProgramHeader *>(
  109. GetDxilProgramHeader(static_cast<const DxilContainerHeader *>(pHeader), fourCC));
  110. }
  111. } // namespace hlsl