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