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