1*a580b014SDimitry Andric //===- DebugSubsectionRecord.cpp ------------------------------------------===//
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 
1089cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
11*a580b014SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h"
1289cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugSubsection.h"
1389cb50c9SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
14*a580b014SDimitry Andric #include "llvm/Support/BinaryStreamWriter.h"
15*a580b014SDimitry Andric #include "llvm/Support/Error.h"
16*a580b014SDimitry Andric #include "llvm/Support/MathExtras.h"
17*a580b014SDimitry Andric #include <algorithm>
18*a580b014SDimitry Andric #include <cassert>
19*a580b014SDimitry Andric #include <cstdint>
2089cb50c9SDimitry Andric 
2189cb50c9SDimitry Andric using namespace llvm;
2289cb50c9SDimitry Andric using namespace llvm::codeview;
2389cb50c9SDimitry Andric 
24*a580b014SDimitry Andric DebugSubsectionRecord::DebugSubsectionRecord() = default;
2589cb50c9SDimitry Andric 
DebugSubsectionRecord(DebugSubsectionKind Kind,BinaryStreamRef Data,CodeViewContainer Container)2689cb50c9SDimitry Andric DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind,
276d97bb29SDimitry Andric                                              BinaryStreamRef Data,
286d97bb29SDimitry Andric                                              CodeViewContainer Container)
296d97bb29SDimitry Andric     : Container(Container), Kind(Kind), Data(Data) {}
3089cb50c9SDimitry Andric 
initialize(BinaryStreamRef Stream,DebugSubsectionRecord & Info,CodeViewContainer Container)3189cb50c9SDimitry Andric Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream,
326d97bb29SDimitry Andric                                         DebugSubsectionRecord &Info,
336d97bb29SDimitry Andric                                         CodeViewContainer Container) {
3489cb50c9SDimitry Andric   const DebugSubsectionHeader *Header;
3589cb50c9SDimitry Andric   BinaryStreamReader Reader(Stream);
3689cb50c9SDimitry Andric   if (auto EC = Reader.readObject(Header))
3789cb50c9SDimitry Andric     return EC;
3889cb50c9SDimitry Andric 
3989cb50c9SDimitry Andric   DebugSubsectionKind Kind =
4089cb50c9SDimitry Andric       static_cast<DebugSubsectionKind>(uint32_t(Header->Kind));
4189cb50c9SDimitry Andric   if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
4289cb50c9SDimitry Andric     return EC;
436d97bb29SDimitry Andric   Info.Container = Container;
4489cb50c9SDimitry Andric   Info.Kind = Kind;
4589cb50c9SDimitry Andric   return Error::success();
4689cb50c9SDimitry Andric }
4789cb50c9SDimitry Andric 
getRecordLength() const4889cb50c9SDimitry Andric uint32_t DebugSubsectionRecord::getRecordLength() const {
49db17bf38SDimitry Andric   return sizeof(DebugSubsectionHeader) + Data.getLength();
5089cb50c9SDimitry Andric }
5189cb50c9SDimitry Andric 
kind() const5289cb50c9SDimitry Andric DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; }
5389cb50c9SDimitry Andric 
getRecordData() const5489cb50c9SDimitry Andric BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; }
5589cb50c9SDimitry Andric 
DebugSubsectionRecordBuilder(std::shared_ptr<DebugSubsection> Subsection,CodeViewContainer Container)5689cb50c9SDimitry Andric DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
5724d58133SDimitry Andric     std::shared_ptr<DebugSubsection> Subsection, CodeViewContainer Container)
586d97bb29SDimitry Andric     : Subsection(std::move(Subsection)), Container(Container) {}
5989cb50c9SDimitry Andric 
DebugSubsectionRecordBuilder(const DebugSubsectionRecord & Contents,CodeViewContainer Container)60edd7eaddSDimitry Andric DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
61edd7eaddSDimitry Andric     const DebugSubsectionRecord &Contents, CodeViewContainer Container)
62edd7eaddSDimitry Andric     : Contents(Contents), Container(Container) {}
63edd7eaddSDimitry Andric 
calculateSerializedLength()6489cb50c9SDimitry Andric uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() {
65edd7eaddSDimitry Andric   uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
66edd7eaddSDimitry Andric                                  : Contents.getRecordData().getLength();
67edd7eaddSDimitry Andric   // The length of the entire subsection is always padded to 4 bytes,
68edd7eaddSDimitry Andric   // regardless of the container kind.
69edd7eaddSDimitry Andric   return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4);
7089cb50c9SDimitry Andric }
7189cb50c9SDimitry Andric 
commit(BinaryStreamWriter & Writer) const72db17bf38SDimitry Andric Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const {
736d97bb29SDimitry Andric   assert(Writer.getOffset() % alignOf(Container) == 0 &&
746d97bb29SDimitry Andric          "Debug Subsection not properly aligned");
756d97bb29SDimitry Andric 
7689cb50c9SDimitry Andric   DebugSubsectionHeader Header;
77edd7eaddSDimitry Andric   Header.Kind = uint32_t(Subsection ? Subsection->kind() : Contents.kind());
78db17bf38SDimitry Andric   // The value written into the Header's Length field is only padded to the
79db17bf38SDimitry Andric   // container's alignment
80edd7eaddSDimitry Andric   uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
81edd7eaddSDimitry Andric                                  : Contents.getRecordData().getLength();
82edd7eaddSDimitry Andric   Header.Length = alignTo(DataSize, alignOf(Container));
8389cb50c9SDimitry Andric 
8489cb50c9SDimitry Andric   if (auto EC = Writer.writeObject(Header))
8589cb50c9SDimitry Andric     return EC;
86edd7eaddSDimitry Andric   if (Subsection) {
876d97bb29SDimitry Andric     if (auto EC = Subsection->commit(Writer))
8889cb50c9SDimitry Andric       return EC;
89edd7eaddSDimitry Andric   } else {
90edd7eaddSDimitry Andric     if (auto EC = Writer.writeStreamRef(Contents.getRecordData()))
91edd7eaddSDimitry Andric       return EC;
92edd7eaddSDimitry Andric   }
93db17bf38SDimitry Andric   if (auto EC = Writer.padToAlignment(4))
9489cb50c9SDimitry Andric     return EC;
9589cb50c9SDimitry Andric 
9689cb50c9SDimitry Andric   return Error::success();
9789cb50c9SDimitry Andric }
98