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 CodeViewContainer Container); 40 41 static Error initialize(BinaryStreamRef Stream, DebugSubsectionRecord &Info, 42 CodeViewContainer Container); 43 44 uint32_t getRecordLength() const; 45 DebugSubsectionKind kind() const; 46 BinaryStreamRef getRecordData() const; 47 48 private: 49 CodeViewContainer Container = CodeViewContainer::ObjectFile; 50 DebugSubsectionKind Kind = DebugSubsectionKind::None; 51 BinaryStreamRef Data; 52 }; 53 54 class DebugSubsectionRecordBuilder { 55 public: 56 DebugSubsectionRecordBuilder(std::shared_ptr<DebugSubsection> Subsection, 57 CodeViewContainer Container); 58 59 /// Use this to copy existing subsections directly from source to destination. 60 /// For example, line table subsections in an object file only need to be 61 /// relocated before being copied into the PDB. 62 DebugSubsectionRecordBuilder(const DebugSubsectionRecord &Contents, 63 CodeViewContainer Container); 64 65 uint32_t calculateSerializedLength(); 66 Error commit(BinaryStreamWriter &Writer) const; 67 68 private: 69 /// The subsection to build. Will be null if Contents is non-empty. 70 std::shared_ptr<DebugSubsection> Subsection; 71 72 /// The bytes of the subsection. Only non-empty if Subsection is null. 73 DebugSubsectionRecord Contents; 74 75 CodeViewContainer Container; 76 }; 77 78 } // end namespace codeview 79 80 template <> struct VarStreamArrayExtractor<codeview::DebugSubsectionRecord> { 81 Error operator()(BinaryStreamRef Stream, uint32_t &Length, 82 codeview::DebugSubsectionRecord &Info) { 83 // FIXME: We need to pass the container type through to this function. In 84 // practice this isn't super important since the subsection header describes 85 // its length and we can just skip it. It's more important when writing. 86 if (auto EC = codeview::DebugSubsectionRecord::initialize( 87 Stream, Info, codeview::CodeViewContainer::Pdb)) 88 return EC; 89 Length = alignTo(Info.getRecordLength(), 4); 90 return Error::success(); 91 } 92 }; 93 94 namespace codeview { 95 96 using DebugSubsectionArray = VarStreamArray<DebugSubsectionRecord>; 97 98 } // end namespace codeview 99 100 } // end namespace llvm 101 102 #endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGSUBSECTIONRECORD_H 103