1 //===- DebugSubsectionRecord.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 9 #ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGSUBSECTIONRECORD_H 10 #define LLVM_DEBUGINFO_CODEVIEW_DEBUGSUBSECTIONRECORD_H 11 12 #include "llvm/DebugInfo/CodeView/CodeView.h" 13 #include "llvm/Support/BinaryStreamArray.h" 14 #include "llvm/Support/BinaryStreamRef.h" 15 #include "llvm/Support/Endian.h" 16 #include "llvm/Support/Error.h" 17 #include "llvm/Support/MathExtras.h" 18 #include <cstdint> 19 #include <memory> 20 21 namespace llvm { 22 23 class BinaryStreamWriter; 24 25 namespace codeview { 26 27 class DebugSubsection; 28 29 // Corresponds to the `CV_DebugSSubsectionHeader_t` structure. 30 struct DebugSubsectionHeader { 31 support::ulittle32_t Kind; // codeview::DebugSubsectionKind enum 32 support::ulittle32_t Length; // number of bytes occupied by this record. 33 }; 34 35 class DebugSubsectionRecord { 36 public: 37 DebugSubsectionRecord(); 38 DebugSubsectionRecord(DebugSubsectionKind Kind, BinaryStreamRef Data); 39 40 static Error initialize(BinaryStreamRef Stream, DebugSubsectionRecord &Info); 41 42 uint32_t getRecordLength() const; 43 DebugSubsectionKind kind() const; 44 BinaryStreamRef getRecordData() const; 45 46 private: 47 DebugSubsectionKind Kind = DebugSubsectionKind::None; 48 BinaryStreamRef Data; 49 }; 50 51 class DebugSubsectionRecordBuilder { 52 public: 53 DebugSubsectionRecordBuilder(std::shared_ptr<DebugSubsection> Subsection); 54 55 /// Use this to copy existing subsections directly from source to destination. 56 /// For example, line table subsections in an object file only need to be 57 /// relocated before being copied into the PDB. 58 DebugSubsectionRecordBuilder(const DebugSubsectionRecord &Contents); 59 60 uint32_t calculateSerializedLength() const; 61 Error commit(BinaryStreamWriter &Writer, CodeViewContainer Container) const; 62 63 private: 64 /// The subsection to build. Will be null if Contents is non-empty. 65 std::shared_ptr<DebugSubsection> Subsection; 66 67 /// The bytes of the subsection. Only non-empty if Subsection is null. 68 /// FIXME: Reduce the size of this. 69 DebugSubsectionRecord Contents; 70 }; 71 72 } // end namespace codeview 73 74 template <> struct VarStreamArrayExtractor<codeview::DebugSubsectionRecord> { 75 Error operator()(BinaryStreamRef Stream, uint32_t &Length, 76 codeview::DebugSubsectionRecord &Info) { 77 // FIXME: We need to pass the container type through to this function. In 78 // practice this isn't super important since the subsection header describes 79 // its length and we can just skip it. It's more important when writing. 80 if (auto EC = codeview::DebugSubsectionRecord::initialize(Stream, Info)) 81 return EC; 82 Length = alignTo(Info.getRecordLength(), 4); 83 return Error::success(); 84 } 85 }; 86 87 namespace codeview { 88 89 using DebugSubsectionArray = VarStreamArray<DebugSubsectionRecord>; 90 91 } // end namespace codeview 92 93 } // end namespace llvm 94 95 #endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGSUBSECTIONRECORD_H 96