1 //===- CodeViewRecordIO.cpp -------------------------------------*- 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 #include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h"
11 #include "llvm/DebugInfo/CodeView/CodeView.h"
12 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
13 #include "llvm/DebugInfo/MSF/StreamReader.h"
14 #include "llvm/DebugInfo/MSF/StreamWriter.h"
15 
16 using namespace llvm;
17 using namespace llvm::codeview;
18 
19 Error CodeViewRecordIO::beginRecord(uint16_t Kind) {
20   assert(!CurrentRecord.hasValue() && "There is already a record active!");
21   CurrentRecord.emplace();
22 
23   CurrentRecord->Kind = Kind;
24   return Error::success();
25 }
26 
27 Error CodeViewRecordIO::endRecord() {
28   assert(CurrentRecord.hasValue() && "Not in a record!");
29   CurrentRecord.reset();
30   return Error::success();
31 }
32 
33 Error CodeViewRecordIO::skipPadding() {
34   assert(!isWriting() && "Cannot skip padding while writing!");
35 
36   if (Reader->bytesRemaining() == 0)
37     return Error::success();
38 
39   uint8_t Leaf = Reader->peek();
40   if (Leaf < LF_PAD0)
41     return Error::success();
42   // Leaf is greater than 0xf0. We should advance by the number of bytes in
43   // the low 4 bits.
44   unsigned BytesToAdvance = Leaf & 0x0F;
45   return Reader->skip(BytesToAdvance);
46 }
47 
48 Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) {
49   if (isWriting()) {
50     if (auto EC = Writer->writeBytes(Bytes))
51       return EC;
52   } else {
53     if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining()))
54       return EC;
55   }
56   return Error::success();
57 }
58 
59 Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) {
60   if (isWriting()) {
61     if (auto EC = Writer->writeInteger(TypeInd.getIndex()))
62       return EC;
63     return Error::success();
64   }
65 
66   uint32_t I;
67   if (auto EC = Reader->readInteger(I))
68     return EC;
69   TypeInd.setIndex(I);
70   return Error::success();
71 }
72 
73 Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) {
74   if (isWriting()) {
75     if (Value >= 0) {
76       if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value)))
77         return EC;
78     } else {
79       if (auto EC = writeEncodedSignedInteger(Value))
80         return EC;
81     }
82   } else {
83     APSInt N;
84     if (auto EC = consume(*Reader, N))
85       return EC;
86     Value = N.getExtValue();
87   }
88 
89   return Error::success();
90 }
91 
92 Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) {
93   if (isWriting()) {
94     if (auto EC = writeEncodedUnsignedInteger(Value))
95       return EC;
96   } else {
97     APSInt N;
98     if (auto EC = consume(*Reader, N))
99       return EC;
100     Value = N.getZExtValue();
101   }
102   return Error::success();
103 }
104 
105 Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) {
106   if (isWriting()) {
107     if (Value.isSigned())
108       return writeEncodedSignedInteger(Value.getSExtValue());
109     return writeEncodedUnsignedInteger(Value.getZExtValue());
110   }
111 
112   return consume(*Reader, Value);
113 }
114 
115 Error CodeViewRecordIO::mapStringZ(StringRef &Value) {
116   if (isWriting()) {
117     if (auto EC = Writer->writeZeroString(Value))
118       return EC;
119   } else {
120     if (auto EC = Reader->readZeroString(Value))
121       return EC;
122   }
123   return Error::success();
124 }
125 
126 Error CodeViewRecordIO::mapGuid(StringRef &Guid) {
127   if (isWriting()) {
128     assert(Guid.size() == 16 && "Invalid Guid Size!");
129     if (auto EC = Writer->writeFixedString(Guid))
130       return EC;
131   } else {
132     if (auto EC = Reader->readFixedString(Guid, 16))
133       return EC;
134   }
135   return Error::success();
136 }
137 
138 Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
139   assert(Value < 0 && "Encoded integer is not signed!");
140   if (Value >= std::numeric_limits<int8_t>::min()) {
141     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_CHAR)))
142       return EC;
143     if (auto EC = Writer->writeInteger(static_cast<int8_t>(Value)))
144       return EC;
145   } else if (Value >= std::numeric_limits<int16_t>::min()) {
146     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_SHORT)))
147       return EC;
148     if (auto EC = Writer->writeInteger(static_cast<int16_t>(Value)))
149       return EC;
150   } else if (Value >= std::numeric_limits<int32_t>::min()) {
151     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_LONG)))
152       return EC;
153     if (auto EC = Writer->writeInteger(static_cast<int32_t>(Value)))
154       return EC;
155   } else {
156     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_QUADWORD)))
157       return EC;
158     if (auto EC = Writer->writeInteger(Value))
159       return EC;
160   }
161   return Error::success();
162 }
163 
164 Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) {
165   if (Value < LF_NUMERIC) {
166     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(Value)))
167       return EC;
168   } else if (Value <= std::numeric_limits<uint16_t>::max()) {
169     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_USHORT)))
170       return EC;
171     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(Value)))
172       return EC;
173   } else if (Value <= std::numeric_limits<uint32_t>::max()) {
174     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_ULONG)))
175       return EC;
176     if (auto EC = Writer->writeInteger(static_cast<uint32_t>(Value)))
177       return EC;
178   } else {
179     if (auto EC = Writer->writeInteger(static_cast<uint16_t>(LF_UQUADWORD)))
180       return EC;
181     if (auto EC = Writer->writeInteger(Value))
182       return EC;
183   }
184 
185   return Error::success();
186 }
187