Line data Source code
1 : //===- CodeViewRecordIO.h ---------------------------------------*- C++ -*-===//
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 : #ifndef LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
11 : #define LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
12 :
13 : #include "llvm/ADT/APSInt.h"
14 : #include "llvm/ADT/None.h"
15 : #include "llvm/ADT/Optional.h"
16 : #include "llvm/ADT/SmallVector.h"
17 : #include "llvm/ADT/StringRef.h"
18 : #include "llvm/DebugInfo/CodeView/CodeViewError.h"
19 : #include "llvm/DebugInfo/CodeView/TypeRecord.h"
20 : #include "llvm/Support/BinaryStreamReader.h"
21 : #include "llvm/Support/BinaryStreamWriter.h"
22 : #include "llvm/Support/Error.h"
23 : #include <cassert>
24 : #include <cstdint>
25 : #include <type_traits>
26 :
27 : namespace llvm {
28 : namespace codeview {
29 :
30 : class CodeViewRecordIO {
31 : uint32_t getCurrentOffset() const {
32 57375 : return (isWriting()) ? Writer->getOffset() : Reader->getOffset();
33 : }
34 :
35 : public:
36 3549 : explicit CodeViewRecordIO(BinaryStreamReader &Reader) : Reader(&Reader) {}
37 9344 : explicit CodeViewRecordIO(BinaryStreamWriter &Writer) : Writer(&Writer) {}
38 :
39 : Error beginRecord(Optional<uint32_t> MaxLength);
40 : Error endRecord();
41 :
42 : Error mapInteger(TypeIndex &TypeInd);
43 :
44 0 : bool isReading() const { return Reader != nullptr; }
45 175294 : bool isWriting() const { return !isReading(); }
46 :
47 : uint32_t maxFieldLength() const;
48 :
49 177 : template <typename T> Error mapObject(T &Value) {
50 177 : if (isWriting())
51 30 : return Writer->writeObject(Value);
52 :
53 : const T *ValuePtr;
54 294 : if (auto EC = Reader->readObject(ValuePtr))
55 : return EC;
56 147 : Value = *ValuePtr;
57 : return Error::success();
58 : }
59 7 :
60 37264 : template <typename T> Error mapInteger(T &Value) {
61 37257 : if (isWriting())
62 10089 : return Writer->writeInteger(Value);
63 :
64 27182 : return Reader->readInteger(Value);
65 : }
66 5125 :
67 5118 : template <typename T> Error mapEnum(T &Value) {
68 989 : if (sizeof(Value) > maxFieldLength())
69 16 : return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
70 4145 :
71 4 : using U = typename std::underlying_type<T>::type;
72 2743 : U X;
73 2743 : if (isWriting())
74 557 : X = static_cast<U>(Value);
75 :
76 2222 : if (auto EC = mapInteger(X))
77 : return EC;
78 1797 : if (isReading())
79 1951 : Value = static_cast<T>(X);
80 414 : return Error::success();
81 26 : }
82 1537 :
83 : Error mapEncodedInteger(int64_t &Value);
84 27855 : Error mapEncodedInteger(uint64_t &Value);
85 27599 : Error mapEncodedInteger(APSInt &Value);
86 8435 : Error mapStringZ(StringRef &Value);
87 : Error mapGuid(GUID &Guid);
88 19292 :
89 : Error mapStringZVectorZ(std::vector<StringRef> &Value);
90 12712 :
91 21585 : template <typename SizeType, typename T, typename ElementMapper>
92 13629 : Error mapVectorN(T &Items, const ElementMapper &Mapper) {
93 : SizeType Size;
94 7956 : if (isWriting()) {
95 : Size = static_cast<SizeType>(Items.size());
96 177 : if (auto EC = Writer->writeInteger(Size))
97 9050 : return EC;
98 1434 :
99 : for (auto &X : Items) {
100 17919 : if (auto EC = Mapper(*this, X))
101 : return EC;
102 9864 : }
103 8434 : } else {
104 599 : if (auto EC = Reader->readInteger(Size))
105 : return EC;
106 393 : for (SizeType I = 0; I < Size; ++I) {
107 1 : typename T::value_type Item;
108 6737 : if (auto EC = Mapper(*this, Item))
109 6737 : return EC;
110 2307 : Items.push_back(Item);
111 : }
112 4431 : }
113 0 :
114 4807 : return Error::success();
115 4809 : }
116 1846 :
117 1 : template <typename T, typename ElementMapper>
118 2962 : Error mapVectorTail(T &Items, const ElementMapper &Mapper) {
119 : if (isWriting()) {
120 : for (auto &Item : Items) {
121 5360 : if (auto EC = Mapper(*this, Item))
122 5360 : return EC;
123 : }
124 : } else {
125 : typename T::value_type Field;
126 : // Stop when we run out of bytes or we hit record padding bytes.
127 5360 : while (!Reader->empty() && Reader->peek() < 0xf0 /* LF_PAD0 */) {
128 1028 : if (auto EC = Mapper(*this, Field))
129 : return EC;
130 10720 : Items.push_back(Field);
131 : }
132 5360 : }
133 4332 : return Error::success();
134 : }
135 :
136 349 : Error mapByteVectorTail(ArrayRef<uint8_t> &Bytes);
137 349 : Error mapByteVectorTail(std::vector<uint8_t> &Bytes);
138 :
139 : Error padToAlignment(uint32_t Align);
140 : Error skipPadding();
141 :
142 349 : private:
143 73 : Error writeEncodedSignedInteger(const int64_t &Value);
144 : Error writeEncodedUnsignedInteger(const uint64_t &Value);
145 698 :
146 42736 : struct RecordLimit {
147 349 : uint32_t BeginOffset;
148 276 : Optional<uint32_t> MaxLength;
149 :
150 : Optional<uint32_t> bytesRemaining(uint32_t CurrentOffset) const {
151 30795 : if (!MaxLength.hasValue())
152 2950 : return None;
153 : assert(CurrentOffset >= BeginOffset);
154 :
155 21242 : uint32_t BytesUsed = CurrentOffset - BeginOffset;
156 21242 : if (BytesUsed >= *MaxLength)
157 2950 : return 0;
158 21938 : return *MaxLength - BytesUsed;
159 : }
160 5900 : };
161 :
162 2950 : SmallVector<RecordLimit, 2> Limits;
163 2254 :
164 : BinaryStreamReader *Reader = nullptr;
165 : BinaryStreamWriter *Writer = nullptr;
166 2547 : };
167 2547 :
168 : } // end namespace codeview
169 : } // end namespace llvm
170 :
171 : #endif // LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
|