1 //===-- DataExtractor.cpp -------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Support/DataExtractor.h"
10 #include "llvm/Support/Errc.h"
11 #include "llvm/Support/ErrorHandling.h"
12 #include "llvm/Support/LEB128.h"
13 #include "llvm/Support/SwapByteOrder.h"
17 bool DataExtractor::prepareRead(uint64_t Offset
, uint64_t Size
,
19 if (isValidOffsetForDataOfSize(Offset
, Size
))
22 if (Offset
<= Data
.size())
23 *E
= createStringError(
24 errc::illegal_byte_sequence
,
25 "unexpected end of data at offset 0x%zx while reading [0x%" PRIx64
27 Data
.size(), Offset
, Offset
+ Size
);
29 *E
= createStringError(errc::invalid_argument
,
31 " is beyond the end of data at 0x%zx",
37 static bool isError(Error
*E
) { return E
&& *E
; }
40 T
DataExtractor::getU(uint64_t *offset_ptr
, Error
*Err
) const {
41 ErrorAsOutParameter
ErrAsOut(Err
);
46 uint64_t offset
= *offset_ptr
;
47 if (!prepareRead(offset
, sizeof(T
), Err
))
49 std::memcpy(&val
, &Data
.data()[offset
], sizeof(val
));
50 if (sys::IsLittleEndianHost
!= IsLittleEndian
)
51 sys::swapByteOrder(val
);
54 *offset_ptr
+= sizeof(val
);
59 T
*DataExtractor::getUs(uint64_t *offset_ptr
, T
*dst
, uint32_t count
,
61 ErrorAsOutParameter
ErrAsOut(Err
);
65 uint64_t offset
= *offset_ptr
;
67 if (!prepareRead(offset
, sizeof(*dst
) * count
, Err
))
69 for (T
*value_ptr
= dst
, *end
= dst
+ count
; value_ptr
!= end
;
70 ++value_ptr
, offset
+= sizeof(*dst
))
71 *value_ptr
= getU
<T
>(offset_ptr
, Err
);
74 // Return a non-NULL pointer to the converted data as an indicator of
79 uint8_t DataExtractor::getU8(uint64_t *offset_ptr
, llvm::Error
*Err
) const {
80 return getU
<uint8_t>(offset_ptr
, Err
);
83 uint8_t *DataExtractor::getU8(uint64_t *offset_ptr
, uint8_t *dst
,
84 uint32_t count
) const {
85 return getUs
<uint8_t>(offset_ptr
, dst
, count
, nullptr);
88 uint8_t *DataExtractor::getU8(Cursor
&C
, uint8_t *Dst
, uint32_t Count
) const {
89 return getUs
<uint8_t>(&C
.Offset
, Dst
, Count
, &C
.Err
);
92 uint16_t DataExtractor::getU16(uint64_t *offset_ptr
, llvm::Error
*Err
) const {
93 return getU
<uint16_t>(offset_ptr
, Err
);
96 uint16_t *DataExtractor::getU16(uint64_t *offset_ptr
, uint16_t *dst
,
97 uint32_t count
) const {
98 return getUs
<uint16_t>(offset_ptr
, dst
, count
, nullptr);
101 uint32_t DataExtractor::getU24(uint64_t *OffsetPtr
, Error
*Err
) const {
102 uint24_t ExtractedVal
= getU
<uint24_t
>(OffsetPtr
, Err
);
103 // The 3 bytes are in the correct byte order for the host.
104 return ExtractedVal
.getAsUint32(sys::IsLittleEndianHost
);
107 uint32_t DataExtractor::getU32(uint64_t *offset_ptr
, llvm::Error
*Err
) const {
108 return getU
<uint32_t>(offset_ptr
, Err
);
111 uint32_t *DataExtractor::getU32(uint64_t *offset_ptr
, uint32_t *dst
,
112 uint32_t count
) const {
113 return getUs
<uint32_t>(offset_ptr
, dst
, count
, nullptr);
116 uint64_t DataExtractor::getU64(uint64_t *offset_ptr
, llvm::Error
*Err
) const {
117 return getU
<uint64_t>(offset_ptr
, Err
);
120 uint64_t *DataExtractor::getU64(uint64_t *offset_ptr
, uint64_t *dst
,
121 uint32_t count
) const {
122 return getUs
<uint64_t>(offset_ptr
, dst
, count
, nullptr);
125 uint64_t DataExtractor::getUnsigned(uint64_t *offset_ptr
, uint32_t byte_size
,
126 llvm::Error
*Err
) const {
129 return getU8(offset_ptr
, Err
);
131 return getU16(offset_ptr
, Err
);
133 return getU32(offset_ptr
, Err
);
135 return getU64(offset_ptr
, Err
);
137 llvm_unreachable("getUnsigned unhandled case!");
141 DataExtractor::getSigned(uint64_t *offset_ptr
, uint32_t byte_size
) const {
144 return (int8_t)getU8(offset_ptr
);
146 return (int16_t)getU16(offset_ptr
);
148 return (int32_t)getU32(offset_ptr
);
150 return (int64_t)getU64(offset_ptr
);
152 llvm_unreachable("getSigned unhandled case!");
155 StringRef
DataExtractor::getCStrRef(uint64_t *OffsetPtr
, Error
*Err
) const {
156 ErrorAsOutParameter
ErrAsOut(Err
);
160 uint64_t Start
= *OffsetPtr
;
161 StringRef::size_type Pos
= Data
.find('\0', Start
);
162 if (Pos
!= StringRef::npos
) {
163 *OffsetPtr
= Pos
+ 1;
164 return StringRef(Data
.data() + Start
, Pos
- Start
);
167 *Err
= createStringError(errc::illegal_byte_sequence
,
168 "no null terminated string at offset 0x%" PRIx64
,
173 StringRef
DataExtractor::getFixedLengthString(uint64_t *OffsetPtr
,
175 StringRef TrimChars
) const {
176 StringRef
Bytes(getBytes(OffsetPtr
, Length
));
177 return Bytes
.trim(TrimChars
);
180 StringRef
DataExtractor::getBytes(uint64_t *OffsetPtr
, uint64_t Length
,
182 ErrorAsOutParameter
ErrAsOut(Err
);
186 if (!prepareRead(*OffsetPtr
, Length
, Err
))
189 StringRef Result
= Data
.substr(*OffsetPtr
, Length
);
190 *OffsetPtr
+= Length
;
194 template <typename T
>
195 static T
getLEB128(StringRef Data
, uint64_t *OffsetPtr
, Error
*Err
,
196 T (&Decoder
)(const uint8_t *p
, unsigned *n
,
197 const uint8_t *end
, const char **error
)) {
198 ArrayRef
<uint8_t> Bytes
= arrayRefFromStringRef(Data
);
199 assert(*OffsetPtr
<= Bytes
.size());
200 ErrorAsOutParameter
ErrAsOut(Err
);
207 Decoder(Bytes
.data() + *OffsetPtr
, &bytes_read
, Bytes
.end(), &error
);
210 *Err
= createStringError(errc::illegal_byte_sequence
,
211 "unable to decode LEB128 at offset 0x%8.8" PRIx64
216 *OffsetPtr
+= bytes_read
;
220 uint64_t DataExtractor::getULEB128(uint64_t *offset_ptr
, Error
*Err
) const {
221 return getLEB128(Data
, offset_ptr
, Err
, decodeULEB128
);
224 int64_t DataExtractor::getSLEB128(uint64_t *offset_ptr
, Error
*Err
) const {
225 return getLEB128(Data
, offset_ptr
, Err
, decodeSLEB128
);
228 void DataExtractor::skip(Cursor
&C
, uint64_t Length
) const {
229 ErrorAsOutParameter
ErrAsOut(&C
.Err
);
233 if (prepareRead(C
.Offset
, Length
, &C
.Err
))