394 lines · cpp
1//===- CodeViewRecordIO.cpp -------------------------------------*- C++ -*-===//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/CodeViewRecordIO.h"10#include "llvm/ADT/StringExtras.h"11#include "llvm/DebugInfo/CodeView/CodeView.h"12#include "llvm/DebugInfo/CodeView/GUID.h"13#include "llvm/DebugInfo/CodeView/RecordSerialization.h"14#include "llvm/DebugInfo/CodeView/TypeIndex.h"15#include "llvm/Support/BinaryStreamReader.h"16#include "llvm/Support/BinaryStreamWriter.h"17 18using namespace llvm;19using namespace llvm::codeview;20 21Error CodeViewRecordIO::beginRecord(std::optional<uint32_t> MaxLength) {22 RecordLimit Limit;23 Limit.MaxLength = MaxLength;24 Limit.BeginOffset = getCurrentOffset();25 Limits.push_back(Limit);26 return Error::success();27}28 29Error CodeViewRecordIO::endRecord() {30 assert(!Limits.empty() && "Not in a record!");31 Limits.pop_back();32 // We would like to assert that we actually read / wrote all the bytes that we33 // expected to for this record, but unfortunately we can't do this. Some34 // producers such as MASM over-allocate for certain types of records and35 // commit the extraneous data, so when reading we can't be sure every byte36 // will have been read. And when writing we over-allocate temporarily since37 // we don't know how big the record is until we're finished writing it, so38 // even though we don't commit the extraneous data, we still can't guarantee39 // we're at the end of the allocated data.40 41 if (isStreaming()) {42 // For streaming mode, add padding to align with 4 byte boundaries for each43 // record44 uint32_t Align = getStreamedLen() % 4;45 if (Align == 0)46 return Error::success();47 48 int PaddingBytes = 4 - Align;49 while (PaddingBytes > 0) {50 char Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes);51 StringRef BytesSR = StringRef(&Pad, sizeof(Pad));52 Streamer->emitBytes(BytesSR);53 --PaddingBytes;54 }55 resetStreamedLen();56 }57 return Error::success();58}59 60uint32_t CodeViewRecordIO::maxFieldLength() const {61 if (isStreaming())62 return 0;63 64 assert(!Limits.empty() && "Not in a record!");65 66 // The max length of the next field is the minimum of all lengths that would67 // be allowed by any of the sub-records we're in. In practice, we can only68 // ever be at most 1 sub-record deep (in a FieldList), but this works for69 // the general case.70 uint32_t Offset = getCurrentOffset();71 std::optional<uint32_t> Min = Limits.front().bytesRemaining(Offset);72 for (auto X : ArrayRef(Limits).drop_front()) {73 std::optional<uint32_t> ThisMin = X.bytesRemaining(Offset);74 if (ThisMin)75 Min = Min ? std::min(*Min, *ThisMin) : *ThisMin;76 }77 assert(Min && "Every field must have a maximum length!");78 79 return *Min;80}81 82Error CodeViewRecordIO::padToAlignment(uint32_t Align) {83 if (isReading())84 return Reader->padToAlignment(Align);85 return Writer->padToAlignment(Align);86}87 88Error CodeViewRecordIO::skipPadding() {89 assert(!isWriting() && "Cannot skip padding while writing!");90 91 if (Reader->bytesRemaining() == 0)92 return Error::success();93 94 uint8_t Leaf = Reader->peek();95 if (Leaf < LF_PAD0)96 return Error::success();97 // Leaf is greater than 0xf0. We should advance by the number of bytes in98 // the low 4 bits.99 unsigned BytesToAdvance = Leaf & 0x0F;100 return Reader->skip(BytesToAdvance);101}102 103Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes,104 const Twine &Comment) {105 if (isStreaming()) {106 emitComment(Comment);107 Streamer->emitBinaryData(toStringRef(Bytes));108 incrStreamedLen(Bytes.size());109 } else if (isWriting()) {110 if (auto EC = Writer->writeBytes(Bytes))111 return EC;112 } else {113 if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining()))114 return EC;115 }116 return Error::success();117}118 119Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes,120 const Twine &Comment) {121 ArrayRef<uint8_t> BytesRef(Bytes);122 if (auto EC = mapByteVectorTail(BytesRef, Comment))123 return EC;124 if (!isWriting())125 Bytes.assign(BytesRef.begin(), BytesRef.end());126 127 return Error::success();128}129 130Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd, const Twine &Comment) {131 if (isStreaming()) {132 std::string TypeNameStr = Streamer->getTypeName(TypeInd);133 if (!TypeNameStr.empty())134 emitComment(Comment + ": " + TypeNameStr);135 else136 emitComment(Comment);137 Streamer->emitIntValue(TypeInd.getIndex(), sizeof(TypeInd.getIndex()));138 incrStreamedLen(sizeof(TypeInd.getIndex()));139 } else if (isWriting()) {140 if (auto EC = Writer->writeInteger(TypeInd.getIndex()))141 return EC;142 } else {143 uint32_t I;144 if (auto EC = Reader->readInteger(I))145 return EC;146 TypeInd.setIndex(I);147 }148 return Error::success();149}150 151Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value,152 const Twine &Comment) {153 if (isStreaming()) {154 if (Value >= 0)155 emitEncodedUnsignedInteger(static_cast<uint64_t>(Value), Comment);156 else157 emitEncodedSignedInteger(Value, Comment);158 } else if (isWriting()) {159 if (Value >= 0) {160 if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value)))161 return EC;162 } else {163 if (auto EC = writeEncodedSignedInteger(Value))164 return EC;165 }166 } else {167 APSInt N;168 if (auto EC = consume(*Reader, N))169 return EC;170 Value = N.getExtValue();171 }172 173 return Error::success();174}175 176Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value,177 const Twine &Comment) {178 if (isStreaming())179 emitEncodedUnsignedInteger(Value, Comment);180 else if (isWriting()) {181 if (auto EC = writeEncodedUnsignedInteger(Value))182 return EC;183 } else {184 APSInt N;185 if (auto EC = consume(*Reader, N))186 return EC;187 Value = N.getZExtValue();188 }189 return Error::success();190}191 192Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value, const Twine &Comment) {193 if (isStreaming()) {194 // FIXME: We also need to handle big values here, but it's195 // not clear how we can excercise this code path yet.196 if (Value.isSigned())197 emitEncodedSignedInteger(Value.getSExtValue(), Comment);198 else199 emitEncodedUnsignedInteger(Value.getZExtValue(), Comment);200 } else if (isWriting()) {201 if (Value.isSigned())202 return writeEncodedSignedInteger(203 Value.isSingleWord() ? Value.getSExtValue() : INT64_MIN);204 return writeEncodedUnsignedInteger(Value.getLimitedValue());205 } else206 return consume(*Reader, Value);207 return Error::success();208}209 210Error CodeViewRecordIO::mapStringZ(StringRef &Value, const Twine &Comment) {211 if (isStreaming()) {212 auto NullTerminatedString = StringRef(Value.data(), Value.size() + 1);213 emitComment(Comment);214 Streamer->emitBytes(NullTerminatedString);215 incrStreamedLen(NullTerminatedString.size());216 } else if (isWriting()) {217 // Truncate if we attempt to write too much.218 StringRef S = Value.take_front(maxFieldLength() - 1);219 if (auto EC = Writer->writeCString(S))220 return EC;221 } else {222 if (auto EC = Reader->readCString(Value))223 return EC;224 }225 return Error::success();226}227 228Error CodeViewRecordIO::mapGuid(GUID &Guid, const Twine &Comment) {229 constexpr uint32_t GuidSize = 16;230 231 if (isStreaming()) {232 StringRef GuidSR =233 StringRef((reinterpret_cast<const char *>(&Guid)), GuidSize);234 emitComment(Comment);235 Streamer->emitBytes(GuidSR);236 incrStreamedLen(GuidSize);237 return Error::success();238 }239 240 if (maxFieldLength() < GuidSize)241 return make_error<CodeViewError>(cv_error_code::insufficient_buffer);242 243 if (isWriting()) {244 if (auto EC = Writer->writeBytes(Guid.Guid))245 return EC;246 } else {247 ArrayRef<uint8_t> GuidBytes;248 if (auto EC = Reader->readBytes(GuidBytes, GuidSize))249 return EC;250 memcpy(Guid.Guid, GuidBytes.data(), GuidSize);251 }252 return Error::success();253}254 255Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value,256 const Twine &Comment) {257 258 if (!isReading()) {259 emitComment(Comment);260 for (auto V : Value) {261 if (auto EC = mapStringZ(V))262 return EC;263 }264 uint8_t FinalZero = 0;265 if (auto EC = mapInteger(FinalZero))266 return EC;267 } else {268 StringRef S;269 if (auto EC = mapStringZ(S))270 return EC;271 while (!S.empty()) {272 Value.push_back(S);273 if (auto EC = mapStringZ(S))274 return EC;275 };276 }277 return Error::success();278}279 280void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value,281 const Twine &Comment) {282 // FIXME: There are no test cases covering this function.283 // This may be because we always consider enumerators to be unsigned.284 // See FIXME at CodeViewDebug.cpp : CodeViewDebug::lowerTypeEnum.285 if (Value < LF_NUMERIC && Value >= 0) {286 emitComment(Comment);287 Streamer->emitIntValue(Value, 2);288 incrStreamedLen(2);289 } else if (Value >= std::numeric_limits<int8_t>::min() &&290 Value <= std::numeric_limits<int8_t>::max()) {291 Streamer->emitIntValue(LF_CHAR, 2);292 emitComment(Comment);293 Streamer->emitIntValue(Value, 1);294 incrStreamedLen(3);295 } else if (Value >= std::numeric_limits<int16_t>::min() &&296 Value <= std::numeric_limits<int16_t>::max()) {297 Streamer->emitIntValue(LF_SHORT, 2);298 emitComment(Comment);299 Streamer->emitIntValue(Value, 2);300 incrStreamedLen(4);301 } else if (Value >= std::numeric_limits<int32_t>::min() &&302 Value <= std::numeric_limits<int32_t>::max()) {303 Streamer->emitIntValue(LF_LONG, 2);304 emitComment(Comment);305 Streamer->emitIntValue(Value, 4);306 incrStreamedLen(6);307 } else {308 Streamer->emitIntValue(LF_QUADWORD, 2);309 emitComment(Comment);310 Streamer->emitIntValue(Value, 4); // FIXME: Why not 8 (size of quadword)?311 incrStreamedLen(6); // FIXME: Why not 10 (8 + 2)?312 }313}314 315void CodeViewRecordIO::emitEncodedUnsignedInteger(const uint64_t &Value,316 const Twine &Comment) {317 if (Value < LF_NUMERIC) {318 emitComment(Comment);319 Streamer->emitIntValue(Value, 2);320 incrStreamedLen(2);321 } else if (Value <= std::numeric_limits<uint16_t>::max()) {322 Streamer->emitIntValue(LF_USHORT, 2);323 emitComment(Comment);324 Streamer->emitIntValue(Value, 2);325 incrStreamedLen(4);326 } else if (Value <= std::numeric_limits<uint32_t>::max()) {327 Streamer->emitIntValue(LF_ULONG, 2);328 emitComment(Comment);329 Streamer->emitIntValue(Value, 4);330 incrStreamedLen(6);331 } else {332 // FIXME: There are no test cases covering this block.333 Streamer->emitIntValue(LF_UQUADWORD, 2);334 emitComment(Comment);335 Streamer->emitIntValue(Value, 8);336 incrStreamedLen(6); // FIXME: Why not 10 (8 + 2)?337 }338}339 340Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {341 if (Value < LF_NUMERIC && Value >= 0) {342 if (auto EC = Writer->writeInteger<int16_t>(Value))343 return EC;344 } else if (Value >= std::numeric_limits<int8_t>::min() &&345 Value <= std::numeric_limits<int8_t>::max()) {346 if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR))347 return EC;348 if (auto EC = Writer->writeInteger<int8_t>(Value))349 return EC;350 } else if (Value >= std::numeric_limits<int16_t>::min() &&351 Value <= std::numeric_limits<int16_t>::max()) {352 if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT))353 return EC;354 if (auto EC = Writer->writeInteger<int16_t>(Value))355 return EC;356 } else if (Value >= std::numeric_limits<int32_t>::min() &&357 Value <= std::numeric_limits<int32_t>::max()) {358 if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG))359 return EC;360 if (auto EC = Writer->writeInteger<int32_t>(Value))361 return EC;362 } else {363 if (auto EC = Writer->writeInteger<uint16_t>(LF_QUADWORD))364 return EC;365 if (auto EC = Writer->writeInteger(Value))366 return EC;367 }368 return Error::success();369}370 371Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) {372 if (Value < LF_NUMERIC) {373 if (auto EC = Writer->writeInteger<uint16_t>(Value))374 return EC;375 } else if (Value <= std::numeric_limits<uint16_t>::max()) {376 if (auto EC = Writer->writeInteger<uint16_t>(LF_USHORT))377 return EC;378 if (auto EC = Writer->writeInteger<uint16_t>(Value))379 return EC;380 } else if (Value <= std::numeric_limits<uint32_t>::max()) {381 if (auto EC = Writer->writeInteger<uint16_t>(LF_ULONG))382 return EC;383 if (auto EC = Writer->writeInteger<uint32_t>(Value))384 return EC;385 } else {386 if (auto EC = Writer->writeInteger<uint16_t>(LF_UQUADWORD))387 return EC;388 if (auto EC = Writer->writeInteger(Value))389 return EC;390 }391 392 return Error::success();393}394