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