Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:39

0001 //===- CVRecord.h -----------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
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 /// CVRecord is a fat pointer (base + size pair) to a symbol or type record.
0027 /// Carrying the size separately instead of trusting the size stored in the
0028 /// record prefix provides some extra safety and flexibility.
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 // There are two kinds of codeview records: type and symbol records.
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 /// Read a complete record from a stream at a random offset.
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 } // end namespace codeview
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 } // namespace codeview
0130 
0131 } // end namespace llvm
0132 
0133 #endif // LLVM_DEBUGINFO_CODEVIEW_CVRECORD_H