CodeViewRecordIO.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. //===- CodeViewRecordIO.h ---------------------------------------*- C++ -*-===//
  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-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #ifndef LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
  9. #define LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
  10. #include "llvm/ADT/APSInt.h"
  11. #include "llvm/ADT/None.h"
  12. #include "llvm/ADT/Optional.h"
  13. #include "llvm/ADT/SmallVector.h"
  14. #include "llvm/ADT/StringRef.h"
  15. #include "llvm/DebugInfo/CodeView/CodeViewError.h"
  16. #include "llvm/DebugInfo/CodeView/TypeRecord.h"
  17. #include "llvm/Support/BinaryStreamReader.h"
  18. #include "llvm/Support/BinaryStreamWriter.h"
  19. #include "llvm/Support/Error.h"
  20. #include <cassert>
  21. #include <cstdint>
  22. #include <type_traits>
  23. namespace llvm {
  24. namespace codeview {
  25. class CodeViewRecordStreamer {
  26. public:
  27. virtual void EmitBytes(StringRef Data) = 0;
  28. virtual void EmitIntValue(uint64_t Value, unsigned Size) = 0;
  29. virtual void EmitBinaryData(StringRef Data) = 0;
  30. virtual ~CodeViewRecordStreamer() = default;
  31. };
  32. class CodeViewRecordIO {
  33. uint32_t getCurrentOffset() const {
  34. if (isWriting())
  35. return Writer->getOffset();
  36. else if (isReading())
  37. return Reader->getOffset();
  38. else
  39. return 0;
  40. }
  41. public:
  42. // deserializes records to structures
  43. explicit CodeViewRecordIO(BinaryStreamReader &Reader) : Reader(&Reader) {}
  44. // serializes records to buffer
  45. explicit CodeViewRecordIO(BinaryStreamWriter &Writer) : Writer(&Writer) {}
  46. // writes records to assembly file using MC library interface
  47. explicit CodeViewRecordIO(CodeViewRecordStreamer &Streamer)
  48. : Streamer(&Streamer) {}
  49. Error beginRecord(Optional<uint32_t> MaxLength);
  50. Error endRecord();
  51. Error mapInteger(TypeIndex &TypeInd);
  52. bool isStreaming() const {
  53. return (Streamer != nullptr) && (Reader == nullptr) && (Writer == nullptr);
  54. }
  55. bool isReading() const {
  56. return (Reader != nullptr) && (Streamer == nullptr) && (Writer == nullptr);
  57. }
  58. bool isWriting() const {
  59. return (Writer != nullptr) && (Streamer == nullptr) && (Reader == nullptr);
  60. }
  61. uint32_t maxFieldLength() const;
  62. template <typename T> Error mapObject(T &Value) {
  63. if (isStreaming()) {
  64. StringRef BytesSR =
  65. StringRef((reinterpret_cast<const char *>(&Value)), sizeof(Value));
  66. Streamer->EmitBytes(BytesSR);
  67. incrStreamedLen(sizeof(T));
  68. return Error::success();
  69. }
  70. if (isWriting())
  71. return Writer->writeObject(Value);
  72. const T *ValuePtr;
  73. if (auto EC = Reader->readObject(ValuePtr))
  74. return EC;
  75. Value = *ValuePtr;
  76. return Error::success();
  77. }
  78. template <typename T> Error mapInteger(T &Value) {
  79. if (isStreaming()) {
  80. Streamer->EmitIntValue((int)Value, sizeof(T));
  81. incrStreamedLen(sizeof(T));
  82. return Error::success();
  83. }
  84. if (isWriting())
  85. return Writer->writeInteger(Value);
  86. return Reader->readInteger(Value);
  87. }
  88. template <typename T> Error mapEnum(T &Value) {
  89. if (!isStreaming() && sizeof(Value) > maxFieldLength())
  90. return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
  91. using U = typename std::underlying_type<T>::type;
  92. U X;
  93. if (isWriting() || isStreaming())
  94. X = static_cast<U>(Value);
  95. if (auto EC = mapInteger(X))
  96. return EC;
  97. if (isReading())
  98. Value = static_cast<T>(X);
  99. return Error::success();
  100. }
  101. Error mapEncodedInteger(int64_t &Value);
  102. Error mapEncodedInteger(uint64_t &Value);
  103. Error mapEncodedInteger(APSInt &Value);
  104. Error mapStringZ(StringRef &Value);
  105. Error mapGuid(GUID &Guid);
  106. Error mapStringZVectorZ(std::vector<StringRef> &Value);
  107. template <typename SizeType, typename T, typename ElementMapper>
  108. Error mapVectorN(T &Items, const ElementMapper &Mapper) {
  109. SizeType Size;
  110. if (isStreaming()) {
  111. Size = static_cast<SizeType>(Items.size());
  112. Streamer->EmitIntValue(Size, sizeof(Size));
  113. incrStreamedLen(sizeof(Size)); // add 1 for the delimiter
  114. for (auto &X : Items) {
  115. if (auto EC = Mapper(*this, X))
  116. return EC;
  117. }
  118. } else if (isWriting()) {
  119. Size = static_cast<SizeType>(Items.size());
  120. if (auto EC = Writer->writeInteger(Size))
  121. return EC;
  122. for (auto &X : Items) {
  123. if (auto EC = Mapper(*this, X))
  124. return EC;
  125. }
  126. } else {
  127. if (auto EC = Reader->readInteger(Size))
  128. return EC;
  129. for (SizeType I = 0; I < Size; ++I) {
  130. typename T::value_type Item;
  131. if (auto EC = Mapper(*this, Item))
  132. return EC;
  133. Items.push_back(Item);
  134. }
  135. }
  136. return Error::success();
  137. }
  138. template <typename T, typename ElementMapper>
  139. Error mapVectorTail(T &Items, const ElementMapper &Mapper) {
  140. if (isStreaming() || isWriting()) {
  141. for (auto &Item : Items) {
  142. if (auto EC = Mapper(*this, Item))
  143. return EC;
  144. }
  145. } else {
  146. typename T::value_type Field;
  147. // Stop when we run out of bytes or we hit record padding bytes.
  148. while (!Reader->empty() && Reader->peek() < 0xf0 /* LF_PAD0 */) {
  149. if (auto EC = Mapper(*this, Field))
  150. return EC;
  151. Items.push_back(Field);
  152. }
  153. }
  154. return Error::success();
  155. }
  156. Error mapByteVectorTail(ArrayRef<uint8_t> &Bytes);
  157. Error mapByteVectorTail(std::vector<uint8_t> &Bytes);
  158. Error padToAlignment(uint32_t Align);
  159. Error skipPadding();
  160. uint64_t getStreamedLen() {
  161. if (isStreaming())
  162. return StreamedLen;
  163. return 0;
  164. }
  165. private:
  166. void emitEncodedSignedInteger(const int64_t &Value);
  167. void emitEncodedUnsignedInteger(const uint64_t &Value);
  168. Error writeEncodedSignedInteger(const int64_t &Value);
  169. Error writeEncodedUnsignedInteger(const uint64_t &Value);
  170. void incrStreamedLen(const uint64_t &Len) {
  171. if (isStreaming())
  172. StreamedLen += Len;
  173. }
  174. void resetStreamedLen() {
  175. if (isStreaming())
  176. StreamedLen = 4; // The record prefix is 4 bytes long
  177. }
  178. struct RecordLimit {
  179. uint32_t BeginOffset;
  180. Optional<uint32_t> MaxLength;
  181. Optional<uint32_t> bytesRemaining(uint32_t CurrentOffset) const {
  182. if (!MaxLength.hasValue())
  183. return None;
  184. assert(CurrentOffset >= BeginOffset);
  185. uint32_t BytesUsed = CurrentOffset - BeginOffset;
  186. if (BytesUsed >= *MaxLength)
  187. return 0;
  188. return *MaxLength - BytesUsed;
  189. }
  190. };
  191. SmallVector<RecordLimit, 2> Limits;
  192. BinaryStreamReader *Reader = nullptr;
  193. BinaryStreamWriter *Writer = nullptr;
  194. CodeViewRecordStreamer *Streamer = nullptr;
  195. uint64_t StreamedLen = 0;
  196. };
  197. } // end namespace codeview
  198. } // end namespace llvm
  199. #endif // LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H