180814287SRaphael Isemann //===-- DataExtractor.cpp -------------------------------------------------===//
2666cc0b2SZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6666cc0b2SZachary Turner //
7666cc0b2SZachary Turner //===----------------------------------------------------------------------===//
8666cc0b2SZachary Turner 
94479ac15SZachary Turner #include "lldb/Utility/DataExtractor.h"
10666cc0b2SZachary Turner 
11672d2c12SJonas Devlieghere #include "lldb/lldb-defines.h"
12672d2c12SJonas Devlieghere #include "lldb/lldb-enumerations.h"
13672d2c12SJonas Devlieghere #include "lldb/lldb-forward.h"
14672d2c12SJonas Devlieghere #include "lldb/lldb-types.h"
154479ac15SZachary Turner 
16666cc0b2SZachary Turner #include "lldb/Utility/DataBuffer.h"
17666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h"
18dbd7c338SPetr Pavlu #include "lldb/Utility/LLDBAssert.h"
19666cc0b2SZachary Turner #include "lldb/Utility/Log.h"
20666cc0b2SZachary Turner #include "lldb/Utility/Stream.h"
21666cc0b2SZachary Turner #include "lldb/Utility/StreamString.h"
22666cc0b2SZachary Turner #include "lldb/Utility/UUID.h"
23666cc0b2SZachary Turner 
24666cc0b2SZachary Turner #include "llvm/ADT/ArrayRef.h"
25666cc0b2SZachary Turner #include "llvm/ADT/SmallVector.h"
26bb9d93f4SRaphael Isemann #include "llvm/Support/LEB128.h"
27666cc0b2SZachary Turner #include "llvm/Support/MD5.h"
28666cc0b2SZachary Turner #include "llvm/Support/MathExtras.h"
29666cc0b2SZachary Turner 
30672d2c12SJonas Devlieghere #include <algorithm>
31672d2c12SJonas Devlieghere #include <array>
324479ac15SZachary Turner #include <cassert>
33672d2c12SJonas Devlieghere #include <cstdint>
344479ac15SZachary Turner #include <string>
354479ac15SZachary Turner 
3676e47d48SRaphael Isemann #include <cctype>
3776e47d48SRaphael Isemann #include <cinttypes>
3876e47d48SRaphael Isemann #include <cstring>
394479ac15SZachary Turner 
40666cc0b2SZachary Turner using namespace lldb;
41666cc0b2SZachary Turner using namespace lldb_private;
42666cc0b2SZachary Turner 
ReadInt16(const unsigned char * ptr,offset_t offset)43666cc0b2SZachary Turner static inline uint16_t ReadInt16(const unsigned char *ptr, offset_t offset) {
44666cc0b2SZachary Turner   uint16_t value;
45666cc0b2SZachary Turner   memcpy(&value, ptr + offset, 2);
46666cc0b2SZachary Turner   return value;
47666cc0b2SZachary Turner }
48666cc0b2SZachary Turner 
ReadInt32(const unsigned char * ptr,offset_t offset=0)49666cc0b2SZachary Turner static inline uint32_t ReadInt32(const unsigned char *ptr,
50666cc0b2SZachary Turner                                  offset_t offset = 0) {
51666cc0b2SZachary Turner   uint32_t value;
52666cc0b2SZachary Turner   memcpy(&value, ptr + offset, 4);
53666cc0b2SZachary Turner   return value;
54666cc0b2SZachary Turner }
55666cc0b2SZachary Turner 
ReadInt64(const unsigned char * ptr,offset_t offset=0)56666cc0b2SZachary Turner static inline uint64_t ReadInt64(const unsigned char *ptr,
57666cc0b2SZachary Turner                                  offset_t offset = 0) {
58666cc0b2SZachary Turner   uint64_t value;
59666cc0b2SZachary Turner   memcpy(&value, ptr + offset, 8);
60666cc0b2SZachary Turner   return value;
61666cc0b2SZachary Turner }
62666cc0b2SZachary Turner 
ReadInt16(const void * ptr)63666cc0b2SZachary Turner static inline uint16_t ReadInt16(const void *ptr) {
64666cc0b2SZachary Turner   uint16_t value;
65666cc0b2SZachary Turner   memcpy(&value, ptr, 2);
66666cc0b2SZachary Turner   return value;
67666cc0b2SZachary Turner }
68666cc0b2SZachary Turner 
ReadSwapInt16(const unsigned char * ptr,offset_t offset)69666cc0b2SZachary Turner static inline uint16_t ReadSwapInt16(const unsigned char *ptr,
70666cc0b2SZachary Turner                                      offset_t offset) {
71666cc0b2SZachary Turner   uint16_t value;
72666cc0b2SZachary Turner   memcpy(&value, ptr + offset, 2);
73666cc0b2SZachary Turner   return llvm::ByteSwap_16(value);
74666cc0b2SZachary Turner }
75666cc0b2SZachary Turner 
ReadSwapInt32(const unsigned char * ptr,offset_t offset)76666cc0b2SZachary Turner static inline uint32_t ReadSwapInt32(const unsigned char *ptr,
77666cc0b2SZachary Turner                                      offset_t offset) {
78666cc0b2SZachary Turner   uint32_t value;
79666cc0b2SZachary Turner   memcpy(&value, ptr + offset, 4);
80666cc0b2SZachary Turner   return llvm::ByteSwap_32(value);
81666cc0b2SZachary Turner }
82666cc0b2SZachary Turner 
ReadSwapInt64(const unsigned char * ptr,offset_t offset)83666cc0b2SZachary Turner static inline uint64_t ReadSwapInt64(const unsigned char *ptr,
84666cc0b2SZachary Turner                                      offset_t offset) {
85666cc0b2SZachary Turner   uint64_t value;
86666cc0b2SZachary Turner   memcpy(&value, ptr + offset, 8);
87666cc0b2SZachary Turner   return llvm::ByteSwap_64(value);
88666cc0b2SZachary Turner }
89666cc0b2SZachary Turner 
ReadSwapInt16(const void * ptr)90666cc0b2SZachary Turner static inline uint16_t ReadSwapInt16(const void *ptr) {
91666cc0b2SZachary Turner   uint16_t value;
92666cc0b2SZachary Turner   memcpy(&value, ptr, 2);
93666cc0b2SZachary Turner   return llvm::ByteSwap_16(value);
94666cc0b2SZachary Turner }
95666cc0b2SZachary Turner 
ReadSwapInt32(const void * ptr)96666cc0b2SZachary Turner static inline uint32_t ReadSwapInt32(const void *ptr) {
97666cc0b2SZachary Turner   uint32_t value;
98666cc0b2SZachary Turner   memcpy(&value, ptr, 4);
99666cc0b2SZachary Turner   return llvm::ByteSwap_32(value);
100666cc0b2SZachary Turner }
101666cc0b2SZachary Turner 
ReadSwapInt64(const void * ptr)102666cc0b2SZachary Turner static inline uint64_t ReadSwapInt64(const void *ptr) {
103666cc0b2SZachary Turner   uint64_t value;
104666cc0b2SZachary Turner   memcpy(&value, ptr, 8);
105666cc0b2SZachary Turner   return llvm::ByteSwap_64(value);
106666cc0b2SZachary Turner }
107666cc0b2SZachary Turner 
ReadMaxInt64(const uint8_t * data,size_t byte_size,ByteOrder byte_order)108dbd7c338SPetr Pavlu static inline uint64_t ReadMaxInt64(const uint8_t *data, size_t byte_size,
109dbd7c338SPetr Pavlu                                     ByteOrder byte_order) {
110dbd7c338SPetr Pavlu   uint64_t res = 0;
111dbd7c338SPetr Pavlu   if (byte_order == eByteOrderBig)
112dbd7c338SPetr Pavlu     for (size_t i = 0; i < byte_size; ++i)
113dbd7c338SPetr Pavlu       res = (res << 8) | data[i];
114dbd7c338SPetr Pavlu   else {
115dbd7c338SPetr Pavlu     assert(byte_order == eByteOrderLittle);
116dbd7c338SPetr Pavlu     for (size_t i = 0; i < byte_size; ++i)
117dbd7c338SPetr Pavlu       res = (res << 8) | data[byte_size - 1 - i];
118dbd7c338SPetr Pavlu   }
119dbd7c338SPetr Pavlu   return res;
120dbd7c338SPetr Pavlu }
121dbd7c338SPetr Pavlu 
DataExtractor()122666cc0b2SZachary Turner DataExtractor::DataExtractor()
1239494c510SJonas Devlieghere     : m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)),
1249494c510SJonas Devlieghere       m_data_sp() {}
125666cc0b2SZachary Turner 
12605097246SAdrian Prantl // This constructor allows us to use data that is owned by someone else. The
12705097246SAdrian Prantl // data must stay around as long as this object is valid.
DataExtractor(const void * data,offset_t length,ByteOrder endian,uint32_t addr_size,uint32_t target_byte_size)128666cc0b2SZachary Turner DataExtractor::DataExtractor(const void *data, offset_t length,
129666cc0b2SZachary Turner                              ByteOrder endian, uint32_t addr_size,
130666cc0b2SZachary Turner                              uint32_t target_byte_size /*=1*/)
13165fdb342SRaphael Isemann     : m_start(const_cast<uint8_t *>(static_cast<const uint8_t *>(data))),
13265fdb342SRaphael Isemann       m_end(const_cast<uint8_t *>(static_cast<const uint8_t *>(data)) + length),
133666cc0b2SZachary Turner       m_byte_order(endian), m_addr_size(addr_size), m_data_sp(),
134666cc0b2SZachary Turner       m_target_byte_size(target_byte_size) {
135ec1efe71SAyke van Laethem   assert(addr_size >= 1 && addr_size <= 8);
136666cc0b2SZachary Turner }
137666cc0b2SZachary Turner 
13805097246SAdrian Prantl // Make a shared pointer reference to the shared data in "data_sp" and set the
13905097246SAdrian Prantl // endian swapping setting to "swap", and the address size to "addr_size". The
14005097246SAdrian Prantl // shared data reference will ensure the data lives as long as any
14105097246SAdrian Prantl // DataExtractor objects exist that have a reference to this data.
DataExtractor(const DataBufferSP & data_sp,ByteOrder endian,uint32_t addr_size,uint32_t target_byte_size)142666cc0b2SZachary Turner DataExtractor::DataExtractor(const DataBufferSP &data_sp, ByteOrder endian,
143666cc0b2SZachary Turner                              uint32_t addr_size,
144666cc0b2SZachary Turner                              uint32_t target_byte_size /*=1*/)
14528c878aeSShafik Yaghmour     : m_byte_order(endian), m_addr_size(addr_size), m_data_sp(),
146666cc0b2SZachary Turner       m_target_byte_size(target_byte_size) {
147ec1efe71SAyke van Laethem   assert(addr_size >= 1 && addr_size <= 8);
148666cc0b2SZachary Turner   SetData(data_sp);
149666cc0b2SZachary Turner }
150666cc0b2SZachary Turner 
15105097246SAdrian Prantl // Initialize this object with a subset of the data bytes in "data". If "data"
15205097246SAdrian Prantl // contains shared data, then a reference to this shared data will added and
15305097246SAdrian Prantl // the shared data will stay around as long as any object contains a reference
15405097246SAdrian Prantl // to that data. The endian swap and address size settings are copied from
15505097246SAdrian Prantl // "data".
DataExtractor(const DataExtractor & data,offset_t offset,offset_t length,uint32_t target_byte_size)156666cc0b2SZachary Turner DataExtractor::DataExtractor(const DataExtractor &data, offset_t offset,
157666cc0b2SZachary Turner                              offset_t length, uint32_t target_byte_size /*=1*/)
15828c878aeSShafik Yaghmour     : m_byte_order(data.m_byte_order), m_addr_size(data.m_addr_size),
15928c878aeSShafik Yaghmour       m_data_sp(), m_target_byte_size(target_byte_size) {
160ec1efe71SAyke van Laethem   assert(m_addr_size >= 1 && m_addr_size <= 8);
161666cc0b2SZachary Turner   if (data.ValidOffset(offset)) {
162666cc0b2SZachary Turner     offset_t bytes_available = data.GetByteSize() - offset;
163666cc0b2SZachary Turner     if (length > bytes_available)
164666cc0b2SZachary Turner       length = bytes_available;
165666cc0b2SZachary Turner     SetData(data, offset, length);
166666cc0b2SZachary Turner   }
167666cc0b2SZachary Turner }
168666cc0b2SZachary Turner 
DataExtractor(const DataExtractor & rhs)169666cc0b2SZachary Turner DataExtractor::DataExtractor(const DataExtractor &rhs)
170666cc0b2SZachary Turner     : m_start(rhs.m_start), m_end(rhs.m_end), m_byte_order(rhs.m_byte_order),
171666cc0b2SZachary Turner       m_addr_size(rhs.m_addr_size), m_data_sp(rhs.m_data_sp),
172666cc0b2SZachary Turner       m_target_byte_size(rhs.m_target_byte_size) {
173ec1efe71SAyke van Laethem   assert(m_addr_size >= 1 && m_addr_size <= 8);
174666cc0b2SZachary Turner }
175666cc0b2SZachary Turner 
176666cc0b2SZachary Turner // Assignment operator
operator =(const DataExtractor & rhs)177666cc0b2SZachary Turner const DataExtractor &DataExtractor::operator=(const DataExtractor &rhs) {
178666cc0b2SZachary Turner   if (this != &rhs) {
179666cc0b2SZachary Turner     m_start = rhs.m_start;
180666cc0b2SZachary Turner     m_end = rhs.m_end;
181666cc0b2SZachary Turner     m_byte_order = rhs.m_byte_order;
182666cc0b2SZachary Turner     m_addr_size = rhs.m_addr_size;
183666cc0b2SZachary Turner     m_data_sp = rhs.m_data_sp;
184666cc0b2SZachary Turner   }
185666cc0b2SZachary Turner   return *this;
186666cc0b2SZachary Turner }
187666cc0b2SZachary Turner 
188666cc0b2SZachary Turner DataExtractor::~DataExtractor() = default;
189666cc0b2SZachary Turner 
19005097246SAdrian Prantl // Clears the object contents back to a default invalid state, and release any
19105097246SAdrian Prantl // references to shared data that this object may contain.
Clear()192666cc0b2SZachary Turner void DataExtractor::Clear() {
193666cc0b2SZachary Turner   m_start = nullptr;
194666cc0b2SZachary Turner   m_end = nullptr;
195666cc0b2SZachary Turner   m_byte_order = endian::InlHostByteOrder();
196666cc0b2SZachary Turner   m_addr_size = sizeof(void *);
197666cc0b2SZachary Turner   m_data_sp.reset();
198666cc0b2SZachary Turner }
199666cc0b2SZachary Turner 
20005097246SAdrian Prantl // If this object contains shared data, this function returns the offset into
20105097246SAdrian Prantl // that shared data. Else zero is returned.
GetSharedDataOffset() const202666cc0b2SZachary Turner size_t DataExtractor::GetSharedDataOffset() const {
203666cc0b2SZachary Turner   if (m_start != nullptr) {
204666cc0b2SZachary Turner     const DataBuffer *data = m_data_sp.get();
205666cc0b2SZachary Turner     if (data != nullptr) {
206666cc0b2SZachary Turner       const uint8_t *data_bytes = data->GetBytes();
207666cc0b2SZachary Turner       if (data_bytes != nullptr) {
208666cc0b2SZachary Turner         assert(m_start >= data_bytes);
209666cc0b2SZachary Turner         return m_start - data_bytes;
210666cc0b2SZachary Turner       }
211666cc0b2SZachary Turner     }
212666cc0b2SZachary Turner   }
213666cc0b2SZachary Turner   return 0;
214666cc0b2SZachary Turner }
215666cc0b2SZachary Turner 
21605097246SAdrian Prantl // Set the data with which this object will extract from to data starting at
21705097246SAdrian Prantl // BYTES and set the length of the data to LENGTH bytes long. The data is
21805097246SAdrian Prantl // externally owned must be around at least as long as this object points to
21905097246SAdrian Prantl // the data. No copy of the data is made, this object just refers to this data
22005097246SAdrian Prantl // and can extract from it. If this object refers to any shared data upon
22105097246SAdrian Prantl // entry, the reference to that data will be released. Is SWAP is set to true,
222666cc0b2SZachary Turner // any data extracted will be endian swapped.
SetData(const void * bytes,offset_t length,ByteOrder endian)223666cc0b2SZachary Turner lldb::offset_t DataExtractor::SetData(const void *bytes, offset_t length,
224666cc0b2SZachary Turner                                       ByteOrder endian) {
225666cc0b2SZachary Turner   m_byte_order = endian;
226666cc0b2SZachary Turner   m_data_sp.reset();
227666cc0b2SZachary Turner   if (bytes == nullptr || length == 0) {
228666cc0b2SZachary Turner     m_start = nullptr;
229666cc0b2SZachary Turner     m_end = nullptr;
230666cc0b2SZachary Turner   } else {
23165fdb342SRaphael Isemann     m_start = const_cast<uint8_t *>(static_cast<const uint8_t *>(bytes));
232666cc0b2SZachary Turner     m_end = m_start + length;
233666cc0b2SZachary Turner   }
234666cc0b2SZachary Turner   return GetByteSize();
235666cc0b2SZachary Turner }
236666cc0b2SZachary Turner 
23705097246SAdrian Prantl // Assign the data for this object to be a subrange in "data" starting
23805097246SAdrian Prantl // "data_offset" bytes into "data" and ending "data_length" bytes later. If
23905097246SAdrian Prantl // "data_offset" is not a valid offset into "data", then this object will
24005097246SAdrian Prantl // contain no bytes. If "data_offset" is within "data" yet "data_length" is too
24105097246SAdrian Prantl // large, the length will be capped at the number of bytes remaining in "data".
24205097246SAdrian Prantl // If "data" contains a shared pointer to other data, then a ref counted
24305097246SAdrian Prantl // pointer to that data will be made in this object. If "data" doesn't contain
24405097246SAdrian Prantl // a shared pointer to data, then the bytes referred to in "data" will need to
24505097246SAdrian Prantl // exist at least as long as this object refers to those bytes. The address
24605097246SAdrian Prantl // size and endian swap settings are copied from the current values in "data".
SetData(const DataExtractor & data,offset_t data_offset,offset_t data_length)247666cc0b2SZachary Turner lldb::offset_t DataExtractor::SetData(const DataExtractor &data,
248666cc0b2SZachary Turner                                       offset_t data_offset,
249666cc0b2SZachary Turner                                       offset_t data_length) {
250666cc0b2SZachary Turner   m_addr_size = data.m_addr_size;
251ec1efe71SAyke van Laethem   assert(m_addr_size >= 1 && m_addr_size <= 8);
252666cc0b2SZachary Turner   // If "data" contains shared pointer to data, then we can use that
253666cc0b2SZachary Turner   if (data.m_data_sp) {
254666cc0b2SZachary Turner     m_byte_order = data.m_byte_order;
255666cc0b2SZachary Turner     return SetData(data.m_data_sp, data.GetSharedDataOffset() + data_offset,
256666cc0b2SZachary Turner                    data_length);
257666cc0b2SZachary Turner   }
258666cc0b2SZachary Turner 
259666cc0b2SZachary Turner   // We have a DataExtractor object that just has a pointer to bytes
260666cc0b2SZachary Turner   if (data.ValidOffset(data_offset)) {
261666cc0b2SZachary Turner     if (data_length > data.GetByteSize() - data_offset)
262666cc0b2SZachary Turner       data_length = data.GetByteSize() - data_offset;
263666cc0b2SZachary Turner     return SetData(data.GetDataStart() + data_offset, data_length,
264666cc0b2SZachary Turner                    data.GetByteOrder());
265666cc0b2SZachary Turner   }
266666cc0b2SZachary Turner   return 0;
267666cc0b2SZachary Turner }
268666cc0b2SZachary Turner 
26905097246SAdrian Prantl // Assign the data for this object to be a subrange of the shared data in
27005097246SAdrian Prantl // "data_sp" starting "data_offset" bytes into "data_sp" and ending
27105097246SAdrian Prantl // "data_length" bytes later. If "data_offset" is not a valid offset into
27205097246SAdrian Prantl // "data_sp", then this object will contain no bytes. If "data_offset" is
27305097246SAdrian Prantl // within "data_sp" yet "data_length" is too large, the length will be capped
27405097246SAdrian Prantl // at the number of bytes remaining in "data_sp". A ref counted pointer to the
27505097246SAdrian Prantl // data in "data_sp" will be made in this object IF the number of bytes this
27605097246SAdrian Prantl // object refers to in greater than zero (if at least one byte was available
27705097246SAdrian Prantl // starting at "data_offset") to ensure the data stays around as long as it is
27805097246SAdrian Prantl // needed. The address size and endian swap settings will remain unchanged from
27905097246SAdrian Prantl // their current settings.
SetData(const DataBufferSP & data_sp,offset_t data_offset,offset_t data_length)280666cc0b2SZachary Turner lldb::offset_t DataExtractor::SetData(const DataBufferSP &data_sp,
281666cc0b2SZachary Turner                                       offset_t data_offset,
282666cc0b2SZachary Turner                                       offset_t data_length) {
283666cc0b2SZachary Turner   m_start = m_end = nullptr;
284666cc0b2SZachary Turner 
285666cc0b2SZachary Turner   if (data_length > 0) {
286666cc0b2SZachary Turner     m_data_sp = data_sp;
287666cc0b2SZachary Turner     if (data_sp) {
288666cc0b2SZachary Turner       const size_t data_size = data_sp->GetByteSize();
289666cc0b2SZachary Turner       if (data_offset < data_size) {
290666cc0b2SZachary Turner         m_start = data_sp->GetBytes() + data_offset;
291666cc0b2SZachary Turner         const size_t bytes_left = data_size - data_offset;
292666cc0b2SZachary Turner         // Cap the length of we asked for too many
293666cc0b2SZachary Turner         if (data_length <= bytes_left)
294666cc0b2SZachary Turner           m_end = m_start + data_length; // We got all the bytes we wanted
295666cc0b2SZachary Turner         else
296666cc0b2SZachary Turner           m_end = m_start + bytes_left; // Not all the bytes requested were
297666cc0b2SZachary Turner                                         // available in the shared data
298666cc0b2SZachary Turner       }
299666cc0b2SZachary Turner     }
300666cc0b2SZachary Turner   }
301666cc0b2SZachary Turner 
302666cc0b2SZachary Turner   size_t new_size = GetByteSize();
303666cc0b2SZachary Turner 
30405097246SAdrian Prantl   // Don't hold a shared pointer to the data buffer if we don't share any valid
30505097246SAdrian Prantl   // bytes in the shared buffer.
306666cc0b2SZachary Turner   if (new_size == 0)
307666cc0b2SZachary Turner     m_data_sp.reset();
308666cc0b2SZachary Turner 
309666cc0b2SZachary Turner   return new_size;
310666cc0b2SZachary Turner }
311666cc0b2SZachary Turner 
31205097246SAdrian Prantl // Extract a single unsigned char from the binary data and update the offset
31305097246SAdrian Prantl // pointed to by "offset_ptr".
314666cc0b2SZachary Turner //
315666cc0b2SZachary Turner // RETURNS the byte that was extracted, or zero on failure.
GetU8(offset_t * offset_ptr) const316666cc0b2SZachary Turner uint8_t DataExtractor::GetU8(offset_t *offset_ptr) const {
31724374aefSJonas Devlieghere   const uint8_t *data = static_cast<const uint8_t *>(GetData(offset_ptr, 1));
318666cc0b2SZachary Turner   if (data)
319666cc0b2SZachary Turner     return *data;
320666cc0b2SZachary Turner   return 0;
321666cc0b2SZachary Turner }
322666cc0b2SZachary Turner 
32305097246SAdrian Prantl // Extract "count" unsigned chars from the binary data and update the offset
32405097246SAdrian Prantl // pointed to by "offset_ptr". The extracted data is copied into "dst".
325666cc0b2SZachary Turner //
326666cc0b2SZachary Turner // RETURNS the non-nullptr buffer pointer upon successful extraction of
32705097246SAdrian Prantl // all the requested bytes, or nullptr when the data is not available in the
32805097246SAdrian Prantl // buffer due to being out of bounds, or insufficient data.
GetU8(offset_t * offset_ptr,void * dst,uint32_t count) const329666cc0b2SZachary Turner void *DataExtractor::GetU8(offset_t *offset_ptr, void *dst,
330666cc0b2SZachary Turner                            uint32_t count) const {
33124374aefSJonas Devlieghere   const uint8_t *data =
33224374aefSJonas Devlieghere       static_cast<const uint8_t *>(GetData(offset_ptr, count));
333666cc0b2SZachary Turner   if (data) {
334666cc0b2SZachary Turner     // Copy the data into the buffer
335666cc0b2SZachary Turner     memcpy(dst, data, count);
336666cc0b2SZachary Turner     // Return a non-nullptr pointer to the converted data as an indicator of
337666cc0b2SZachary Turner     // success
338666cc0b2SZachary Turner     return dst;
339666cc0b2SZachary Turner   }
340666cc0b2SZachary Turner   return nullptr;
341666cc0b2SZachary Turner }
342666cc0b2SZachary Turner 
34305097246SAdrian Prantl // Extract a single uint16_t from the data and update the offset pointed to by
34405097246SAdrian Prantl // "offset_ptr".
345666cc0b2SZachary Turner //
346666cc0b2SZachary Turner // RETURNS the uint16_t that was extracted, or zero on failure.
GetU16(offset_t * offset_ptr) const347666cc0b2SZachary Turner uint16_t DataExtractor::GetU16(offset_t *offset_ptr) const {
348666cc0b2SZachary Turner   uint16_t val = 0;
34924374aefSJonas Devlieghere   const uint8_t *data =
35024374aefSJonas Devlieghere       static_cast<const uint8_t *>(GetData(offset_ptr, sizeof(val)));
351666cc0b2SZachary Turner   if (data) {
352666cc0b2SZachary Turner     if (m_byte_order != endian::InlHostByteOrder())
353666cc0b2SZachary Turner       val = ReadSwapInt16(data);
354666cc0b2SZachary Turner     else
355666cc0b2SZachary Turner       val = ReadInt16(data);
356666cc0b2SZachary Turner   }
357666cc0b2SZachary Turner   return val;
358666cc0b2SZachary Turner }
359666cc0b2SZachary Turner 
GetU16_unchecked(offset_t * offset_ptr) const360666cc0b2SZachary Turner uint16_t DataExtractor::GetU16_unchecked(offset_t *offset_ptr) const {
361666cc0b2SZachary Turner   uint16_t val;
362666cc0b2SZachary Turner   if (m_byte_order == endian::InlHostByteOrder())
363666cc0b2SZachary Turner     val = ReadInt16(m_start, *offset_ptr);
364666cc0b2SZachary Turner   else
365666cc0b2SZachary Turner     val = ReadSwapInt16(m_start, *offset_ptr);
366666cc0b2SZachary Turner   *offset_ptr += sizeof(val);
367666cc0b2SZachary Turner   return val;
368666cc0b2SZachary Turner }
369666cc0b2SZachary Turner 
GetU32_unchecked(offset_t * offset_ptr) const370666cc0b2SZachary Turner uint32_t DataExtractor::GetU32_unchecked(offset_t *offset_ptr) const {
371666cc0b2SZachary Turner   uint32_t val;
372666cc0b2SZachary Turner   if (m_byte_order == endian::InlHostByteOrder())
373666cc0b2SZachary Turner     val = ReadInt32(m_start, *offset_ptr);
374666cc0b2SZachary Turner   else
375666cc0b2SZachary Turner     val = ReadSwapInt32(m_start, *offset_ptr);
376666cc0b2SZachary Turner   *offset_ptr += sizeof(val);
377666cc0b2SZachary Turner   return val;
378666cc0b2SZachary Turner }
379666cc0b2SZachary Turner 
GetU64_unchecked(offset_t * offset_ptr) const380666cc0b2SZachary Turner uint64_t DataExtractor::GetU64_unchecked(offset_t *offset_ptr) const {
381666cc0b2SZachary Turner   uint64_t val;
382666cc0b2SZachary Turner   if (m_byte_order == endian::InlHostByteOrder())
383666cc0b2SZachary Turner     val = ReadInt64(m_start, *offset_ptr);
384666cc0b2SZachary Turner   else
385666cc0b2SZachary Turner     val = ReadSwapInt64(m_start, *offset_ptr);
386666cc0b2SZachary Turner   *offset_ptr += sizeof(val);
387666cc0b2SZachary Turner   return val;
388666cc0b2SZachary Turner }
389666cc0b2SZachary Turner 
39005097246SAdrian Prantl // Extract "count" uint16_t values from the binary data and update the offset
39105097246SAdrian Prantl // pointed to by "offset_ptr". The extracted data is copied into "dst".
392666cc0b2SZachary Turner //
393666cc0b2SZachary Turner // RETURNS the non-nullptr buffer pointer upon successful extraction of
39405097246SAdrian Prantl // all the requested bytes, or nullptr when the data is not available in the
39505097246SAdrian Prantl // buffer due to being out of bounds, or insufficient data.
GetU16(offset_t * offset_ptr,void * void_dst,uint32_t count) const396666cc0b2SZachary Turner void *DataExtractor::GetU16(offset_t *offset_ptr, void *void_dst,
397666cc0b2SZachary Turner                             uint32_t count) const {
398666cc0b2SZachary Turner   const size_t src_size = sizeof(uint16_t) * count;
39924374aefSJonas Devlieghere   const uint16_t *src =
40024374aefSJonas Devlieghere       static_cast<const uint16_t *>(GetData(offset_ptr, src_size));
401666cc0b2SZachary Turner   if (src) {
402666cc0b2SZachary Turner     if (m_byte_order != endian::InlHostByteOrder()) {
40324374aefSJonas Devlieghere       uint16_t *dst_pos = static_cast<uint16_t *>(void_dst);
404666cc0b2SZachary Turner       uint16_t *dst_end = dst_pos + count;
405666cc0b2SZachary Turner       const uint16_t *src_pos = src;
406666cc0b2SZachary Turner       while (dst_pos < dst_end) {
407666cc0b2SZachary Turner         *dst_pos = ReadSwapInt16(src_pos);
408666cc0b2SZachary Turner         ++dst_pos;
409666cc0b2SZachary Turner         ++src_pos;
410666cc0b2SZachary Turner       }
411666cc0b2SZachary Turner     } else {
412666cc0b2SZachary Turner       memcpy(void_dst, src, src_size);
413666cc0b2SZachary Turner     }
414666cc0b2SZachary Turner     // Return a non-nullptr pointer to the converted data as an indicator of
415666cc0b2SZachary Turner     // success
416666cc0b2SZachary Turner     return void_dst;
417666cc0b2SZachary Turner   }
418666cc0b2SZachary Turner   return nullptr;
419666cc0b2SZachary Turner }
420666cc0b2SZachary Turner 
42105097246SAdrian Prantl // Extract a single uint32_t from the data and update the offset pointed to by
42205097246SAdrian Prantl // "offset_ptr".
423666cc0b2SZachary Turner //
424666cc0b2SZachary Turner // RETURNS the uint32_t that was extracted, or zero on failure.
GetU32(offset_t * offset_ptr) const425666cc0b2SZachary Turner uint32_t DataExtractor::GetU32(offset_t *offset_ptr) const {
426666cc0b2SZachary Turner   uint32_t val = 0;
42724374aefSJonas Devlieghere   const uint8_t *data =
42824374aefSJonas Devlieghere       static_cast<const uint8_t *>(GetData(offset_ptr, sizeof(val)));
429666cc0b2SZachary Turner   if (data) {
430666cc0b2SZachary Turner     if (m_byte_order != endian::InlHostByteOrder()) {
431666cc0b2SZachary Turner       val = ReadSwapInt32(data);
432666cc0b2SZachary Turner     } else {
433666cc0b2SZachary Turner       memcpy(&val, data, 4);
434666cc0b2SZachary Turner     }
435666cc0b2SZachary Turner   }
436666cc0b2SZachary Turner   return val;
437666cc0b2SZachary Turner }
438666cc0b2SZachary Turner 
43905097246SAdrian Prantl // Extract "count" uint32_t values from the binary data and update the offset
44005097246SAdrian Prantl // pointed to by "offset_ptr". The extracted data is copied into "dst".
441666cc0b2SZachary Turner //
442666cc0b2SZachary Turner // RETURNS the non-nullptr buffer pointer upon successful extraction of
44305097246SAdrian Prantl // all the requested bytes, or nullptr when the data is not available in the
44405097246SAdrian Prantl // buffer due to being out of bounds, or insufficient data.
GetU32(offset_t * offset_ptr,void * void_dst,uint32_t count) const445666cc0b2SZachary Turner void *DataExtractor::GetU32(offset_t *offset_ptr, void *void_dst,
446666cc0b2SZachary Turner                             uint32_t count) const {
447666cc0b2SZachary Turner   const size_t src_size = sizeof(uint32_t) * count;
44824374aefSJonas Devlieghere   const uint32_t *src =
44924374aefSJonas Devlieghere       static_cast<const uint32_t *>(GetData(offset_ptr, src_size));
450666cc0b2SZachary Turner   if (src) {
451666cc0b2SZachary Turner     if (m_byte_order != endian::InlHostByteOrder()) {
45224374aefSJonas Devlieghere       uint32_t *dst_pos = static_cast<uint32_t *>(void_dst);
453666cc0b2SZachary Turner       uint32_t *dst_end = dst_pos + count;
454666cc0b2SZachary Turner       const uint32_t *src_pos = src;
455666cc0b2SZachary Turner       while (dst_pos < dst_end) {
456666cc0b2SZachary Turner         *dst_pos = ReadSwapInt32(src_pos);
457666cc0b2SZachary Turner         ++dst_pos;
458666cc0b2SZachary Turner         ++src_pos;
459666cc0b2SZachary Turner       }
460666cc0b2SZachary Turner     } else {
461666cc0b2SZachary Turner       memcpy(void_dst, src, src_size);
462666cc0b2SZachary Turner     }
463666cc0b2SZachary Turner     // Return a non-nullptr pointer to the converted data as an indicator of
464666cc0b2SZachary Turner     // success
465666cc0b2SZachary Turner     return void_dst;
466666cc0b2SZachary Turner   }
467666cc0b2SZachary Turner   return nullptr;
468666cc0b2SZachary Turner }
469666cc0b2SZachary Turner 
47005097246SAdrian Prantl // Extract a single uint64_t from the data and update the offset pointed to by
47105097246SAdrian Prantl // "offset_ptr".
472666cc0b2SZachary Turner //
473666cc0b2SZachary Turner // RETURNS the uint64_t that was extracted, or zero on failure.
GetU64(offset_t * offset_ptr) const474666cc0b2SZachary Turner uint64_t DataExtractor::GetU64(offset_t *offset_ptr) const {
475666cc0b2SZachary Turner   uint64_t val = 0;
47624374aefSJonas Devlieghere   const uint8_t *data =
47724374aefSJonas Devlieghere       static_cast<const uint8_t *>(GetData(offset_ptr, sizeof(val)));
478666cc0b2SZachary Turner   if (data) {
479666cc0b2SZachary Turner     if (m_byte_order != endian::InlHostByteOrder()) {
480666cc0b2SZachary Turner       val = ReadSwapInt64(data);
481666cc0b2SZachary Turner     } else {
482666cc0b2SZachary Turner       memcpy(&val, data, 8);
483666cc0b2SZachary Turner     }
484666cc0b2SZachary Turner   }
485666cc0b2SZachary Turner   return val;
486666cc0b2SZachary Turner }
487666cc0b2SZachary Turner 
488666cc0b2SZachary Turner // GetU64
489666cc0b2SZachary Turner //
49005097246SAdrian Prantl // Get multiple consecutive 64 bit values. Return true if the entire read
49105097246SAdrian Prantl // succeeds and increment the offset pointed to by offset_ptr, else return
49205097246SAdrian Prantl // false and leave the offset pointed to by offset_ptr unchanged.
GetU64(offset_t * offset_ptr,void * void_dst,uint32_t count) const493666cc0b2SZachary Turner void *DataExtractor::GetU64(offset_t *offset_ptr, void *void_dst,
494666cc0b2SZachary Turner                             uint32_t count) const {
495666cc0b2SZachary Turner   const size_t src_size = sizeof(uint64_t) * count;
49624374aefSJonas Devlieghere   const uint64_t *src =
49724374aefSJonas Devlieghere       static_cast<const uint64_t *>(GetData(offset_ptr, src_size));
498666cc0b2SZachary Turner   if (src) {
499666cc0b2SZachary Turner     if (m_byte_order != endian::InlHostByteOrder()) {
50024374aefSJonas Devlieghere       uint64_t *dst_pos = static_cast<uint64_t *>(void_dst);
501666cc0b2SZachary Turner       uint64_t *dst_end = dst_pos + count;
502666cc0b2SZachary Turner       const uint64_t *src_pos = src;
503666cc0b2SZachary Turner       while (dst_pos < dst_end) {
504666cc0b2SZachary Turner         *dst_pos = ReadSwapInt64(src_pos);
505666cc0b2SZachary Turner         ++dst_pos;
506666cc0b2SZachary Turner         ++src_pos;
507666cc0b2SZachary Turner       }
508666cc0b2SZachary Turner     } else {
509666cc0b2SZachary Turner       memcpy(void_dst, src, src_size);
510666cc0b2SZachary Turner     }
511666cc0b2SZachary Turner     // Return a non-nullptr pointer to the converted data as an indicator of
512666cc0b2SZachary Turner     // success
513666cc0b2SZachary Turner     return void_dst;
514666cc0b2SZachary Turner   }
515666cc0b2SZachary Turner   return nullptr;
516666cc0b2SZachary Turner }
517666cc0b2SZachary Turner 
GetMaxU32(offset_t * offset_ptr,size_t byte_size) const518666cc0b2SZachary Turner uint32_t DataExtractor::GetMaxU32(offset_t *offset_ptr,
519666cc0b2SZachary Turner                                   size_t byte_size) const {
520dbd7c338SPetr Pavlu   lldbassert(byte_size > 0 && byte_size <= 4 && "GetMaxU32 invalid byte_size!");
521dbd7c338SPetr Pavlu   return GetMaxU64(offset_ptr, byte_size);
522dbd7c338SPetr Pavlu }
523dbd7c338SPetr Pavlu 
GetMaxU64(offset_t * offset_ptr,size_t byte_size) const524dbd7c338SPetr Pavlu uint64_t DataExtractor::GetMaxU64(offset_t *offset_ptr,
525dbd7c338SPetr Pavlu                                   size_t byte_size) const {
526dbd7c338SPetr Pavlu   lldbassert(byte_size > 0 && byte_size <= 8 && "GetMaxU64 invalid byte_size!");
527666cc0b2SZachary Turner   switch (byte_size) {
528666cc0b2SZachary Turner   case 1:
529666cc0b2SZachary Turner     return GetU8(offset_ptr);
530666cc0b2SZachary Turner   case 2:
531666cc0b2SZachary Turner     return GetU16(offset_ptr);
532666cc0b2SZachary Turner   case 4:
533666cc0b2SZachary Turner     return GetU32(offset_ptr);
534666cc0b2SZachary Turner   case 8:
535666cc0b2SZachary Turner     return GetU64(offset_ptr);
536dbd7c338SPetr Pavlu   default: {
537dbd7c338SPetr Pavlu     // General case.
538dbd7c338SPetr Pavlu     const uint8_t *data =
539dbd7c338SPetr Pavlu         static_cast<const uint8_t *>(GetData(offset_ptr, byte_size));
540dbd7c338SPetr Pavlu     if (data == nullptr)
541dbd7c338SPetr Pavlu       return 0;
542dbd7c338SPetr Pavlu     return ReadMaxInt64(data, byte_size, m_byte_order);
543dbd7c338SPetr Pavlu   }
544666cc0b2SZachary Turner   }
545666cc0b2SZachary Turner   return 0;
546666cc0b2SZachary Turner }
547666cc0b2SZachary Turner 
GetMaxU64_unchecked(offset_t * offset_ptr,size_t byte_size) const548666cc0b2SZachary Turner uint64_t DataExtractor::GetMaxU64_unchecked(offset_t *offset_ptr,
549dbd7c338SPetr Pavlu                                             size_t byte_size) const {
550dbd7c338SPetr Pavlu   switch (byte_size) {
551666cc0b2SZachary Turner   case 1:
552666cc0b2SZachary Turner     return GetU8_unchecked(offset_ptr);
553666cc0b2SZachary Turner   case 2:
554666cc0b2SZachary Turner     return GetU16_unchecked(offset_ptr);
555666cc0b2SZachary Turner   case 4:
556666cc0b2SZachary Turner     return GetU32_unchecked(offset_ptr);
557666cc0b2SZachary Turner   case 8:
558666cc0b2SZachary Turner     return GetU64_unchecked(offset_ptr);
559dbd7c338SPetr Pavlu   default: {
560dbd7c338SPetr Pavlu     uint64_t res = ReadMaxInt64(&m_start[*offset_ptr], byte_size, m_byte_order);
561dbd7c338SPetr Pavlu     *offset_ptr += byte_size;
562dbd7c338SPetr Pavlu     return res;
563dbd7c338SPetr Pavlu   }
564666cc0b2SZachary Turner   }
565666cc0b2SZachary Turner   return 0;
566666cc0b2SZachary Turner }
567666cc0b2SZachary Turner 
GetMaxS64(offset_t * offset_ptr,size_t byte_size) const568dbd7c338SPetr Pavlu int64_t DataExtractor::GetMaxS64(offset_t *offset_ptr, size_t byte_size) const {
569dbd7c338SPetr Pavlu   uint64_t u64 = GetMaxU64(offset_ptr, byte_size);
570dbd7c338SPetr Pavlu   return llvm::SignExtend64(u64, 8 * byte_size);
571666cc0b2SZachary Turner }
572666cc0b2SZachary Turner 
GetMaxU64Bitfield(offset_t * offset_ptr,size_t size,uint32_t bitfield_bit_size,uint32_t bitfield_bit_offset) const573666cc0b2SZachary Turner uint64_t DataExtractor::GetMaxU64Bitfield(offset_t *offset_ptr, size_t size,
574666cc0b2SZachary Turner                                           uint32_t bitfield_bit_size,
575666cc0b2SZachary Turner                                           uint32_t bitfield_bit_offset) const {
576fffd7029Sshafik   assert(bitfield_bit_size <= 64);
577666cc0b2SZachary Turner   uint64_t uval64 = GetMaxU64(offset_ptr, size);
578fffd7029Sshafik 
579fffd7029Sshafik   if (bitfield_bit_size == 0)
580fffd7029Sshafik     return uval64;
581fffd7029Sshafik 
582666cc0b2SZachary Turner   int32_t lsbcount = bitfield_bit_offset;
583666cc0b2SZachary Turner   if (m_byte_order == eByteOrderBig)
584666cc0b2SZachary Turner     lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size;
585fffd7029Sshafik 
586666cc0b2SZachary Turner   if (lsbcount > 0)
587666cc0b2SZachary Turner     uval64 >>= lsbcount;
588fffd7029Sshafik 
589fffd7029Sshafik   uint64_t bitfield_mask =
590fffd7029Sshafik       (bitfield_bit_size == 64
591fffd7029Sshafik            ? std::numeric_limits<uint64_t>::max()
592fffd7029Sshafik            : ((static_cast<uint64_t>(1) << bitfield_bit_size) - 1));
593666cc0b2SZachary Turner   if (!bitfield_mask && bitfield_bit_offset == 0 && bitfield_bit_size == 64)
594666cc0b2SZachary Turner     return uval64;
595fffd7029Sshafik 
596666cc0b2SZachary Turner   uval64 &= bitfield_mask;
597fffd7029Sshafik 
598666cc0b2SZachary Turner   return uval64;
599666cc0b2SZachary Turner }
600666cc0b2SZachary Turner 
GetMaxS64Bitfield(offset_t * offset_ptr,size_t size,uint32_t bitfield_bit_size,uint32_t bitfield_bit_offset) const601666cc0b2SZachary Turner int64_t DataExtractor::GetMaxS64Bitfield(offset_t *offset_ptr, size_t size,
602666cc0b2SZachary Turner                                          uint32_t bitfield_bit_size,
603666cc0b2SZachary Turner                                          uint32_t bitfield_bit_offset) const {
6047b90cdedSVedant Kumar   assert(size >= 1 && "GetMaxS64Bitfield size must be >= 1");
6057b90cdedSVedant Kumar   assert(size <= 8 && "GetMaxS64Bitfield size must be <= 8");
606666cc0b2SZachary Turner   int64_t sval64 = GetMaxS64(offset_ptr, size);
607bb6646ceSVedant Kumar   if (bitfield_bit_size == 0)
608bb6646ceSVedant Kumar     return sval64;
609666cc0b2SZachary Turner   int32_t lsbcount = bitfield_bit_offset;
610666cc0b2SZachary Turner   if (m_byte_order == eByteOrderBig)
611666cc0b2SZachary Turner     lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size;
612666cc0b2SZachary Turner   if (lsbcount > 0)
613666cc0b2SZachary Turner     sval64 >>= lsbcount;
614bb6646ceSVedant Kumar   uint64_t bitfield_mask = llvm::maskTrailingOnes<uint64_t>(bitfield_bit_size);
615666cc0b2SZachary Turner   sval64 &= bitfield_mask;
616666cc0b2SZachary Turner   // sign extend if needed
61724374aefSJonas Devlieghere   if (sval64 & ((static_cast<uint64_t>(1)) << (bitfield_bit_size - 1)))
618666cc0b2SZachary Turner     sval64 |= ~bitfield_mask;
619666cc0b2SZachary Turner   return sval64;
620666cc0b2SZachary Turner }
621666cc0b2SZachary Turner 
GetFloat(offset_t * offset_ptr) const622666cc0b2SZachary Turner float DataExtractor::GetFloat(offset_t *offset_ptr) const {
6235e9b16b6SJonas Devlieghere   return Get<float>(offset_ptr, 0.0f);
624666cc0b2SZachary Turner }
625666cc0b2SZachary Turner 
GetDouble(offset_t * offset_ptr) const626666cc0b2SZachary Turner double DataExtractor::GetDouble(offset_t *offset_ptr) const {
6275e9b16b6SJonas Devlieghere   return Get<double>(offset_ptr, 0.0);
628666cc0b2SZachary Turner }
629666cc0b2SZachary Turner 
GetLongDouble(offset_t * offset_ptr) const630666cc0b2SZachary Turner long double DataExtractor::GetLongDouble(offset_t *offset_ptr) const {
631666cc0b2SZachary Turner   long double val = 0.0;
632666cc0b2SZachary Turner #if defined(__i386__) || defined(__amd64__) || defined(__x86_64__) ||          \
633666cc0b2SZachary Turner     defined(_M_IX86) || defined(_M_IA64) || defined(_M_X64)
634666cc0b2SZachary Turner   *offset_ptr += CopyByteOrderedData(*offset_ptr, 10, &val, sizeof(val),
635666cc0b2SZachary Turner                                      endian::InlHostByteOrder());
636666cc0b2SZachary Turner #else
637666cc0b2SZachary Turner   *offset_ptr += CopyByteOrderedData(*offset_ptr, sizeof(val), &val,
638666cc0b2SZachary Turner                                      sizeof(val), endian::InlHostByteOrder());
639666cc0b2SZachary Turner #endif
640666cc0b2SZachary Turner   return val;
641666cc0b2SZachary Turner }
642666cc0b2SZachary Turner 
64305097246SAdrian Prantl // Extract a single address from the data and update the offset pointed to by
64405097246SAdrian Prantl // "offset_ptr". The size of the extracted address comes from the
64505097246SAdrian Prantl // "this->m_addr_size" member variable and should be set correctly prior to
64605097246SAdrian Prantl // extracting any address values.
647666cc0b2SZachary Turner //
648666cc0b2SZachary Turner // RETURNS the address that was extracted, or zero on failure.
GetAddress(offset_t * offset_ptr) const649666cc0b2SZachary Turner uint64_t DataExtractor::GetAddress(offset_t *offset_ptr) const {
650ec1efe71SAyke van Laethem   assert(m_addr_size >= 1 && m_addr_size <= 8);
651666cc0b2SZachary Turner   return GetMaxU64(offset_ptr, m_addr_size);
652666cc0b2SZachary Turner }
653666cc0b2SZachary Turner 
GetAddress_unchecked(offset_t * offset_ptr) const654666cc0b2SZachary Turner uint64_t DataExtractor::GetAddress_unchecked(offset_t *offset_ptr) const {
655ec1efe71SAyke van Laethem   assert(m_addr_size >= 1 && m_addr_size <= 8);
656666cc0b2SZachary Turner   return GetMaxU64_unchecked(offset_ptr, m_addr_size);
657666cc0b2SZachary Turner }
658666cc0b2SZachary Turner 
ExtractBytes(offset_t offset,offset_t length,ByteOrder dst_byte_order,void * dst) const659666cc0b2SZachary Turner size_t DataExtractor::ExtractBytes(offset_t offset, offset_t length,
660666cc0b2SZachary Turner                                    ByteOrder dst_byte_order, void *dst) const {
661666cc0b2SZachary Turner   const uint8_t *src = PeekData(offset, length);
662666cc0b2SZachary Turner   if (src) {
663666cc0b2SZachary Turner     if (dst_byte_order != GetByteOrder()) {
664666cc0b2SZachary Turner       // Validate that only a word- or register-sized dst is byte swapped
665666cc0b2SZachary Turner       assert(length == 1 || length == 2 || length == 4 || length == 8 ||
666666cc0b2SZachary Turner              length == 10 || length == 16 || length == 32);
667666cc0b2SZachary Turner 
668666cc0b2SZachary Turner       for (uint32_t i = 0; i < length; ++i)
66924374aefSJonas Devlieghere         (static_cast<uint8_t *>(dst))[i] = src[length - i - 1];
670666cc0b2SZachary Turner     } else
671666cc0b2SZachary Turner       ::memcpy(dst, src, length);
672666cc0b2SZachary Turner     return length;
673666cc0b2SZachary Turner   }
674666cc0b2SZachary Turner   return 0;
675666cc0b2SZachary Turner }
676666cc0b2SZachary Turner 
677666cc0b2SZachary Turner // Extract data as it exists in target memory
CopyData(offset_t offset,offset_t length,void * dst) const678666cc0b2SZachary Turner lldb::offset_t DataExtractor::CopyData(offset_t offset, offset_t length,
679666cc0b2SZachary Turner                                        void *dst) const {
680666cc0b2SZachary Turner   const uint8_t *src = PeekData(offset, length);
681666cc0b2SZachary Turner   if (src) {
682666cc0b2SZachary Turner     ::memcpy(dst, src, length);
683666cc0b2SZachary Turner     return length;
684666cc0b2SZachary Turner   }
685666cc0b2SZachary Turner   return 0;
686666cc0b2SZachary Turner }
687666cc0b2SZachary Turner 
688666cc0b2SZachary Turner // Extract data and swap if needed when doing the copy
689666cc0b2SZachary Turner lldb::offset_t
CopyByteOrderedData(offset_t src_offset,offset_t src_len,void * dst_void_ptr,offset_t dst_len,ByteOrder dst_byte_order) const690666cc0b2SZachary Turner DataExtractor::CopyByteOrderedData(offset_t src_offset, offset_t src_len,
691666cc0b2SZachary Turner                                    void *dst_void_ptr, offset_t dst_len,
692666cc0b2SZachary Turner                                    ByteOrder dst_byte_order) const {
693666cc0b2SZachary Turner   // Validate the source info
694666cc0b2SZachary Turner   if (!ValidOffsetForDataOfSize(src_offset, src_len))
695666cc0b2SZachary Turner     assert(ValidOffsetForDataOfSize(src_offset, src_len));
696666cc0b2SZachary Turner   assert(src_len > 0);
697666cc0b2SZachary Turner   assert(m_byte_order == eByteOrderBig || m_byte_order == eByteOrderLittle);
698666cc0b2SZachary Turner 
699666cc0b2SZachary Turner   // Validate the destination info
700666cc0b2SZachary Turner   assert(dst_void_ptr != nullptr);
701666cc0b2SZachary Turner   assert(dst_len > 0);
702666cc0b2SZachary Turner   assert(dst_byte_order == eByteOrderBig || dst_byte_order == eByteOrderLittle);
703666cc0b2SZachary Turner 
704666cc0b2SZachary Turner   // Validate that only a word- or register-sized dst is byte swapped
705666cc0b2SZachary Turner   assert(dst_byte_order == m_byte_order || dst_len == 1 || dst_len == 2 ||
706666cc0b2SZachary Turner          dst_len == 4 || dst_len == 8 || dst_len == 10 || dst_len == 16 ||
707666cc0b2SZachary Turner          dst_len == 32);
708666cc0b2SZachary Turner 
709666cc0b2SZachary Turner   // Must have valid byte orders set in this object and for destination
710666cc0b2SZachary Turner   if (!(dst_byte_order == eByteOrderBig ||
711666cc0b2SZachary Turner         dst_byte_order == eByteOrderLittle) ||
712666cc0b2SZachary Turner       !(m_byte_order == eByteOrderBig || m_byte_order == eByteOrderLittle))
713666cc0b2SZachary Turner     return 0;
714666cc0b2SZachary Turner 
71524374aefSJonas Devlieghere   uint8_t *dst = static_cast<uint8_t *>(dst_void_ptr);
71624374aefSJonas Devlieghere   const uint8_t *src = PeekData(src_offset, src_len);
717666cc0b2SZachary Turner   if (src) {
718666cc0b2SZachary Turner     if (dst_len >= src_len) {
71905097246SAdrian Prantl       // We are copying the entire value from src into dst. Calculate how many,
72005097246SAdrian Prantl       // if any, zeroes we need for the most significant bytes if "dst_len" is
72105097246SAdrian Prantl       // greater than "src_len"...
722666cc0b2SZachary Turner       const size_t num_zeroes = dst_len - src_len;
723666cc0b2SZachary Turner       if (dst_byte_order == eByteOrderBig) {
724666cc0b2SZachary Turner         // Big endian, so we lead with zeroes...
725666cc0b2SZachary Turner         if (num_zeroes > 0)
726666cc0b2SZachary Turner           ::memset(dst, 0, num_zeroes);
727666cc0b2SZachary Turner         // Then either copy or swap the rest
728666cc0b2SZachary Turner         if (m_byte_order == eByteOrderBig) {
729666cc0b2SZachary Turner           ::memcpy(dst + num_zeroes, src, src_len);
730666cc0b2SZachary Turner         } else {
731666cc0b2SZachary Turner           for (uint32_t i = 0; i < src_len; ++i)
732666cc0b2SZachary Turner             dst[i + num_zeroes] = src[src_len - 1 - i];
733666cc0b2SZachary Turner         }
734666cc0b2SZachary Turner       } else {
735666cc0b2SZachary Turner         // Little endian destination, so we lead the value bytes
736666cc0b2SZachary Turner         if (m_byte_order == eByteOrderBig) {
737666cc0b2SZachary Turner           for (uint32_t i = 0; i < src_len; ++i)
738666cc0b2SZachary Turner             dst[i] = src[src_len - 1 - i];
739666cc0b2SZachary Turner         } else {
740666cc0b2SZachary Turner           ::memcpy(dst, src, src_len);
741666cc0b2SZachary Turner         }
742666cc0b2SZachary Turner         // And zero the rest...
743666cc0b2SZachary Turner         if (num_zeroes > 0)
744666cc0b2SZachary Turner           ::memset(dst + src_len, 0, num_zeroes);
745666cc0b2SZachary Turner       }
746666cc0b2SZachary Turner       return src_len;
747666cc0b2SZachary Turner     } else {
748666cc0b2SZachary Turner       // We are only copying some of the value from src into dst..
749666cc0b2SZachary Turner 
750666cc0b2SZachary Turner       if (dst_byte_order == eByteOrderBig) {
751666cc0b2SZachary Turner         // Big endian dst
752666cc0b2SZachary Turner         if (m_byte_order == eByteOrderBig) {
753666cc0b2SZachary Turner           // Big endian dst, with big endian src
754666cc0b2SZachary Turner           ::memcpy(dst, src + (src_len - dst_len), dst_len);
755666cc0b2SZachary Turner         } else {
756666cc0b2SZachary Turner           // Big endian dst, with little endian src
757666cc0b2SZachary Turner           for (uint32_t i = 0; i < dst_len; ++i)
758666cc0b2SZachary Turner             dst[i] = src[dst_len - 1 - i];
759666cc0b2SZachary Turner         }
760666cc0b2SZachary Turner       } else {
761666cc0b2SZachary Turner         // Little endian dst
762666cc0b2SZachary Turner         if (m_byte_order == eByteOrderBig) {
763666cc0b2SZachary Turner           // Little endian dst, with big endian src
764666cc0b2SZachary Turner           for (uint32_t i = 0; i < dst_len; ++i)
765666cc0b2SZachary Turner             dst[i] = src[src_len - 1 - i];
766666cc0b2SZachary Turner         } else {
767666cc0b2SZachary Turner           // Little endian dst, with big endian src
768666cc0b2SZachary Turner           ::memcpy(dst, src, dst_len);
769666cc0b2SZachary Turner         }
770666cc0b2SZachary Turner       }
771666cc0b2SZachary Turner       return dst_len;
772666cc0b2SZachary Turner     }
773666cc0b2SZachary Turner   }
774666cc0b2SZachary Turner   return 0;
775666cc0b2SZachary Turner }
776666cc0b2SZachary Turner 
77705097246SAdrian Prantl // Extracts a variable length NULL terminated C string from the data at the
77805097246SAdrian Prantl // offset pointed to by "offset_ptr".  The "offset_ptr" will be updated with
77905097246SAdrian Prantl // the offset of the byte that follows the NULL terminator byte.
780666cc0b2SZachary Turner //
78105097246SAdrian Prantl // If the offset pointed to by "offset_ptr" is out of bounds, or if "length" is
78205097246SAdrian Prantl // non-zero and there aren't enough available bytes, nullptr will be returned
78305097246SAdrian Prantl // and "offset_ptr" will not be updated.
GetCStr(offset_t * offset_ptr) const784666cc0b2SZachary Turner const char *DataExtractor::GetCStr(offset_t *offset_ptr) const {
785067bb1f5SRaphael Isemann   const char *start = reinterpret_cast<const char *>(PeekData(*offset_ptr, 1));
786067bb1f5SRaphael Isemann   // Already at the end of the data.
787067bb1f5SRaphael Isemann   if (!start)
788666cc0b2SZachary Turner     return nullptr;
789067bb1f5SRaphael Isemann 
790067bb1f5SRaphael Isemann   const char *end = reinterpret_cast<const char *>(m_end);
791067bb1f5SRaphael Isemann 
792067bb1f5SRaphael Isemann   // Check all bytes for a null terminator that terminates a C string.
793067bb1f5SRaphael Isemann   const char *terminator_or_end = std::find(start, end, '\0');
794067bb1f5SRaphael Isemann 
795067bb1f5SRaphael Isemann   // We didn't find a null terminator, so return nullptr to indicate that there
796067bb1f5SRaphael Isemann   // is no valid C string at that offset.
797067bb1f5SRaphael Isemann   if (terminator_or_end == end)
798067bb1f5SRaphael Isemann     return nullptr;
799067bb1f5SRaphael Isemann 
800067bb1f5SRaphael Isemann   // Update offset_ptr for the caller to point to the data behind the
801067bb1f5SRaphael Isemann   // terminator (which is 1 byte long).
802067bb1f5SRaphael Isemann   *offset_ptr += (terminator_or_end - start + 1UL);
803067bb1f5SRaphael Isemann   return start;
804666cc0b2SZachary Turner }
805666cc0b2SZachary Turner 
80605097246SAdrian Prantl // Extracts a NULL terminated C string from the fixed length field of length
80705097246SAdrian Prantl // "len" at the offset pointed to by "offset_ptr". The "offset_ptr" will be
80805097246SAdrian Prantl // updated with the offset of the byte that follows the fixed length field.
809666cc0b2SZachary Turner //
81005097246SAdrian Prantl // If the offset pointed to by "offset_ptr" is out of bounds, or if the offset
81105097246SAdrian Prantl // plus the length of the field is out of bounds, or if the field does not
81205097246SAdrian Prantl // contain a NULL terminator byte, nullptr will be returned and "offset_ptr"
81305097246SAdrian Prantl // will not be updated.
GetCStr(offset_t * offset_ptr,offset_t len) const814666cc0b2SZachary Turner const char *DataExtractor::GetCStr(offset_t *offset_ptr, offset_t len) const {
81524374aefSJonas Devlieghere   const char *cstr = reinterpret_cast<const char *>(PeekData(*offset_ptr, len));
816666cc0b2SZachary Turner   if (cstr != nullptr) {
817666cc0b2SZachary Turner     if (memchr(cstr, '\0', len) == nullptr) {
818666cc0b2SZachary Turner       return nullptr;
819666cc0b2SZachary Turner     }
820666cc0b2SZachary Turner     *offset_ptr += len;
821666cc0b2SZachary Turner     return cstr;
822666cc0b2SZachary Turner   }
823666cc0b2SZachary Turner   return nullptr;
824666cc0b2SZachary Turner }
825666cc0b2SZachary Turner 
82605097246SAdrian Prantl // Peeks at a string in the contained data. No verification is done to make
82705097246SAdrian Prantl // sure the entire string lies within the bounds of this object's data, only
82805097246SAdrian Prantl // "offset" is verified to be a valid offset.
829666cc0b2SZachary Turner //
83005097246SAdrian Prantl // Returns a valid C string pointer if "offset" is a valid offset in this
83105097246SAdrian Prantl // object's data, else nullptr is returned.
PeekCStr(offset_t offset) const832666cc0b2SZachary Turner const char *DataExtractor::PeekCStr(offset_t offset) const {
83324374aefSJonas Devlieghere   return reinterpret_cast<const char *>(PeekData(offset, 1));
834666cc0b2SZachary Turner }
835666cc0b2SZachary Turner 
83605097246SAdrian Prantl // Extracts an unsigned LEB128 number from this object's data starting at the
83705097246SAdrian Prantl // offset pointed to by "offset_ptr". The offset pointed to by "offset_ptr"
83805097246SAdrian Prantl // will be updated with the offset of the byte following the last extracted
83905097246SAdrian Prantl // byte.
840666cc0b2SZachary Turner //
841666cc0b2SZachary Turner // Returned the extracted integer value.
GetULEB128(offset_t * offset_ptr) const842666cc0b2SZachary Turner uint64_t DataExtractor::GetULEB128(offset_t *offset_ptr) const {
84324374aefSJonas Devlieghere   const uint8_t *src = PeekData(*offset_ptr, 1);
844666cc0b2SZachary Turner   if (src == nullptr)
845666cc0b2SZachary Turner     return 0;
846666cc0b2SZachary Turner 
847bb9d93f4SRaphael Isemann   unsigned byte_count = 0;
848bb9d93f4SRaphael Isemann   uint64_t result = llvm::decodeULEB128(src, &byte_count, m_end);
849bb9d93f4SRaphael Isemann   *offset_ptr += byte_count;
850666cc0b2SZachary Turner   return result;
851666cc0b2SZachary Turner }
852666cc0b2SZachary Turner 
85305097246SAdrian Prantl // Extracts an signed LEB128 number from this object's data starting at the
85405097246SAdrian Prantl // offset pointed to by "offset_ptr". The offset pointed to by "offset_ptr"
85505097246SAdrian Prantl // will be updated with the offset of the byte following the last extracted
85605097246SAdrian Prantl // byte.
857666cc0b2SZachary Turner //
858666cc0b2SZachary Turner // Returned the extracted integer value.
GetSLEB128(offset_t * offset_ptr) const859666cc0b2SZachary Turner int64_t DataExtractor::GetSLEB128(offset_t *offset_ptr) const {
86024374aefSJonas Devlieghere   const uint8_t *src = PeekData(*offset_ptr, 1);
861666cc0b2SZachary Turner   if (src == nullptr)
862666cc0b2SZachary Turner     return 0;
863666cc0b2SZachary Turner 
864bb9d93f4SRaphael Isemann   unsigned byte_count = 0;
865bb9d93f4SRaphael Isemann   int64_t result = llvm::decodeSLEB128(src, &byte_count, m_end);
866bb9d93f4SRaphael Isemann   *offset_ptr += byte_count;
867666cc0b2SZachary Turner   return result;
868666cc0b2SZachary Turner }
869666cc0b2SZachary Turner 
87005097246SAdrian Prantl // Skips a ULEB128 number (signed or unsigned) from this object's data starting
87105097246SAdrian Prantl // at the offset pointed to by "offset_ptr". The offset pointed to by
87205097246SAdrian Prantl // "offset_ptr" will be updated with the offset of the byte following the last
87305097246SAdrian Prantl // extracted byte.
874666cc0b2SZachary Turner //
875666cc0b2SZachary Turner // Returns the number of bytes consumed during the extraction.
Skip_LEB128(offset_t * offset_ptr) const876666cc0b2SZachary Turner uint32_t DataExtractor::Skip_LEB128(offset_t *offset_ptr) const {
877666cc0b2SZachary Turner   uint32_t bytes_consumed = 0;
87824374aefSJonas Devlieghere   const uint8_t *src = PeekData(*offset_ptr, 1);
879666cc0b2SZachary Turner   if (src == nullptr)
880666cc0b2SZachary Turner     return 0;
881666cc0b2SZachary Turner 
882666cc0b2SZachary Turner   const uint8_t *end = m_end;
883666cc0b2SZachary Turner 
884666cc0b2SZachary Turner   if (src < end) {
885666cc0b2SZachary Turner     const uint8_t *src_pos = src;
886666cc0b2SZachary Turner     while ((src_pos < end) && (*src_pos++ & 0x80))
887666cc0b2SZachary Turner       ++bytes_consumed;
888666cc0b2SZachary Turner     *offset_ptr += src_pos - src;
889666cc0b2SZachary Turner   }
890666cc0b2SZachary Turner   return bytes_consumed;
891666cc0b2SZachary Turner }
892666cc0b2SZachary Turner 
893666cc0b2SZachary Turner // Dumps bytes from this object's data to the stream "s" starting
89405097246SAdrian Prantl // "start_offset" bytes into this data, and ending with the byte before
89505097246SAdrian Prantl // "end_offset". "base_addr" will be added to the offset into the dumped data
89605097246SAdrian Prantl // when showing the offset into the data in the output information.
89705097246SAdrian Prantl // "num_per_line" objects of type "type" will be dumped with the option to
89805097246SAdrian Prantl // override the format for each object with "type_format". "type_format" is a
89905097246SAdrian Prantl // printf style formatting string. If "type_format" is nullptr, then an
90005097246SAdrian Prantl // appropriate format string will be used for the supplied "type". If the
90105097246SAdrian Prantl // stream "s" is nullptr, then the output will be send to Log().
PutToLog(Log * log,offset_t start_offset,offset_t length,uint64_t base_addr,uint32_t num_per_line,DataExtractor::Type type) const902666cc0b2SZachary Turner lldb::offset_t DataExtractor::PutToLog(Log *log, offset_t start_offset,
903666cc0b2SZachary Turner                                        offset_t length, uint64_t base_addr,
904666cc0b2SZachary Turner                                        uint32_t num_per_line,
905b6e2cf32SRaphael Isemann                                        DataExtractor::Type type) const {
906666cc0b2SZachary Turner   if (log == nullptr)
907666cc0b2SZachary Turner     return start_offset;
908666cc0b2SZachary Turner 
909666cc0b2SZachary Turner   offset_t offset;
910666cc0b2SZachary Turner   offset_t end_offset;
911666cc0b2SZachary Turner   uint32_t count;
912666cc0b2SZachary Turner   StreamString sstr;
913666cc0b2SZachary Turner   for (offset = start_offset, end_offset = offset + length, count = 0;
914666cc0b2SZachary Turner        ValidOffset(offset) && offset < end_offset; ++count) {
915666cc0b2SZachary Turner     if ((count % num_per_line) == 0) {
916666cc0b2SZachary Turner       // Print out any previous string
917666cc0b2SZachary Turner       if (sstr.GetSize() > 0) {
918666cc0b2SZachary Turner         log->PutString(sstr.GetString());
919666cc0b2SZachary Turner         sstr.Clear();
920666cc0b2SZachary Turner       }
921666cc0b2SZachary Turner       // Reset string offset and fill the current line string with address:
922666cc0b2SZachary Turner       if (base_addr != LLDB_INVALID_ADDRESS)
923666cc0b2SZachary Turner         sstr.Printf("0x%8.8" PRIx64 ":",
92424374aefSJonas Devlieghere                     static_cast<uint64_t>(base_addr + (offset - start_offset)));
925666cc0b2SZachary Turner     }
926666cc0b2SZachary Turner 
927666cc0b2SZachary Turner     switch (type) {
928666cc0b2SZachary Turner     case TypeUInt8:
929b6e2cf32SRaphael Isemann       sstr.Printf(" %2.2x", GetU8(&offset));
930666cc0b2SZachary Turner       break;
931666cc0b2SZachary Turner     case TypeChar: {
932666cc0b2SZachary Turner       char ch = GetU8(&offset);
933f5eaa2afSRaphael Isemann       sstr.Printf(" %c", llvm::isPrint(ch) ? ch : ' ');
934666cc0b2SZachary Turner     } break;
935666cc0b2SZachary Turner     case TypeUInt16:
936b6e2cf32SRaphael Isemann       sstr.Printf(" %4.4x", GetU16(&offset));
937666cc0b2SZachary Turner       break;
938666cc0b2SZachary Turner     case TypeUInt32:
939b6e2cf32SRaphael Isemann       sstr.Printf(" %8.8x", GetU32(&offset));
940666cc0b2SZachary Turner       break;
941666cc0b2SZachary Turner     case TypeUInt64:
942b6e2cf32SRaphael Isemann       sstr.Printf(" %16.16" PRIx64, GetU64(&offset));
943666cc0b2SZachary Turner       break;
944666cc0b2SZachary Turner     case TypePointer:
945b6e2cf32SRaphael Isemann       sstr.Printf(" 0x%" PRIx64, GetAddress(&offset));
946666cc0b2SZachary Turner       break;
947666cc0b2SZachary Turner     case TypeULEB128:
948b6e2cf32SRaphael Isemann       sstr.Printf(" 0x%" PRIx64, GetULEB128(&offset));
949666cc0b2SZachary Turner       break;
950666cc0b2SZachary Turner     case TypeSLEB128:
951b6e2cf32SRaphael Isemann       sstr.Printf(" %" PRId64, GetSLEB128(&offset));
952666cc0b2SZachary Turner       break;
953666cc0b2SZachary Turner     }
954666cc0b2SZachary Turner   }
955666cc0b2SZachary Turner 
956666cc0b2SZachary Turner   if (!sstr.Empty())
957666cc0b2SZachary Turner     log->PutString(sstr.GetString());
958666cc0b2SZachary Turner 
959666cc0b2SZachary Turner   return offset; // Return the offset at which we ended up
960666cc0b2SZachary Turner }
961666cc0b2SZachary Turner 
Copy(DataExtractor & dest_data) const962666cc0b2SZachary Turner size_t DataExtractor::Copy(DataExtractor &dest_data) const {
963666cc0b2SZachary Turner   if (m_data_sp) {
964666cc0b2SZachary Turner     // we can pass along the SP to the data
965666cc0b2SZachary Turner     dest_data.SetData(m_data_sp);
966666cc0b2SZachary Turner   } else {
967666cc0b2SZachary Turner     const uint8_t *base_ptr = m_start;
968666cc0b2SZachary Turner     size_t data_size = GetByteSize();
969666cc0b2SZachary Turner     dest_data.SetData(DataBufferSP(new DataBufferHeap(base_ptr, data_size)));
970666cc0b2SZachary Turner   }
971666cc0b2SZachary Turner   return GetByteSize();
972666cc0b2SZachary Turner }
973666cc0b2SZachary Turner 
Append(DataExtractor & rhs)974666cc0b2SZachary Turner bool DataExtractor::Append(DataExtractor &rhs) {
975666cc0b2SZachary Turner   if (rhs.GetByteOrder() != GetByteOrder())
976666cc0b2SZachary Turner     return false;
977666cc0b2SZachary Turner 
978666cc0b2SZachary Turner   if (rhs.GetByteSize() == 0)
979666cc0b2SZachary Turner     return true;
980666cc0b2SZachary Turner 
981666cc0b2SZachary Turner   if (GetByteSize() == 0)
982666cc0b2SZachary Turner     return (rhs.Copy(*this) > 0);
983666cc0b2SZachary Turner 
984666cc0b2SZachary Turner   size_t bytes = GetByteSize() + rhs.GetByteSize();
985666cc0b2SZachary Turner 
986666cc0b2SZachary Turner   DataBufferHeap *buffer_heap_ptr = nullptr;
987666cc0b2SZachary Turner   DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0));
988666cc0b2SZachary Turner 
989666cc0b2SZachary Turner   if (!buffer_sp || buffer_heap_ptr == nullptr)
990666cc0b2SZachary Turner     return false;
991666cc0b2SZachary Turner 
992666cc0b2SZachary Turner   uint8_t *bytes_ptr = buffer_heap_ptr->GetBytes();
993666cc0b2SZachary Turner 
994666cc0b2SZachary Turner   memcpy(bytes_ptr, GetDataStart(), GetByteSize());
995666cc0b2SZachary Turner   memcpy(bytes_ptr + GetByteSize(), rhs.GetDataStart(), rhs.GetByteSize());
996666cc0b2SZachary Turner 
997666cc0b2SZachary Turner   SetData(buffer_sp);
998666cc0b2SZachary Turner 
999666cc0b2SZachary Turner   return true;
1000666cc0b2SZachary Turner }
1001666cc0b2SZachary Turner 
Append(void * buf,offset_t length)1002666cc0b2SZachary Turner bool DataExtractor::Append(void *buf, offset_t length) {
1003666cc0b2SZachary Turner   if (buf == nullptr)
1004666cc0b2SZachary Turner     return false;
1005666cc0b2SZachary Turner 
1006666cc0b2SZachary Turner   if (length == 0)
1007666cc0b2SZachary Turner     return true;
1008666cc0b2SZachary Turner 
1009666cc0b2SZachary Turner   size_t bytes = GetByteSize() + length;
1010666cc0b2SZachary Turner 
1011666cc0b2SZachary Turner   DataBufferHeap *buffer_heap_ptr = nullptr;
1012666cc0b2SZachary Turner   DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0));
1013666cc0b2SZachary Turner 
1014666cc0b2SZachary Turner   if (!buffer_sp || buffer_heap_ptr == nullptr)
1015666cc0b2SZachary Turner     return false;
1016666cc0b2SZachary Turner 
1017666cc0b2SZachary Turner   uint8_t *bytes_ptr = buffer_heap_ptr->GetBytes();
1018666cc0b2SZachary Turner 
1019666cc0b2SZachary Turner   if (GetByteSize() > 0)
1020666cc0b2SZachary Turner     memcpy(bytes_ptr, GetDataStart(), GetByteSize());
1021666cc0b2SZachary Turner 
1022666cc0b2SZachary Turner   memcpy(bytes_ptr + GetByteSize(), buf, length);
1023666cc0b2SZachary Turner 
1024666cc0b2SZachary Turner   SetData(buffer_sp);
1025666cc0b2SZachary Turner 
1026666cc0b2SZachary Turner   return true;
1027666cc0b2SZachary Turner }
1028666cc0b2SZachary Turner 
Checksum(llvm::SmallVectorImpl<uint8_t> & dest,uint64_t max_data)1029666cc0b2SZachary Turner void DataExtractor::Checksum(llvm::SmallVectorImpl<uint8_t> &dest,
1030666cc0b2SZachary Turner                              uint64_t max_data) {
1031666cc0b2SZachary Turner   if (max_data == 0)
1032666cc0b2SZachary Turner     max_data = GetByteSize();
1033666cc0b2SZachary Turner   else
1034666cc0b2SZachary Turner     max_data = std::min(max_data, GetByteSize());
1035666cc0b2SZachary Turner 
1036666cc0b2SZachary Turner   llvm::MD5 md5;
1037666cc0b2SZachary Turner 
1038666cc0b2SZachary Turner   const llvm::ArrayRef<uint8_t> data(GetDataStart(), max_data);
1039666cc0b2SZachary Turner   md5.update(data);
1040666cc0b2SZachary Turner 
1041666cc0b2SZachary Turner   llvm::MD5::MD5Result result;
1042666cc0b2SZachary Turner   md5.final(result);
1043666cc0b2SZachary Turner 
104482a0c97bSZachary Turner   dest.clear();
1045*0cf21a7eSArgyrios Kyrtzidis   dest.append(result.begin(), result.end());
1046666cc0b2SZachary Turner }
1047