LLVM  4.0.0
CodeViewRecordIO.h
Go to the documentation of this file.
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"
22 #include "llvm/Support/Error.h"
23 #include <cassert>
24 #include <cstdint>
25 #include <type_traits>
26 
27 namespace llvm {
28 namespace codeview {
29 
31  uint32_t getCurrentOffset() const {
32  return (isWriting()) ? Writer->getOffset() : Reader->getOffset();
33  }
34 
35 public:
36  explicit CodeViewRecordIO(msf::StreamReader &Reader) : Reader(&Reader) {}
37  explicit CodeViewRecordIO(msf::StreamWriter &Writer) : Writer(&Writer) {}
38 
40  Error endRecord();
41 
42  Error mapInteger(TypeIndex &TypeInd);
43 
44  bool isReading() const { return Reader != nullptr; }
45  bool isWriting() const { return !isReading(); }
46 
47  uint32_t maxFieldLength() const;
48 
49  template <typename T> Error mapObject(T &Value) {
50  if (isWriting())
51  return Writer->writeObject(Value);
52 
53  const T *ValuePtr;
54  if (auto EC = Reader->readObject(ValuePtr))
55  return EC;
56  Value = *ValuePtr;
57  return Error::success();
58  }
59 
60  template <typename T> Error mapInteger(T &Value) {
61  if (isWriting())
62  return Writer->writeInteger(Value);
63 
64  return Reader->readInteger(Value);
65  }
66 
67  template <typename T> Error mapEnum(T &Value) {
68  if (sizeof(Value) > maxFieldLength())
69  return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
70 
71  using U = typename std::underlying_type<T>::type;
72  U X;
73  if (isWriting())
74  X = static_cast<U>(Value);
75 
76  if (auto EC = mapInteger(X))
77  return EC;
78  if (isReading())
79  Value = static_cast<T>(X);
80  return Error::success();
81  }
82 
83  Error mapEncodedInteger(int64_t &Value);
84  Error mapEncodedInteger(uint64_t &Value);
87  Error mapGuid(StringRef &Guid);
88 
89  Error mapStringZVectorZ(std::vector<StringRef> &Value);
90 
91  template <typename SizeType, typename T, typename ElementMapper>
92  Error mapVectorN(T &Items, const ElementMapper &Mapper) {
93  SizeType Size;
94  if (isWriting()) {
95  Size = static_cast<SizeType>(Items.size());
96  if (auto EC = Writer->writeInteger(Size))
97  return EC;
98 
99  for (auto &X : Items) {
100  if (auto EC = Mapper(*this, X))
101  return EC;
102  }
103  } else {
104  if (auto EC = Reader->readInteger(Size))
105  return EC;
106  for (SizeType I = 0; I < Size; ++I) {
107  typename T::value_type Item;
108  if (auto EC = Mapper(*this, Item))
109  return EC;
110  Items.push_back(Item);
111  }
112  }
113 
114  return Error::success();
115  }
116 
117  template <typename T, typename ElementMapper>
118  Error mapVectorTail(T &Items, const ElementMapper &Mapper) {
119  if (isWriting()) {
120  for (auto &Item : Items) {
121  if (auto EC = Mapper(*this, Item))
122  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  while (!Reader->empty() && Reader->peek() < 0xf0 /* LF_PAD0 */) {
128  if (auto EC = Mapper(*this, Field))
129  return EC;
130  Items.push_back(Field);
131  }
132  }
133  return Error::success();
134  }
135 
137  Error mapByteVectorTail(std::vector<uint8_t> &Bytes);
138 
139  Error skipPadding();
140 
141 private:
142  Error writeEncodedSignedInteger(const int64_t &Value);
143  Error writeEncodedUnsignedInteger(const uint64_t &Value);
144 
145  struct RecordLimit {
146  uint32_t BeginOffset;
147  Optional<uint32_t> MaxLength;
148 
149  Optional<uint32_t> bytesRemaining(uint32_t CurrentOffset) const {
150  if (!MaxLength.hasValue())
151  return None;
152  assert(CurrentOffset >= BeginOffset);
153 
154  uint32_t BytesUsed = CurrentOffset - BeginOffset;
155  if (BytesUsed >= *MaxLength)
156  return 0;
157  return *MaxLength - BytesUsed;
158  }
159  };
160 
161  SmallVector<RecordLimit, 2> Limits;
162 
163  msf::StreamReader *Reader = nullptr;
164  msf::StreamWriter *Writer = nullptr;
165 };
166 
167 } // end namespace codeview
168 } // end namespace llvm
169 
170 #endif // LLVM_DEBUGINFO_CODEVIEW_CODEVIEWRECORDIO_H
Error mapByteVectorTail(ArrayRef< uint8_t > &Bytes)
Error mapVectorN(T &Items, const ElementMapper &Mapper)
Error mapInteger(TypeIndex &TypeInd)
Error mapStringZVectorZ(std::vector< StringRef > &Value)
Error beginRecord(Optional< uint32_t > MaxLength)
Error writeObject(const T &Obj)
Definition: StreamWriter.h:49
CodeViewRecordIO(msf::StreamReader &Reader)
A 32-bit type reference.
Definition: TypeIndex.h:89
CodeViewRecordIO(msf::StreamWriter &Writer)
Error readInteger(uint8_t &Dest)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
Error writeInteger(uint8_t Int)
uint32_t getOffset() const
Definition: StreamReader.h:106
static ErrorSuccess success()
Create a success value.
Error mapEncodedInteger(int64_t &Value)
uint32_t getOffset() const
Definition: StreamWriter.h:80
uint8_t peek() const
#define I(x, y, z)
Definition: MD5.cpp:54
Error mapStringZ(StringRef &Value)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:71
Lightweight error class with error context and mandatory checking.
Error mapVectorTail(T &Items, const ElementMapper &Mapper)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
Error readObject(const T *&Dest)
Definition: StreamReader.h:53