1*a580b014SDimitry Andric //===- DebugSubsectionRecord.h ----------------------------------*- C++ -*-===// 289cb50c9SDimitry Andric // 389cb50c9SDimitry Andric // The LLVM Compiler Infrastructure 489cb50c9SDimitry Andric // 589cb50c9SDimitry Andric // This file is distributed under the University of Illinois Open Source 689cb50c9SDimitry Andric // License. See LICENSE.TXT for details. 789cb50c9SDimitry Andric // 889cb50c9SDimitry Andric //===----------------------------------------------------------------------===// 989cb50c9SDimitry Andric 10*a580b014SDimitry Andric #ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGSUBSECTIONRECORD_H 11*a580b014SDimitry Andric #define LLVM_DEBUGINFO_CODEVIEW_DEBUGSUBSECTIONRECORD_H 1289cb50c9SDimitry Andric 1389cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h" 1489cb50c9SDimitry Andric #include "llvm/Support/BinaryStreamArray.h" 1589cb50c9SDimitry Andric #include "llvm/Support/BinaryStreamRef.h" 1689cb50c9SDimitry Andric #include "llvm/Support/Endian.h" 1789cb50c9SDimitry Andric #include "llvm/Support/Error.h" 18*a580b014SDimitry Andric #include "llvm/Support/MathExtras.h" 19*a580b014SDimitry Andric #include <cstdint> 20*a580b014SDimitry Andric #include <memory> 2189cb50c9SDimitry Andric 2289cb50c9SDimitry Andric namespace llvm { 23*a580b014SDimitry Andric 24*a580b014SDimitry Andric class BinaryStreamWriter; 25*a580b014SDimitry Andric 2689cb50c9SDimitry Andric namespace codeview { 2789cb50c9SDimitry Andric 2889cb50c9SDimitry Andric class DebugSubsection; 2989cb50c9SDimitry Andric 3089cb50c9SDimitry Andric // Corresponds to the `CV_DebugSSubsectionHeader_t` structure. 3189cb50c9SDimitry Andric struct DebugSubsectionHeader { 3289cb50c9SDimitry Andric support::ulittle32_t Kind; // codeview::DebugSubsectionKind enum 3389cb50c9SDimitry Andric support::ulittle32_t Length; // number of bytes occupied by this record. 3489cb50c9SDimitry Andric }; 3589cb50c9SDimitry Andric 3689cb50c9SDimitry Andric class DebugSubsectionRecord { 3789cb50c9SDimitry Andric public: 3889cb50c9SDimitry Andric DebugSubsectionRecord(); 396d97bb29SDimitry Andric DebugSubsectionRecord(DebugSubsectionKind Kind, BinaryStreamRef Data, 406d97bb29SDimitry Andric CodeViewContainer Container); 4189cb50c9SDimitry Andric 426d97bb29SDimitry Andric static Error initialize(BinaryStreamRef Stream, DebugSubsectionRecord &Info, 436d97bb29SDimitry Andric CodeViewContainer Container); 4489cb50c9SDimitry Andric 4589cb50c9SDimitry Andric uint32_t getRecordLength() const; 4689cb50c9SDimitry Andric DebugSubsectionKind kind() const; 4789cb50c9SDimitry Andric BinaryStreamRef getRecordData() const; 4889cb50c9SDimitry Andric 4989cb50c9SDimitry Andric private: 50*a580b014SDimitry Andric CodeViewContainer Container = CodeViewContainer::ObjectFile; 51*a580b014SDimitry Andric DebugSubsectionKind Kind = DebugSubsectionKind::None; 5289cb50c9SDimitry Andric BinaryStreamRef Data; 5389cb50c9SDimitry Andric }; 5489cb50c9SDimitry Andric 5589cb50c9SDimitry Andric class DebugSubsectionRecordBuilder { 5689cb50c9SDimitry Andric public: 5724d58133SDimitry Andric DebugSubsectionRecordBuilder(std::shared_ptr<DebugSubsection> Subsection, 586d97bb29SDimitry Andric CodeViewContainer Container); 59edd7eaddSDimitry Andric 60edd7eaddSDimitry Andric /// Use this to copy existing subsections directly from source to destination. 61edd7eaddSDimitry Andric /// For example, line table subsections in an object file only need to be 62edd7eaddSDimitry Andric /// relocated before being copied into the PDB. 63edd7eaddSDimitry Andric DebugSubsectionRecordBuilder(const DebugSubsectionRecord &Contents, 64edd7eaddSDimitry Andric CodeViewContainer Container); 65edd7eaddSDimitry Andric 6689cb50c9SDimitry Andric uint32_t calculateSerializedLength(); 67db17bf38SDimitry Andric Error commit(BinaryStreamWriter &Writer) const; 6889cb50c9SDimitry Andric 6989cb50c9SDimitry Andric private: 70edd7eaddSDimitry Andric /// The subsection to build. Will be null if Contents is non-empty. 7124d58133SDimitry Andric std::shared_ptr<DebugSubsection> Subsection; 72edd7eaddSDimitry Andric 73edd7eaddSDimitry Andric /// The bytes of the subsection. Only non-empty if Subsection is null. 74edd7eaddSDimitry Andric DebugSubsectionRecord Contents; 75edd7eaddSDimitry Andric 766d97bb29SDimitry Andric CodeViewContainer Container; 7789cb50c9SDimitry Andric }; 7889cb50c9SDimitry Andric 79*a580b014SDimitry Andric } // end namespace codeview 8089cb50c9SDimitry Andric 8189cb50c9SDimitry Andric template <> struct VarStreamArrayExtractor<codeview::DebugSubsectionRecord> { 82db17bf38SDimitry Andric Error operator()(BinaryStreamRef Stream, uint32_t &Length, 8389cb50c9SDimitry Andric codeview::DebugSubsectionRecord &Info) { 8424d58133SDimitry Andric // FIXME: We need to pass the container type through to this function. In 8524d58133SDimitry Andric // practice this isn't super important since the subsection header describes 8624d58133SDimitry Andric // its length and we can just skip it. It's more important when writing. 876d97bb29SDimitry Andric if (auto EC = codeview::DebugSubsectionRecord::initialize( 886d97bb29SDimitry Andric Stream, Info, codeview::CodeViewContainer::Pdb)) 8989cb50c9SDimitry Andric return EC; 90db17bf38SDimitry Andric Length = alignTo(Info.getRecordLength(), 4); 9189cb50c9SDimitry Andric return Error::success(); 9289cb50c9SDimitry Andric } 9389cb50c9SDimitry Andric }; 9489cb50c9SDimitry Andric 9589cb50c9SDimitry Andric namespace codeview { 9689cb50c9SDimitry Andric 97*a580b014SDimitry Andric using DebugSubsectionArray = VarStreamArray<DebugSubsectionRecord>; 98*a580b014SDimitry Andric 99*a580b014SDimitry Andric } // end namespace codeview 100*a580b014SDimitry Andric 101*a580b014SDimitry Andric } // end namespace llvm 102*a580b014SDimitry Andric 103*a580b014SDimitry Andric #endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGSUBSECTIONRECORD_H 104