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