1*8456b16eSEugene Zelenko //===- DebugSubsectionRecord.cpp ------------------------------------------===// 28c099fe0SZachary Turner // 38c099fe0SZachary Turner // The LLVM Compiler Infrastructure 48c099fe0SZachary Turner // 58c099fe0SZachary Turner // This file is distributed under the University of Illinois Open Source 68c099fe0SZachary Turner // License. See LICENSE.TXT for details. 78c099fe0SZachary Turner // 88c099fe0SZachary Turner //===----------------------------------------------------------------------===// 98c099fe0SZachary Turner 108c099fe0SZachary Turner #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" 11*8456b16eSEugene Zelenko #include "llvm/DebugInfo/CodeView/CodeView.h" 128c099fe0SZachary Turner #include "llvm/DebugInfo/CodeView/DebugSubsection.h" 138c099fe0SZachary Turner #include "llvm/Support/BinaryStreamReader.h" 14*8456b16eSEugene Zelenko #include "llvm/Support/BinaryStreamWriter.h" 15*8456b16eSEugene Zelenko #include "llvm/Support/Error.h" 16*8456b16eSEugene Zelenko #include "llvm/Support/MathExtras.h" 17*8456b16eSEugene Zelenko #include <algorithm> 18*8456b16eSEugene Zelenko #include <cassert> 19*8456b16eSEugene Zelenko #include <cstdint> 208c099fe0SZachary Turner 218c099fe0SZachary Turner using namespace llvm; 228c099fe0SZachary Turner using namespace llvm::codeview; 238c099fe0SZachary Turner 24*8456b16eSEugene Zelenko DebugSubsectionRecord::DebugSubsectionRecord() = default; 258c099fe0SZachary Turner 268c099fe0SZachary Turner DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind, 27ebd3ae83SZachary Turner BinaryStreamRef Data, 28ebd3ae83SZachary Turner CodeViewContainer Container) 29afb81a83SZachary Turner : Container(Container), Kind(Kind), Data(Data) {} 308c099fe0SZachary Turner 318c099fe0SZachary Turner Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream, 32ebd3ae83SZachary Turner DebugSubsectionRecord &Info, 33ebd3ae83SZachary Turner CodeViewContainer Container) { 348c099fe0SZachary Turner const DebugSubsectionHeader *Header; 358c099fe0SZachary Turner BinaryStreamReader Reader(Stream); 368c099fe0SZachary Turner if (auto EC = Reader.readObject(Header)) 378c099fe0SZachary Turner return EC; 388c099fe0SZachary Turner 398c099fe0SZachary Turner DebugSubsectionKind Kind = 408c099fe0SZachary Turner static_cast<DebugSubsectionKind>(uint32_t(Header->Kind)); 418c099fe0SZachary Turner if (auto EC = Reader.readStreamRef(Info.Data, Header->Length)) 428c099fe0SZachary Turner return EC; 43ebd3ae83SZachary Turner Info.Container = Container; 448c099fe0SZachary Turner Info.Kind = Kind; 458c099fe0SZachary Turner return Error::success(); 468c099fe0SZachary Turner } 478c099fe0SZachary Turner 488c099fe0SZachary Turner uint32_t DebugSubsectionRecord::getRecordLength() const { 49deb39130SZachary Turner return sizeof(DebugSubsectionHeader) + Data.getLength(); 508c099fe0SZachary Turner } 518c099fe0SZachary Turner 528c099fe0SZachary Turner DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; } 538c099fe0SZachary Turner 548c099fe0SZachary Turner BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; } 558c099fe0SZachary Turner 568c099fe0SZachary Turner DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( 57a8cfc29cSZachary Turner std::shared_ptr<DebugSubsection> Subsection, CodeViewContainer Container) 5892dcdda6SZachary Turner : Subsection(std::move(Subsection)), Container(Container) {} 598c099fe0SZachary Turner 6044cdb109SReid Kleckner DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( 6144cdb109SReid Kleckner const DebugSubsectionRecord &Contents, CodeViewContainer Container) 6244cdb109SReid Kleckner : Contents(Contents), Container(Container) {} 6344cdb109SReid Kleckner 648c099fe0SZachary Turner uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() { 6544cdb109SReid Kleckner uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize() 6644cdb109SReid Kleckner : Contents.getRecordData().getLength(); 6744cdb109SReid Kleckner // The length of the entire subsection is always padded to 4 bytes, 6844cdb109SReid Kleckner // regardless of the container kind. 6944cdb109SReid Kleckner return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4); 708c099fe0SZachary Turner } 718c099fe0SZachary Turner 72deb39130SZachary Turner Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const { 73ebd3ae83SZachary Turner assert(Writer.getOffset() % alignOf(Container) == 0 && 74ebd3ae83SZachary Turner "Debug Subsection not properly aligned"); 75ebd3ae83SZachary Turner 768c099fe0SZachary Turner DebugSubsectionHeader Header; 7744cdb109SReid Kleckner Header.Kind = uint32_t(Subsection ? Subsection->kind() : Contents.kind()); 78deb39130SZachary Turner // The value written into the Header's Length field is only padded to the 79deb39130SZachary Turner // container's alignment 8044cdb109SReid Kleckner uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize() 8144cdb109SReid Kleckner : Contents.getRecordData().getLength(); 8244cdb109SReid Kleckner Header.Length = alignTo(DataSize, alignOf(Container)); 838c099fe0SZachary Turner 848c099fe0SZachary Turner if (auto EC = Writer.writeObject(Header)) 858c099fe0SZachary Turner return EC; 8644cdb109SReid Kleckner if (Subsection) { 8792dcdda6SZachary Turner if (auto EC = Subsection->commit(Writer)) 888c099fe0SZachary Turner return EC; 8944cdb109SReid Kleckner } else { 9044cdb109SReid Kleckner if (auto EC = Writer.writeStreamRef(Contents.getRecordData())) 9144cdb109SReid Kleckner return EC; 9244cdb109SReid Kleckner } 93deb39130SZachary Turner if (auto EC = Writer.padToAlignment(4)) 948c099fe0SZachary Turner return EC; 958c099fe0SZachary Turner 968c099fe0SZachary Turner return Error::success(); 978c099fe0SZachary Turner } 98