LLVM  8.0.1
DataExtractor.cpp
Go to the documentation of this file.
1 //===-- DataExtractor.cpp -------------------------------------------------===//
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 
12 #include "llvm/Support/Host.h"
14 using namespace llvm;
15 
16 template <typename T>
17 static T getU(uint32_t *offset_ptr, const DataExtractor *de,
18  bool isLittleEndian, const char *Data) {
19  T val = 0;
20  uint32_t offset = *offset_ptr;
21  if (de->isValidOffsetForDataOfSize(offset, sizeof(val))) {
22  std::memcpy(&val, &Data[offset], sizeof(val));
23  if (sys::IsLittleEndianHost != isLittleEndian)
24  sys::swapByteOrder(val);
25 
26  // Advance the offset
27  *offset_ptr += sizeof(val);
28  }
29  return val;
30 }
31 
32 template <typename T>
33 static T *getUs(uint32_t *offset_ptr, T *dst, uint32_t count,
34  const DataExtractor *de, bool isLittleEndian, const char *Data){
35  uint32_t offset = *offset_ptr;
36 
37  if (count > 0 && de->isValidOffsetForDataOfSize(offset, sizeof(*dst)*count)) {
38  for (T *value_ptr = dst, *end = dst + count; value_ptr != end;
39  ++value_ptr, offset += sizeof(*dst))
40  *value_ptr = getU<T>(offset_ptr, de, isLittleEndian, Data);
41  // Advance the offset
42  *offset_ptr = offset;
43  // Return a non-NULL pointer to the converted data as an indicator of
44  // success
45  return dst;
46  }
47  return nullptr;
48 }
49 
50 uint8_t DataExtractor::getU8(uint32_t *offset_ptr) const {
51  return getU<uint8_t>(offset_ptr, this, IsLittleEndian, Data.data());
52 }
53 
54 uint8_t *
55 DataExtractor::getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const {
56  return getUs<uint8_t>(offset_ptr, dst, count, this, IsLittleEndian,
57  Data.data());
58 }
59 
60 
61 uint16_t DataExtractor::getU16(uint32_t *offset_ptr) const {
62  return getU<uint16_t>(offset_ptr, this, IsLittleEndian, Data.data());
63 }
64 
65 uint16_t *DataExtractor::getU16(uint32_t *offset_ptr, uint16_t *dst,
66  uint32_t count) const {
67  return getUs<uint16_t>(offset_ptr, dst, count, this, IsLittleEndian,
68  Data.data());
69 }
70 
72  uint24_t ExtractedVal =
73  getU<uint24_t>(offset_ptr, this, IsLittleEndian, Data.data());
74  // The 3 bytes are in the correct byte order for the host.
75  return ExtractedVal.getAsUint32(sys::IsLittleEndianHost);
76 }
77 
79  return getU<uint32_t>(offset_ptr, this, IsLittleEndian, Data.data());
80 }
81 
83  uint32_t count) const {
84  return getUs<uint32_t>(offset_ptr, dst, count, this, IsLittleEndian,
85  Data.data());
86 }
87 
88 uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const {
89  return getU<uint64_t>(offset_ptr, this, IsLittleEndian, Data.data());
90 }
91 
92 uint64_t *DataExtractor::getU64(uint32_t *offset_ptr, uint64_t *dst,
93  uint32_t count) const {
94  return getUs<uint64_t>(offset_ptr, dst, count, this, IsLittleEndian,
95  Data.data());
96 }
97 
98 uint64_t
99 DataExtractor::getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const {
100  switch (byte_size) {
101  case 1:
102  return getU8(offset_ptr);
103  case 2:
104  return getU16(offset_ptr);
105  case 4:
106  return getU32(offset_ptr);
107  case 8:
108  return getU64(offset_ptr);
109  }
110  llvm_unreachable("getUnsigned unhandled case!");
111 }
112 
113 int64_t
114 DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const {
115  switch (byte_size) {
116  case 1:
117  return (int8_t)getU8(offset_ptr);
118  case 2:
119  return (int16_t)getU16(offset_ptr);
120  case 4:
121  return (int32_t)getU32(offset_ptr);
122  case 8:
123  return (int64_t)getU64(offset_ptr);
124  }
125  llvm_unreachable("getSigned unhandled case!");
126 }
127 
128 const char *DataExtractor::getCStr(uint32_t *offset_ptr) const {
129  uint32_t offset = *offset_ptr;
130  StringRef::size_type pos = Data.find('\0', offset);
131  if (pos != StringRef::npos) {
132  *offset_ptr = pos + 1;
133  return Data.data() + offset;
134  }
135  return nullptr;
136 }
137 
139  uint32_t Start = *OffsetPtr;
140  StringRef::size_type Pos = Data.find('\0', Start);
141  if (Pos != StringRef::npos) {
142  *OffsetPtr = Pos + 1;
143  return StringRef(Data.data() + Start, Pos - Start);
144  }
145  return StringRef();
146 }
147 
148 uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const {
149  uint64_t result = 0;
150  if (Data.empty())
151  return 0;
152 
153  unsigned shift = 0;
154  uint32_t offset = *offset_ptr;
155  uint8_t byte = 0;
156 
157  while (isValidOffset(offset)) {
158  byte = Data[offset++];
159  result |= uint64_t(byte & 0x7f) << shift;
160  shift += 7;
161  if ((byte & 0x80) == 0)
162  break;
163  }
164 
165  *offset_ptr = offset;
166  return result;
167 }
168 
169 int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
170  int64_t result = 0;
171  if (Data.empty())
172  return 0;
173 
174  unsigned shift = 0;
175  uint32_t offset = *offset_ptr;
176  uint8_t byte = 0;
177 
178  while (isValidOffset(offset)) {
179  byte = Data[offset++];
180  result |= uint64_t(byte & 0x7f) << shift;
181  shift += 7;
182  if ((byte & 0x80) == 0)
183  break;
184  }
185 
186  // Sign bit of byte is 2nd high order bit (0x40)
187  if (shift < 64 && (byte & 0x40))
188  result |= -(1ULL << shift);
189 
190  *offset_ptr = offset;
191  return result;
192 }
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:259
void swapByteOrder(T &Value)
uint64_t getULEB128(uint32_t *offset_ptr) const
Extract a unsigned LEB128 value from *offset_ptr.
This class represents lattice values for constants.
Definition: AllocatorList.h:24
uint32_t getU24(uint32_t *offset_ptr) const
Extract a 24-bit unsigned value from *offset_ptr and return it in a uint32_t.
uint32_t getAsUint32(bool IsLittleEndian) const
Definition: DataExtractor.h:27
uint16_t getU16(uint32_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:128
uint32_t getU32(uint32_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
An auxiliary type to facilitate extraction of 3-byte entities.
Definition: DataExtractor.h:19
static const bool IsLittleEndianHost
Definition: Host.h:50
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:133
int64_t getSLEB128(uint32_t *offset_ptr) const
Extract a signed LEB128 value from *offset_ptr.
auto count(R &&Range, const E &Element) -> typename std::iterator_traits< decltype(adl_begin(Range))>::difference_type
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition: STLExtras.h:1252
bool isValidOffsetForDataOfSize(uint32_t offset, uint32_t length) const
Test the availability of length bytes of data from offset.
static T * getUs(uint32_t *offset_ptr, T *dst, uint32_t count, const DataExtractor *de, bool isLittleEndian, const char *Data)
int64_t getSigned(uint32_t *offset_ptr, uint32_t size) const
Extract an signed integer of size byte_size from *offset_ptr.
uint8_t getU8(uint32_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
uint64_t getU64(uint32_t *offset_ptr) const
Extract a uint64_t value from *offset_ptr.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static const size_t npos
Definition: StringRef.h:51
uint64_t getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const
Extract an unsigned integer of size byte_size from *offset_ptr.
const char * getCStr(uint32_t *offset_ptr) const
Extract a C string from *offset_ptr.
bool isValidOffset(uint32_t offset) const
Test the validity of offset.
StringRef getCStrRef(uint32_t *OffsetPtr) const
Extract a C string from *OffsetPtr.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:298
static T getU(uint32_t *offset_ptr, const DataExtractor *de, bool isLittleEndian, const char *Data)