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