File indexing completed on 2026-05-10 08:43:39
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_DEBUGINFO_CODEVIEW_CVRECORD_H
0010 #define LLVM_DEBUGINFO_CODEVIEW_CVRECORD_H
0011
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/DebugInfo/CodeView/CodeView.h"
0014 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
0015 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
0016 #include "llvm/Support/BinaryStreamReader.h"
0017 #include "llvm/Support/BinaryStreamRef.h"
0018 #include "llvm/Support/Endian.h"
0019 #include "llvm/Support/Error.h"
0020 #include <cstdint>
0021
0022 namespace llvm {
0023
0024 namespace codeview {
0025
0026
0027
0028
0029 template <typename Kind> class CVRecord {
0030 public:
0031 CVRecord() = default;
0032
0033 CVRecord(ArrayRef<uint8_t> Data) : RecordData(Data) {}
0034
0035 CVRecord(const RecordPrefix *P, size_t Size)
0036 : RecordData(reinterpret_cast<const uint8_t *>(P), Size) {}
0037
0038 bool valid() const { return kind() != Kind(0); }
0039
0040 uint32_t length() const { return RecordData.size(); }
0041
0042 Kind kind() const {
0043 if (RecordData.size() < sizeof(RecordPrefix))
0044 return Kind(0);
0045 return static_cast<Kind>(static_cast<uint16_t>(
0046 reinterpret_cast<const RecordPrefix *>(RecordData.data())->RecordKind));
0047 }
0048
0049 ArrayRef<uint8_t> data() const { return RecordData; }
0050
0051 StringRef str_data() const {
0052 return StringRef(reinterpret_cast<const char *>(RecordData.data()),
0053 RecordData.size());
0054 }
0055
0056 ArrayRef<uint8_t> content() const {
0057 return RecordData.drop_front(sizeof(RecordPrefix));
0058 }
0059
0060 ArrayRef<uint8_t> RecordData;
0061 };
0062
0063
0064 using CVType = CVRecord<TypeLeafKind>;
0065 using CVSymbol = CVRecord<SymbolKind>;
0066
0067 template <typename Record, typename Func>
0068 Error forEachCodeViewRecord(ArrayRef<uint8_t> StreamBuffer, Func F) {
0069 while (!StreamBuffer.empty()) {
0070 if (StreamBuffer.size() < sizeof(RecordPrefix))
0071 return make_error<CodeViewError>(cv_error_code::corrupt_record);
0072
0073 const RecordPrefix *Prefix =
0074 reinterpret_cast<const RecordPrefix *>(StreamBuffer.data());
0075
0076 size_t RealLen = Prefix->RecordLen + 2;
0077 if (StreamBuffer.size() < RealLen)
0078 return make_error<CodeViewError>(cv_error_code::corrupt_record);
0079
0080 ArrayRef<uint8_t> Data = StreamBuffer.take_front(RealLen);
0081 StreamBuffer = StreamBuffer.drop_front(RealLen);
0082
0083 Record R(Data);
0084 if (auto EC = F(R))
0085 return EC;
0086 }
0087 return Error::success();
0088 }
0089
0090
0091 template <typename Kind>
0092 inline Expected<CVRecord<Kind>> readCVRecordFromStream(BinaryStreamRef Stream,
0093 uint32_t Offset) {
0094 const RecordPrefix *Prefix = nullptr;
0095 BinaryStreamReader Reader(Stream);
0096 Reader.setOffset(Offset);
0097
0098 if (auto EC = Reader.readObject(Prefix))
0099 return std::move(EC);
0100 if (Prefix->RecordLen < 2)
0101 return make_error<CodeViewError>(cv_error_code::corrupt_record);
0102
0103 Reader.setOffset(Offset);
0104 ArrayRef<uint8_t> RawData;
0105 if (auto EC = Reader.readBytes(RawData, Prefix->RecordLen + sizeof(uint16_t)))
0106 return std::move(EC);
0107 return codeview::CVRecord<Kind>(RawData);
0108 }
0109
0110 }
0111
0112 template <typename Kind>
0113 struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> {
0114 Error operator()(BinaryStreamRef Stream, uint32_t &Len,
0115 codeview::CVRecord<Kind> &Item) {
0116 auto ExpectedRec = codeview::readCVRecordFromStream<Kind>(Stream, 0);
0117 if (!ExpectedRec)
0118 return ExpectedRec.takeError();
0119 Item = *ExpectedRec;
0120 Len = ExpectedRec->length();
0121 return Error::success();
0122 }
0123 };
0124
0125 namespace codeview {
0126 using CVSymbolArray = VarStreamArray<CVSymbol>;
0127 using CVTypeArray = VarStreamArray<CVType>;
0128 using CVTypeRange = iterator_range<CVTypeArray::Iterator>;
0129 }
0130
0131 }
0132
0133 #endif