Line data Source code
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 0 : DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind,
27 : BinaryStreamRef Data,
28 0 : CodeViewContainer Container)
29 0 : : Container(Container), Kind(Kind), Data(Data) {}
30 :
31 988 : Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream,
32 : DebugSubsectionRecord &Info,
33 : CodeViewContainer Container) {
34 : const DebugSubsectionHeader *Header;
35 988 : BinaryStreamReader Reader(Stream);
36 1976 : if (auto EC = Reader.readObject(Header))
37 : return EC;
38 :
39 : DebugSubsectionKind Kind =
40 988 : static_cast<DebugSubsectionKind>(uint32_t(Header->Kind));
41 1976 : if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
42 : return EC;
43 988 : Info.Container = Container;
44 988 : Info.Kind = Kind;
45 : return Error::success();
46 : }
47 :
48 998 : uint32_t DebugSubsectionRecord::getRecordLength() const {
49 998 : return sizeof(DebugSubsectionHeader) + Data.getLength();
50 : }
51 :
52 1121 : DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; }
53 :
54 897 : BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; }
55 :
56 345 : DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
57 345 : std::shared_ptr<DebugSubsection> Subsection, CodeViewContainer Container)
58 345 : : Subsection(std::move(Subsection)), Container(Container) {}
59 :
60 72 : DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
61 72 : const DebugSubsectionRecord &Contents, CodeViewContainer Container)
62 72 : : Contents(Contents), Container(Container) {}
63 :
64 556 : uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() {
65 412 : uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
66 556 : : Contents.getRecordData().getLength();
67 : // The length of the entire subsection is always padded to 4 bytes,
68 : // regardless of the container kind.
69 1112 : return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4);
70 : }
71 :
72 417 : Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const {
73 : assert(Writer.getOffset() % alignOf(Container) == 0 &&
74 : "Debug Subsection not properly aligned");
75 :
76 : DebugSubsectionHeader Header;
77 417 : 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 345 : uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
81 417 : : Contents.getRecordData().getLength();
82 973 : Header.Length = alignTo(DataSize, alignOf(Container));
83 :
84 417 : if (auto EC = Writer.writeObject(Header))
85 : return EC;
86 417 : if (Subsection) {
87 690 : if (auto EC = Subsection->commit(Writer))
88 : return EC;
89 : } else {
90 144 : if (auto EC = Writer.writeStreamRef(Contents.getRecordData()))
91 : return EC;
92 : }
93 834 : if (auto EC = Writer.padToAlignment(4))
94 : return EC;
95 :
96 : return Error::success();
97 : }
|