LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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  val = 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 NULL;
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 
71 uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const {
72  return getU<uint32_t>(offset_ptr, this, IsLittleEndian, Data.data());
73 }
74 
75 uint32_t *DataExtractor::getU32(uint32_t *offset_ptr, uint32_t *dst,
76  uint32_t count) const {
77  return getUs<uint32_t>(offset_ptr, dst, count, this, IsLittleEndian,
78  Data.data());
79 }
80 
81 uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const {
82  return getU<uint64_t>(offset_ptr, this, IsLittleEndian, Data.data());
83 }
84 
85 uint64_t *DataExtractor::getU64(uint32_t *offset_ptr, uint64_t *dst,
86  uint32_t count) const {
87  return getUs<uint64_t>(offset_ptr, dst, count, this, IsLittleEndian,
88  Data.data());
89 }
90 
91 uint64_t
92 DataExtractor::getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const {
93  switch (byte_size) {
94  case 1:
95  return getU8(offset_ptr);
96  case 2:
97  return getU16(offset_ptr);
98  case 4:
99  return getU32(offset_ptr);
100  case 8:
101  return getU64(offset_ptr);
102  }
103  llvm_unreachable("getUnsigned unhandled case!");
104 }
105 
106 int64_t
107 DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const {
108  switch (byte_size) {
109  case 1:
110  return (int8_t)getU8(offset_ptr);
111  case 2:
112  return (int16_t)getU16(offset_ptr);
113  case 4:
114  return (int32_t)getU32(offset_ptr);
115  case 8:
116  return (int64_t)getU64(offset_ptr);
117  }
118  llvm_unreachable("getSigned unhandled case!");
119 }
120 
121 const char *DataExtractor::getCStr(uint32_t *offset_ptr) const {
122  uint32_t offset = *offset_ptr;
123  StringRef::size_type pos = Data.find('\0', offset);
124  if (pos != StringRef::npos) {
125  *offset_ptr = pos + 1;
126  return Data.data() + offset;
127  }
128  return NULL;
129 }
130 
131 uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const {
132  uint64_t result = 0;
133  if (Data.empty())
134  return 0;
135 
136  unsigned shift = 0;
137  uint32_t offset = *offset_ptr;
138  uint8_t byte = 0;
139 
140  while (isValidOffset(offset)) {
141  byte = Data[offset++];
142  result |= uint64_t(byte & 0x7f) << shift;
143  shift += 7;
144  if ((byte & 0x80) == 0)
145  break;
146  }
147 
148  *offset_ptr = offset;
149  return result;
150 }
151 
152 int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
153  int64_t result = 0;
154  if (Data.empty())
155  return 0;
156 
157  unsigned shift = 0;
158  uint32_t offset = *offset_ptr;
159  uint8_t byte = 0;
160 
161  while (isValidOffset(offset)) {
162  byte = Data[offset++];
163  result |= uint64_t(byte & 0x7f) << shift;
164  shift += 7;
165  if ((byte & 0x80) == 0)
166  break;
167  }
168 
169  // Sign bit of byte is 2nd high order bit (0x40)
170  if (shift < 64 && (byte & 0x40))
171  result |= -(1ULL << shift);
172 
173  *offset_ptr = offset;
174  return result;
175 }
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:181
size_t find(char C, size_t From=0) const
Definition: StringRef.h:233
int64_t getSigned(uint32_t *offset_ptr, uint32_t size) const
bool isValidOffset(uint32_t offset) const
uint32_t getU32(uint32_t *offset_ptr) const
#define llvm_unreachable(msg)
bool isValidOffsetForDataOfSize(uint32_t offset, uint32_t length) const
static const bool IsLittleEndianHost
Definition: Host.h:38
const char * data() const
Definition: StringRef.h:107
static T * getUs(uint32_t *offset_ptr, T *dst, uint32_t count, const DataExtractor *de, bool isLittleEndian, const char *Data)
const char * getCStr(uint32_t *offset_ptr) const
uint8_t getU8(uint32_t *offset_ptr) const
uint64_t getULEB128(uint32_t *offset_ptr) const
uint64_t getU64(uint32_t *offset_ptr) const
unsigned char SwapByteOrder(unsigned char C)
Definition: SwapByteOrder.h:71
uint16_t getU16(uint32_t *offset_ptr) const
static const size_t npos
Definition: StringRef.h:45
size_t size_type
Definition: StringRef.h:46
uint64_t getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const
int64_t getSLEB128(uint32_t *offset_ptr) const
bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:110
static T getU(uint32_t *offset_ptr, const DataExtractor *de, bool isLittleEndian, const char *Data)