1*666cc0b2SZachary Turner //===-- DataExtractor.cpp ---------------------------------------*- C++ -*-===//
2*666cc0b2SZachary Turner //
3*666cc0b2SZachary Turner //                     The LLVM Compiler Infrastructure
4*666cc0b2SZachary Turner //
5*666cc0b2SZachary Turner // This file is distributed under the University of Illinois Open Source
6*666cc0b2SZachary Turner // License. See LICENSE.TXT for details.
7*666cc0b2SZachary Turner //
8*666cc0b2SZachary Turner //===----------------------------------------------------------------------===//
9*666cc0b2SZachary Turner 
10*666cc0b2SZachary Turner // C Includes
11*666cc0b2SZachary Turner // C++ Includes
12*666cc0b2SZachary Turner #include <cassert>
13*666cc0b2SZachary Turner #include <cmath>
14*666cc0b2SZachary Turner #include <cstddef>
15*666cc0b2SZachary Turner #include <string>
16*666cc0b2SZachary Turner 
17*666cc0b2SZachary Turner // Project includes
18*666cc0b2SZachary Turner #include "lldb/Utility/DataBuffer.h"
19*666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h"
20*666cc0b2SZachary Turner #include "lldb/Utility/DataExtractor.h"
21*666cc0b2SZachary Turner #include "lldb/Utility/Endian.h"
22*666cc0b2SZachary Turner #include "lldb/Utility/Log.h"
23*666cc0b2SZachary Turner #include "lldb/Utility/Stream.h"
24*666cc0b2SZachary Turner #include "lldb/Utility/StreamString.h"
25*666cc0b2SZachary Turner #include "lldb/Utility/UUID.h"
26*666cc0b2SZachary Turner 
27*666cc0b2SZachary Turner // Other libraries and framework includes
28*666cc0b2SZachary Turner #include "llvm/ADT/ArrayRef.h"
29*666cc0b2SZachary Turner #include "llvm/ADT/SmallVector.h"
30*666cc0b2SZachary Turner #include "llvm/Support/MD5.h"
31*666cc0b2SZachary Turner #include "llvm/Support/MathExtras.h"
32*666cc0b2SZachary Turner 
33*666cc0b2SZachary Turner using namespace lldb;
34*666cc0b2SZachary Turner using namespace lldb_private;
35*666cc0b2SZachary Turner 
36*666cc0b2SZachary Turner static inline uint16_t ReadInt16(const unsigned char *ptr, offset_t offset) {
37*666cc0b2SZachary Turner   uint16_t value;
38*666cc0b2SZachary Turner   memcpy(&value, ptr + offset, 2);
39*666cc0b2SZachary Turner   return value;
40*666cc0b2SZachary Turner }
41*666cc0b2SZachary Turner 
42*666cc0b2SZachary Turner static inline uint32_t ReadInt32(const unsigned char *ptr,
43*666cc0b2SZachary Turner                                  offset_t offset = 0) {
44*666cc0b2SZachary Turner   uint32_t value;
45*666cc0b2SZachary Turner   memcpy(&value, ptr + offset, 4);
46*666cc0b2SZachary Turner   return value;
47*666cc0b2SZachary Turner }
48*666cc0b2SZachary Turner 
49*666cc0b2SZachary Turner static inline uint64_t ReadInt64(const unsigned char *ptr,
50*666cc0b2SZachary Turner                                  offset_t offset = 0) {
51*666cc0b2SZachary Turner   uint64_t value;
52*666cc0b2SZachary Turner   memcpy(&value, ptr + offset, 8);
53*666cc0b2SZachary Turner   return value;
54*666cc0b2SZachary Turner }
55*666cc0b2SZachary Turner 
56*666cc0b2SZachary Turner static inline uint16_t ReadInt16(const void *ptr) {
57*666cc0b2SZachary Turner   uint16_t value;
58*666cc0b2SZachary Turner   memcpy(&value, ptr, 2);
59*666cc0b2SZachary Turner   return value;
60*666cc0b2SZachary Turner }
61*666cc0b2SZachary Turner 
62*666cc0b2SZachary Turner static inline uint16_t ReadSwapInt16(const unsigned char *ptr,
63*666cc0b2SZachary Turner                                      offset_t offset) {
64*666cc0b2SZachary Turner   uint16_t value;
65*666cc0b2SZachary Turner   memcpy(&value, ptr + offset, 2);
66*666cc0b2SZachary Turner   return llvm::ByteSwap_16(value);
67*666cc0b2SZachary Turner }
68*666cc0b2SZachary Turner 
69*666cc0b2SZachary Turner static inline uint32_t ReadSwapInt32(const unsigned char *ptr,
70*666cc0b2SZachary Turner                                      offset_t offset) {
71*666cc0b2SZachary Turner   uint32_t value;
72*666cc0b2SZachary Turner   memcpy(&value, ptr + offset, 4);
73*666cc0b2SZachary Turner   return llvm::ByteSwap_32(value);
74*666cc0b2SZachary Turner }
75*666cc0b2SZachary Turner 
76*666cc0b2SZachary Turner static inline uint64_t ReadSwapInt64(const unsigned char *ptr,
77*666cc0b2SZachary Turner                                      offset_t offset) {
78*666cc0b2SZachary Turner   uint64_t value;
79*666cc0b2SZachary Turner   memcpy(&value, ptr + offset, 8);
80*666cc0b2SZachary Turner   return llvm::ByteSwap_64(value);
81*666cc0b2SZachary Turner }
82*666cc0b2SZachary Turner 
83*666cc0b2SZachary Turner static inline uint16_t ReadSwapInt16(const void *ptr) {
84*666cc0b2SZachary Turner   uint16_t value;
85*666cc0b2SZachary Turner   memcpy(&value, ptr, 2);
86*666cc0b2SZachary Turner   return llvm::ByteSwap_16(value);
87*666cc0b2SZachary Turner }
88*666cc0b2SZachary Turner 
89*666cc0b2SZachary Turner static inline uint32_t ReadSwapInt32(const void *ptr) {
90*666cc0b2SZachary Turner   uint32_t value;
91*666cc0b2SZachary Turner   memcpy(&value, ptr, 4);
92*666cc0b2SZachary Turner   return llvm::ByteSwap_32(value);
93*666cc0b2SZachary Turner }
94*666cc0b2SZachary Turner 
95*666cc0b2SZachary Turner static inline uint64_t ReadSwapInt64(const void *ptr) {
96*666cc0b2SZachary Turner   uint64_t value;
97*666cc0b2SZachary Turner   memcpy(&value, ptr, 8);
98*666cc0b2SZachary Turner   return llvm::ByteSwap_64(value);
99*666cc0b2SZachary Turner }
100*666cc0b2SZachary Turner 
101*666cc0b2SZachary Turner DataExtractor::DataExtractor()
102*666cc0b2SZachary Turner     : m_start(nullptr), m_end(nullptr),
103*666cc0b2SZachary Turner       m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)),
104*666cc0b2SZachary Turner       m_data_sp(), m_target_byte_size(1) {}
105*666cc0b2SZachary Turner 
106*666cc0b2SZachary Turner //----------------------------------------------------------------------
107*666cc0b2SZachary Turner // This constructor allows us to use data that is owned by someone else.
108*666cc0b2SZachary Turner // The data must stay around as long as this object is valid.
109*666cc0b2SZachary Turner //----------------------------------------------------------------------
110*666cc0b2SZachary Turner DataExtractor::DataExtractor(const void *data, offset_t length,
111*666cc0b2SZachary Turner                              ByteOrder endian, uint32_t addr_size,
112*666cc0b2SZachary Turner                              uint32_t target_byte_size /*=1*/)
113*666cc0b2SZachary Turner     : m_start(const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(data))),
114*666cc0b2SZachary Turner       m_end(const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(data)) +
115*666cc0b2SZachary Turner             length),
116*666cc0b2SZachary Turner       m_byte_order(endian), m_addr_size(addr_size), m_data_sp(),
117*666cc0b2SZachary Turner       m_target_byte_size(target_byte_size) {
118*666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG
119*666cc0b2SZachary Turner   assert(addr_size == 4 || addr_size == 8);
120*666cc0b2SZachary Turner #endif
121*666cc0b2SZachary Turner }
122*666cc0b2SZachary Turner 
123*666cc0b2SZachary Turner //----------------------------------------------------------------------
124*666cc0b2SZachary Turner // Make a shared pointer reference to the shared data in "data_sp" and
125*666cc0b2SZachary Turner // set the endian swapping setting to "swap", and the address size to
126*666cc0b2SZachary Turner // "addr_size". The shared data reference will ensure the data lives
127*666cc0b2SZachary Turner // as long as any DataExtractor objects exist that have a reference to
128*666cc0b2SZachary Turner // this data.
129*666cc0b2SZachary Turner //----------------------------------------------------------------------
130*666cc0b2SZachary Turner DataExtractor::DataExtractor(const DataBufferSP &data_sp, ByteOrder endian,
131*666cc0b2SZachary Turner                              uint32_t addr_size,
132*666cc0b2SZachary Turner                              uint32_t target_byte_size /*=1*/)
133*666cc0b2SZachary Turner     : m_start(nullptr), m_end(nullptr), m_byte_order(endian),
134*666cc0b2SZachary Turner       m_addr_size(addr_size), m_data_sp(),
135*666cc0b2SZachary Turner       m_target_byte_size(target_byte_size) {
136*666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG
137*666cc0b2SZachary Turner   assert(addr_size == 4 || addr_size == 8);
138*666cc0b2SZachary Turner #endif
139*666cc0b2SZachary Turner   SetData(data_sp);
140*666cc0b2SZachary Turner }
141*666cc0b2SZachary Turner 
142*666cc0b2SZachary Turner //----------------------------------------------------------------------
143*666cc0b2SZachary Turner // Initialize this object with a subset of the data bytes in "data".
144*666cc0b2SZachary Turner // If "data" contains shared data, then a reference to this shared
145*666cc0b2SZachary Turner // data will added and the shared data will stay around as long
146*666cc0b2SZachary Turner // as any object contains a reference to that data. The endian
147*666cc0b2SZachary Turner // swap and address size settings are copied from "data".
148*666cc0b2SZachary Turner //----------------------------------------------------------------------
149*666cc0b2SZachary Turner DataExtractor::DataExtractor(const DataExtractor &data, offset_t offset,
150*666cc0b2SZachary Turner                              offset_t length, uint32_t target_byte_size /*=1*/)
151*666cc0b2SZachary Turner     : m_start(nullptr), m_end(nullptr), m_byte_order(data.m_byte_order),
152*666cc0b2SZachary Turner       m_addr_size(data.m_addr_size), m_data_sp(),
153*666cc0b2SZachary Turner       m_target_byte_size(target_byte_size) {
154*666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG
155*666cc0b2SZachary Turner   assert(m_addr_size == 4 || m_addr_size == 8);
156*666cc0b2SZachary Turner #endif
157*666cc0b2SZachary Turner   if (data.ValidOffset(offset)) {
158*666cc0b2SZachary Turner     offset_t bytes_available = data.GetByteSize() - offset;
159*666cc0b2SZachary Turner     if (length > bytes_available)
160*666cc0b2SZachary Turner       length = bytes_available;
161*666cc0b2SZachary Turner     SetData(data, offset, length);
162*666cc0b2SZachary Turner   }
163*666cc0b2SZachary Turner }
164*666cc0b2SZachary Turner 
165*666cc0b2SZachary Turner DataExtractor::DataExtractor(const DataExtractor &rhs)
166*666cc0b2SZachary Turner     : m_start(rhs.m_start), m_end(rhs.m_end), m_byte_order(rhs.m_byte_order),
167*666cc0b2SZachary Turner       m_addr_size(rhs.m_addr_size), m_data_sp(rhs.m_data_sp),
168*666cc0b2SZachary Turner       m_target_byte_size(rhs.m_target_byte_size) {
169*666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG
170*666cc0b2SZachary Turner   assert(m_addr_size == 4 || m_addr_size == 8);
171*666cc0b2SZachary Turner #endif
172*666cc0b2SZachary Turner }
173*666cc0b2SZachary Turner 
174*666cc0b2SZachary Turner //----------------------------------------------------------------------
175*666cc0b2SZachary Turner // Assignment operator
176*666cc0b2SZachary Turner //----------------------------------------------------------------------
177*666cc0b2SZachary Turner const DataExtractor &DataExtractor::operator=(const DataExtractor &rhs) {
178*666cc0b2SZachary Turner   if (this != &rhs) {
179*666cc0b2SZachary Turner     m_start = rhs.m_start;
180*666cc0b2SZachary Turner     m_end = rhs.m_end;
181*666cc0b2SZachary Turner     m_byte_order = rhs.m_byte_order;
182*666cc0b2SZachary Turner     m_addr_size = rhs.m_addr_size;
183*666cc0b2SZachary Turner     m_data_sp = rhs.m_data_sp;
184*666cc0b2SZachary Turner   }
185*666cc0b2SZachary Turner   return *this;
186*666cc0b2SZachary Turner }
187*666cc0b2SZachary Turner 
188*666cc0b2SZachary Turner DataExtractor::~DataExtractor() = default;
189*666cc0b2SZachary Turner 
190*666cc0b2SZachary Turner //------------------------------------------------------------------
191*666cc0b2SZachary Turner // Clears the object contents back to a default invalid state, and
192*666cc0b2SZachary Turner // release any references to shared data that this object may
193*666cc0b2SZachary Turner // contain.
194*666cc0b2SZachary Turner //------------------------------------------------------------------
195*666cc0b2SZachary Turner void DataExtractor::Clear() {
196*666cc0b2SZachary Turner   m_start = nullptr;
197*666cc0b2SZachary Turner   m_end = nullptr;
198*666cc0b2SZachary Turner   m_byte_order = endian::InlHostByteOrder();
199*666cc0b2SZachary Turner   m_addr_size = sizeof(void *);
200*666cc0b2SZachary Turner   m_data_sp.reset();
201*666cc0b2SZachary Turner }
202*666cc0b2SZachary Turner 
203*666cc0b2SZachary Turner //------------------------------------------------------------------
204*666cc0b2SZachary Turner // If this object contains shared data, this function returns the
205*666cc0b2SZachary Turner // offset into that shared data. Else zero is returned.
206*666cc0b2SZachary Turner //------------------------------------------------------------------
207*666cc0b2SZachary Turner size_t DataExtractor::GetSharedDataOffset() const {
208*666cc0b2SZachary Turner   if (m_start != nullptr) {
209*666cc0b2SZachary Turner     const DataBuffer *data = m_data_sp.get();
210*666cc0b2SZachary Turner     if (data != nullptr) {
211*666cc0b2SZachary Turner       const uint8_t *data_bytes = data->GetBytes();
212*666cc0b2SZachary Turner       if (data_bytes != nullptr) {
213*666cc0b2SZachary Turner         assert(m_start >= data_bytes);
214*666cc0b2SZachary Turner         return m_start - data_bytes;
215*666cc0b2SZachary Turner       }
216*666cc0b2SZachary Turner     }
217*666cc0b2SZachary Turner   }
218*666cc0b2SZachary Turner   return 0;
219*666cc0b2SZachary Turner }
220*666cc0b2SZachary Turner 
221*666cc0b2SZachary Turner //----------------------------------------------------------------------
222*666cc0b2SZachary Turner // Set the data with which this object will extract from to data
223*666cc0b2SZachary Turner // starting at BYTES and set the length of the data to LENGTH bytes
224*666cc0b2SZachary Turner // long. The data is externally owned must be around at least as
225*666cc0b2SZachary Turner // long as this object points to the data. No copy of the data is
226*666cc0b2SZachary Turner // made, this object just refers to this data and can extract from
227*666cc0b2SZachary Turner // it. If this object refers to any shared data upon entry, the
228*666cc0b2SZachary Turner // reference to that data will be released. Is SWAP is set to true,
229*666cc0b2SZachary Turner // any data extracted will be endian swapped.
230*666cc0b2SZachary Turner //----------------------------------------------------------------------
231*666cc0b2SZachary Turner lldb::offset_t DataExtractor::SetData(const void *bytes, offset_t length,
232*666cc0b2SZachary Turner                                       ByteOrder endian) {
233*666cc0b2SZachary Turner   m_byte_order = endian;
234*666cc0b2SZachary Turner   m_data_sp.reset();
235*666cc0b2SZachary Turner   if (bytes == nullptr || length == 0) {
236*666cc0b2SZachary Turner     m_start = nullptr;
237*666cc0b2SZachary Turner     m_end = nullptr;
238*666cc0b2SZachary Turner   } else {
239*666cc0b2SZachary Turner     m_start = const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(bytes));
240*666cc0b2SZachary Turner     m_end = m_start + length;
241*666cc0b2SZachary Turner   }
242*666cc0b2SZachary Turner   return GetByteSize();
243*666cc0b2SZachary Turner }
244*666cc0b2SZachary Turner 
245*666cc0b2SZachary Turner //----------------------------------------------------------------------
246*666cc0b2SZachary Turner // Assign the data for this object to be a subrange in "data"
247*666cc0b2SZachary Turner // starting "data_offset" bytes into "data" and ending "data_length"
248*666cc0b2SZachary Turner // bytes later. If "data_offset" is not a valid offset into "data",
249*666cc0b2SZachary Turner // then this object will contain no bytes. If "data_offset" is
250*666cc0b2SZachary Turner // within "data" yet "data_length" is too large, the length will be
251*666cc0b2SZachary Turner // capped at the number of bytes remaining in "data". If "data"
252*666cc0b2SZachary Turner // contains a shared pointer to other data, then a ref counted
253*666cc0b2SZachary Turner // pointer to that data will be made in this object. If "data"
254*666cc0b2SZachary Turner // doesn't contain a shared pointer to data, then the bytes referred
255*666cc0b2SZachary Turner // to in "data" will need to exist at least as long as this object
256*666cc0b2SZachary Turner // refers to those bytes. The address size and endian swap settings
257*666cc0b2SZachary Turner // are copied from the current values in "data".
258*666cc0b2SZachary Turner //----------------------------------------------------------------------
259*666cc0b2SZachary Turner lldb::offset_t DataExtractor::SetData(const DataExtractor &data,
260*666cc0b2SZachary Turner                                       offset_t data_offset,
261*666cc0b2SZachary Turner                                       offset_t data_length) {
262*666cc0b2SZachary Turner   m_addr_size = data.m_addr_size;
263*666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG
264*666cc0b2SZachary Turner   assert(m_addr_size == 4 || m_addr_size == 8);
265*666cc0b2SZachary Turner #endif
266*666cc0b2SZachary Turner   // If "data" contains shared pointer to data, then we can use that
267*666cc0b2SZachary Turner   if (data.m_data_sp) {
268*666cc0b2SZachary Turner     m_byte_order = data.m_byte_order;
269*666cc0b2SZachary Turner     return SetData(data.m_data_sp, data.GetSharedDataOffset() + data_offset,
270*666cc0b2SZachary Turner                    data_length);
271*666cc0b2SZachary Turner   }
272*666cc0b2SZachary Turner 
273*666cc0b2SZachary Turner   // We have a DataExtractor object that just has a pointer to bytes
274*666cc0b2SZachary Turner   if (data.ValidOffset(data_offset)) {
275*666cc0b2SZachary Turner     if (data_length > data.GetByteSize() - data_offset)
276*666cc0b2SZachary Turner       data_length = data.GetByteSize() - data_offset;
277*666cc0b2SZachary Turner     return SetData(data.GetDataStart() + data_offset, data_length,
278*666cc0b2SZachary Turner                    data.GetByteOrder());
279*666cc0b2SZachary Turner   }
280*666cc0b2SZachary Turner   return 0;
281*666cc0b2SZachary Turner }
282*666cc0b2SZachary Turner 
283*666cc0b2SZachary Turner //----------------------------------------------------------------------
284*666cc0b2SZachary Turner // Assign the data for this object to be a subrange of the shared
285*666cc0b2SZachary Turner // data in "data_sp" starting "data_offset" bytes into "data_sp"
286*666cc0b2SZachary Turner // and ending "data_length" bytes later. If "data_offset" is not
287*666cc0b2SZachary Turner // a valid offset into "data_sp", then this object will contain no
288*666cc0b2SZachary Turner // bytes. If "data_offset" is within "data_sp" yet "data_length" is
289*666cc0b2SZachary Turner // too large, the length will be capped at the number of bytes
290*666cc0b2SZachary Turner // remaining in "data_sp". A ref counted pointer to the data in
291*666cc0b2SZachary Turner // "data_sp" will be made in this object IF the number of bytes this
292*666cc0b2SZachary Turner // object refers to in greater than zero (if at least one byte was
293*666cc0b2SZachary Turner // available starting at "data_offset") to ensure the data stays
294*666cc0b2SZachary Turner // around as long as it is needed. The address size and endian swap
295*666cc0b2SZachary Turner // settings will remain unchanged from their current settings.
296*666cc0b2SZachary Turner //----------------------------------------------------------------------
297*666cc0b2SZachary Turner lldb::offset_t DataExtractor::SetData(const DataBufferSP &data_sp,
298*666cc0b2SZachary Turner                                       offset_t data_offset,
299*666cc0b2SZachary Turner                                       offset_t data_length) {
300*666cc0b2SZachary Turner   m_start = m_end = nullptr;
301*666cc0b2SZachary Turner 
302*666cc0b2SZachary Turner   if (data_length > 0) {
303*666cc0b2SZachary Turner     m_data_sp = data_sp;
304*666cc0b2SZachary Turner     if (data_sp) {
305*666cc0b2SZachary Turner       const size_t data_size = data_sp->GetByteSize();
306*666cc0b2SZachary Turner       if (data_offset < data_size) {
307*666cc0b2SZachary Turner         m_start = data_sp->GetBytes() + data_offset;
308*666cc0b2SZachary Turner         const size_t bytes_left = data_size - data_offset;
309*666cc0b2SZachary Turner         // Cap the length of we asked for too many
310*666cc0b2SZachary Turner         if (data_length <= bytes_left)
311*666cc0b2SZachary Turner           m_end = m_start + data_length; // We got all the bytes we wanted
312*666cc0b2SZachary Turner         else
313*666cc0b2SZachary Turner           m_end = m_start + bytes_left; // Not all the bytes requested were
314*666cc0b2SZachary Turner                                         // available in the shared data
315*666cc0b2SZachary Turner       }
316*666cc0b2SZachary Turner     }
317*666cc0b2SZachary Turner   }
318*666cc0b2SZachary Turner 
319*666cc0b2SZachary Turner   size_t new_size = GetByteSize();
320*666cc0b2SZachary Turner 
321*666cc0b2SZachary Turner   // Don't hold a shared pointer to the data buffer if we don't share
322*666cc0b2SZachary Turner   // any valid bytes in the shared buffer.
323*666cc0b2SZachary Turner   if (new_size == 0)
324*666cc0b2SZachary Turner     m_data_sp.reset();
325*666cc0b2SZachary Turner 
326*666cc0b2SZachary Turner   return new_size;
327*666cc0b2SZachary Turner }
328*666cc0b2SZachary Turner 
329*666cc0b2SZachary Turner //----------------------------------------------------------------------
330*666cc0b2SZachary Turner // Extract a single unsigned char from the binary data and update
331*666cc0b2SZachary Turner // the offset pointed to by "offset_ptr".
332*666cc0b2SZachary Turner //
333*666cc0b2SZachary Turner // RETURNS the byte that was extracted, or zero on failure.
334*666cc0b2SZachary Turner //----------------------------------------------------------------------
335*666cc0b2SZachary Turner uint8_t DataExtractor::GetU8(offset_t *offset_ptr) const {
336*666cc0b2SZachary Turner   const uint8_t *data = (const uint8_t *)GetData(offset_ptr, 1);
337*666cc0b2SZachary Turner   if (data)
338*666cc0b2SZachary Turner     return *data;
339*666cc0b2SZachary Turner   return 0;
340*666cc0b2SZachary Turner }
341*666cc0b2SZachary Turner 
342*666cc0b2SZachary Turner //----------------------------------------------------------------------
343*666cc0b2SZachary Turner // Extract "count" unsigned chars from the binary data and update the
344*666cc0b2SZachary Turner // offset pointed to by "offset_ptr". The extracted data is copied into
345*666cc0b2SZachary Turner // "dst".
346*666cc0b2SZachary Turner //
347*666cc0b2SZachary Turner // RETURNS the non-nullptr buffer pointer upon successful extraction of
348*666cc0b2SZachary Turner // all the requested bytes, or nullptr when the data is not available in
349*666cc0b2SZachary Turner // the buffer due to being out of bounds, or insufficient data.
350*666cc0b2SZachary Turner //----------------------------------------------------------------------
351*666cc0b2SZachary Turner void *DataExtractor::GetU8(offset_t *offset_ptr, void *dst,
352*666cc0b2SZachary Turner                            uint32_t count) const {
353*666cc0b2SZachary Turner   const uint8_t *data = (const uint8_t *)GetData(offset_ptr, count);
354*666cc0b2SZachary Turner   if (data) {
355*666cc0b2SZachary Turner     // Copy the data into the buffer
356*666cc0b2SZachary Turner     memcpy(dst, data, count);
357*666cc0b2SZachary Turner     // Return a non-nullptr pointer to the converted data as an indicator of
358*666cc0b2SZachary Turner     // success
359*666cc0b2SZachary Turner     return dst;
360*666cc0b2SZachary Turner   }
361*666cc0b2SZachary Turner   return nullptr;
362*666cc0b2SZachary Turner }
363*666cc0b2SZachary Turner 
364*666cc0b2SZachary Turner //----------------------------------------------------------------------
365*666cc0b2SZachary Turner // Extract a single uint16_t from the data and update the offset
366*666cc0b2SZachary Turner // pointed to by "offset_ptr".
367*666cc0b2SZachary Turner //
368*666cc0b2SZachary Turner // RETURNS the uint16_t that was extracted, or zero on failure.
369*666cc0b2SZachary Turner //----------------------------------------------------------------------
370*666cc0b2SZachary Turner uint16_t DataExtractor::GetU16(offset_t *offset_ptr) const {
371*666cc0b2SZachary Turner   uint16_t val = 0;
372*666cc0b2SZachary Turner   const uint8_t *data = (const uint8_t *)GetData(offset_ptr, sizeof(val));
373*666cc0b2SZachary Turner   if (data) {
374*666cc0b2SZachary Turner     if (m_byte_order != endian::InlHostByteOrder())
375*666cc0b2SZachary Turner       val = ReadSwapInt16(data);
376*666cc0b2SZachary Turner     else
377*666cc0b2SZachary Turner       val = ReadInt16(data);
378*666cc0b2SZachary Turner   }
379*666cc0b2SZachary Turner   return val;
380*666cc0b2SZachary Turner }
381*666cc0b2SZachary Turner 
382*666cc0b2SZachary Turner uint16_t DataExtractor::GetU16_unchecked(offset_t *offset_ptr) const {
383*666cc0b2SZachary Turner   uint16_t val;
384*666cc0b2SZachary Turner   if (m_byte_order == endian::InlHostByteOrder())
385*666cc0b2SZachary Turner     val = ReadInt16(m_start, *offset_ptr);
386*666cc0b2SZachary Turner   else
387*666cc0b2SZachary Turner     val = ReadSwapInt16(m_start, *offset_ptr);
388*666cc0b2SZachary Turner   *offset_ptr += sizeof(val);
389*666cc0b2SZachary Turner   return val;
390*666cc0b2SZachary Turner }
391*666cc0b2SZachary Turner 
392*666cc0b2SZachary Turner uint32_t DataExtractor::GetU32_unchecked(offset_t *offset_ptr) const {
393*666cc0b2SZachary Turner   uint32_t val;
394*666cc0b2SZachary Turner   if (m_byte_order == endian::InlHostByteOrder())
395*666cc0b2SZachary Turner     val = ReadInt32(m_start, *offset_ptr);
396*666cc0b2SZachary Turner   else
397*666cc0b2SZachary Turner     val = ReadSwapInt32(m_start, *offset_ptr);
398*666cc0b2SZachary Turner   *offset_ptr += sizeof(val);
399*666cc0b2SZachary Turner   return val;
400*666cc0b2SZachary Turner }
401*666cc0b2SZachary Turner 
402*666cc0b2SZachary Turner uint64_t DataExtractor::GetU64_unchecked(offset_t *offset_ptr) const {
403*666cc0b2SZachary Turner   uint64_t val;
404*666cc0b2SZachary Turner   if (m_byte_order == endian::InlHostByteOrder())
405*666cc0b2SZachary Turner     val = ReadInt64(m_start, *offset_ptr);
406*666cc0b2SZachary Turner   else
407*666cc0b2SZachary Turner     val = ReadSwapInt64(m_start, *offset_ptr);
408*666cc0b2SZachary Turner   *offset_ptr += sizeof(val);
409*666cc0b2SZachary Turner   return val;
410*666cc0b2SZachary Turner }
411*666cc0b2SZachary Turner 
412*666cc0b2SZachary Turner //----------------------------------------------------------------------
413*666cc0b2SZachary Turner // Extract "count" uint16_t values from the binary data and update
414*666cc0b2SZachary Turner // the offset pointed to by "offset_ptr". The extracted data is
415*666cc0b2SZachary Turner // copied into "dst".
416*666cc0b2SZachary Turner //
417*666cc0b2SZachary Turner // RETURNS the non-nullptr buffer pointer upon successful extraction of
418*666cc0b2SZachary Turner // all the requested bytes, or nullptr when the data is not available
419*666cc0b2SZachary Turner // in the buffer due to being out of bounds, or insufficient data.
420*666cc0b2SZachary Turner //----------------------------------------------------------------------
421*666cc0b2SZachary Turner void *DataExtractor::GetU16(offset_t *offset_ptr, void *void_dst,
422*666cc0b2SZachary Turner                             uint32_t count) const {
423*666cc0b2SZachary Turner   const size_t src_size = sizeof(uint16_t) * count;
424*666cc0b2SZachary Turner   const uint16_t *src = (const uint16_t *)GetData(offset_ptr, src_size);
425*666cc0b2SZachary Turner   if (src) {
426*666cc0b2SZachary Turner     if (m_byte_order != endian::InlHostByteOrder()) {
427*666cc0b2SZachary Turner       uint16_t *dst_pos = (uint16_t *)void_dst;
428*666cc0b2SZachary Turner       uint16_t *dst_end = dst_pos + count;
429*666cc0b2SZachary Turner       const uint16_t *src_pos = src;
430*666cc0b2SZachary Turner       while (dst_pos < dst_end) {
431*666cc0b2SZachary Turner         *dst_pos = ReadSwapInt16(src_pos);
432*666cc0b2SZachary Turner         ++dst_pos;
433*666cc0b2SZachary Turner         ++src_pos;
434*666cc0b2SZachary Turner       }
435*666cc0b2SZachary Turner     } else {
436*666cc0b2SZachary Turner       memcpy(void_dst, src, src_size);
437*666cc0b2SZachary Turner     }
438*666cc0b2SZachary Turner     // Return a non-nullptr pointer to the converted data as an indicator of
439*666cc0b2SZachary Turner     // success
440*666cc0b2SZachary Turner     return void_dst;
441*666cc0b2SZachary Turner   }
442*666cc0b2SZachary Turner   return nullptr;
443*666cc0b2SZachary Turner }
444*666cc0b2SZachary Turner 
445*666cc0b2SZachary Turner //----------------------------------------------------------------------
446*666cc0b2SZachary Turner // Extract a single uint32_t from the data and update the offset
447*666cc0b2SZachary Turner // pointed to by "offset_ptr".
448*666cc0b2SZachary Turner //
449*666cc0b2SZachary Turner // RETURNS the uint32_t that was extracted, or zero on failure.
450*666cc0b2SZachary Turner //----------------------------------------------------------------------
451*666cc0b2SZachary Turner uint32_t DataExtractor::GetU32(offset_t *offset_ptr) const {
452*666cc0b2SZachary Turner   uint32_t val = 0;
453*666cc0b2SZachary Turner   const uint8_t *data = (const uint8_t *)GetData(offset_ptr, sizeof(val));
454*666cc0b2SZachary Turner   if (data) {
455*666cc0b2SZachary Turner     if (m_byte_order != endian::InlHostByteOrder()) {
456*666cc0b2SZachary Turner       val = ReadSwapInt32(data);
457*666cc0b2SZachary Turner     } else {
458*666cc0b2SZachary Turner       memcpy(&val, data, 4);
459*666cc0b2SZachary Turner     }
460*666cc0b2SZachary Turner   }
461*666cc0b2SZachary Turner   return val;
462*666cc0b2SZachary Turner }
463*666cc0b2SZachary Turner 
464*666cc0b2SZachary Turner //----------------------------------------------------------------------
465*666cc0b2SZachary Turner // Extract "count" uint32_t values from the binary data and update
466*666cc0b2SZachary Turner // the offset pointed to by "offset_ptr". The extracted data is
467*666cc0b2SZachary Turner // copied into "dst".
468*666cc0b2SZachary Turner //
469*666cc0b2SZachary Turner // RETURNS the non-nullptr buffer pointer upon successful extraction of
470*666cc0b2SZachary Turner // all the requested bytes, or nullptr when the data is not available
471*666cc0b2SZachary Turner // in the buffer due to being out of bounds, or insufficient data.
472*666cc0b2SZachary Turner //----------------------------------------------------------------------
473*666cc0b2SZachary Turner void *DataExtractor::GetU32(offset_t *offset_ptr, void *void_dst,
474*666cc0b2SZachary Turner                             uint32_t count) const {
475*666cc0b2SZachary Turner   const size_t src_size = sizeof(uint32_t) * count;
476*666cc0b2SZachary Turner   const uint32_t *src = (const uint32_t *)GetData(offset_ptr, src_size);
477*666cc0b2SZachary Turner   if (src) {
478*666cc0b2SZachary Turner     if (m_byte_order != endian::InlHostByteOrder()) {
479*666cc0b2SZachary Turner       uint32_t *dst_pos = (uint32_t *)void_dst;
480*666cc0b2SZachary Turner       uint32_t *dst_end = dst_pos + count;
481*666cc0b2SZachary Turner       const uint32_t *src_pos = src;
482*666cc0b2SZachary Turner       while (dst_pos < dst_end) {
483*666cc0b2SZachary Turner         *dst_pos = ReadSwapInt32(src_pos);
484*666cc0b2SZachary Turner         ++dst_pos;
485*666cc0b2SZachary Turner         ++src_pos;
486*666cc0b2SZachary Turner       }
487*666cc0b2SZachary Turner     } else {
488*666cc0b2SZachary Turner       memcpy(void_dst, src, src_size);
489*666cc0b2SZachary Turner     }
490*666cc0b2SZachary Turner     // Return a non-nullptr pointer to the converted data as an indicator of
491*666cc0b2SZachary Turner     // success
492*666cc0b2SZachary Turner     return void_dst;
493*666cc0b2SZachary Turner   }
494*666cc0b2SZachary Turner   return nullptr;
495*666cc0b2SZachary Turner }
496*666cc0b2SZachary Turner 
497*666cc0b2SZachary Turner //----------------------------------------------------------------------
498*666cc0b2SZachary Turner // Extract a single uint64_t from the data and update the offset
499*666cc0b2SZachary Turner // pointed to by "offset_ptr".
500*666cc0b2SZachary Turner //
501*666cc0b2SZachary Turner // RETURNS the uint64_t that was extracted, or zero on failure.
502*666cc0b2SZachary Turner //----------------------------------------------------------------------
503*666cc0b2SZachary Turner uint64_t DataExtractor::GetU64(offset_t *offset_ptr) const {
504*666cc0b2SZachary Turner   uint64_t val = 0;
505*666cc0b2SZachary Turner   const uint8_t *data = (const uint8_t *)GetData(offset_ptr, sizeof(val));
506*666cc0b2SZachary Turner   if (data) {
507*666cc0b2SZachary Turner     if (m_byte_order != endian::InlHostByteOrder()) {
508*666cc0b2SZachary Turner       val = ReadSwapInt64(data);
509*666cc0b2SZachary Turner     } else {
510*666cc0b2SZachary Turner       memcpy(&val, data, 8);
511*666cc0b2SZachary Turner     }
512*666cc0b2SZachary Turner   }
513*666cc0b2SZachary Turner   return val;
514*666cc0b2SZachary Turner }
515*666cc0b2SZachary Turner 
516*666cc0b2SZachary Turner //----------------------------------------------------------------------
517*666cc0b2SZachary Turner // GetU64
518*666cc0b2SZachary Turner //
519*666cc0b2SZachary Turner // Get multiple consecutive 64 bit values. Return true if the entire
520*666cc0b2SZachary Turner // read succeeds and increment the offset pointed to by offset_ptr, else
521*666cc0b2SZachary Turner // return false and leave the offset pointed to by offset_ptr unchanged.
522*666cc0b2SZachary Turner //----------------------------------------------------------------------
523*666cc0b2SZachary Turner void *DataExtractor::GetU64(offset_t *offset_ptr, void *void_dst,
524*666cc0b2SZachary Turner                             uint32_t count) const {
525*666cc0b2SZachary Turner   const size_t src_size = sizeof(uint64_t) * count;
526*666cc0b2SZachary Turner   const uint64_t *src = (const uint64_t *)GetData(offset_ptr, src_size);
527*666cc0b2SZachary Turner   if (src) {
528*666cc0b2SZachary Turner     if (m_byte_order != endian::InlHostByteOrder()) {
529*666cc0b2SZachary Turner       uint64_t *dst_pos = (uint64_t *)void_dst;
530*666cc0b2SZachary Turner       uint64_t *dst_end = dst_pos + count;
531*666cc0b2SZachary Turner       const uint64_t *src_pos = src;
532*666cc0b2SZachary Turner       while (dst_pos < dst_end) {
533*666cc0b2SZachary Turner         *dst_pos = ReadSwapInt64(src_pos);
534*666cc0b2SZachary Turner         ++dst_pos;
535*666cc0b2SZachary Turner         ++src_pos;
536*666cc0b2SZachary Turner       }
537*666cc0b2SZachary Turner     } else {
538*666cc0b2SZachary Turner       memcpy(void_dst, src, src_size);
539*666cc0b2SZachary Turner     }
540*666cc0b2SZachary Turner     // Return a non-nullptr pointer to the converted data as an indicator of
541*666cc0b2SZachary Turner     // success
542*666cc0b2SZachary Turner     return void_dst;
543*666cc0b2SZachary Turner   }
544*666cc0b2SZachary Turner   return nullptr;
545*666cc0b2SZachary Turner }
546*666cc0b2SZachary Turner 
547*666cc0b2SZachary Turner //----------------------------------------------------------------------
548*666cc0b2SZachary Turner // Extract a single integer value from the data and update the offset
549*666cc0b2SZachary Turner // pointed to by "offset_ptr". The size of the extracted integer
550*666cc0b2SZachary Turner // is specified by the "byte_size" argument. "byte_size" should have
551*666cc0b2SZachary Turner // a value between 1 and 4 since the return value is only 32 bits
552*666cc0b2SZachary Turner // wide. Any "byte_size" values less than 1 or greater than 4 will
553*666cc0b2SZachary Turner // result in nothing being extracted, and zero being returned.
554*666cc0b2SZachary Turner //
555*666cc0b2SZachary Turner // RETURNS the integer value that was extracted, or zero on failure.
556*666cc0b2SZachary Turner //----------------------------------------------------------------------
557*666cc0b2SZachary Turner uint32_t DataExtractor::GetMaxU32(offset_t *offset_ptr,
558*666cc0b2SZachary Turner                                   size_t byte_size) const {
559*666cc0b2SZachary Turner   switch (byte_size) {
560*666cc0b2SZachary Turner   case 1:
561*666cc0b2SZachary Turner     return GetU8(offset_ptr);
562*666cc0b2SZachary Turner     break;
563*666cc0b2SZachary Turner   case 2:
564*666cc0b2SZachary Turner     return GetU16(offset_ptr);
565*666cc0b2SZachary Turner     break;
566*666cc0b2SZachary Turner   case 4:
567*666cc0b2SZachary Turner     return GetU32(offset_ptr);
568*666cc0b2SZachary Turner     break;
569*666cc0b2SZachary Turner   default:
570*666cc0b2SZachary Turner     assert(false && "GetMaxU32 unhandled case!");
571*666cc0b2SZachary Turner     break;
572*666cc0b2SZachary Turner   }
573*666cc0b2SZachary Turner   return 0;
574*666cc0b2SZachary Turner }
575*666cc0b2SZachary Turner 
576*666cc0b2SZachary Turner //----------------------------------------------------------------------
577*666cc0b2SZachary Turner // Extract a single integer value from the data and update the offset
578*666cc0b2SZachary Turner // pointed to by "offset_ptr". The size of the extracted integer
579*666cc0b2SZachary Turner // is specified by the "byte_size" argument. "byte_size" should have
580*666cc0b2SZachary Turner // a value >= 1 and <= 8 since the return value is only 64 bits
581*666cc0b2SZachary Turner // wide. Any "byte_size" values less than 1 or greater than 8 will
582*666cc0b2SZachary Turner // result in nothing being extracted, and zero being returned.
583*666cc0b2SZachary Turner //
584*666cc0b2SZachary Turner // RETURNS the integer value that was extracted, or zero on failure.
585*666cc0b2SZachary Turner //----------------------------------------------------------------------
586*666cc0b2SZachary Turner uint64_t DataExtractor::GetMaxU64(offset_t *offset_ptr, size_t size) const {
587*666cc0b2SZachary Turner   switch (size) {
588*666cc0b2SZachary Turner   case 1:
589*666cc0b2SZachary Turner     return GetU8(offset_ptr);
590*666cc0b2SZachary Turner     break;
591*666cc0b2SZachary Turner   case 2:
592*666cc0b2SZachary Turner     return GetU16(offset_ptr);
593*666cc0b2SZachary Turner     break;
594*666cc0b2SZachary Turner   case 4:
595*666cc0b2SZachary Turner     return GetU32(offset_ptr);
596*666cc0b2SZachary Turner     break;
597*666cc0b2SZachary Turner   case 8:
598*666cc0b2SZachary Turner     return GetU64(offset_ptr);
599*666cc0b2SZachary Turner     break;
600*666cc0b2SZachary Turner   default:
601*666cc0b2SZachary Turner     assert(false && "GetMax64 unhandled case!");
602*666cc0b2SZachary Turner     break;
603*666cc0b2SZachary Turner   }
604*666cc0b2SZachary Turner   return 0;
605*666cc0b2SZachary Turner }
606*666cc0b2SZachary Turner 
607*666cc0b2SZachary Turner uint64_t DataExtractor::GetMaxU64_unchecked(offset_t *offset_ptr,
608*666cc0b2SZachary Turner                                             size_t size) const {
609*666cc0b2SZachary Turner   switch (size) {
610*666cc0b2SZachary Turner   case 1:
611*666cc0b2SZachary Turner     return GetU8_unchecked(offset_ptr);
612*666cc0b2SZachary Turner     break;
613*666cc0b2SZachary Turner   case 2:
614*666cc0b2SZachary Turner     return GetU16_unchecked(offset_ptr);
615*666cc0b2SZachary Turner     break;
616*666cc0b2SZachary Turner   case 4:
617*666cc0b2SZachary Turner     return GetU32_unchecked(offset_ptr);
618*666cc0b2SZachary Turner     break;
619*666cc0b2SZachary Turner   case 8:
620*666cc0b2SZachary Turner     return GetU64_unchecked(offset_ptr);
621*666cc0b2SZachary Turner     break;
622*666cc0b2SZachary Turner   default:
623*666cc0b2SZachary Turner     assert(false && "GetMax64 unhandled case!");
624*666cc0b2SZachary Turner     break;
625*666cc0b2SZachary Turner   }
626*666cc0b2SZachary Turner   return 0;
627*666cc0b2SZachary Turner }
628*666cc0b2SZachary Turner 
629*666cc0b2SZachary Turner int64_t DataExtractor::GetMaxS64(offset_t *offset_ptr, size_t size) const {
630*666cc0b2SZachary Turner   switch (size) {
631*666cc0b2SZachary Turner   case 1:
632*666cc0b2SZachary Turner     return (int8_t)GetU8(offset_ptr);
633*666cc0b2SZachary Turner     break;
634*666cc0b2SZachary Turner   case 2:
635*666cc0b2SZachary Turner     return (int16_t)GetU16(offset_ptr);
636*666cc0b2SZachary Turner     break;
637*666cc0b2SZachary Turner   case 4:
638*666cc0b2SZachary Turner     return (int32_t)GetU32(offset_ptr);
639*666cc0b2SZachary Turner     break;
640*666cc0b2SZachary Turner   case 8:
641*666cc0b2SZachary Turner     return (int64_t)GetU64(offset_ptr);
642*666cc0b2SZachary Turner     break;
643*666cc0b2SZachary Turner   default:
644*666cc0b2SZachary Turner     assert(false && "GetMax64 unhandled case!");
645*666cc0b2SZachary Turner     break;
646*666cc0b2SZachary Turner   }
647*666cc0b2SZachary Turner   return 0;
648*666cc0b2SZachary Turner }
649*666cc0b2SZachary Turner 
650*666cc0b2SZachary Turner uint64_t DataExtractor::GetMaxU64Bitfield(offset_t *offset_ptr, size_t size,
651*666cc0b2SZachary Turner                                           uint32_t bitfield_bit_size,
652*666cc0b2SZachary Turner                                           uint32_t bitfield_bit_offset) const {
653*666cc0b2SZachary Turner   uint64_t uval64 = GetMaxU64(offset_ptr, size);
654*666cc0b2SZachary Turner   if (bitfield_bit_size > 0) {
655*666cc0b2SZachary Turner     int32_t lsbcount = bitfield_bit_offset;
656*666cc0b2SZachary Turner     if (m_byte_order == eByteOrderBig)
657*666cc0b2SZachary Turner       lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size;
658*666cc0b2SZachary Turner     if (lsbcount > 0)
659*666cc0b2SZachary Turner       uval64 >>= lsbcount;
660*666cc0b2SZachary Turner     uint64_t bitfield_mask = ((1ul << bitfield_bit_size) - 1);
661*666cc0b2SZachary Turner     if (!bitfield_mask && bitfield_bit_offset == 0 && bitfield_bit_size == 64)
662*666cc0b2SZachary Turner       return uval64;
663*666cc0b2SZachary Turner     uval64 &= bitfield_mask;
664*666cc0b2SZachary Turner   }
665*666cc0b2SZachary Turner   return uval64;
666*666cc0b2SZachary Turner }
667*666cc0b2SZachary Turner 
668*666cc0b2SZachary Turner int64_t DataExtractor::GetMaxS64Bitfield(offset_t *offset_ptr, size_t size,
669*666cc0b2SZachary Turner                                          uint32_t bitfield_bit_size,
670*666cc0b2SZachary Turner                                          uint32_t bitfield_bit_offset) const {
671*666cc0b2SZachary Turner   int64_t sval64 = GetMaxS64(offset_ptr, size);
672*666cc0b2SZachary Turner   if (bitfield_bit_size > 0) {
673*666cc0b2SZachary Turner     int32_t lsbcount = bitfield_bit_offset;
674*666cc0b2SZachary Turner     if (m_byte_order == eByteOrderBig)
675*666cc0b2SZachary Turner       lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size;
676*666cc0b2SZachary Turner     if (lsbcount > 0)
677*666cc0b2SZachary Turner       sval64 >>= lsbcount;
678*666cc0b2SZachary Turner     uint64_t bitfield_mask = (((uint64_t)1) << bitfield_bit_size) - 1;
679*666cc0b2SZachary Turner     sval64 &= bitfield_mask;
680*666cc0b2SZachary Turner     // sign extend if needed
681*666cc0b2SZachary Turner     if (sval64 & (((uint64_t)1) << (bitfield_bit_size - 1)))
682*666cc0b2SZachary Turner       sval64 |= ~bitfield_mask;
683*666cc0b2SZachary Turner   }
684*666cc0b2SZachary Turner   return sval64;
685*666cc0b2SZachary Turner }
686*666cc0b2SZachary Turner 
687*666cc0b2SZachary Turner float DataExtractor::GetFloat(offset_t *offset_ptr) const {
688*666cc0b2SZachary Turner   typedef float float_type;
689*666cc0b2SZachary Turner   float_type val = 0.0;
690*666cc0b2SZachary Turner   const size_t src_size = sizeof(float_type);
691*666cc0b2SZachary Turner   const float_type *src = (const float_type *)GetData(offset_ptr, src_size);
692*666cc0b2SZachary Turner   if (src) {
693*666cc0b2SZachary Turner     if (m_byte_order != endian::InlHostByteOrder()) {
694*666cc0b2SZachary Turner       const uint8_t *src_data = (const uint8_t *)src;
695*666cc0b2SZachary Turner       uint8_t *dst_data = (uint8_t *)&val;
696*666cc0b2SZachary Turner       for (size_t i = 0; i < sizeof(float_type); ++i)
697*666cc0b2SZachary Turner         dst_data[sizeof(float_type) - 1 - i] = src_data[i];
698*666cc0b2SZachary Turner     } else {
699*666cc0b2SZachary Turner       val = *src;
700*666cc0b2SZachary Turner     }
701*666cc0b2SZachary Turner   }
702*666cc0b2SZachary Turner   return val;
703*666cc0b2SZachary Turner }
704*666cc0b2SZachary Turner 
705*666cc0b2SZachary Turner double DataExtractor::GetDouble(offset_t *offset_ptr) const {
706*666cc0b2SZachary Turner   typedef double float_type;
707*666cc0b2SZachary Turner   float_type val = 0.0;
708*666cc0b2SZachary Turner   const size_t src_size = sizeof(float_type);
709*666cc0b2SZachary Turner   const float_type *src = (const float_type *)GetData(offset_ptr, src_size);
710*666cc0b2SZachary Turner   if (src) {
711*666cc0b2SZachary Turner     if (m_byte_order != endian::InlHostByteOrder()) {
712*666cc0b2SZachary Turner       const uint8_t *src_data = (const uint8_t *)src;
713*666cc0b2SZachary Turner       uint8_t *dst_data = (uint8_t *)&val;
714*666cc0b2SZachary Turner       for (size_t i = 0; i < sizeof(float_type); ++i)
715*666cc0b2SZachary Turner         dst_data[sizeof(float_type) - 1 - i] = src_data[i];
716*666cc0b2SZachary Turner     } else {
717*666cc0b2SZachary Turner       val = *src;
718*666cc0b2SZachary Turner     }
719*666cc0b2SZachary Turner   }
720*666cc0b2SZachary Turner   return val;
721*666cc0b2SZachary Turner }
722*666cc0b2SZachary Turner 
723*666cc0b2SZachary Turner long double DataExtractor::GetLongDouble(offset_t *offset_ptr) const {
724*666cc0b2SZachary Turner   long double val = 0.0;
725*666cc0b2SZachary Turner #if defined(__i386__) || defined(__amd64__) || defined(__x86_64__) ||          \
726*666cc0b2SZachary Turner     defined(_M_IX86) || defined(_M_IA64) || defined(_M_X64)
727*666cc0b2SZachary Turner   *offset_ptr += CopyByteOrderedData(*offset_ptr, 10, &val, sizeof(val),
728*666cc0b2SZachary Turner                                      endian::InlHostByteOrder());
729*666cc0b2SZachary Turner #else
730*666cc0b2SZachary Turner   *offset_ptr += CopyByteOrderedData(*offset_ptr, sizeof(val), &val,
731*666cc0b2SZachary Turner                                      sizeof(val), endian::InlHostByteOrder());
732*666cc0b2SZachary Turner #endif
733*666cc0b2SZachary Turner   return val;
734*666cc0b2SZachary Turner }
735*666cc0b2SZachary Turner 
736*666cc0b2SZachary Turner //------------------------------------------------------------------
737*666cc0b2SZachary Turner // Extract a single address from the data and update the offset
738*666cc0b2SZachary Turner // pointed to by "offset_ptr". The size of the extracted address
739*666cc0b2SZachary Turner // comes from the "this->m_addr_size" member variable and should be
740*666cc0b2SZachary Turner // set correctly prior to extracting any address values.
741*666cc0b2SZachary Turner //
742*666cc0b2SZachary Turner // RETURNS the address that was extracted, or zero on failure.
743*666cc0b2SZachary Turner //------------------------------------------------------------------
744*666cc0b2SZachary Turner uint64_t DataExtractor::GetAddress(offset_t *offset_ptr) const {
745*666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG
746*666cc0b2SZachary Turner   assert(m_addr_size == 4 || m_addr_size == 8);
747*666cc0b2SZachary Turner #endif
748*666cc0b2SZachary Turner   return GetMaxU64(offset_ptr, m_addr_size);
749*666cc0b2SZachary Turner }
750*666cc0b2SZachary Turner 
751*666cc0b2SZachary Turner uint64_t DataExtractor::GetAddress_unchecked(offset_t *offset_ptr) const {
752*666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG
753*666cc0b2SZachary Turner   assert(m_addr_size == 4 || m_addr_size == 8);
754*666cc0b2SZachary Turner #endif
755*666cc0b2SZachary Turner   return GetMaxU64_unchecked(offset_ptr, m_addr_size);
756*666cc0b2SZachary Turner }
757*666cc0b2SZachary Turner 
758*666cc0b2SZachary Turner //------------------------------------------------------------------
759*666cc0b2SZachary Turner // Extract a single pointer from the data and update the offset
760*666cc0b2SZachary Turner // pointed to by "offset_ptr". The size of the extracted pointer
761*666cc0b2SZachary Turner // comes from the "this->m_addr_size" member variable and should be
762*666cc0b2SZachary Turner // set correctly prior to extracting any pointer values.
763*666cc0b2SZachary Turner //
764*666cc0b2SZachary Turner // RETURNS the pointer that was extracted, or zero on failure.
765*666cc0b2SZachary Turner //------------------------------------------------------------------
766*666cc0b2SZachary Turner uint64_t DataExtractor::GetPointer(offset_t *offset_ptr) const {
767*666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG
768*666cc0b2SZachary Turner   assert(m_addr_size == 4 || m_addr_size == 8);
769*666cc0b2SZachary Turner #endif
770*666cc0b2SZachary Turner   return GetMaxU64(offset_ptr, m_addr_size);
771*666cc0b2SZachary Turner }
772*666cc0b2SZachary Turner 
773*666cc0b2SZachary Turner size_t DataExtractor::ExtractBytes(offset_t offset, offset_t length,
774*666cc0b2SZachary Turner                                    ByteOrder dst_byte_order, void *dst) const {
775*666cc0b2SZachary Turner   const uint8_t *src = PeekData(offset, length);
776*666cc0b2SZachary Turner   if (src) {
777*666cc0b2SZachary Turner     if (dst_byte_order != GetByteOrder()) {
778*666cc0b2SZachary Turner       // Validate that only a word- or register-sized dst is byte swapped
779*666cc0b2SZachary Turner       assert(length == 1 || length == 2 || length == 4 || length == 8 ||
780*666cc0b2SZachary Turner              length == 10 || length == 16 || length == 32);
781*666cc0b2SZachary Turner 
782*666cc0b2SZachary Turner       for (uint32_t i = 0; i < length; ++i)
783*666cc0b2SZachary Turner         ((uint8_t *)dst)[i] = src[length - i - 1];
784*666cc0b2SZachary Turner     } else
785*666cc0b2SZachary Turner       ::memcpy(dst, src, length);
786*666cc0b2SZachary Turner     return length;
787*666cc0b2SZachary Turner   }
788*666cc0b2SZachary Turner   return 0;
789*666cc0b2SZachary Turner }
790*666cc0b2SZachary Turner 
791*666cc0b2SZachary Turner // Extract data as it exists in target memory
792*666cc0b2SZachary Turner lldb::offset_t DataExtractor::CopyData(offset_t offset, offset_t length,
793*666cc0b2SZachary Turner                                        void *dst) const {
794*666cc0b2SZachary Turner   const uint8_t *src = PeekData(offset, length);
795*666cc0b2SZachary Turner   if (src) {
796*666cc0b2SZachary Turner     ::memcpy(dst, src, length);
797*666cc0b2SZachary Turner     return length;
798*666cc0b2SZachary Turner   }
799*666cc0b2SZachary Turner   return 0;
800*666cc0b2SZachary Turner }
801*666cc0b2SZachary Turner 
802*666cc0b2SZachary Turner // Extract data and swap if needed when doing the copy
803*666cc0b2SZachary Turner lldb::offset_t
804*666cc0b2SZachary Turner DataExtractor::CopyByteOrderedData(offset_t src_offset, offset_t src_len,
805*666cc0b2SZachary Turner                                    void *dst_void_ptr, offset_t dst_len,
806*666cc0b2SZachary Turner                                    ByteOrder dst_byte_order) const {
807*666cc0b2SZachary Turner   // Validate the source info
808*666cc0b2SZachary Turner   if (!ValidOffsetForDataOfSize(src_offset, src_len))
809*666cc0b2SZachary Turner     assert(ValidOffsetForDataOfSize(src_offset, src_len));
810*666cc0b2SZachary Turner   assert(src_len > 0);
811*666cc0b2SZachary Turner   assert(m_byte_order == eByteOrderBig || m_byte_order == eByteOrderLittle);
812*666cc0b2SZachary Turner 
813*666cc0b2SZachary Turner   // Validate the destination info
814*666cc0b2SZachary Turner   assert(dst_void_ptr != nullptr);
815*666cc0b2SZachary Turner   assert(dst_len > 0);
816*666cc0b2SZachary Turner   assert(dst_byte_order == eByteOrderBig || dst_byte_order == eByteOrderLittle);
817*666cc0b2SZachary Turner 
818*666cc0b2SZachary Turner   // Validate that only a word- or register-sized dst is byte swapped
819*666cc0b2SZachary Turner   assert(dst_byte_order == m_byte_order || dst_len == 1 || dst_len == 2 ||
820*666cc0b2SZachary Turner          dst_len == 4 || dst_len == 8 || dst_len == 10 || dst_len == 16 ||
821*666cc0b2SZachary Turner          dst_len == 32);
822*666cc0b2SZachary Turner 
823*666cc0b2SZachary Turner   // Must have valid byte orders set in this object and for destination
824*666cc0b2SZachary Turner   if (!(dst_byte_order == eByteOrderBig ||
825*666cc0b2SZachary Turner         dst_byte_order == eByteOrderLittle) ||
826*666cc0b2SZachary Turner       !(m_byte_order == eByteOrderBig || m_byte_order == eByteOrderLittle))
827*666cc0b2SZachary Turner     return 0;
828*666cc0b2SZachary Turner 
829*666cc0b2SZachary Turner   uint8_t *dst = (uint8_t *)dst_void_ptr;
830*666cc0b2SZachary Turner   const uint8_t *src = (const uint8_t *)PeekData(src_offset, src_len);
831*666cc0b2SZachary Turner   if (src) {
832*666cc0b2SZachary Turner     if (dst_len >= src_len) {
833*666cc0b2SZachary Turner       // We are copying the entire value from src into dst.
834*666cc0b2SZachary Turner       // Calculate how many, if any, zeroes we need for the most
835*666cc0b2SZachary Turner       // significant bytes if "dst_len" is greater than "src_len"...
836*666cc0b2SZachary Turner       const size_t num_zeroes = dst_len - src_len;
837*666cc0b2SZachary Turner       if (dst_byte_order == eByteOrderBig) {
838*666cc0b2SZachary Turner         // Big endian, so we lead with zeroes...
839*666cc0b2SZachary Turner         if (num_zeroes > 0)
840*666cc0b2SZachary Turner           ::memset(dst, 0, num_zeroes);
841*666cc0b2SZachary Turner         // Then either copy or swap the rest
842*666cc0b2SZachary Turner         if (m_byte_order == eByteOrderBig) {
843*666cc0b2SZachary Turner           ::memcpy(dst + num_zeroes, src, src_len);
844*666cc0b2SZachary Turner         } else {
845*666cc0b2SZachary Turner           for (uint32_t i = 0; i < src_len; ++i)
846*666cc0b2SZachary Turner             dst[i + num_zeroes] = src[src_len - 1 - i];
847*666cc0b2SZachary Turner         }
848*666cc0b2SZachary Turner       } else {
849*666cc0b2SZachary Turner         // Little endian destination, so we lead the value bytes
850*666cc0b2SZachary Turner         if (m_byte_order == eByteOrderBig) {
851*666cc0b2SZachary Turner           for (uint32_t i = 0; i < src_len; ++i)
852*666cc0b2SZachary Turner             dst[i] = src[src_len - 1 - i];
853*666cc0b2SZachary Turner         } else {
854*666cc0b2SZachary Turner           ::memcpy(dst, src, src_len);
855*666cc0b2SZachary Turner         }
856*666cc0b2SZachary Turner         // And zero the rest...
857*666cc0b2SZachary Turner         if (num_zeroes > 0)
858*666cc0b2SZachary Turner           ::memset(dst + src_len, 0, num_zeroes);
859*666cc0b2SZachary Turner       }
860*666cc0b2SZachary Turner       return src_len;
861*666cc0b2SZachary Turner     } else {
862*666cc0b2SZachary Turner       // We are only copying some of the value from src into dst..
863*666cc0b2SZachary Turner 
864*666cc0b2SZachary Turner       if (dst_byte_order == eByteOrderBig) {
865*666cc0b2SZachary Turner         // Big endian dst
866*666cc0b2SZachary Turner         if (m_byte_order == eByteOrderBig) {
867*666cc0b2SZachary Turner           // Big endian dst, with big endian src
868*666cc0b2SZachary Turner           ::memcpy(dst, src + (src_len - dst_len), dst_len);
869*666cc0b2SZachary Turner         } else {
870*666cc0b2SZachary Turner           // Big endian dst, with little endian src
871*666cc0b2SZachary Turner           for (uint32_t i = 0; i < dst_len; ++i)
872*666cc0b2SZachary Turner             dst[i] = src[dst_len - 1 - i];
873*666cc0b2SZachary Turner         }
874*666cc0b2SZachary Turner       } else {
875*666cc0b2SZachary Turner         // Little endian dst
876*666cc0b2SZachary Turner         if (m_byte_order == eByteOrderBig) {
877*666cc0b2SZachary Turner           // Little endian dst, with big endian src
878*666cc0b2SZachary Turner           for (uint32_t i = 0; i < dst_len; ++i)
879*666cc0b2SZachary Turner             dst[i] = src[src_len - 1 - i];
880*666cc0b2SZachary Turner         } else {
881*666cc0b2SZachary Turner           // Little endian dst, with big endian src
882*666cc0b2SZachary Turner           ::memcpy(dst, src, dst_len);
883*666cc0b2SZachary Turner         }
884*666cc0b2SZachary Turner       }
885*666cc0b2SZachary Turner       return dst_len;
886*666cc0b2SZachary Turner     }
887*666cc0b2SZachary Turner   }
888*666cc0b2SZachary Turner   return 0;
889*666cc0b2SZachary Turner }
890*666cc0b2SZachary Turner 
891*666cc0b2SZachary Turner //----------------------------------------------------------------------
892*666cc0b2SZachary Turner // Extracts a variable length NULL terminated C string from
893*666cc0b2SZachary Turner // the data at the offset pointed to by "offset_ptr".  The
894*666cc0b2SZachary Turner // "offset_ptr" will be updated with the offset of the byte that
895*666cc0b2SZachary Turner // follows the NULL terminator byte.
896*666cc0b2SZachary Turner //
897*666cc0b2SZachary Turner // If the offset pointed to by "offset_ptr" is out of bounds, or if
898*666cc0b2SZachary Turner // "length" is non-zero and there aren't enough available
899*666cc0b2SZachary Turner // bytes, nullptr will be returned and "offset_ptr" will not be
900*666cc0b2SZachary Turner // updated.
901*666cc0b2SZachary Turner //----------------------------------------------------------------------
902*666cc0b2SZachary Turner const char *DataExtractor::GetCStr(offset_t *offset_ptr) const {
903*666cc0b2SZachary Turner   const char *cstr = (const char *)PeekData(*offset_ptr, 1);
904*666cc0b2SZachary Turner   if (cstr) {
905*666cc0b2SZachary Turner     const char *cstr_end = cstr;
906*666cc0b2SZachary Turner     const char *end = (const char *)m_end;
907*666cc0b2SZachary Turner     while (cstr_end < end && *cstr_end)
908*666cc0b2SZachary Turner       ++cstr_end;
909*666cc0b2SZachary Turner 
910*666cc0b2SZachary Turner     // Now we are either at the end of the data or we point to the
911*666cc0b2SZachary Turner     // NULL C string terminator with cstr_end...
912*666cc0b2SZachary Turner     if (*cstr_end == '\0') {
913*666cc0b2SZachary Turner       // Advance the offset with one extra byte for the NULL terminator
914*666cc0b2SZachary Turner       *offset_ptr += (cstr_end - cstr + 1);
915*666cc0b2SZachary Turner       return cstr;
916*666cc0b2SZachary Turner     }
917*666cc0b2SZachary Turner 
918*666cc0b2SZachary Turner     // We reached the end of the data without finding a NULL C string
919*666cc0b2SZachary Turner     // terminator. Fall through and return nullptr otherwise anyone that
920*666cc0b2SZachary Turner     // would have used the result as a C string can wander into
921*666cc0b2SZachary Turner     // unknown memory...
922*666cc0b2SZachary Turner   }
923*666cc0b2SZachary Turner   return nullptr;
924*666cc0b2SZachary Turner }
925*666cc0b2SZachary Turner 
926*666cc0b2SZachary Turner //----------------------------------------------------------------------
927*666cc0b2SZachary Turner // Extracts a NULL terminated C string from the fixed length field of
928*666cc0b2SZachary Turner // length "len" at the offset pointed to by "offset_ptr".
929*666cc0b2SZachary Turner // The "offset_ptr" will be updated with the offset of the byte that
930*666cc0b2SZachary Turner // follows the fixed length field.
931*666cc0b2SZachary Turner //
932*666cc0b2SZachary Turner // If the offset pointed to by "offset_ptr" is out of bounds, or if
933*666cc0b2SZachary Turner // the offset plus the length of the field is out of bounds, or if the
934*666cc0b2SZachary Turner // field does not contain a NULL terminator byte, nullptr will be returned
935*666cc0b2SZachary Turner // and "offset_ptr" will not be updated.
936*666cc0b2SZachary Turner //----------------------------------------------------------------------
937*666cc0b2SZachary Turner const char *DataExtractor::GetCStr(offset_t *offset_ptr, offset_t len) const {
938*666cc0b2SZachary Turner   const char *cstr = (const char *)PeekData(*offset_ptr, len);
939*666cc0b2SZachary Turner   if (cstr != nullptr) {
940*666cc0b2SZachary Turner     if (memchr(cstr, '\0', len) == nullptr) {
941*666cc0b2SZachary Turner       return nullptr;
942*666cc0b2SZachary Turner     }
943*666cc0b2SZachary Turner     *offset_ptr += len;
944*666cc0b2SZachary Turner     return cstr;
945*666cc0b2SZachary Turner   }
946*666cc0b2SZachary Turner   return nullptr;
947*666cc0b2SZachary Turner }
948*666cc0b2SZachary Turner 
949*666cc0b2SZachary Turner //------------------------------------------------------------------
950*666cc0b2SZachary Turner // Peeks at a string in the contained data. No verification is done
951*666cc0b2SZachary Turner // to make sure the entire string lies within the bounds of this
952*666cc0b2SZachary Turner // object's data, only "offset" is verified to be a valid offset.
953*666cc0b2SZachary Turner //
954*666cc0b2SZachary Turner // Returns a valid C string pointer if "offset" is a valid offset in
955*666cc0b2SZachary Turner // this object's data, else nullptr is returned.
956*666cc0b2SZachary Turner //------------------------------------------------------------------
957*666cc0b2SZachary Turner const char *DataExtractor::PeekCStr(offset_t offset) const {
958*666cc0b2SZachary Turner   return (const char *)PeekData(offset, 1);
959*666cc0b2SZachary Turner }
960*666cc0b2SZachary Turner 
961*666cc0b2SZachary Turner //----------------------------------------------------------------------
962*666cc0b2SZachary Turner // Extracts an unsigned LEB128 number from this object's data
963*666cc0b2SZachary Turner // starting at the offset pointed to by "offset_ptr". The offset
964*666cc0b2SZachary Turner // pointed to by "offset_ptr" will be updated with the offset of the
965*666cc0b2SZachary Turner // byte following the last extracted byte.
966*666cc0b2SZachary Turner //
967*666cc0b2SZachary Turner // Returned the extracted integer value.
968*666cc0b2SZachary Turner //----------------------------------------------------------------------
969*666cc0b2SZachary Turner uint64_t DataExtractor::GetULEB128(offset_t *offset_ptr) const {
970*666cc0b2SZachary Turner   const uint8_t *src = (const uint8_t *)PeekData(*offset_ptr, 1);
971*666cc0b2SZachary Turner   if (src == nullptr)
972*666cc0b2SZachary Turner     return 0;
973*666cc0b2SZachary Turner 
974*666cc0b2SZachary Turner   const uint8_t *end = m_end;
975*666cc0b2SZachary Turner 
976*666cc0b2SZachary Turner   if (src < end) {
977*666cc0b2SZachary Turner     uint64_t result = *src++;
978*666cc0b2SZachary Turner     if (result >= 0x80) {
979*666cc0b2SZachary Turner       result &= 0x7f;
980*666cc0b2SZachary Turner       int shift = 7;
981*666cc0b2SZachary Turner       while (src < end) {
982*666cc0b2SZachary Turner         uint8_t byte = *src++;
983*666cc0b2SZachary Turner         result |= (uint64_t)(byte & 0x7f) << shift;
984*666cc0b2SZachary Turner         if ((byte & 0x80) == 0)
985*666cc0b2SZachary Turner           break;
986*666cc0b2SZachary Turner         shift += 7;
987*666cc0b2SZachary Turner       }
988*666cc0b2SZachary Turner     }
989*666cc0b2SZachary Turner     *offset_ptr = src - m_start;
990*666cc0b2SZachary Turner     return result;
991*666cc0b2SZachary Turner   }
992*666cc0b2SZachary Turner 
993*666cc0b2SZachary Turner   return 0;
994*666cc0b2SZachary Turner }
995*666cc0b2SZachary Turner 
996*666cc0b2SZachary Turner //----------------------------------------------------------------------
997*666cc0b2SZachary Turner // Extracts an signed LEB128 number from this object's data
998*666cc0b2SZachary Turner // starting at the offset pointed to by "offset_ptr". The offset
999*666cc0b2SZachary Turner // pointed to by "offset_ptr" will be updated with the offset of the
1000*666cc0b2SZachary Turner // byte following the last extracted byte.
1001*666cc0b2SZachary Turner //
1002*666cc0b2SZachary Turner // Returned the extracted integer value.
1003*666cc0b2SZachary Turner //----------------------------------------------------------------------
1004*666cc0b2SZachary Turner int64_t DataExtractor::GetSLEB128(offset_t *offset_ptr) const {
1005*666cc0b2SZachary Turner   const uint8_t *src = (const uint8_t *)PeekData(*offset_ptr, 1);
1006*666cc0b2SZachary Turner   if (src == nullptr)
1007*666cc0b2SZachary Turner     return 0;
1008*666cc0b2SZachary Turner 
1009*666cc0b2SZachary Turner   const uint8_t *end = m_end;
1010*666cc0b2SZachary Turner 
1011*666cc0b2SZachary Turner   if (src < end) {
1012*666cc0b2SZachary Turner     int64_t result = 0;
1013*666cc0b2SZachary Turner     int shift = 0;
1014*666cc0b2SZachary Turner     int size = sizeof(int64_t) * 8;
1015*666cc0b2SZachary Turner 
1016*666cc0b2SZachary Turner     uint8_t byte = 0;
1017*666cc0b2SZachary Turner     int bytecount = 0;
1018*666cc0b2SZachary Turner 
1019*666cc0b2SZachary Turner     while (src < end) {
1020*666cc0b2SZachary Turner       bytecount++;
1021*666cc0b2SZachary Turner       byte = *src++;
1022*666cc0b2SZachary Turner       result |= (int64_t)(byte & 0x7f) << shift;
1023*666cc0b2SZachary Turner       shift += 7;
1024*666cc0b2SZachary Turner       if ((byte & 0x80) == 0)
1025*666cc0b2SZachary Turner         break;
1026*666cc0b2SZachary Turner     }
1027*666cc0b2SZachary Turner 
1028*666cc0b2SZachary Turner     // Sign bit of byte is 2nd high order bit (0x40)
1029*666cc0b2SZachary Turner     if (shift < size && (byte & 0x40))
1030*666cc0b2SZachary Turner       result |= -(1 << shift);
1031*666cc0b2SZachary Turner 
1032*666cc0b2SZachary Turner     *offset_ptr += bytecount;
1033*666cc0b2SZachary Turner     return result;
1034*666cc0b2SZachary Turner   }
1035*666cc0b2SZachary Turner   return 0;
1036*666cc0b2SZachary Turner }
1037*666cc0b2SZachary Turner 
1038*666cc0b2SZachary Turner //----------------------------------------------------------------------
1039*666cc0b2SZachary Turner // Skips a ULEB128 number (signed or unsigned) from this object's
1040*666cc0b2SZachary Turner // data starting at the offset pointed to by "offset_ptr". The
1041*666cc0b2SZachary Turner // offset pointed to by "offset_ptr" will be updated with the offset
1042*666cc0b2SZachary Turner // of the byte following the last extracted byte.
1043*666cc0b2SZachary Turner //
1044*666cc0b2SZachary Turner // Returns the number of bytes consumed during the extraction.
1045*666cc0b2SZachary Turner //----------------------------------------------------------------------
1046*666cc0b2SZachary Turner uint32_t DataExtractor::Skip_LEB128(offset_t *offset_ptr) const {
1047*666cc0b2SZachary Turner   uint32_t bytes_consumed = 0;
1048*666cc0b2SZachary Turner   const uint8_t *src = (const uint8_t *)PeekData(*offset_ptr, 1);
1049*666cc0b2SZachary Turner   if (src == nullptr)
1050*666cc0b2SZachary Turner     return 0;
1051*666cc0b2SZachary Turner 
1052*666cc0b2SZachary Turner   const uint8_t *end = m_end;
1053*666cc0b2SZachary Turner 
1054*666cc0b2SZachary Turner   if (src < end) {
1055*666cc0b2SZachary Turner     const uint8_t *src_pos = src;
1056*666cc0b2SZachary Turner     while ((src_pos < end) && (*src_pos++ & 0x80))
1057*666cc0b2SZachary Turner       ++bytes_consumed;
1058*666cc0b2SZachary Turner     *offset_ptr += src_pos - src;
1059*666cc0b2SZachary Turner   }
1060*666cc0b2SZachary Turner   return bytes_consumed;
1061*666cc0b2SZachary Turner }
1062*666cc0b2SZachary Turner 
1063*666cc0b2SZachary Turner //----------------------------------------------------------------------
1064*666cc0b2SZachary Turner // Dumps bytes from this object's data to the stream "s" starting
1065*666cc0b2SZachary Turner // "start_offset" bytes into this data, and ending with the byte
1066*666cc0b2SZachary Turner // before "end_offset". "base_addr" will be added to the offset
1067*666cc0b2SZachary Turner // into the dumped data when showing the offset into the data in the
1068*666cc0b2SZachary Turner // output information. "num_per_line" objects of type "type" will
1069*666cc0b2SZachary Turner // be dumped with the option to override the format for each object
1070*666cc0b2SZachary Turner // with "type_format". "type_format" is a printf style formatting
1071*666cc0b2SZachary Turner // string. If "type_format" is nullptr, then an appropriate format
1072*666cc0b2SZachary Turner // string will be used for the supplied "type". If the stream "s"
1073*666cc0b2SZachary Turner // is nullptr, then the output will be send to Log().
1074*666cc0b2SZachary Turner //----------------------------------------------------------------------
1075*666cc0b2SZachary Turner lldb::offset_t DataExtractor::PutToLog(Log *log, offset_t start_offset,
1076*666cc0b2SZachary Turner                                        offset_t length, uint64_t base_addr,
1077*666cc0b2SZachary Turner                                        uint32_t num_per_line,
1078*666cc0b2SZachary Turner                                        DataExtractor::Type type,
1079*666cc0b2SZachary Turner                                        const char *format) const {
1080*666cc0b2SZachary Turner   if (log == nullptr)
1081*666cc0b2SZachary Turner     return start_offset;
1082*666cc0b2SZachary Turner 
1083*666cc0b2SZachary Turner   offset_t offset;
1084*666cc0b2SZachary Turner   offset_t end_offset;
1085*666cc0b2SZachary Turner   uint32_t count;
1086*666cc0b2SZachary Turner   StreamString sstr;
1087*666cc0b2SZachary Turner   for (offset = start_offset, end_offset = offset + length, count = 0;
1088*666cc0b2SZachary Turner        ValidOffset(offset) && offset < end_offset; ++count) {
1089*666cc0b2SZachary Turner     if ((count % num_per_line) == 0) {
1090*666cc0b2SZachary Turner       // Print out any previous string
1091*666cc0b2SZachary Turner       if (sstr.GetSize() > 0) {
1092*666cc0b2SZachary Turner         log->PutString(sstr.GetString());
1093*666cc0b2SZachary Turner         sstr.Clear();
1094*666cc0b2SZachary Turner       }
1095*666cc0b2SZachary Turner       // Reset string offset and fill the current line string with address:
1096*666cc0b2SZachary Turner       if (base_addr != LLDB_INVALID_ADDRESS)
1097*666cc0b2SZachary Turner         sstr.Printf("0x%8.8" PRIx64 ":",
1098*666cc0b2SZachary Turner                     (uint64_t)(base_addr + (offset - start_offset)));
1099*666cc0b2SZachary Turner     }
1100*666cc0b2SZachary Turner 
1101*666cc0b2SZachary Turner     switch (type) {
1102*666cc0b2SZachary Turner     case TypeUInt8:
1103*666cc0b2SZachary Turner       sstr.Printf(format ? format : " %2.2x", GetU8(&offset));
1104*666cc0b2SZachary Turner       break;
1105*666cc0b2SZachary Turner     case TypeChar: {
1106*666cc0b2SZachary Turner       char ch = GetU8(&offset);
1107*666cc0b2SZachary Turner       sstr.Printf(format ? format : " %c", isprint(ch) ? ch : ' ');
1108*666cc0b2SZachary Turner     } break;
1109*666cc0b2SZachary Turner     case TypeUInt16:
1110*666cc0b2SZachary Turner       sstr.Printf(format ? format : " %4.4x", GetU16(&offset));
1111*666cc0b2SZachary Turner       break;
1112*666cc0b2SZachary Turner     case TypeUInt32:
1113*666cc0b2SZachary Turner       sstr.Printf(format ? format : " %8.8x", GetU32(&offset));
1114*666cc0b2SZachary Turner       break;
1115*666cc0b2SZachary Turner     case TypeUInt64:
1116*666cc0b2SZachary Turner       sstr.Printf(format ? format : " %16.16" PRIx64, GetU64(&offset));
1117*666cc0b2SZachary Turner       break;
1118*666cc0b2SZachary Turner     case TypePointer:
1119*666cc0b2SZachary Turner       sstr.Printf(format ? format : " 0x%" PRIx64, GetAddress(&offset));
1120*666cc0b2SZachary Turner       break;
1121*666cc0b2SZachary Turner     case TypeULEB128:
1122*666cc0b2SZachary Turner       sstr.Printf(format ? format : " 0x%" PRIx64, GetULEB128(&offset));
1123*666cc0b2SZachary Turner       break;
1124*666cc0b2SZachary Turner     case TypeSLEB128:
1125*666cc0b2SZachary Turner       sstr.Printf(format ? format : " %" PRId64, GetSLEB128(&offset));
1126*666cc0b2SZachary Turner       break;
1127*666cc0b2SZachary Turner     }
1128*666cc0b2SZachary Turner   }
1129*666cc0b2SZachary Turner 
1130*666cc0b2SZachary Turner   if (!sstr.Empty())
1131*666cc0b2SZachary Turner     log->PutString(sstr.GetString());
1132*666cc0b2SZachary Turner 
1133*666cc0b2SZachary Turner   return offset; // Return the offset at which we ended up
1134*666cc0b2SZachary Turner }
1135*666cc0b2SZachary Turner 
1136*666cc0b2SZachary Turner //----------------------------------------------------------------------
1137*666cc0b2SZachary Turner // DumpUUID
1138*666cc0b2SZachary Turner //
1139*666cc0b2SZachary Turner // Dump out a UUID starting at 'offset' bytes into the buffer
1140*666cc0b2SZachary Turner //----------------------------------------------------------------------
1141*666cc0b2SZachary Turner void DataExtractor::DumpUUID(Stream *s, offset_t offset) const {
1142*666cc0b2SZachary Turner   if (s) {
1143*666cc0b2SZachary Turner     const uint8_t *uuid_data = PeekData(offset, 16);
1144*666cc0b2SZachary Turner     if (uuid_data) {
1145*666cc0b2SZachary Turner       lldb_private::UUID uuid(uuid_data, 16);
1146*666cc0b2SZachary Turner       uuid.Dump(s);
1147*666cc0b2SZachary Turner     } else {
1148*666cc0b2SZachary Turner       s->Printf("<not enough data for UUID at offset 0x%8.8" PRIx64 ">",
1149*666cc0b2SZachary Turner                 offset);
1150*666cc0b2SZachary Turner     }
1151*666cc0b2SZachary Turner   }
1152*666cc0b2SZachary Turner }
1153*666cc0b2SZachary Turner 
1154*666cc0b2SZachary Turner size_t DataExtractor::Copy(DataExtractor &dest_data) const {
1155*666cc0b2SZachary Turner   if (m_data_sp) {
1156*666cc0b2SZachary Turner     // we can pass along the SP to the data
1157*666cc0b2SZachary Turner     dest_data.SetData(m_data_sp);
1158*666cc0b2SZachary Turner   } else {
1159*666cc0b2SZachary Turner     const uint8_t *base_ptr = m_start;
1160*666cc0b2SZachary Turner     size_t data_size = GetByteSize();
1161*666cc0b2SZachary Turner     dest_data.SetData(DataBufferSP(new DataBufferHeap(base_ptr, data_size)));
1162*666cc0b2SZachary Turner   }
1163*666cc0b2SZachary Turner   return GetByteSize();
1164*666cc0b2SZachary Turner }
1165*666cc0b2SZachary Turner 
1166*666cc0b2SZachary Turner bool DataExtractor::Append(DataExtractor &rhs) {
1167*666cc0b2SZachary Turner   if (rhs.GetByteOrder() != GetByteOrder())
1168*666cc0b2SZachary Turner     return false;
1169*666cc0b2SZachary Turner 
1170*666cc0b2SZachary Turner   if (rhs.GetByteSize() == 0)
1171*666cc0b2SZachary Turner     return true;
1172*666cc0b2SZachary Turner 
1173*666cc0b2SZachary Turner   if (GetByteSize() == 0)
1174*666cc0b2SZachary Turner     return (rhs.Copy(*this) > 0);
1175*666cc0b2SZachary Turner 
1176*666cc0b2SZachary Turner   size_t bytes = GetByteSize() + rhs.GetByteSize();
1177*666cc0b2SZachary Turner 
1178*666cc0b2SZachary Turner   DataBufferHeap *buffer_heap_ptr = nullptr;
1179*666cc0b2SZachary Turner   DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0));
1180*666cc0b2SZachary Turner 
1181*666cc0b2SZachary Turner   if (!buffer_sp || buffer_heap_ptr == nullptr)
1182*666cc0b2SZachary Turner     return false;
1183*666cc0b2SZachary Turner 
1184*666cc0b2SZachary Turner   uint8_t *bytes_ptr = buffer_heap_ptr->GetBytes();
1185*666cc0b2SZachary Turner 
1186*666cc0b2SZachary Turner   memcpy(bytes_ptr, GetDataStart(), GetByteSize());
1187*666cc0b2SZachary Turner   memcpy(bytes_ptr + GetByteSize(), rhs.GetDataStart(), rhs.GetByteSize());
1188*666cc0b2SZachary Turner 
1189*666cc0b2SZachary Turner   SetData(buffer_sp);
1190*666cc0b2SZachary Turner 
1191*666cc0b2SZachary Turner   return true;
1192*666cc0b2SZachary Turner }
1193*666cc0b2SZachary Turner 
1194*666cc0b2SZachary Turner bool DataExtractor::Append(void *buf, offset_t length) {
1195*666cc0b2SZachary Turner   if (buf == nullptr)
1196*666cc0b2SZachary Turner     return false;
1197*666cc0b2SZachary Turner 
1198*666cc0b2SZachary Turner   if (length == 0)
1199*666cc0b2SZachary Turner     return true;
1200*666cc0b2SZachary Turner 
1201*666cc0b2SZachary Turner   size_t bytes = GetByteSize() + length;
1202*666cc0b2SZachary Turner 
1203*666cc0b2SZachary Turner   DataBufferHeap *buffer_heap_ptr = nullptr;
1204*666cc0b2SZachary Turner   DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0));
1205*666cc0b2SZachary Turner 
1206*666cc0b2SZachary Turner   if (!buffer_sp || buffer_heap_ptr == nullptr)
1207*666cc0b2SZachary Turner     return false;
1208*666cc0b2SZachary Turner 
1209*666cc0b2SZachary Turner   uint8_t *bytes_ptr = buffer_heap_ptr->GetBytes();
1210*666cc0b2SZachary Turner 
1211*666cc0b2SZachary Turner   if (GetByteSize() > 0)
1212*666cc0b2SZachary Turner     memcpy(bytes_ptr, GetDataStart(), GetByteSize());
1213*666cc0b2SZachary Turner 
1214*666cc0b2SZachary Turner   memcpy(bytes_ptr + GetByteSize(), buf, length);
1215*666cc0b2SZachary Turner 
1216*666cc0b2SZachary Turner   SetData(buffer_sp);
1217*666cc0b2SZachary Turner 
1218*666cc0b2SZachary Turner   return true;
1219*666cc0b2SZachary Turner }
1220*666cc0b2SZachary Turner 
1221*666cc0b2SZachary Turner void DataExtractor::Checksum(llvm::SmallVectorImpl<uint8_t> &dest,
1222*666cc0b2SZachary Turner                              uint64_t max_data) {
1223*666cc0b2SZachary Turner   if (max_data == 0)
1224*666cc0b2SZachary Turner     max_data = GetByteSize();
1225*666cc0b2SZachary Turner   else
1226*666cc0b2SZachary Turner     max_data = std::min(max_data, GetByteSize());
1227*666cc0b2SZachary Turner 
1228*666cc0b2SZachary Turner   llvm::MD5 md5;
1229*666cc0b2SZachary Turner 
1230*666cc0b2SZachary Turner   const llvm::ArrayRef<uint8_t> data(GetDataStart(), max_data);
1231*666cc0b2SZachary Turner   md5.update(data);
1232*666cc0b2SZachary Turner 
1233*666cc0b2SZachary Turner   llvm::MD5::MD5Result result;
1234*666cc0b2SZachary Turner   md5.final(result);
1235*666cc0b2SZachary Turner 
1236*666cc0b2SZachary Turner   dest.resize(16);
1237*666cc0b2SZachary Turner   std::copy(result, result + 16, dest.begin());
1238*666cc0b2SZachary Turner }
1239