xref: /freebsd-src/contrib/llvm-project/lldb/source/Utility/DataExtractor.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
15ffd83dbSDimitry Andric //===-- DataExtractor.cpp -------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/lldb-defines.h"
120b57cec5SDimitry Andric #include "lldb/lldb-enumerations.h"
130b57cec5SDimitry Andric #include "lldb/lldb-forward.h"
140b57cec5SDimitry Andric #include "lldb/lldb-types.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "lldb/Utility/DataBuffer.h"
170b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
180b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
190b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
200b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
210b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
220b57cec5SDimitry Andric #include "lldb/Utility/UUID.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
250b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
26*06c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h"
275ffd83dbSDimitry Andric #include "llvm/Support/LEB128.h"
280b57cec5SDimitry Andric #include "llvm/Support/MD5.h"
290b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric #include <algorithm>
320b57cec5SDimitry Andric #include <array>
330b57cec5SDimitry Andric #include <cassert>
340b57cec5SDimitry Andric #include <cstdint>
350b57cec5SDimitry Andric #include <string>
360b57cec5SDimitry Andric 
37fe6060f1SDimitry Andric #include <cctype>
38fe6060f1SDimitry Andric #include <cinttypes>
39fe6060f1SDimitry Andric #include <cstring>
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric using namespace lldb;
420b57cec5SDimitry Andric using namespace lldb_private;
430b57cec5SDimitry Andric 
ReadInt16(const unsigned char * ptr,offset_t offset)440b57cec5SDimitry Andric static inline uint16_t ReadInt16(const unsigned char *ptr, offset_t offset) {
450b57cec5SDimitry Andric   uint16_t value;
460b57cec5SDimitry Andric   memcpy(&value, ptr + offset, 2);
470b57cec5SDimitry Andric   return value;
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
ReadInt32(const unsigned char * ptr,offset_t offset=0)500b57cec5SDimitry Andric static inline uint32_t ReadInt32(const unsigned char *ptr,
510b57cec5SDimitry Andric                                  offset_t offset = 0) {
520b57cec5SDimitry Andric   uint32_t value;
530b57cec5SDimitry Andric   memcpy(&value, ptr + offset, 4);
540b57cec5SDimitry Andric   return value;
550b57cec5SDimitry Andric }
560b57cec5SDimitry Andric 
ReadInt64(const unsigned char * ptr,offset_t offset=0)570b57cec5SDimitry Andric static inline uint64_t ReadInt64(const unsigned char *ptr,
580b57cec5SDimitry Andric                                  offset_t offset = 0) {
590b57cec5SDimitry Andric   uint64_t value;
600b57cec5SDimitry Andric   memcpy(&value, ptr + offset, 8);
610b57cec5SDimitry Andric   return value;
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric 
ReadInt16(const void * ptr)640b57cec5SDimitry Andric static inline uint16_t ReadInt16(const void *ptr) {
650b57cec5SDimitry Andric   uint16_t value;
660b57cec5SDimitry Andric   memcpy(&value, ptr, 2);
670b57cec5SDimitry Andric   return value;
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
ReadSwapInt16(const unsigned char * ptr,offset_t offset)700b57cec5SDimitry Andric static inline uint16_t ReadSwapInt16(const unsigned char *ptr,
710b57cec5SDimitry Andric                                      offset_t offset) {
720b57cec5SDimitry Andric   uint16_t value;
730b57cec5SDimitry Andric   memcpy(&value, ptr + offset, 2);
74*06c3fb27SDimitry Andric   return llvm::byteswap<uint16_t>(value);
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
ReadSwapInt32(const unsigned char * ptr,offset_t offset)770b57cec5SDimitry Andric static inline uint32_t ReadSwapInt32(const unsigned char *ptr,
780b57cec5SDimitry Andric                                      offset_t offset) {
790b57cec5SDimitry Andric   uint32_t value;
800b57cec5SDimitry Andric   memcpy(&value, ptr + offset, 4);
81*06c3fb27SDimitry Andric   return llvm::byteswap<uint32_t>(value);
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
ReadSwapInt64(const unsigned char * ptr,offset_t offset)840b57cec5SDimitry Andric static inline uint64_t ReadSwapInt64(const unsigned char *ptr,
850b57cec5SDimitry Andric                                      offset_t offset) {
860b57cec5SDimitry Andric   uint64_t value;
870b57cec5SDimitry Andric   memcpy(&value, ptr + offset, 8);
88*06c3fb27SDimitry Andric   return llvm::byteswap<uint64_t>(value);
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric 
ReadSwapInt16(const void * ptr)910b57cec5SDimitry Andric static inline uint16_t ReadSwapInt16(const void *ptr) {
920b57cec5SDimitry Andric   uint16_t value;
930b57cec5SDimitry Andric   memcpy(&value, ptr, 2);
94*06c3fb27SDimitry Andric   return llvm::byteswap<uint16_t>(value);
950b57cec5SDimitry Andric }
960b57cec5SDimitry Andric 
ReadSwapInt32(const void * ptr)970b57cec5SDimitry Andric static inline uint32_t ReadSwapInt32(const void *ptr) {
980b57cec5SDimitry Andric   uint32_t value;
990b57cec5SDimitry Andric   memcpy(&value, ptr, 4);
100*06c3fb27SDimitry Andric   return llvm::byteswap<uint32_t>(value);
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric 
ReadSwapInt64(const void * ptr)1030b57cec5SDimitry Andric static inline uint64_t ReadSwapInt64(const void *ptr) {
1040b57cec5SDimitry Andric   uint64_t value;
1050b57cec5SDimitry Andric   memcpy(&value, ptr, 8);
106*06c3fb27SDimitry Andric   return llvm::byteswap<uint64_t>(value);
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric 
ReadMaxInt64(const uint8_t * data,size_t byte_size,ByteOrder byte_order)1090b57cec5SDimitry Andric static inline uint64_t ReadMaxInt64(const uint8_t *data, size_t byte_size,
1100b57cec5SDimitry Andric                                     ByteOrder byte_order) {
1110b57cec5SDimitry Andric   uint64_t res = 0;
1120b57cec5SDimitry Andric   if (byte_order == eByteOrderBig)
1130b57cec5SDimitry Andric     for (size_t i = 0; i < byte_size; ++i)
1140b57cec5SDimitry Andric       res = (res << 8) | data[i];
1150b57cec5SDimitry Andric   else {
1160b57cec5SDimitry Andric     assert(byte_order == eByteOrderLittle);
1170b57cec5SDimitry Andric     for (size_t i = 0; i < byte_size; ++i)
1180b57cec5SDimitry Andric       res = (res << 8) | data[byte_size - 1 - i];
1190b57cec5SDimitry Andric   }
1200b57cec5SDimitry Andric   return res;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
DataExtractor()1230b57cec5SDimitry Andric DataExtractor::DataExtractor()
124fe6060f1SDimitry Andric     : m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)),
125fe6060f1SDimitry Andric       m_data_sp() {}
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric // This constructor allows us to use data that is owned by someone else. The
1280b57cec5SDimitry Andric // 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)1290b57cec5SDimitry Andric DataExtractor::DataExtractor(const void *data, offset_t length,
1300b57cec5SDimitry Andric                              ByteOrder endian, uint32_t addr_size,
1310b57cec5SDimitry Andric                              uint32_t target_byte_size /*=1*/)
132480093f4SDimitry Andric     : m_start(const_cast<uint8_t *>(static_cast<const uint8_t *>(data))),
133480093f4SDimitry Andric       m_end(const_cast<uint8_t *>(static_cast<const uint8_t *>(data)) + length),
1340b57cec5SDimitry Andric       m_byte_order(endian), m_addr_size(addr_size), m_data_sp(),
1350b57cec5SDimitry Andric       m_target_byte_size(target_byte_size) {
1365ffd83dbSDimitry Andric   assert(addr_size >= 1 && addr_size <= 8);
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric // Make a shared pointer reference to the shared data in "data_sp" and set the
1400b57cec5SDimitry Andric // endian swapping setting to "swap", and the address size to "addr_size". The
1410b57cec5SDimitry Andric // shared data reference will ensure the data lives as long as any
1420b57cec5SDimitry Andric // 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)1430b57cec5SDimitry Andric DataExtractor::DataExtractor(const DataBufferSP &data_sp, ByteOrder endian,
1440b57cec5SDimitry Andric                              uint32_t addr_size,
1450b57cec5SDimitry Andric                              uint32_t target_byte_size /*=1*/)
14681ad6265SDimitry Andric     : m_byte_order(endian), m_addr_size(addr_size), m_data_sp(),
1470b57cec5SDimitry Andric       m_target_byte_size(target_byte_size) {
1485ffd83dbSDimitry Andric   assert(addr_size >= 1 && addr_size <= 8);
1490b57cec5SDimitry Andric   SetData(data_sp);
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric // Initialize this object with a subset of the data bytes in "data". If "data"
1530b57cec5SDimitry Andric // contains shared data, then a reference to this shared data will added and
1540b57cec5SDimitry Andric // the shared data will stay around as long as any object contains a reference
1550b57cec5SDimitry Andric // to that data. The endian swap and address size settings are copied from
1560b57cec5SDimitry Andric // "data".
DataExtractor(const DataExtractor & data,offset_t offset,offset_t length,uint32_t target_byte_size)1570b57cec5SDimitry Andric DataExtractor::DataExtractor(const DataExtractor &data, offset_t offset,
1580b57cec5SDimitry Andric                              offset_t length, uint32_t target_byte_size /*=1*/)
15981ad6265SDimitry Andric     : m_byte_order(data.m_byte_order), m_addr_size(data.m_addr_size),
16081ad6265SDimitry Andric       m_data_sp(), m_target_byte_size(target_byte_size) {
1615ffd83dbSDimitry Andric   assert(m_addr_size >= 1 && m_addr_size <= 8);
1620b57cec5SDimitry Andric   if (data.ValidOffset(offset)) {
1630b57cec5SDimitry Andric     offset_t bytes_available = data.GetByteSize() - offset;
1640b57cec5SDimitry Andric     if (length > bytes_available)
1650b57cec5SDimitry Andric       length = bytes_available;
1660b57cec5SDimitry Andric     SetData(data, offset, length);
1670b57cec5SDimitry Andric   }
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric 
DataExtractor(const DataExtractor & rhs)1700b57cec5SDimitry Andric DataExtractor::DataExtractor(const DataExtractor &rhs)
1710b57cec5SDimitry Andric     : m_start(rhs.m_start), m_end(rhs.m_end), m_byte_order(rhs.m_byte_order),
1720b57cec5SDimitry Andric       m_addr_size(rhs.m_addr_size), m_data_sp(rhs.m_data_sp),
1730b57cec5SDimitry Andric       m_target_byte_size(rhs.m_target_byte_size) {
1745ffd83dbSDimitry Andric   assert(m_addr_size >= 1 && m_addr_size <= 8);
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric // Assignment operator
operator =(const DataExtractor & rhs)1780b57cec5SDimitry Andric const DataExtractor &DataExtractor::operator=(const DataExtractor &rhs) {
1790b57cec5SDimitry Andric   if (this != &rhs) {
1800b57cec5SDimitry Andric     m_start = rhs.m_start;
1810b57cec5SDimitry Andric     m_end = rhs.m_end;
1820b57cec5SDimitry Andric     m_byte_order = rhs.m_byte_order;
1830b57cec5SDimitry Andric     m_addr_size = rhs.m_addr_size;
1840b57cec5SDimitry Andric     m_data_sp = rhs.m_data_sp;
1850b57cec5SDimitry Andric   }
1860b57cec5SDimitry Andric   return *this;
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric DataExtractor::~DataExtractor() = default;
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric // Clears the object contents back to a default invalid state, and release any
1920b57cec5SDimitry Andric // references to shared data that this object may contain.
Clear()1930b57cec5SDimitry Andric void DataExtractor::Clear() {
1940b57cec5SDimitry Andric   m_start = nullptr;
1950b57cec5SDimitry Andric   m_end = nullptr;
1960b57cec5SDimitry Andric   m_byte_order = endian::InlHostByteOrder();
1970b57cec5SDimitry Andric   m_addr_size = sizeof(void *);
1980b57cec5SDimitry Andric   m_data_sp.reset();
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric // If this object contains shared data, this function returns the offset into
2020b57cec5SDimitry Andric // that shared data. Else zero is returned.
GetSharedDataOffset() const2030b57cec5SDimitry Andric size_t DataExtractor::GetSharedDataOffset() const {
2040b57cec5SDimitry Andric   if (m_start != nullptr) {
2050b57cec5SDimitry Andric     const DataBuffer *data = m_data_sp.get();
2060b57cec5SDimitry Andric     if (data != nullptr) {
2070b57cec5SDimitry Andric       const uint8_t *data_bytes = data->GetBytes();
2080b57cec5SDimitry Andric       if (data_bytes != nullptr) {
2090b57cec5SDimitry Andric         assert(m_start >= data_bytes);
2100b57cec5SDimitry Andric         return m_start - data_bytes;
2110b57cec5SDimitry Andric       }
2120b57cec5SDimitry Andric     }
2130b57cec5SDimitry Andric   }
2140b57cec5SDimitry Andric   return 0;
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric // Set the data with which this object will extract from to data starting at
2180b57cec5SDimitry Andric // BYTES and set the length of the data to LENGTH bytes long. The data is
2190b57cec5SDimitry Andric // externally owned must be around at least as long as this object points to
2200b57cec5SDimitry Andric // the data. No copy of the data is made, this object just refers to this data
2210b57cec5SDimitry Andric // and can extract from it. If this object refers to any shared data upon
2220b57cec5SDimitry Andric // entry, the reference to that data will be released. Is SWAP is set to true,
2230b57cec5SDimitry Andric // any data extracted will be endian swapped.
SetData(const void * bytes,offset_t length,ByteOrder endian)2240b57cec5SDimitry Andric lldb::offset_t DataExtractor::SetData(const void *bytes, offset_t length,
2250b57cec5SDimitry Andric                                       ByteOrder endian) {
2260b57cec5SDimitry Andric   m_byte_order = endian;
2270b57cec5SDimitry Andric   m_data_sp.reset();
2280b57cec5SDimitry Andric   if (bytes == nullptr || length == 0) {
2290b57cec5SDimitry Andric     m_start = nullptr;
2300b57cec5SDimitry Andric     m_end = nullptr;
2310b57cec5SDimitry Andric   } else {
232480093f4SDimitry Andric     m_start = const_cast<uint8_t *>(static_cast<const uint8_t *>(bytes));
2330b57cec5SDimitry Andric     m_end = m_start + length;
2340b57cec5SDimitry Andric   }
2350b57cec5SDimitry Andric   return GetByteSize();
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric // Assign the data for this object to be a subrange in "data" starting
2390b57cec5SDimitry Andric // "data_offset" bytes into "data" and ending "data_length" bytes later. If
2400b57cec5SDimitry Andric // "data_offset" is not a valid offset into "data", then this object will
2410b57cec5SDimitry Andric // contain no bytes. If "data_offset" is within "data" yet "data_length" is too
2420b57cec5SDimitry Andric // large, the length will be capped at the number of bytes remaining in "data".
2430b57cec5SDimitry Andric // If "data" contains a shared pointer to other data, then a ref counted
2440b57cec5SDimitry Andric // pointer to that data will be made in this object. If "data" doesn't contain
2450b57cec5SDimitry Andric // a shared pointer to data, then the bytes referred to in "data" will need to
2460b57cec5SDimitry Andric // exist at least as long as this object refers to those bytes. The address
2470b57cec5SDimitry Andric // 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)2480b57cec5SDimitry Andric lldb::offset_t DataExtractor::SetData(const DataExtractor &data,
2490b57cec5SDimitry Andric                                       offset_t data_offset,
2500b57cec5SDimitry Andric                                       offset_t data_length) {
2510b57cec5SDimitry Andric   m_addr_size = data.m_addr_size;
2525ffd83dbSDimitry Andric   assert(m_addr_size >= 1 && m_addr_size <= 8);
2530b57cec5SDimitry Andric   // If "data" contains shared pointer to data, then we can use that
2540b57cec5SDimitry Andric   if (data.m_data_sp) {
2550b57cec5SDimitry Andric     m_byte_order = data.m_byte_order;
2560b57cec5SDimitry Andric     return SetData(data.m_data_sp, data.GetSharedDataOffset() + data_offset,
2570b57cec5SDimitry Andric                    data_length);
2580b57cec5SDimitry Andric   }
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric   // We have a DataExtractor object that just has a pointer to bytes
2610b57cec5SDimitry Andric   if (data.ValidOffset(data_offset)) {
2620b57cec5SDimitry Andric     if (data_length > data.GetByteSize() - data_offset)
2630b57cec5SDimitry Andric       data_length = data.GetByteSize() - data_offset;
2640b57cec5SDimitry Andric     return SetData(data.GetDataStart() + data_offset, data_length,
2650b57cec5SDimitry Andric                    data.GetByteOrder());
2660b57cec5SDimitry Andric   }
2670b57cec5SDimitry Andric   return 0;
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric // Assign the data for this object to be a subrange of the shared data in
2710b57cec5SDimitry Andric // "data_sp" starting "data_offset" bytes into "data_sp" and ending
2720b57cec5SDimitry Andric // "data_length" bytes later. If "data_offset" is not a valid offset into
2730b57cec5SDimitry Andric // "data_sp", then this object will contain no bytes. If "data_offset" is
2740b57cec5SDimitry Andric // within "data_sp" yet "data_length" is too large, the length will be capped
2750b57cec5SDimitry Andric // at the number of bytes remaining in "data_sp". A ref counted pointer to the
2760b57cec5SDimitry Andric // data in "data_sp" will be made in this object IF the number of bytes this
2770b57cec5SDimitry Andric // object refers to in greater than zero (if at least one byte was available
2780b57cec5SDimitry Andric // starting at "data_offset") to ensure the data stays around as long as it is
2790b57cec5SDimitry Andric // needed. The address size and endian swap settings will remain unchanged from
2800b57cec5SDimitry Andric // their current settings.
SetData(const DataBufferSP & data_sp,offset_t data_offset,offset_t data_length)2810b57cec5SDimitry Andric lldb::offset_t DataExtractor::SetData(const DataBufferSP &data_sp,
2820b57cec5SDimitry Andric                                       offset_t data_offset,
2830b57cec5SDimitry Andric                                       offset_t data_length) {
2840b57cec5SDimitry Andric   m_start = m_end = nullptr;
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   if (data_length > 0) {
2870b57cec5SDimitry Andric     m_data_sp = data_sp;
2880b57cec5SDimitry Andric     if (data_sp) {
2890b57cec5SDimitry Andric       const size_t data_size = data_sp->GetByteSize();
2900b57cec5SDimitry Andric       if (data_offset < data_size) {
2910b57cec5SDimitry Andric         m_start = data_sp->GetBytes() + data_offset;
2920b57cec5SDimitry Andric         const size_t bytes_left = data_size - data_offset;
2930b57cec5SDimitry Andric         // Cap the length of we asked for too many
2940b57cec5SDimitry Andric         if (data_length <= bytes_left)
2950b57cec5SDimitry Andric           m_end = m_start + data_length; // We got all the bytes we wanted
2960b57cec5SDimitry Andric         else
2970b57cec5SDimitry Andric           m_end = m_start + bytes_left; // Not all the bytes requested were
2980b57cec5SDimitry Andric                                         // available in the shared data
2990b57cec5SDimitry Andric       }
3000b57cec5SDimitry Andric     }
3010b57cec5SDimitry Andric   }
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric   size_t new_size = GetByteSize();
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric   // Don't hold a shared pointer to the data buffer if we don't share any valid
3060b57cec5SDimitry Andric   // bytes in the shared buffer.
3070b57cec5SDimitry Andric   if (new_size == 0)
3080b57cec5SDimitry Andric     m_data_sp.reset();
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   return new_size;
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric // Extract a single unsigned char from the binary data and update the offset
3140b57cec5SDimitry Andric // pointed to by "offset_ptr".
3150b57cec5SDimitry Andric //
3160b57cec5SDimitry Andric // RETURNS the byte that was extracted, or zero on failure.
GetU8(offset_t * offset_ptr) const3170b57cec5SDimitry Andric uint8_t DataExtractor::GetU8(offset_t *offset_ptr) const {
3180b57cec5SDimitry Andric   const uint8_t *data = static_cast<const uint8_t *>(GetData(offset_ptr, 1));
3190b57cec5SDimitry Andric   if (data)
3200b57cec5SDimitry Andric     return *data;
3210b57cec5SDimitry Andric   return 0;
3220b57cec5SDimitry Andric }
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric // Extract "count" unsigned chars from the binary data and update the offset
3250b57cec5SDimitry Andric // pointed to by "offset_ptr". The extracted data is copied into "dst".
3260b57cec5SDimitry Andric //
3270b57cec5SDimitry Andric // RETURNS the non-nullptr buffer pointer upon successful extraction of
3280b57cec5SDimitry Andric // all the requested bytes, or nullptr when the data is not available in the
3290b57cec5SDimitry Andric // buffer due to being out of bounds, or insufficient data.
GetU8(offset_t * offset_ptr,void * dst,uint32_t count) const3300b57cec5SDimitry Andric void *DataExtractor::GetU8(offset_t *offset_ptr, void *dst,
3310b57cec5SDimitry Andric                            uint32_t count) const {
3320b57cec5SDimitry Andric   const uint8_t *data =
3330b57cec5SDimitry Andric       static_cast<const uint8_t *>(GetData(offset_ptr, count));
3340b57cec5SDimitry Andric   if (data) {
3350b57cec5SDimitry Andric     // Copy the data into the buffer
3360b57cec5SDimitry Andric     memcpy(dst, data, count);
3370b57cec5SDimitry Andric     // Return a non-nullptr pointer to the converted data as an indicator of
3380b57cec5SDimitry Andric     // success
3390b57cec5SDimitry Andric     return dst;
3400b57cec5SDimitry Andric   }
3410b57cec5SDimitry Andric   return nullptr;
3420b57cec5SDimitry Andric }
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric // Extract a single uint16_t from the data and update the offset pointed to by
3450b57cec5SDimitry Andric // "offset_ptr".
3460b57cec5SDimitry Andric //
3470b57cec5SDimitry Andric // RETURNS the uint16_t that was extracted, or zero on failure.
GetU16(offset_t * offset_ptr) const3480b57cec5SDimitry Andric uint16_t DataExtractor::GetU16(offset_t *offset_ptr) const {
3490b57cec5SDimitry Andric   uint16_t val = 0;
3500b57cec5SDimitry Andric   const uint8_t *data =
3510b57cec5SDimitry Andric       static_cast<const uint8_t *>(GetData(offset_ptr, sizeof(val)));
3520b57cec5SDimitry Andric   if (data) {
3530b57cec5SDimitry Andric     if (m_byte_order != endian::InlHostByteOrder())
3540b57cec5SDimitry Andric       val = ReadSwapInt16(data);
3550b57cec5SDimitry Andric     else
3560b57cec5SDimitry Andric       val = ReadInt16(data);
3570b57cec5SDimitry Andric   }
3580b57cec5SDimitry Andric   return val;
3590b57cec5SDimitry Andric }
3600b57cec5SDimitry Andric 
GetU16_unchecked(offset_t * offset_ptr) const3610b57cec5SDimitry Andric uint16_t DataExtractor::GetU16_unchecked(offset_t *offset_ptr) const {
3620b57cec5SDimitry Andric   uint16_t val;
3630b57cec5SDimitry Andric   if (m_byte_order == endian::InlHostByteOrder())
3640b57cec5SDimitry Andric     val = ReadInt16(m_start, *offset_ptr);
3650b57cec5SDimitry Andric   else
3660b57cec5SDimitry Andric     val = ReadSwapInt16(m_start, *offset_ptr);
3670b57cec5SDimitry Andric   *offset_ptr += sizeof(val);
3680b57cec5SDimitry Andric   return val;
3690b57cec5SDimitry Andric }
3700b57cec5SDimitry Andric 
GetU32_unchecked(offset_t * offset_ptr) const3710b57cec5SDimitry Andric uint32_t DataExtractor::GetU32_unchecked(offset_t *offset_ptr) const {
3720b57cec5SDimitry Andric   uint32_t val;
3730b57cec5SDimitry Andric   if (m_byte_order == endian::InlHostByteOrder())
3740b57cec5SDimitry Andric     val = ReadInt32(m_start, *offset_ptr);
3750b57cec5SDimitry Andric   else
3760b57cec5SDimitry Andric     val = ReadSwapInt32(m_start, *offset_ptr);
3770b57cec5SDimitry Andric   *offset_ptr += sizeof(val);
3780b57cec5SDimitry Andric   return val;
3790b57cec5SDimitry Andric }
3800b57cec5SDimitry Andric 
GetU64_unchecked(offset_t * offset_ptr) const3810b57cec5SDimitry Andric uint64_t DataExtractor::GetU64_unchecked(offset_t *offset_ptr) const {
3820b57cec5SDimitry Andric   uint64_t val;
3830b57cec5SDimitry Andric   if (m_byte_order == endian::InlHostByteOrder())
3840b57cec5SDimitry Andric     val = ReadInt64(m_start, *offset_ptr);
3850b57cec5SDimitry Andric   else
3860b57cec5SDimitry Andric     val = ReadSwapInt64(m_start, *offset_ptr);
3870b57cec5SDimitry Andric   *offset_ptr += sizeof(val);
3880b57cec5SDimitry Andric   return val;
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric // Extract "count" uint16_t values from the binary data and update the offset
3920b57cec5SDimitry Andric // pointed to by "offset_ptr". The extracted data is copied into "dst".
3930b57cec5SDimitry Andric //
3940b57cec5SDimitry Andric // RETURNS the non-nullptr buffer pointer upon successful extraction of
3950b57cec5SDimitry Andric // all the requested bytes, or nullptr when the data is not available in the
3960b57cec5SDimitry Andric // buffer due to being out of bounds, or insufficient data.
GetU16(offset_t * offset_ptr,void * void_dst,uint32_t count) const3970b57cec5SDimitry Andric void *DataExtractor::GetU16(offset_t *offset_ptr, void *void_dst,
3980b57cec5SDimitry Andric                             uint32_t count) const {
3990b57cec5SDimitry Andric   const size_t src_size = sizeof(uint16_t) * count;
4000b57cec5SDimitry Andric   const uint16_t *src =
4010b57cec5SDimitry Andric       static_cast<const uint16_t *>(GetData(offset_ptr, src_size));
4020b57cec5SDimitry Andric   if (src) {
4030b57cec5SDimitry Andric     if (m_byte_order != endian::InlHostByteOrder()) {
4040b57cec5SDimitry Andric       uint16_t *dst_pos = static_cast<uint16_t *>(void_dst);
4050b57cec5SDimitry Andric       uint16_t *dst_end = dst_pos + count;
4060b57cec5SDimitry Andric       const uint16_t *src_pos = src;
4070b57cec5SDimitry Andric       while (dst_pos < dst_end) {
4080b57cec5SDimitry Andric         *dst_pos = ReadSwapInt16(src_pos);
4090b57cec5SDimitry Andric         ++dst_pos;
4100b57cec5SDimitry Andric         ++src_pos;
4110b57cec5SDimitry Andric       }
4120b57cec5SDimitry Andric     } else {
4130b57cec5SDimitry Andric       memcpy(void_dst, src, src_size);
4140b57cec5SDimitry Andric     }
4150b57cec5SDimitry Andric     // Return a non-nullptr pointer to the converted data as an indicator of
4160b57cec5SDimitry Andric     // success
4170b57cec5SDimitry Andric     return void_dst;
4180b57cec5SDimitry Andric   }
4190b57cec5SDimitry Andric   return nullptr;
4200b57cec5SDimitry Andric }
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric // Extract a single uint32_t from the data and update the offset pointed to by
4230b57cec5SDimitry Andric // "offset_ptr".
4240b57cec5SDimitry Andric //
4250b57cec5SDimitry Andric // RETURNS the uint32_t that was extracted, or zero on failure.
GetU32(offset_t * offset_ptr) const4260b57cec5SDimitry Andric uint32_t DataExtractor::GetU32(offset_t *offset_ptr) const {
4270b57cec5SDimitry Andric   uint32_t val = 0;
4280b57cec5SDimitry Andric   const uint8_t *data =
4290b57cec5SDimitry Andric       static_cast<const uint8_t *>(GetData(offset_ptr, sizeof(val)));
4300b57cec5SDimitry Andric   if (data) {
4310b57cec5SDimitry Andric     if (m_byte_order != endian::InlHostByteOrder()) {
4320b57cec5SDimitry Andric       val = ReadSwapInt32(data);
4330b57cec5SDimitry Andric     } else {
4340b57cec5SDimitry Andric       memcpy(&val, data, 4);
4350b57cec5SDimitry Andric     }
4360b57cec5SDimitry Andric   }
4370b57cec5SDimitry Andric   return val;
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric // Extract "count" uint32_t values from the binary data and update the offset
4410b57cec5SDimitry Andric // pointed to by "offset_ptr". The extracted data is copied into "dst".
4420b57cec5SDimitry Andric //
4430b57cec5SDimitry Andric // RETURNS the non-nullptr buffer pointer upon successful extraction of
4440b57cec5SDimitry Andric // all the requested bytes, or nullptr when the data is not available in the
4450b57cec5SDimitry Andric // buffer due to being out of bounds, or insufficient data.
GetU32(offset_t * offset_ptr,void * void_dst,uint32_t count) const4460b57cec5SDimitry Andric void *DataExtractor::GetU32(offset_t *offset_ptr, void *void_dst,
4470b57cec5SDimitry Andric                             uint32_t count) const {
4480b57cec5SDimitry Andric   const size_t src_size = sizeof(uint32_t) * count;
4490b57cec5SDimitry Andric   const uint32_t *src =
4500b57cec5SDimitry Andric       static_cast<const uint32_t *>(GetData(offset_ptr, src_size));
4510b57cec5SDimitry Andric   if (src) {
4520b57cec5SDimitry Andric     if (m_byte_order != endian::InlHostByteOrder()) {
4530b57cec5SDimitry Andric       uint32_t *dst_pos = static_cast<uint32_t *>(void_dst);
4540b57cec5SDimitry Andric       uint32_t *dst_end = dst_pos + count;
4550b57cec5SDimitry Andric       const uint32_t *src_pos = src;
4560b57cec5SDimitry Andric       while (dst_pos < dst_end) {
4570b57cec5SDimitry Andric         *dst_pos = ReadSwapInt32(src_pos);
4580b57cec5SDimitry Andric         ++dst_pos;
4590b57cec5SDimitry Andric         ++src_pos;
4600b57cec5SDimitry Andric       }
4610b57cec5SDimitry Andric     } else {
4620b57cec5SDimitry Andric       memcpy(void_dst, src, src_size);
4630b57cec5SDimitry Andric     }
4640b57cec5SDimitry Andric     // Return a non-nullptr pointer to the converted data as an indicator of
4650b57cec5SDimitry Andric     // success
4660b57cec5SDimitry Andric     return void_dst;
4670b57cec5SDimitry Andric   }
4680b57cec5SDimitry Andric   return nullptr;
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric // Extract a single uint64_t from the data and update the offset pointed to by
4720b57cec5SDimitry Andric // "offset_ptr".
4730b57cec5SDimitry Andric //
4740b57cec5SDimitry Andric // RETURNS the uint64_t that was extracted, or zero on failure.
GetU64(offset_t * offset_ptr) const4750b57cec5SDimitry Andric uint64_t DataExtractor::GetU64(offset_t *offset_ptr) const {
4760b57cec5SDimitry Andric   uint64_t val = 0;
4770b57cec5SDimitry Andric   const uint8_t *data =
4780b57cec5SDimitry Andric       static_cast<const uint8_t *>(GetData(offset_ptr, sizeof(val)));
4790b57cec5SDimitry Andric   if (data) {
4800b57cec5SDimitry Andric     if (m_byte_order != endian::InlHostByteOrder()) {
4810b57cec5SDimitry Andric       val = ReadSwapInt64(data);
4820b57cec5SDimitry Andric     } else {
4830b57cec5SDimitry Andric       memcpy(&val, data, 8);
4840b57cec5SDimitry Andric     }
4850b57cec5SDimitry Andric   }
4860b57cec5SDimitry Andric   return val;
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric // GetU64
4900b57cec5SDimitry Andric //
4910b57cec5SDimitry Andric // Get multiple consecutive 64 bit values. Return true if the entire read
4920b57cec5SDimitry Andric // succeeds and increment the offset pointed to by offset_ptr, else return
4930b57cec5SDimitry Andric // false and leave the offset pointed to by offset_ptr unchanged.
GetU64(offset_t * offset_ptr,void * void_dst,uint32_t count) const4940b57cec5SDimitry Andric void *DataExtractor::GetU64(offset_t *offset_ptr, void *void_dst,
4950b57cec5SDimitry Andric                             uint32_t count) const {
4960b57cec5SDimitry Andric   const size_t src_size = sizeof(uint64_t) * count;
4970b57cec5SDimitry Andric   const uint64_t *src =
4980b57cec5SDimitry Andric       static_cast<const uint64_t *>(GetData(offset_ptr, src_size));
4990b57cec5SDimitry Andric   if (src) {
5000b57cec5SDimitry Andric     if (m_byte_order != endian::InlHostByteOrder()) {
5010b57cec5SDimitry Andric       uint64_t *dst_pos = static_cast<uint64_t *>(void_dst);
5020b57cec5SDimitry Andric       uint64_t *dst_end = dst_pos + count;
5030b57cec5SDimitry Andric       const uint64_t *src_pos = src;
5040b57cec5SDimitry Andric       while (dst_pos < dst_end) {
5050b57cec5SDimitry Andric         *dst_pos = ReadSwapInt64(src_pos);
5060b57cec5SDimitry Andric         ++dst_pos;
5070b57cec5SDimitry Andric         ++src_pos;
5080b57cec5SDimitry Andric       }
5090b57cec5SDimitry Andric     } else {
5100b57cec5SDimitry Andric       memcpy(void_dst, src, src_size);
5110b57cec5SDimitry Andric     }
5120b57cec5SDimitry Andric     // Return a non-nullptr pointer to the converted data as an indicator of
5130b57cec5SDimitry Andric     // success
5140b57cec5SDimitry Andric     return void_dst;
5150b57cec5SDimitry Andric   }
5160b57cec5SDimitry Andric   return nullptr;
5170b57cec5SDimitry Andric }
5180b57cec5SDimitry Andric 
GetMaxU32(offset_t * offset_ptr,size_t byte_size) const5190b57cec5SDimitry Andric uint32_t DataExtractor::GetMaxU32(offset_t *offset_ptr,
5200b57cec5SDimitry Andric                                   size_t byte_size) const {
5210b57cec5SDimitry Andric   lldbassert(byte_size > 0 && byte_size <= 4 && "GetMaxU32 invalid byte_size!");
5220b57cec5SDimitry Andric   return GetMaxU64(offset_ptr, byte_size);
5230b57cec5SDimitry Andric }
5240b57cec5SDimitry Andric 
GetMaxU64(offset_t * offset_ptr,size_t byte_size) const5250b57cec5SDimitry Andric uint64_t DataExtractor::GetMaxU64(offset_t *offset_ptr,
5260b57cec5SDimitry Andric                                   size_t byte_size) const {
5270b57cec5SDimitry Andric   lldbassert(byte_size > 0 && byte_size <= 8 && "GetMaxU64 invalid byte_size!");
5280b57cec5SDimitry Andric   switch (byte_size) {
5290b57cec5SDimitry Andric   case 1:
5300b57cec5SDimitry Andric     return GetU8(offset_ptr);
5310b57cec5SDimitry Andric   case 2:
5320b57cec5SDimitry Andric     return GetU16(offset_ptr);
5330b57cec5SDimitry Andric   case 4:
5340b57cec5SDimitry Andric     return GetU32(offset_ptr);
5350b57cec5SDimitry Andric   case 8:
5360b57cec5SDimitry Andric     return GetU64(offset_ptr);
5370b57cec5SDimitry Andric   default: {
5380b57cec5SDimitry Andric     // General case.
5390b57cec5SDimitry Andric     const uint8_t *data =
5400b57cec5SDimitry Andric         static_cast<const uint8_t *>(GetData(offset_ptr, byte_size));
5410b57cec5SDimitry Andric     if (data == nullptr)
5420b57cec5SDimitry Andric       return 0;
5430b57cec5SDimitry Andric     return ReadMaxInt64(data, byte_size, m_byte_order);
5440b57cec5SDimitry Andric   }
5450b57cec5SDimitry Andric   }
5460b57cec5SDimitry Andric   return 0;
5470b57cec5SDimitry Andric }
5480b57cec5SDimitry Andric 
GetMaxU64_unchecked(offset_t * offset_ptr,size_t byte_size) const5490b57cec5SDimitry Andric uint64_t DataExtractor::GetMaxU64_unchecked(offset_t *offset_ptr,
5500b57cec5SDimitry Andric                                             size_t byte_size) const {
5510b57cec5SDimitry Andric   switch (byte_size) {
5520b57cec5SDimitry Andric   case 1:
5530b57cec5SDimitry Andric     return GetU8_unchecked(offset_ptr);
5540b57cec5SDimitry Andric   case 2:
5550b57cec5SDimitry Andric     return GetU16_unchecked(offset_ptr);
5560b57cec5SDimitry Andric   case 4:
5570b57cec5SDimitry Andric     return GetU32_unchecked(offset_ptr);
5580b57cec5SDimitry Andric   case 8:
5590b57cec5SDimitry Andric     return GetU64_unchecked(offset_ptr);
5600b57cec5SDimitry Andric   default: {
5610b57cec5SDimitry Andric     uint64_t res = ReadMaxInt64(&m_start[*offset_ptr], byte_size, m_byte_order);
5620b57cec5SDimitry Andric     *offset_ptr += byte_size;
5630b57cec5SDimitry Andric     return res;
5640b57cec5SDimitry Andric   }
5650b57cec5SDimitry Andric   }
5660b57cec5SDimitry Andric   return 0;
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric 
GetMaxS64(offset_t * offset_ptr,size_t byte_size) const5690b57cec5SDimitry Andric int64_t DataExtractor::GetMaxS64(offset_t *offset_ptr, size_t byte_size) const {
5700b57cec5SDimitry Andric   uint64_t u64 = GetMaxU64(offset_ptr, byte_size);
5710b57cec5SDimitry Andric   return llvm::SignExtend64(u64, 8 * byte_size);
5720b57cec5SDimitry Andric }
5730b57cec5SDimitry Andric 
GetMaxU64Bitfield(offset_t * offset_ptr,size_t size,uint32_t bitfield_bit_size,uint32_t bitfield_bit_offset) const5740b57cec5SDimitry Andric uint64_t DataExtractor::GetMaxU64Bitfield(offset_t *offset_ptr, size_t size,
5750b57cec5SDimitry Andric                                           uint32_t bitfield_bit_size,
5760b57cec5SDimitry Andric                                           uint32_t bitfield_bit_offset) const {
577480093f4SDimitry Andric   assert(bitfield_bit_size <= 64);
5780b57cec5SDimitry Andric   uint64_t uval64 = GetMaxU64(offset_ptr, size);
579480093f4SDimitry Andric 
580480093f4SDimitry Andric   if (bitfield_bit_size == 0)
581480093f4SDimitry Andric     return uval64;
582480093f4SDimitry Andric 
5830b57cec5SDimitry Andric   int32_t lsbcount = bitfield_bit_offset;
5840b57cec5SDimitry Andric   if (m_byte_order == eByteOrderBig)
5850b57cec5SDimitry Andric     lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size;
586480093f4SDimitry Andric 
5870b57cec5SDimitry Andric   if (lsbcount > 0)
5880b57cec5SDimitry Andric     uval64 >>= lsbcount;
589480093f4SDimitry Andric 
590480093f4SDimitry Andric   uint64_t bitfield_mask =
591480093f4SDimitry Andric       (bitfield_bit_size == 64
592480093f4SDimitry Andric            ? std::numeric_limits<uint64_t>::max()
593480093f4SDimitry Andric            : ((static_cast<uint64_t>(1) << bitfield_bit_size) - 1));
5940b57cec5SDimitry Andric   if (!bitfield_mask && bitfield_bit_offset == 0 && bitfield_bit_size == 64)
5950b57cec5SDimitry Andric     return uval64;
596480093f4SDimitry Andric 
5970b57cec5SDimitry Andric   uval64 &= bitfield_mask;
598480093f4SDimitry Andric 
5990b57cec5SDimitry Andric   return uval64;
6000b57cec5SDimitry Andric }
6010b57cec5SDimitry Andric 
GetMaxS64Bitfield(offset_t * offset_ptr,size_t size,uint32_t bitfield_bit_size,uint32_t bitfield_bit_offset) const6020b57cec5SDimitry Andric int64_t DataExtractor::GetMaxS64Bitfield(offset_t *offset_ptr, size_t size,
6030b57cec5SDimitry Andric                                          uint32_t bitfield_bit_size,
6040b57cec5SDimitry Andric                                          uint32_t bitfield_bit_offset) const {
6055ffd83dbSDimitry Andric   assert(size >= 1 && "GetMaxS64Bitfield size must be >= 1");
6065ffd83dbSDimitry Andric   assert(size <= 8 && "GetMaxS64Bitfield size must be <= 8");
6070b57cec5SDimitry Andric   int64_t sval64 = GetMaxS64(offset_ptr, size);
6085ffd83dbSDimitry Andric   if (bitfield_bit_size == 0)
6095ffd83dbSDimitry Andric     return sval64;
6100b57cec5SDimitry Andric   int32_t lsbcount = bitfield_bit_offset;
6110b57cec5SDimitry Andric   if (m_byte_order == eByteOrderBig)
6120b57cec5SDimitry Andric     lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size;
6130b57cec5SDimitry Andric   if (lsbcount > 0)
6140b57cec5SDimitry Andric     sval64 >>= lsbcount;
6155ffd83dbSDimitry Andric   uint64_t bitfield_mask = llvm::maskTrailingOnes<uint64_t>(bitfield_bit_size);
6160b57cec5SDimitry Andric   sval64 &= bitfield_mask;
6170b57cec5SDimitry Andric   // sign extend if needed
6180b57cec5SDimitry Andric   if (sval64 & ((static_cast<uint64_t>(1)) << (bitfield_bit_size - 1)))
6190b57cec5SDimitry Andric     sval64 |= ~bitfield_mask;
6200b57cec5SDimitry Andric   return sval64;
6210b57cec5SDimitry Andric }
6220b57cec5SDimitry Andric 
GetFloat(offset_t * offset_ptr) const6230b57cec5SDimitry Andric float DataExtractor::GetFloat(offset_t *offset_ptr) const {
6245ffd83dbSDimitry Andric   return Get<float>(offset_ptr, 0.0f);
6250b57cec5SDimitry Andric }
6260b57cec5SDimitry Andric 
GetDouble(offset_t * offset_ptr) const6270b57cec5SDimitry Andric double DataExtractor::GetDouble(offset_t *offset_ptr) const {
6285ffd83dbSDimitry Andric   return Get<double>(offset_ptr, 0.0);
6290b57cec5SDimitry Andric }
6300b57cec5SDimitry Andric 
GetLongDouble(offset_t * offset_ptr) const6310b57cec5SDimitry Andric long double DataExtractor::GetLongDouble(offset_t *offset_ptr) const {
6320b57cec5SDimitry Andric   long double val = 0.0;
6330b57cec5SDimitry Andric #if defined(__i386__) || defined(__amd64__) || defined(__x86_64__) ||          \
6340b57cec5SDimitry Andric     defined(_M_IX86) || defined(_M_IA64) || defined(_M_X64)
6350b57cec5SDimitry Andric   *offset_ptr += CopyByteOrderedData(*offset_ptr, 10, &val, sizeof(val),
6360b57cec5SDimitry Andric                                      endian::InlHostByteOrder());
6370b57cec5SDimitry Andric #else
6380b57cec5SDimitry Andric   *offset_ptr += CopyByteOrderedData(*offset_ptr, sizeof(val), &val,
6390b57cec5SDimitry Andric                                      sizeof(val), endian::InlHostByteOrder());
6400b57cec5SDimitry Andric #endif
6410b57cec5SDimitry Andric   return val;
6420b57cec5SDimitry Andric }
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric // Extract a single address from the data and update the offset pointed to by
6450b57cec5SDimitry Andric // "offset_ptr". The size of the extracted address comes from the
6460b57cec5SDimitry Andric // "this->m_addr_size" member variable and should be set correctly prior to
6470b57cec5SDimitry Andric // extracting any address values.
6480b57cec5SDimitry Andric //
6490b57cec5SDimitry Andric // RETURNS the address that was extracted, or zero on failure.
GetAddress(offset_t * offset_ptr) const6500b57cec5SDimitry Andric uint64_t DataExtractor::GetAddress(offset_t *offset_ptr) const {
6515ffd83dbSDimitry Andric   assert(m_addr_size >= 1 && m_addr_size <= 8);
6520b57cec5SDimitry Andric   return GetMaxU64(offset_ptr, m_addr_size);
6530b57cec5SDimitry Andric }
6540b57cec5SDimitry Andric 
GetAddress_unchecked(offset_t * offset_ptr) const6550b57cec5SDimitry Andric uint64_t DataExtractor::GetAddress_unchecked(offset_t *offset_ptr) const {
6565ffd83dbSDimitry Andric   assert(m_addr_size >= 1 && m_addr_size <= 8);
6570b57cec5SDimitry Andric   return GetMaxU64_unchecked(offset_ptr, m_addr_size);
6580b57cec5SDimitry Andric }
6590b57cec5SDimitry Andric 
ExtractBytes(offset_t offset,offset_t length,ByteOrder dst_byte_order,void * dst) const6600b57cec5SDimitry Andric size_t DataExtractor::ExtractBytes(offset_t offset, offset_t length,
6610b57cec5SDimitry Andric                                    ByteOrder dst_byte_order, void *dst) const {
6620b57cec5SDimitry Andric   const uint8_t *src = PeekData(offset, length);
6630b57cec5SDimitry Andric   if (src) {
6640b57cec5SDimitry Andric     if (dst_byte_order != GetByteOrder()) {
6650b57cec5SDimitry Andric       // Validate that only a word- or register-sized dst is byte swapped
6660b57cec5SDimitry Andric       assert(length == 1 || length == 2 || length == 4 || length == 8 ||
6670b57cec5SDimitry Andric              length == 10 || length == 16 || length == 32);
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric       for (uint32_t i = 0; i < length; ++i)
6700b57cec5SDimitry Andric         (static_cast<uint8_t *>(dst))[i] = src[length - i - 1];
6710b57cec5SDimitry Andric     } else
6720b57cec5SDimitry Andric       ::memcpy(dst, src, length);
6730b57cec5SDimitry Andric     return length;
6740b57cec5SDimitry Andric   }
6750b57cec5SDimitry Andric   return 0;
6760b57cec5SDimitry Andric }
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric // Extract data as it exists in target memory
CopyData(offset_t offset,offset_t length,void * dst) const6790b57cec5SDimitry Andric lldb::offset_t DataExtractor::CopyData(offset_t offset, offset_t length,
6800b57cec5SDimitry Andric                                        void *dst) const {
6810b57cec5SDimitry Andric   const uint8_t *src = PeekData(offset, length);
6820b57cec5SDimitry Andric   if (src) {
6830b57cec5SDimitry Andric     ::memcpy(dst, src, length);
6840b57cec5SDimitry Andric     return length;
6850b57cec5SDimitry Andric   }
6860b57cec5SDimitry Andric   return 0;
6870b57cec5SDimitry Andric }
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric // Extract data and swap if needed when doing the copy
6900b57cec5SDimitry Andric lldb::offset_t
CopyByteOrderedData(offset_t src_offset,offset_t src_len,void * dst_void_ptr,offset_t dst_len,ByteOrder dst_byte_order) const6910b57cec5SDimitry Andric DataExtractor::CopyByteOrderedData(offset_t src_offset, offset_t src_len,
6920b57cec5SDimitry Andric                                    void *dst_void_ptr, offset_t dst_len,
6930b57cec5SDimitry Andric                                    ByteOrder dst_byte_order) const {
6940b57cec5SDimitry Andric   // Validate the source info
6950b57cec5SDimitry Andric   if (!ValidOffsetForDataOfSize(src_offset, src_len))
6960b57cec5SDimitry Andric     assert(ValidOffsetForDataOfSize(src_offset, src_len));
6970b57cec5SDimitry Andric   assert(src_len > 0);
6980b57cec5SDimitry Andric   assert(m_byte_order == eByteOrderBig || m_byte_order == eByteOrderLittle);
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric   // Validate the destination info
7010b57cec5SDimitry Andric   assert(dst_void_ptr != nullptr);
7020b57cec5SDimitry Andric   assert(dst_len > 0);
7030b57cec5SDimitry Andric   assert(dst_byte_order == eByteOrderBig || dst_byte_order == eByteOrderLittle);
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric   // Validate that only a word- or register-sized dst is byte swapped
7060b57cec5SDimitry Andric   assert(dst_byte_order == m_byte_order || dst_len == 1 || dst_len == 2 ||
7070b57cec5SDimitry Andric          dst_len == 4 || dst_len == 8 || dst_len == 10 || dst_len == 16 ||
7080b57cec5SDimitry Andric          dst_len == 32);
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric   // Must have valid byte orders set in this object and for destination
7110b57cec5SDimitry Andric   if (!(dst_byte_order == eByteOrderBig ||
7120b57cec5SDimitry Andric         dst_byte_order == eByteOrderLittle) ||
7130b57cec5SDimitry Andric       !(m_byte_order == eByteOrderBig || m_byte_order == eByteOrderLittle))
7140b57cec5SDimitry Andric     return 0;
7150b57cec5SDimitry Andric 
7160b57cec5SDimitry Andric   uint8_t *dst = static_cast<uint8_t *>(dst_void_ptr);
7170b57cec5SDimitry Andric   const uint8_t *src = PeekData(src_offset, src_len);
7180b57cec5SDimitry Andric   if (src) {
7190b57cec5SDimitry Andric     if (dst_len >= src_len) {
7200b57cec5SDimitry Andric       // We are copying the entire value from src into dst. Calculate how many,
7210b57cec5SDimitry Andric       // if any, zeroes we need for the most significant bytes if "dst_len" is
7220b57cec5SDimitry Andric       // greater than "src_len"...
7230b57cec5SDimitry Andric       const size_t num_zeroes = dst_len - src_len;
7240b57cec5SDimitry Andric       if (dst_byte_order == eByteOrderBig) {
7250b57cec5SDimitry Andric         // Big endian, so we lead with zeroes...
7260b57cec5SDimitry Andric         if (num_zeroes > 0)
7270b57cec5SDimitry Andric           ::memset(dst, 0, num_zeroes);
7280b57cec5SDimitry Andric         // Then either copy or swap the rest
7290b57cec5SDimitry Andric         if (m_byte_order == eByteOrderBig) {
7300b57cec5SDimitry Andric           ::memcpy(dst + num_zeroes, src, src_len);
7310b57cec5SDimitry Andric         } else {
7320b57cec5SDimitry Andric           for (uint32_t i = 0; i < src_len; ++i)
7330b57cec5SDimitry Andric             dst[i + num_zeroes] = src[src_len - 1 - i];
7340b57cec5SDimitry Andric         }
7350b57cec5SDimitry Andric       } else {
7360b57cec5SDimitry Andric         // Little endian destination, so we lead the value bytes
7370b57cec5SDimitry Andric         if (m_byte_order == eByteOrderBig) {
7380b57cec5SDimitry Andric           for (uint32_t i = 0; i < src_len; ++i)
7390b57cec5SDimitry Andric             dst[i] = src[src_len - 1 - i];
7400b57cec5SDimitry Andric         } else {
7410b57cec5SDimitry Andric           ::memcpy(dst, src, src_len);
7420b57cec5SDimitry Andric         }
7430b57cec5SDimitry Andric         // And zero the rest...
7440b57cec5SDimitry Andric         if (num_zeroes > 0)
7450b57cec5SDimitry Andric           ::memset(dst + src_len, 0, num_zeroes);
7460b57cec5SDimitry Andric       }
7470b57cec5SDimitry Andric       return src_len;
7480b57cec5SDimitry Andric     } else {
7490b57cec5SDimitry Andric       // We are only copying some of the value from src into dst..
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric       if (dst_byte_order == eByteOrderBig) {
7520b57cec5SDimitry Andric         // Big endian dst
7530b57cec5SDimitry Andric         if (m_byte_order == eByteOrderBig) {
7540b57cec5SDimitry Andric           // Big endian dst, with big endian src
7550b57cec5SDimitry Andric           ::memcpy(dst, src + (src_len - dst_len), dst_len);
7560b57cec5SDimitry Andric         } else {
7570b57cec5SDimitry Andric           // Big endian dst, with little endian src
7580b57cec5SDimitry Andric           for (uint32_t i = 0; i < dst_len; ++i)
7590b57cec5SDimitry Andric             dst[i] = src[dst_len - 1 - i];
7600b57cec5SDimitry Andric         }
7610b57cec5SDimitry Andric       } else {
7620b57cec5SDimitry Andric         // Little endian dst
7630b57cec5SDimitry Andric         if (m_byte_order == eByteOrderBig) {
7640b57cec5SDimitry Andric           // Little endian dst, with big endian src
7650b57cec5SDimitry Andric           for (uint32_t i = 0; i < dst_len; ++i)
7660b57cec5SDimitry Andric             dst[i] = src[src_len - 1 - i];
7670b57cec5SDimitry Andric         } else {
7680b57cec5SDimitry Andric           // Little endian dst, with big endian src
7690b57cec5SDimitry Andric           ::memcpy(dst, src, dst_len);
7700b57cec5SDimitry Andric         }
7710b57cec5SDimitry Andric       }
7720b57cec5SDimitry Andric       return dst_len;
7730b57cec5SDimitry Andric     }
7740b57cec5SDimitry Andric   }
7750b57cec5SDimitry Andric   return 0;
7760b57cec5SDimitry Andric }
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric // Extracts a variable length NULL terminated C string from the data at the
7790b57cec5SDimitry Andric // offset pointed to by "offset_ptr".  The "offset_ptr" will be updated with
7800b57cec5SDimitry Andric // the offset of the byte that follows the NULL terminator byte.
7810b57cec5SDimitry Andric //
7820b57cec5SDimitry Andric // If the offset pointed to by "offset_ptr" is out of bounds, or if "length" is
7830b57cec5SDimitry Andric // non-zero and there aren't enough available bytes, nullptr will be returned
7840b57cec5SDimitry Andric // and "offset_ptr" will not be updated.
GetCStr(offset_t * offset_ptr) const7850b57cec5SDimitry Andric const char *DataExtractor::GetCStr(offset_t *offset_ptr) const {
7869dba64beSDimitry Andric   const char *start = reinterpret_cast<const char *>(PeekData(*offset_ptr, 1));
7879dba64beSDimitry Andric   // Already at the end of the data.
7889dba64beSDimitry Andric   if (!start)
7890b57cec5SDimitry Andric     return nullptr;
7909dba64beSDimitry Andric 
7919dba64beSDimitry Andric   const char *end = reinterpret_cast<const char *>(m_end);
7929dba64beSDimitry Andric 
7939dba64beSDimitry Andric   // Check all bytes for a null terminator that terminates a C string.
7949dba64beSDimitry Andric   const char *terminator_or_end = std::find(start, end, '\0');
7959dba64beSDimitry Andric 
7969dba64beSDimitry Andric   // We didn't find a null terminator, so return nullptr to indicate that there
7979dba64beSDimitry Andric   // is no valid C string at that offset.
7989dba64beSDimitry Andric   if (terminator_or_end == end)
7999dba64beSDimitry Andric     return nullptr;
8009dba64beSDimitry Andric 
8019dba64beSDimitry Andric   // Update offset_ptr for the caller to point to the data behind the
8029dba64beSDimitry Andric   // terminator (which is 1 byte long).
8039dba64beSDimitry Andric   *offset_ptr += (terminator_or_end - start + 1UL);
8049dba64beSDimitry Andric   return start;
8050b57cec5SDimitry Andric }
8060b57cec5SDimitry Andric 
8070b57cec5SDimitry Andric // Extracts a NULL terminated C string from the fixed length field of length
8080b57cec5SDimitry Andric // "len" at the offset pointed to by "offset_ptr". The "offset_ptr" will be
8090b57cec5SDimitry Andric // updated with the offset of the byte that follows the fixed length field.
8100b57cec5SDimitry Andric //
8110b57cec5SDimitry Andric // If the offset pointed to by "offset_ptr" is out of bounds, or if the offset
8120b57cec5SDimitry Andric // plus the length of the field is out of bounds, or if the field does not
8130b57cec5SDimitry Andric // contain a NULL terminator byte, nullptr will be returned and "offset_ptr"
8140b57cec5SDimitry Andric // will not be updated.
GetCStr(offset_t * offset_ptr,offset_t len) const8150b57cec5SDimitry Andric const char *DataExtractor::GetCStr(offset_t *offset_ptr, offset_t len) const {
8160b57cec5SDimitry Andric   const char *cstr = reinterpret_cast<const char *>(PeekData(*offset_ptr, len));
8170b57cec5SDimitry Andric   if (cstr != nullptr) {
8180b57cec5SDimitry Andric     if (memchr(cstr, '\0', len) == nullptr) {
8190b57cec5SDimitry Andric       return nullptr;
8200b57cec5SDimitry Andric     }
8210b57cec5SDimitry Andric     *offset_ptr += len;
8220b57cec5SDimitry Andric     return cstr;
8230b57cec5SDimitry Andric   }
8240b57cec5SDimitry Andric   return nullptr;
8250b57cec5SDimitry Andric }
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric // Peeks at a string in the contained data. No verification is done to make
8280b57cec5SDimitry Andric // sure the entire string lies within the bounds of this object's data, only
8290b57cec5SDimitry Andric // "offset" is verified to be a valid offset.
8300b57cec5SDimitry Andric //
8310b57cec5SDimitry Andric // Returns a valid C string pointer if "offset" is a valid offset in this
8320b57cec5SDimitry Andric // object's data, else nullptr is returned.
PeekCStr(offset_t offset) const8330b57cec5SDimitry Andric const char *DataExtractor::PeekCStr(offset_t offset) const {
8340b57cec5SDimitry Andric   return reinterpret_cast<const char *>(PeekData(offset, 1));
8350b57cec5SDimitry Andric }
8360b57cec5SDimitry Andric 
8370b57cec5SDimitry Andric // Extracts an unsigned LEB128 number from this object's data starting at the
8380b57cec5SDimitry Andric // offset pointed to by "offset_ptr". The offset pointed to by "offset_ptr"
8390b57cec5SDimitry Andric // will be updated with the offset of the byte following the last extracted
8400b57cec5SDimitry Andric // byte.
8410b57cec5SDimitry Andric //
8420b57cec5SDimitry Andric // Returned the extracted integer value.
GetULEB128(offset_t * offset_ptr) const8430b57cec5SDimitry Andric uint64_t DataExtractor::GetULEB128(offset_t *offset_ptr) const {
8440b57cec5SDimitry Andric   const uint8_t *src = PeekData(*offset_ptr, 1);
8450b57cec5SDimitry Andric   if (src == nullptr)
8460b57cec5SDimitry Andric     return 0;
8470b57cec5SDimitry Andric 
8485ffd83dbSDimitry Andric   unsigned byte_count = 0;
8495ffd83dbSDimitry Andric   uint64_t result = llvm::decodeULEB128(src, &byte_count, m_end);
8505ffd83dbSDimitry Andric   *offset_ptr += byte_count;
8510b57cec5SDimitry Andric   return result;
8520b57cec5SDimitry Andric }
8530b57cec5SDimitry Andric 
8540b57cec5SDimitry Andric // Extracts an signed LEB128 number from this object's data starting at the
8550b57cec5SDimitry Andric // offset pointed to by "offset_ptr". The offset pointed to by "offset_ptr"
8560b57cec5SDimitry Andric // will be updated with the offset of the byte following the last extracted
8570b57cec5SDimitry Andric // byte.
8580b57cec5SDimitry Andric //
8590b57cec5SDimitry Andric // Returned the extracted integer value.
GetSLEB128(offset_t * offset_ptr) const8600b57cec5SDimitry Andric int64_t DataExtractor::GetSLEB128(offset_t *offset_ptr) const {
8610b57cec5SDimitry Andric   const uint8_t *src = PeekData(*offset_ptr, 1);
8620b57cec5SDimitry Andric   if (src == nullptr)
8630b57cec5SDimitry Andric     return 0;
8640b57cec5SDimitry Andric 
8655ffd83dbSDimitry Andric   unsigned byte_count = 0;
8665ffd83dbSDimitry Andric   int64_t result = llvm::decodeSLEB128(src, &byte_count, m_end);
8675ffd83dbSDimitry Andric   *offset_ptr += byte_count;
8680b57cec5SDimitry Andric   return result;
8690b57cec5SDimitry Andric }
8700b57cec5SDimitry Andric 
8710b57cec5SDimitry Andric // Skips a ULEB128 number (signed or unsigned) from this object's data starting
8720b57cec5SDimitry Andric // at the offset pointed to by "offset_ptr". The offset pointed to by
8730b57cec5SDimitry Andric // "offset_ptr" will be updated with the offset of the byte following the last
8740b57cec5SDimitry Andric // extracted byte.
8750b57cec5SDimitry Andric //
8760b57cec5SDimitry Andric // Returns the number of bytes consumed during the extraction.
Skip_LEB128(offset_t * offset_ptr) const8770b57cec5SDimitry Andric uint32_t DataExtractor::Skip_LEB128(offset_t *offset_ptr) const {
8780b57cec5SDimitry Andric   uint32_t bytes_consumed = 0;
8790b57cec5SDimitry Andric   const uint8_t *src = PeekData(*offset_ptr, 1);
8800b57cec5SDimitry Andric   if (src == nullptr)
8810b57cec5SDimitry Andric     return 0;
8820b57cec5SDimitry Andric 
8830b57cec5SDimitry Andric   const uint8_t *end = m_end;
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric   if (src < end) {
8860b57cec5SDimitry Andric     const uint8_t *src_pos = src;
8870b57cec5SDimitry Andric     while ((src_pos < end) && (*src_pos++ & 0x80))
8880b57cec5SDimitry Andric       ++bytes_consumed;
8890b57cec5SDimitry Andric     *offset_ptr += src_pos - src;
8900b57cec5SDimitry Andric   }
8910b57cec5SDimitry Andric   return bytes_consumed;
8920b57cec5SDimitry Andric }
8930b57cec5SDimitry Andric 
8940b57cec5SDimitry Andric // Dumps bytes from this object's data to the stream "s" starting
8950b57cec5SDimitry Andric // "start_offset" bytes into this data, and ending with the byte before
8960b57cec5SDimitry Andric // "end_offset". "base_addr" will be added to the offset into the dumped data
8970b57cec5SDimitry Andric // when showing the offset into the data in the output information.
8980b57cec5SDimitry Andric // "num_per_line" objects of type "type" will be dumped with the option to
8990b57cec5SDimitry Andric // override the format for each object with "type_format". "type_format" is a
9000b57cec5SDimitry Andric // printf style formatting string. If "type_format" is nullptr, then an
9010b57cec5SDimitry Andric // appropriate format string will be used for the supplied "type". If the
9020b57cec5SDimitry Andric // 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) const9030b57cec5SDimitry Andric lldb::offset_t DataExtractor::PutToLog(Log *log, offset_t start_offset,
9040b57cec5SDimitry Andric                                        offset_t length, uint64_t base_addr,
9050b57cec5SDimitry Andric                                        uint32_t num_per_line,
906480093f4SDimitry Andric                                        DataExtractor::Type type) const {
9070b57cec5SDimitry Andric   if (log == nullptr)
9080b57cec5SDimitry Andric     return start_offset;
9090b57cec5SDimitry Andric 
9100b57cec5SDimitry Andric   offset_t offset;
9110b57cec5SDimitry Andric   offset_t end_offset;
9120b57cec5SDimitry Andric   uint32_t count;
9130b57cec5SDimitry Andric   StreamString sstr;
9140b57cec5SDimitry Andric   for (offset = start_offset, end_offset = offset + length, count = 0;
9150b57cec5SDimitry Andric        ValidOffset(offset) && offset < end_offset; ++count) {
9160b57cec5SDimitry Andric     if ((count % num_per_line) == 0) {
9170b57cec5SDimitry Andric       // Print out any previous string
9180b57cec5SDimitry Andric       if (sstr.GetSize() > 0) {
9190b57cec5SDimitry Andric         log->PutString(sstr.GetString());
9200b57cec5SDimitry Andric         sstr.Clear();
9210b57cec5SDimitry Andric       }
9220b57cec5SDimitry Andric       // Reset string offset and fill the current line string with address:
9230b57cec5SDimitry Andric       if (base_addr != LLDB_INVALID_ADDRESS)
9240b57cec5SDimitry Andric         sstr.Printf("0x%8.8" PRIx64 ":",
9250b57cec5SDimitry Andric                     static_cast<uint64_t>(base_addr + (offset - start_offset)));
9260b57cec5SDimitry Andric     }
9270b57cec5SDimitry Andric 
9280b57cec5SDimitry Andric     switch (type) {
9290b57cec5SDimitry Andric     case TypeUInt8:
930480093f4SDimitry Andric       sstr.Printf(" %2.2x", GetU8(&offset));
9310b57cec5SDimitry Andric       break;
9320b57cec5SDimitry Andric     case TypeChar: {
9330b57cec5SDimitry Andric       char ch = GetU8(&offset);
9345ffd83dbSDimitry Andric       sstr.Printf(" %c", llvm::isPrint(ch) ? ch : ' ');
9350b57cec5SDimitry Andric     } break;
9360b57cec5SDimitry Andric     case TypeUInt16:
937480093f4SDimitry Andric       sstr.Printf(" %4.4x", GetU16(&offset));
9380b57cec5SDimitry Andric       break;
9390b57cec5SDimitry Andric     case TypeUInt32:
940480093f4SDimitry Andric       sstr.Printf(" %8.8x", GetU32(&offset));
9410b57cec5SDimitry Andric       break;
9420b57cec5SDimitry Andric     case TypeUInt64:
943480093f4SDimitry Andric       sstr.Printf(" %16.16" PRIx64, GetU64(&offset));
9440b57cec5SDimitry Andric       break;
9450b57cec5SDimitry Andric     case TypePointer:
946480093f4SDimitry Andric       sstr.Printf(" 0x%" PRIx64, GetAddress(&offset));
9470b57cec5SDimitry Andric       break;
9480b57cec5SDimitry Andric     case TypeULEB128:
949480093f4SDimitry Andric       sstr.Printf(" 0x%" PRIx64, GetULEB128(&offset));
9500b57cec5SDimitry Andric       break;
9510b57cec5SDimitry Andric     case TypeSLEB128:
952480093f4SDimitry Andric       sstr.Printf(" %" PRId64, GetSLEB128(&offset));
9530b57cec5SDimitry Andric       break;
9540b57cec5SDimitry Andric     }
9550b57cec5SDimitry Andric   }
9560b57cec5SDimitry Andric 
9570b57cec5SDimitry Andric   if (!sstr.Empty())
9580b57cec5SDimitry Andric     log->PutString(sstr.GetString());
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric   return offset; // Return the offset at which we ended up
9610b57cec5SDimitry Andric }
9620b57cec5SDimitry Andric 
Copy(DataExtractor & dest_data) const9630b57cec5SDimitry Andric size_t DataExtractor::Copy(DataExtractor &dest_data) const {
9640b57cec5SDimitry Andric   if (m_data_sp) {
9650b57cec5SDimitry Andric     // we can pass along the SP to the data
9660b57cec5SDimitry Andric     dest_data.SetData(m_data_sp);
9670b57cec5SDimitry Andric   } else {
9680b57cec5SDimitry Andric     const uint8_t *base_ptr = m_start;
9690b57cec5SDimitry Andric     size_t data_size = GetByteSize();
9700b57cec5SDimitry Andric     dest_data.SetData(DataBufferSP(new DataBufferHeap(base_ptr, data_size)));
9710b57cec5SDimitry Andric   }
9720b57cec5SDimitry Andric   return GetByteSize();
9730b57cec5SDimitry Andric }
9740b57cec5SDimitry Andric 
Append(DataExtractor & rhs)9750b57cec5SDimitry Andric bool DataExtractor::Append(DataExtractor &rhs) {
9760b57cec5SDimitry Andric   if (rhs.GetByteOrder() != GetByteOrder())
9770b57cec5SDimitry Andric     return false;
9780b57cec5SDimitry Andric 
9790b57cec5SDimitry Andric   if (rhs.GetByteSize() == 0)
9800b57cec5SDimitry Andric     return true;
9810b57cec5SDimitry Andric 
9820b57cec5SDimitry Andric   if (GetByteSize() == 0)
9830b57cec5SDimitry Andric     return (rhs.Copy(*this) > 0);
9840b57cec5SDimitry Andric 
9850b57cec5SDimitry Andric   size_t bytes = GetByteSize() + rhs.GetByteSize();
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric   DataBufferHeap *buffer_heap_ptr = nullptr;
9880b57cec5SDimitry Andric   DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0));
9890b57cec5SDimitry Andric 
9900b57cec5SDimitry Andric   if (!buffer_sp || buffer_heap_ptr == nullptr)
9910b57cec5SDimitry Andric     return false;
9920b57cec5SDimitry Andric 
9930b57cec5SDimitry Andric   uint8_t *bytes_ptr = buffer_heap_ptr->GetBytes();
9940b57cec5SDimitry Andric 
9950b57cec5SDimitry Andric   memcpy(bytes_ptr, GetDataStart(), GetByteSize());
9960b57cec5SDimitry Andric   memcpy(bytes_ptr + GetByteSize(), rhs.GetDataStart(), rhs.GetByteSize());
9970b57cec5SDimitry Andric 
9980b57cec5SDimitry Andric   SetData(buffer_sp);
9990b57cec5SDimitry Andric 
10000b57cec5SDimitry Andric   return true;
10010b57cec5SDimitry Andric }
10020b57cec5SDimitry Andric 
Append(void * buf,offset_t length)10030b57cec5SDimitry Andric bool DataExtractor::Append(void *buf, offset_t length) {
10040b57cec5SDimitry Andric   if (buf == nullptr)
10050b57cec5SDimitry Andric     return false;
10060b57cec5SDimitry Andric 
10070b57cec5SDimitry Andric   if (length == 0)
10080b57cec5SDimitry Andric     return true;
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric   size_t bytes = GetByteSize() + length;
10110b57cec5SDimitry Andric 
10120b57cec5SDimitry Andric   DataBufferHeap *buffer_heap_ptr = nullptr;
10130b57cec5SDimitry Andric   DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0));
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric   if (!buffer_sp || buffer_heap_ptr == nullptr)
10160b57cec5SDimitry Andric     return false;
10170b57cec5SDimitry Andric 
10180b57cec5SDimitry Andric   uint8_t *bytes_ptr = buffer_heap_ptr->GetBytes();
10190b57cec5SDimitry Andric 
10200b57cec5SDimitry Andric   if (GetByteSize() > 0)
10210b57cec5SDimitry Andric     memcpy(bytes_ptr, GetDataStart(), GetByteSize());
10220b57cec5SDimitry Andric 
10230b57cec5SDimitry Andric   memcpy(bytes_ptr + GetByteSize(), buf, length);
10240b57cec5SDimitry Andric 
10250b57cec5SDimitry Andric   SetData(buffer_sp);
10260b57cec5SDimitry Andric 
10270b57cec5SDimitry Andric   return true;
10280b57cec5SDimitry Andric }
10290b57cec5SDimitry Andric 
Checksum(llvm::SmallVectorImpl<uint8_t> & dest,uint64_t max_data)10300b57cec5SDimitry Andric void DataExtractor::Checksum(llvm::SmallVectorImpl<uint8_t> &dest,
10310b57cec5SDimitry Andric                              uint64_t max_data) {
10320b57cec5SDimitry Andric   if (max_data == 0)
10330b57cec5SDimitry Andric     max_data = GetByteSize();
10340b57cec5SDimitry Andric   else
10350b57cec5SDimitry Andric     max_data = std::min(max_data, GetByteSize());
10360b57cec5SDimitry Andric 
10370b57cec5SDimitry Andric   llvm::MD5 md5;
10380b57cec5SDimitry Andric 
10390b57cec5SDimitry Andric   const llvm::ArrayRef<uint8_t> data(GetDataStart(), max_data);
10400b57cec5SDimitry Andric   md5.update(data);
10410b57cec5SDimitry Andric 
10420b57cec5SDimitry Andric   llvm::MD5::MD5Result result;
10430b57cec5SDimitry Andric   md5.final(result);
10440b57cec5SDimitry Andric 
10450b57cec5SDimitry Andric   dest.clear();
104681ad6265SDimitry Andric   dest.append(result.begin(), result.end());
10470b57cec5SDimitry Andric }
1048