xref: /src/contrib/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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