94 lines · cpp
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-exception6//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 <cassert>17#include <cstdint>18 19using namespace llvm;20using namespace llvm::codeview;21 22DebugSubsectionRecord::DebugSubsectionRecord() = default;23 24DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind,25 BinaryStreamRef Data)26 : Kind(Kind), Data(Data) {}27 28Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream,29 DebugSubsectionRecord &Info) {30 const DebugSubsectionHeader *Header;31 BinaryStreamReader Reader(Stream);32 if (auto EC = Reader.readObject(Header))33 return EC;34 35 DebugSubsectionKind Kind =36 static_cast<DebugSubsectionKind>(uint32_t(Header->Kind));37 if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))38 return EC;39 Info.Kind = Kind;40 return Error::success();41}42 43uint32_t DebugSubsectionRecord::getRecordLength() const {44 return sizeof(DebugSubsectionHeader) + Data.getLength();45}46 47DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; }48 49BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; }50 51DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(52 std::shared_ptr<DebugSubsection> Subsection)53 : Subsection(std::move(Subsection)) {}54 55DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(56 const DebugSubsectionRecord &Contents)57 : Contents(Contents) {}58 59uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() const {60 uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()61 : Contents.getRecordData().getLength();62 // The length of the entire subsection is always padded to 4 bytes,63 // regardless of the container kind.64 return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4);65}66 67Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer,68 CodeViewContainer Container) const {69 assert(Writer.getOffset() % alignOf(Container) == 0 &&70 "Debug Subsection not properly aligned");71 72 DebugSubsectionHeader Header;73 Header.Kind = uint32_t(Subsection ? Subsection->kind() : Contents.kind());74 // The value written into the Header's Length field is only padded to the75 // container's alignment76 uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()77 : Contents.getRecordData().getLength();78 Header.Length = alignTo(DataSize, alignOf(Container));79 80 if (auto EC = Writer.writeObject(Header))81 return EC;82 if (Subsection) {83 if (auto EC = Subsection->commit(Writer))84 return EC;85 } else {86 if (auto EC = Writer.writeStreamRef(Contents.getRecordData()))87 return EC;88 }89 if (auto EC = Writer.padToAlignment(4))90 return EC;91 92 return Error::success();93}94