brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.9 KiB · 0327044 Raw
155 lines · cpp
1//===-- RecordSerialization.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// Utilities for serializing and deserializing CodeView records.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/DebugInfo/CodeView/RecordSerialization.h"14#include "llvm/ADT/APInt.h"15#include "llvm/ADT/APSInt.h"16#include "llvm/DebugInfo/CodeView/CVRecord.h"17#include "llvm/DebugInfo/CodeView/CodeViewError.h"18#include "llvm/DebugInfo/CodeView/SymbolRecord.h"19#include "llvm/Support/BinaryByteStream.h"20 21using namespace llvm;22using namespace llvm::codeview;23using namespace llvm::support;24 25/// Reinterpret a byte array as an array of characters. Does not interpret as26/// a C string, as StringRef has several helpers (split) that make that easy.27StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {28  return StringRef(reinterpret_cast<const char *>(LeafData.data()),29                   LeafData.size());30}31 32StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {33  return getBytesAsCharacters(LeafData).split('\0').first;34}35 36Error llvm::codeview::consume(BinaryStreamReader &Reader, APSInt &Num) {37  // Used to avoid overload ambiguity on APInt constructor.38  bool FalseVal = false;39  uint16_t Short;40  if (auto EC = Reader.readInteger(Short))41    return EC;42 43  if (Short < LF_NUMERIC) {44    Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),45                 /*isUnsigned=*/true);46    return Error::success();47  }48 49  switch (Short) {50  case LF_CHAR: {51    int8_t N;52    if (auto EC = Reader.readInteger(N))53      return EC;54    Num = APSInt(APInt(8, N, true), false);55    return Error::success();56  }57  case LF_SHORT: {58    int16_t N;59    if (auto EC = Reader.readInteger(N))60      return EC;61    Num = APSInt(APInt(16, N, true), false);62    return Error::success();63  }64  case LF_USHORT: {65    uint16_t N;66    if (auto EC = Reader.readInteger(N))67      return EC;68    Num = APSInt(APInt(16, N, false), true);69    return Error::success();70  }71  case LF_LONG: {72    int32_t N;73    if (auto EC = Reader.readInteger(N))74      return EC;75    Num = APSInt(APInt(32, N, true), false);76    return Error::success();77  }78  case LF_ULONG: {79    uint32_t N;80    if (auto EC = Reader.readInteger(N))81      return EC;82    Num = APSInt(APInt(32, N, FalseVal), true);83    return Error::success();84  }85  case LF_QUADWORD: {86    int64_t N;87    if (auto EC = Reader.readInteger(N))88      return EC;89    Num = APSInt(APInt(64, N, true), false);90    return Error::success();91  }92  case LF_UQUADWORD: {93    uint64_t N;94    if (auto EC = Reader.readInteger(N))95      return EC;96    Num = APSInt(APInt(64, N, false), true);97    return Error::success();98  }99  }100  return make_error<CodeViewError>(cv_error_code::corrupt_record,101                                   "Buffer contains invalid APSInt type");102}103 104Error llvm::codeview::consume(StringRef &Data, APSInt &Num) {105  ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());106  BinaryByteStream S(Bytes, llvm::endianness::little);107  BinaryStreamReader SR(S);108  auto EC = consume(SR, Num);109  Data = Data.take_back(SR.bytesRemaining());110  return EC;111}112 113/// Decode a numeric leaf value that is known to be a uint64_t.114Error llvm::codeview::consume_numeric(BinaryStreamReader &Reader,115                                      uint64_t &Num) {116  APSInt N;117  if (auto EC = consume(Reader, N))118    return EC;119  if (N.isSigned() || !N.isIntN(64))120    return make_error<CodeViewError>(cv_error_code::corrupt_record,121                                     "Data is not a numeric value!");122  Num = N.getLimitedValue();123  return Error::success();124}125 126Error llvm::codeview::consume(BinaryStreamReader &Reader, uint32_t &Item) {127  return Reader.readInteger(Item);128}129 130Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) {131  ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());132  BinaryByteStream S(Bytes, llvm::endianness::little);133  BinaryStreamReader SR(S);134  auto EC = consume(SR, Item);135  Data = Data.take_back(SR.bytesRemaining());136  return EC;137}138 139Error llvm::codeview::consume(BinaryStreamReader &Reader, int32_t &Item) {140  return Reader.readInteger(Item);141}142 143Error llvm::codeview::consume(BinaryStreamReader &Reader, StringRef &Item) {144  if (Reader.empty())145    return make_error<CodeViewError>(cv_error_code::corrupt_record,146                                     "Null terminated string buffer is empty!");147 148  return Reader.readCString(Item);149}150 151Expected<CVSymbol> llvm::codeview::readSymbolFromStream(BinaryStreamRef Stream,152                                                        uint32_t Offset) {153  return readCVRecordFromStream<SymbolKind>(Stream, Offset);154}155