1 //===- DebugSubsectionRecord.cpp ------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" 11 #include "llvm/DebugInfo/CodeView/CodeView.h" 12 #include "llvm/DebugInfo/CodeView/DebugSubsection.h" 13 #include "llvm/Support/BinaryStreamReader.h" 14 #include "llvm/Support/BinaryStreamWriter.h" 15 #include "llvm/Support/Error.h" 16 #include "llvm/Support/MathExtras.h" 17 #include <algorithm> 18 #include <cassert> 19 #include <cstdint> 20 21 using namespace llvm; 22 using namespace llvm::codeview; 23 24 DebugSubsectionRecord::DebugSubsectionRecord() = default; 25 26 DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind, 27 BinaryStreamRef Data, 28 CodeViewContainer Container) 29 : Container(Container), Kind(Kind), Data(Data) {} 30 31 Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream, 32 DebugSubsectionRecord &Info, 33 CodeViewContainer Container) { 34 const DebugSubsectionHeader *Header; 35 BinaryStreamReader Reader(Stream); 36 if (auto EC = Reader.readObject(Header)) 37 return EC; 38 39 DebugSubsectionKind Kind = 40 static_cast<DebugSubsectionKind>(uint32_t(Header->Kind)); 41 if (auto EC = Reader.readStreamRef(Info.Data, Header->Length)) 42 return EC; 43 Info.Container = Container; 44 Info.Kind = Kind; 45 return Error::success(); 46 } 47 48 uint32_t DebugSubsectionRecord::getRecordLength() const { 49 return sizeof(DebugSubsectionHeader) + Data.getLength(); 50 } 51 52 DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; } 53 54 BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; } 55 56 DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( 57 std::shared_ptr<DebugSubsection> Subsection, CodeViewContainer Container) 58 : Subsection(std::move(Subsection)), Container(Container) {} 59 60 DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( 61 const DebugSubsectionRecord &Contents, CodeViewContainer Container) 62 : Contents(Contents), Container(Container) {} 63 64 uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() { 65 uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize() 66 : Contents.getRecordData().getLength(); 67 // The length of the entire subsection is always padded to 4 bytes, 68 // regardless of the container kind. 69 return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4); 70 } 71 72 Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const { 73 assert(Writer.getOffset() % alignOf(Container) == 0 && 74 "Debug Subsection not properly aligned"); 75 76 DebugSubsectionHeader Header; 77 Header.Kind = uint32_t(Subsection ? Subsection->kind() : Contents.kind()); 78 // The value written into the Header's Length field is only padded to the 79 // container's alignment 80 uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize() 81 : Contents.getRecordData().getLength(); 82 Header.Length = alignTo(DataSize, alignOf(Container)); 83 84 if (auto EC = Writer.writeObject(Header)) 85 return EC; 86 if (Subsection) { 87 if (auto EC = Subsection->commit(Writer)) 88 return EC; 89 } else { 90 if (auto EC = Writer.writeStreamRef(Contents.getRecordData())) 91 return EC; 92 } 93 if (auto EC = Writer.padToAlignment(4)) 94 return EC; 95 96 return Error::success(); 97 } 98