Coverage Report

Created: 2019-07-24 05:18

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