19df3605dSDimitry Andric //===- DebugSubsectionRecord.cpp ------------------------------------------===//
2ee2f195dSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ee2f195dSDimitry Andric //
7ee2f195dSDimitry Andric //===----------------------------------------------------------------------===//
8ee2f195dSDimitry Andric
9ee2f195dSDimitry Andric #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
109df3605dSDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h"
11ee2f195dSDimitry Andric #include "llvm/DebugInfo/CodeView/DebugSubsection.h"
12ee2f195dSDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
139df3605dSDimitry Andric #include "llvm/Support/BinaryStreamWriter.h"
149df3605dSDimitry Andric #include "llvm/Support/Error.h"
159df3605dSDimitry Andric #include "llvm/Support/MathExtras.h"
169df3605dSDimitry Andric #include <cassert>
179df3605dSDimitry Andric #include <cstdint>
18ee2f195dSDimitry Andric
19ee2f195dSDimitry Andric using namespace llvm;
20ee2f195dSDimitry Andric using namespace llvm::codeview;
21ee2f195dSDimitry Andric
229df3605dSDimitry Andric DebugSubsectionRecord::DebugSubsectionRecord() = default;
23ee2f195dSDimitry Andric
DebugSubsectionRecord(DebugSubsectionKind Kind,BinaryStreamRef Data)24ee2f195dSDimitry Andric DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind,
25cfca06d7SDimitry Andric BinaryStreamRef Data)
26cfca06d7SDimitry Andric : Kind(Kind), Data(Data) {}
27ee2f195dSDimitry Andric
initialize(BinaryStreamRef Stream,DebugSubsectionRecord & Info)28ee2f195dSDimitry Andric Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream,
29cfca06d7SDimitry Andric DebugSubsectionRecord &Info) {
30ee2f195dSDimitry Andric const DebugSubsectionHeader *Header;
31ee2f195dSDimitry Andric BinaryStreamReader Reader(Stream);
32ee2f195dSDimitry Andric if (auto EC = Reader.readObject(Header))
33ee2f195dSDimitry Andric return EC;
34ee2f195dSDimitry Andric
35ee2f195dSDimitry Andric DebugSubsectionKind Kind =
36ee2f195dSDimitry Andric static_cast<DebugSubsectionKind>(uint32_t(Header->Kind));
37ee2f195dSDimitry Andric if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
38ee2f195dSDimitry Andric return EC;
39ee2f195dSDimitry Andric Info.Kind = Kind;
40ee2f195dSDimitry Andric return Error::success();
41ee2f195dSDimitry Andric }
42ee2f195dSDimitry Andric
getRecordLength() const43ee2f195dSDimitry Andric uint32_t DebugSubsectionRecord::getRecordLength() const {
447ab83427SDimitry Andric return sizeof(DebugSubsectionHeader) + Data.getLength();
45ee2f195dSDimitry Andric }
46ee2f195dSDimitry Andric
kind() const47ee2f195dSDimitry Andric DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; }
48ee2f195dSDimitry Andric
getRecordData() const49ee2f195dSDimitry Andric BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; }
50ee2f195dSDimitry Andric
DebugSubsectionRecordBuilder(std::shared_ptr<DebugSubsection> Subsection)51ee2f195dSDimitry Andric DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
52cfca06d7SDimitry Andric std::shared_ptr<DebugSubsection> Subsection)
53cfca06d7SDimitry Andric : Subsection(std::move(Subsection)) {}
54ee2f195dSDimitry Andric
DebugSubsectionRecordBuilder(const DebugSubsectionRecord & Contents)5508bbd35aSDimitry Andric DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
56cfca06d7SDimitry Andric const DebugSubsectionRecord &Contents)
57cfca06d7SDimitry Andric : Contents(Contents) {}
5808bbd35aSDimitry Andric
calculateSerializedLength() const59cfca06d7SDimitry Andric uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() const {
6008bbd35aSDimitry Andric uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
6108bbd35aSDimitry Andric : Contents.getRecordData().getLength();
6208bbd35aSDimitry Andric // The length of the entire subsection is always padded to 4 bytes,
6308bbd35aSDimitry Andric // regardless of the container kind.
6408bbd35aSDimitry Andric return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4);
65ee2f195dSDimitry Andric }
66ee2f195dSDimitry Andric
commit(BinaryStreamWriter & Writer,CodeViewContainer Container) const67cfca06d7SDimitry Andric Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer,
68cfca06d7SDimitry Andric CodeViewContainer Container) const {
69d288ef4cSDimitry Andric assert(Writer.getOffset() % alignOf(Container) == 0 &&
70d288ef4cSDimitry Andric "Debug Subsection not properly aligned");
71d288ef4cSDimitry Andric
72ee2f195dSDimitry Andric DebugSubsectionHeader Header;
7308bbd35aSDimitry Andric Header.Kind = uint32_t(Subsection ? Subsection->kind() : Contents.kind());
747ab83427SDimitry Andric // The value written into the Header's Length field is only padded to the
757ab83427SDimitry Andric // container's alignment
7608bbd35aSDimitry Andric uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
7708bbd35aSDimitry Andric : Contents.getRecordData().getLength();
7808bbd35aSDimitry Andric Header.Length = alignTo(DataSize, alignOf(Container));
79ee2f195dSDimitry Andric
80ee2f195dSDimitry Andric if (auto EC = Writer.writeObject(Header))
81ee2f195dSDimitry Andric return EC;
8208bbd35aSDimitry Andric if (Subsection) {
83d288ef4cSDimitry Andric if (auto EC = Subsection->commit(Writer))
84ee2f195dSDimitry Andric return EC;
8508bbd35aSDimitry Andric } else {
8608bbd35aSDimitry Andric if (auto EC = Writer.writeStreamRef(Contents.getRecordData()))
8708bbd35aSDimitry Andric return EC;
8808bbd35aSDimitry Andric }
897ab83427SDimitry Andric if (auto EC = Writer.padToAlignment(4))
90ee2f195dSDimitry Andric return EC;
91ee2f195dSDimitry Andric
92ee2f195dSDimitry Andric return Error::success();
93ee2f195dSDimitry Andric }
94