xref: /llvm-project/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp (revision 81cde474e2c5a6280cb693b777ddcf473825ae8a)
18456b16eSEugene Zelenko //===- DebugSubsectionRecord.cpp ------------------------------------------===//
28c099fe0SZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68c099fe0SZachary Turner //
78c099fe0SZachary Turner //===----------------------------------------------------------------------===//
88c099fe0SZachary Turner 
98c099fe0SZachary Turner #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
108456b16eSEugene Zelenko #include "llvm/DebugInfo/CodeView/CodeView.h"
118c099fe0SZachary Turner #include "llvm/DebugInfo/CodeView/DebugSubsection.h"
128c099fe0SZachary Turner #include "llvm/Support/BinaryStreamReader.h"
138456b16eSEugene Zelenko #include "llvm/Support/BinaryStreamWriter.h"
148456b16eSEugene Zelenko #include "llvm/Support/Error.h"
158456b16eSEugene Zelenko #include "llvm/Support/MathExtras.h"
168456b16eSEugene Zelenko #include <cassert>
178456b16eSEugene Zelenko #include <cstdint>
188c099fe0SZachary Turner 
198c099fe0SZachary Turner using namespace llvm;
208c099fe0SZachary Turner using namespace llvm::codeview;
218c099fe0SZachary Turner 
228456b16eSEugene Zelenko DebugSubsectionRecord::DebugSubsectionRecord() = default;
238c099fe0SZachary Turner 
DebugSubsectionRecord(DebugSubsectionKind Kind,BinaryStreamRef Data)248c099fe0SZachary Turner DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind,
25*7af4bb16SReid Kleckner                                              BinaryStreamRef Data)
26*7af4bb16SReid Kleckner     : Kind(Kind), Data(Data) {}
278c099fe0SZachary Turner 
initialize(BinaryStreamRef Stream,DebugSubsectionRecord & Info)288c099fe0SZachary Turner Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream,
29*7af4bb16SReid Kleckner                                         DebugSubsectionRecord &Info) {
308c099fe0SZachary Turner   const DebugSubsectionHeader *Header;
318c099fe0SZachary Turner   BinaryStreamReader Reader(Stream);
328c099fe0SZachary Turner   if (auto EC = Reader.readObject(Header))
338c099fe0SZachary Turner     return EC;
348c099fe0SZachary Turner 
358c099fe0SZachary Turner   DebugSubsectionKind Kind =
368c099fe0SZachary Turner       static_cast<DebugSubsectionKind>(uint32_t(Header->Kind));
378c099fe0SZachary Turner   if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
388c099fe0SZachary Turner     return EC;
398c099fe0SZachary Turner   Info.Kind = Kind;
408c099fe0SZachary Turner   return Error::success();
418c099fe0SZachary Turner }
428c099fe0SZachary Turner 
getRecordLength() const438c099fe0SZachary Turner uint32_t DebugSubsectionRecord::getRecordLength() const {
44deb39130SZachary Turner   return sizeof(DebugSubsectionHeader) + Data.getLength();
458c099fe0SZachary Turner }
468c099fe0SZachary Turner 
kind() const478c099fe0SZachary Turner DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; }
488c099fe0SZachary Turner 
getRecordData() const498c099fe0SZachary Turner BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; }
508c099fe0SZachary Turner 
DebugSubsectionRecordBuilder(std::shared_ptr<DebugSubsection> Subsection)518c099fe0SZachary Turner DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
52*7af4bb16SReid Kleckner     std::shared_ptr<DebugSubsection> Subsection)
53*7af4bb16SReid Kleckner     : Subsection(std::move(Subsection)) {}
548c099fe0SZachary Turner 
DebugSubsectionRecordBuilder(const DebugSubsectionRecord & Contents)5544cdb109SReid Kleckner DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
56*7af4bb16SReid Kleckner     const DebugSubsectionRecord &Contents)
57*7af4bb16SReid Kleckner     : Contents(Contents) {}
5844cdb109SReid Kleckner 
calculateSerializedLength() const59*7af4bb16SReid Kleckner uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() const {
6044cdb109SReid Kleckner   uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
6144cdb109SReid Kleckner                                  : Contents.getRecordData().getLength();
6244cdb109SReid Kleckner   // The length of the entire subsection is always padded to 4 bytes,
6344cdb109SReid Kleckner   // regardless of the container kind.
6444cdb109SReid Kleckner   return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4);
658c099fe0SZachary Turner }
668c099fe0SZachary Turner 
commit(BinaryStreamWriter & Writer,CodeViewContainer Container) const67*7af4bb16SReid Kleckner Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer,
68*7af4bb16SReid Kleckner                                            CodeViewContainer Container) const {
69ebd3ae83SZachary Turner   assert(Writer.getOffset() % alignOf(Container) == 0 &&
70ebd3ae83SZachary Turner          "Debug Subsection not properly aligned");
71ebd3ae83SZachary Turner 
728c099fe0SZachary Turner   DebugSubsectionHeader Header;
7344cdb109SReid Kleckner   Header.Kind = uint32_t(Subsection ? Subsection->kind() : Contents.kind());
74deb39130SZachary Turner   // The value written into the Header's Length field is only padded to the
75deb39130SZachary Turner   // container's alignment
7644cdb109SReid Kleckner   uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
7744cdb109SReid Kleckner                                  : Contents.getRecordData().getLength();
7844cdb109SReid Kleckner   Header.Length = alignTo(DataSize, alignOf(Container));
798c099fe0SZachary Turner 
808c099fe0SZachary Turner   if (auto EC = Writer.writeObject(Header))
818c099fe0SZachary Turner     return EC;
8244cdb109SReid Kleckner   if (Subsection) {
8392dcdda6SZachary Turner     if (auto EC = Subsection->commit(Writer))
848c099fe0SZachary Turner       return EC;
8544cdb109SReid Kleckner   } else {
8644cdb109SReid Kleckner     if (auto EC = Writer.writeStreamRef(Contents.getRecordData()))
8744cdb109SReid Kleckner       return EC;
8844cdb109SReid Kleckner   }
89deb39130SZachary Turner   if (auto EC = Writer.padToAlignment(4))
908c099fe0SZachary Turner     return EC;
918c099fe0SZachary Turner 
928c099fe0SZachary Turner   return Error::success();
938c099fe0SZachary Turner }
94