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