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 <algorithm> 178456b16eSEugene Zelenko #include <cassert> 188456b16eSEugene Zelenko #include <cstdint> 198c099fe0SZachary Turner 208c099fe0SZachary Turner using namespace llvm; 218c099fe0SZachary Turner using namespace llvm::codeview; 228c099fe0SZachary Turner 238456b16eSEugene Zelenko DebugSubsectionRecord::DebugSubsectionRecord() = default; 248c099fe0SZachary Turner 258c099fe0SZachary Turner DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind, 26*7af4bb16SReid Kleckner BinaryStreamRef Data) 27*7af4bb16SReid Kleckner : Kind(Kind), Data(Data) {} 288c099fe0SZachary Turner 298c099fe0SZachary Turner Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream, 30*7af4bb16SReid Kleckner DebugSubsectionRecord &Info) { 318c099fe0SZachary Turner const DebugSubsectionHeader *Header; 328c099fe0SZachary Turner BinaryStreamReader Reader(Stream); 338c099fe0SZachary Turner if (auto EC = Reader.readObject(Header)) 348c099fe0SZachary Turner return EC; 358c099fe0SZachary Turner 368c099fe0SZachary Turner DebugSubsectionKind Kind = 378c099fe0SZachary Turner static_cast<DebugSubsectionKind>(uint32_t(Header->Kind)); 388c099fe0SZachary Turner if (auto EC = Reader.readStreamRef(Info.Data, Header->Length)) 398c099fe0SZachary Turner return EC; 408c099fe0SZachary Turner Info.Kind = Kind; 418c099fe0SZachary Turner return Error::success(); 428c099fe0SZachary Turner } 438c099fe0SZachary Turner 448c099fe0SZachary Turner uint32_t DebugSubsectionRecord::getRecordLength() const { 45deb39130SZachary Turner return sizeof(DebugSubsectionHeader) + Data.getLength(); 468c099fe0SZachary Turner } 478c099fe0SZachary Turner 488c099fe0SZachary Turner DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; } 498c099fe0SZachary Turner 508c099fe0SZachary Turner BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; } 518c099fe0SZachary Turner 528c099fe0SZachary Turner DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( 53*7af4bb16SReid Kleckner std::shared_ptr<DebugSubsection> Subsection) 54*7af4bb16SReid Kleckner : Subsection(std::move(Subsection)) {} 558c099fe0SZachary Turner 5644cdb109SReid Kleckner DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( 57*7af4bb16SReid Kleckner const DebugSubsectionRecord &Contents) 58*7af4bb16SReid Kleckner : Contents(Contents) {} 5944cdb109SReid Kleckner 60*7af4bb16SReid Kleckner uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() const { 6144cdb109SReid Kleckner uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize() 6244cdb109SReid Kleckner : Contents.getRecordData().getLength(); 6344cdb109SReid Kleckner // The length of the entire subsection is always padded to 4 bytes, 6444cdb109SReid Kleckner // regardless of the container kind. 6544cdb109SReid Kleckner return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4); 668c099fe0SZachary Turner } 678c099fe0SZachary Turner 68*7af4bb16SReid Kleckner Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer, 69*7af4bb16SReid Kleckner CodeViewContainer Container) const { 70ebd3ae83SZachary Turner assert(Writer.getOffset() % alignOf(Container) == 0 && 71ebd3ae83SZachary Turner "Debug Subsection not properly aligned"); 72ebd3ae83SZachary Turner 738c099fe0SZachary Turner DebugSubsectionHeader Header; 7444cdb109SReid Kleckner Header.Kind = uint32_t(Subsection ? Subsection->kind() : Contents.kind()); 75deb39130SZachary Turner // The value written into the Header's Length field is only padded to the 76deb39130SZachary Turner // container's alignment 7744cdb109SReid Kleckner uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize() 7844cdb109SReid Kleckner : Contents.getRecordData().getLength(); 7944cdb109SReid Kleckner Header.Length = alignTo(DataSize, alignOf(Container)); 808c099fe0SZachary Turner 818c099fe0SZachary Turner if (auto EC = Writer.writeObject(Header)) 828c099fe0SZachary Turner return EC; 8344cdb109SReid Kleckner if (Subsection) { 8492dcdda6SZachary Turner if (auto EC = Subsection->commit(Writer)) 858c099fe0SZachary Turner return EC; 8644cdb109SReid Kleckner } else { 8744cdb109SReid Kleckner if (auto EC = Writer.writeStreamRef(Contents.getRecordData())) 8844cdb109SReid Kleckner return EC; 8944cdb109SReid Kleckner } 90deb39130SZachary Turner if (auto EC = Writer.padToAlignment(4)) 918c099fe0SZachary Turner return EC; 928c099fe0SZachary Turner 938c099fe0SZachary Turner return Error::success(); 948c099fe0SZachary Turner } 95