180814287SRaphael Isemann //===-- DataExtractor.cpp -------------------------------------------------===// 2666cc0b2SZachary Turner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6666cc0b2SZachary Turner // 7666cc0b2SZachary Turner //===----------------------------------------------------------------------===// 8666cc0b2SZachary Turner 94479ac15SZachary Turner #include "lldb/Utility/DataExtractor.h" 10666cc0b2SZachary Turner 11672d2c12SJonas Devlieghere #include "lldb/lldb-defines.h" 12672d2c12SJonas Devlieghere #include "lldb/lldb-enumerations.h" 13672d2c12SJonas Devlieghere #include "lldb/lldb-forward.h" 14672d2c12SJonas Devlieghere #include "lldb/lldb-types.h" 154479ac15SZachary Turner 16666cc0b2SZachary Turner #include "lldb/Utility/DataBuffer.h" 17666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h" 18666cc0b2SZachary Turner #include "lldb/Utility/Endian.h" 19dbd7c338SPetr Pavlu #include "lldb/Utility/LLDBAssert.h" 20666cc0b2SZachary Turner #include "lldb/Utility/Log.h" 21666cc0b2SZachary Turner #include "lldb/Utility/Stream.h" 22666cc0b2SZachary Turner #include "lldb/Utility/StreamString.h" 23666cc0b2SZachary Turner #include "lldb/Utility/UUID.h" 24666cc0b2SZachary Turner 25666cc0b2SZachary Turner #include "llvm/ADT/ArrayRef.h" 26666cc0b2SZachary Turner #include "llvm/ADT/SmallVector.h" 27666cc0b2SZachary Turner #include "llvm/Support/MD5.h" 28666cc0b2SZachary Turner #include "llvm/Support/MathExtras.h" 29666cc0b2SZachary Turner 30672d2c12SJonas Devlieghere #include <algorithm> 31672d2c12SJonas Devlieghere #include <array> 324479ac15SZachary Turner #include <cassert> 33672d2c12SJonas Devlieghere #include <cstdint> 344479ac15SZachary Turner #include <string> 354479ac15SZachary Turner 36672d2c12SJonas Devlieghere #include <ctype.h> 37672d2c12SJonas Devlieghere #include <inttypes.h> 38672d2c12SJonas Devlieghere #include <string.h> 394479ac15SZachary Turner 40666cc0b2SZachary Turner using namespace lldb; 41666cc0b2SZachary Turner using namespace lldb_private; 42666cc0b2SZachary Turner 43666cc0b2SZachary Turner static inline uint16_t ReadInt16(const unsigned char *ptr, offset_t offset) { 44666cc0b2SZachary Turner uint16_t value; 45666cc0b2SZachary Turner memcpy(&value, ptr + offset, 2); 46666cc0b2SZachary Turner return value; 47666cc0b2SZachary Turner } 48666cc0b2SZachary Turner 49666cc0b2SZachary Turner static inline uint32_t ReadInt32(const unsigned char *ptr, 50666cc0b2SZachary Turner offset_t offset = 0) { 51666cc0b2SZachary Turner uint32_t value; 52666cc0b2SZachary Turner memcpy(&value, ptr + offset, 4); 53666cc0b2SZachary Turner return value; 54666cc0b2SZachary Turner } 55666cc0b2SZachary Turner 56666cc0b2SZachary Turner static inline uint64_t ReadInt64(const unsigned char *ptr, 57666cc0b2SZachary Turner offset_t offset = 0) { 58666cc0b2SZachary Turner uint64_t value; 59666cc0b2SZachary Turner memcpy(&value, ptr + offset, 8); 60666cc0b2SZachary Turner return value; 61666cc0b2SZachary Turner } 62666cc0b2SZachary Turner 63666cc0b2SZachary Turner static inline uint16_t ReadInt16(const void *ptr) { 64666cc0b2SZachary Turner uint16_t value; 65666cc0b2SZachary Turner memcpy(&value, ptr, 2); 66666cc0b2SZachary Turner return value; 67666cc0b2SZachary Turner } 68666cc0b2SZachary Turner 69666cc0b2SZachary Turner static inline uint16_t ReadSwapInt16(const unsigned char *ptr, 70666cc0b2SZachary Turner offset_t offset) { 71666cc0b2SZachary Turner uint16_t value; 72666cc0b2SZachary Turner memcpy(&value, ptr + offset, 2); 73666cc0b2SZachary Turner return llvm::ByteSwap_16(value); 74666cc0b2SZachary Turner } 75666cc0b2SZachary Turner 76666cc0b2SZachary Turner static inline uint32_t ReadSwapInt32(const unsigned char *ptr, 77666cc0b2SZachary Turner offset_t offset) { 78666cc0b2SZachary Turner uint32_t value; 79666cc0b2SZachary Turner memcpy(&value, ptr + offset, 4); 80666cc0b2SZachary Turner return llvm::ByteSwap_32(value); 81666cc0b2SZachary Turner } 82666cc0b2SZachary Turner 83666cc0b2SZachary Turner static inline uint64_t ReadSwapInt64(const unsigned char *ptr, 84666cc0b2SZachary Turner offset_t offset) { 85666cc0b2SZachary Turner uint64_t value; 86666cc0b2SZachary Turner memcpy(&value, ptr + offset, 8); 87666cc0b2SZachary Turner return llvm::ByteSwap_64(value); 88666cc0b2SZachary Turner } 89666cc0b2SZachary Turner 90666cc0b2SZachary Turner static inline uint16_t ReadSwapInt16(const void *ptr) { 91666cc0b2SZachary Turner uint16_t value; 92666cc0b2SZachary Turner memcpy(&value, ptr, 2); 93666cc0b2SZachary Turner return llvm::ByteSwap_16(value); 94666cc0b2SZachary Turner } 95666cc0b2SZachary Turner 96666cc0b2SZachary Turner static inline uint32_t ReadSwapInt32(const void *ptr) { 97666cc0b2SZachary Turner uint32_t value; 98666cc0b2SZachary Turner memcpy(&value, ptr, 4); 99666cc0b2SZachary Turner return llvm::ByteSwap_32(value); 100666cc0b2SZachary Turner } 101666cc0b2SZachary Turner 102666cc0b2SZachary Turner static inline uint64_t ReadSwapInt64(const void *ptr) { 103666cc0b2SZachary Turner uint64_t value; 104666cc0b2SZachary Turner memcpy(&value, ptr, 8); 105666cc0b2SZachary Turner return llvm::ByteSwap_64(value); 106666cc0b2SZachary Turner } 107666cc0b2SZachary Turner 108dbd7c338SPetr Pavlu static inline uint64_t ReadMaxInt64(const uint8_t *data, size_t byte_size, 109dbd7c338SPetr Pavlu ByteOrder byte_order) { 110dbd7c338SPetr Pavlu uint64_t res = 0; 111dbd7c338SPetr Pavlu if (byte_order == eByteOrderBig) 112dbd7c338SPetr Pavlu for (size_t i = 0; i < byte_size; ++i) 113dbd7c338SPetr Pavlu res = (res << 8) | data[i]; 114dbd7c338SPetr Pavlu else { 115dbd7c338SPetr Pavlu assert(byte_order == eByteOrderLittle); 116dbd7c338SPetr Pavlu for (size_t i = 0; i < byte_size; ++i) 117dbd7c338SPetr Pavlu res = (res << 8) | data[byte_size - 1 - i]; 118dbd7c338SPetr Pavlu } 119dbd7c338SPetr Pavlu return res; 120dbd7c338SPetr Pavlu } 121dbd7c338SPetr Pavlu 122666cc0b2SZachary Turner DataExtractor::DataExtractor() 123666cc0b2SZachary Turner : m_start(nullptr), m_end(nullptr), 124666cc0b2SZachary Turner m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)), 125666cc0b2SZachary Turner m_data_sp(), m_target_byte_size(1) {} 126666cc0b2SZachary Turner 12705097246SAdrian Prantl // This constructor allows us to use data that is owned by someone else. The 12805097246SAdrian Prantl // data must stay around as long as this object is valid. 129666cc0b2SZachary Turner DataExtractor::DataExtractor(const void *data, offset_t length, 130666cc0b2SZachary Turner ByteOrder endian, uint32_t addr_size, 131666cc0b2SZachary Turner uint32_t target_byte_size /*=1*/) 13265fdb342SRaphael Isemann : m_start(const_cast<uint8_t *>(static_cast<const uint8_t *>(data))), 13365fdb342SRaphael Isemann m_end(const_cast<uint8_t *>(static_cast<const uint8_t *>(data)) + length), 134666cc0b2SZachary Turner m_byte_order(endian), m_addr_size(addr_size), m_data_sp(), 135666cc0b2SZachary Turner m_target_byte_size(target_byte_size) { 136666cc0b2SZachary Turner assert(addr_size == 4 || addr_size == 8); 137666cc0b2SZachary Turner } 138666cc0b2SZachary Turner 13905097246SAdrian Prantl // Make a shared pointer reference to the shared data in "data_sp" and set the 14005097246SAdrian Prantl // endian swapping setting to "swap", and the address size to "addr_size". The 14105097246SAdrian Prantl // shared data reference will ensure the data lives as long as any 14205097246SAdrian Prantl // DataExtractor objects exist that have a reference to this data. 143666cc0b2SZachary Turner DataExtractor::DataExtractor(const DataBufferSP &data_sp, ByteOrder endian, 144666cc0b2SZachary Turner uint32_t addr_size, 145666cc0b2SZachary Turner uint32_t target_byte_size /*=1*/) 146666cc0b2SZachary Turner : m_start(nullptr), m_end(nullptr), m_byte_order(endian), 147666cc0b2SZachary Turner m_addr_size(addr_size), m_data_sp(), 148666cc0b2SZachary Turner m_target_byte_size(target_byte_size) { 149666cc0b2SZachary Turner assert(addr_size == 4 || addr_size == 8); 150666cc0b2SZachary Turner SetData(data_sp); 151666cc0b2SZachary Turner } 152666cc0b2SZachary Turner 15305097246SAdrian Prantl // Initialize this object with a subset of the data bytes in "data". If "data" 15405097246SAdrian Prantl // contains shared data, then a reference to this shared data will added and 15505097246SAdrian Prantl // the shared data will stay around as long as any object contains a reference 15605097246SAdrian Prantl // to that data. The endian swap and address size settings are copied from 15705097246SAdrian Prantl // "data". 158666cc0b2SZachary Turner DataExtractor::DataExtractor(const DataExtractor &data, offset_t offset, 159666cc0b2SZachary Turner offset_t length, uint32_t target_byte_size /*=1*/) 160666cc0b2SZachary Turner : m_start(nullptr), m_end(nullptr), m_byte_order(data.m_byte_order), 161666cc0b2SZachary Turner m_addr_size(data.m_addr_size), m_data_sp(), 162666cc0b2SZachary Turner m_target_byte_size(target_byte_size) { 163666cc0b2SZachary Turner assert(m_addr_size == 4 || m_addr_size == 8); 164666cc0b2SZachary Turner if (data.ValidOffset(offset)) { 165666cc0b2SZachary Turner offset_t bytes_available = data.GetByteSize() - offset; 166666cc0b2SZachary Turner if (length > bytes_available) 167666cc0b2SZachary Turner length = bytes_available; 168666cc0b2SZachary Turner SetData(data, offset, length); 169666cc0b2SZachary Turner } 170666cc0b2SZachary Turner } 171666cc0b2SZachary Turner 172666cc0b2SZachary Turner DataExtractor::DataExtractor(const DataExtractor &rhs) 173666cc0b2SZachary Turner : m_start(rhs.m_start), m_end(rhs.m_end), m_byte_order(rhs.m_byte_order), 174666cc0b2SZachary Turner m_addr_size(rhs.m_addr_size), m_data_sp(rhs.m_data_sp), 175666cc0b2SZachary Turner m_target_byte_size(rhs.m_target_byte_size) { 176666cc0b2SZachary Turner assert(m_addr_size == 4 || m_addr_size == 8); 177666cc0b2SZachary Turner } 178666cc0b2SZachary Turner 179666cc0b2SZachary Turner // Assignment operator 180666cc0b2SZachary Turner const DataExtractor &DataExtractor::operator=(const DataExtractor &rhs) { 181666cc0b2SZachary Turner if (this != &rhs) { 182666cc0b2SZachary Turner m_start = rhs.m_start; 183666cc0b2SZachary Turner m_end = rhs.m_end; 184666cc0b2SZachary Turner m_byte_order = rhs.m_byte_order; 185666cc0b2SZachary Turner m_addr_size = rhs.m_addr_size; 186666cc0b2SZachary Turner m_data_sp = rhs.m_data_sp; 187666cc0b2SZachary Turner } 188666cc0b2SZachary Turner return *this; 189666cc0b2SZachary Turner } 190666cc0b2SZachary Turner 191666cc0b2SZachary Turner DataExtractor::~DataExtractor() = default; 192666cc0b2SZachary Turner 19305097246SAdrian Prantl // Clears the object contents back to a default invalid state, and release any 19405097246SAdrian Prantl // references to shared data that this object may contain. 195666cc0b2SZachary Turner void DataExtractor::Clear() { 196666cc0b2SZachary Turner m_start = nullptr; 197666cc0b2SZachary Turner m_end = nullptr; 198666cc0b2SZachary Turner m_byte_order = endian::InlHostByteOrder(); 199666cc0b2SZachary Turner m_addr_size = sizeof(void *); 200666cc0b2SZachary Turner m_data_sp.reset(); 201666cc0b2SZachary Turner } 202666cc0b2SZachary Turner 20305097246SAdrian Prantl // If this object contains shared data, this function returns the offset into 20405097246SAdrian Prantl // that shared data. Else zero is returned. 205666cc0b2SZachary Turner size_t DataExtractor::GetSharedDataOffset() const { 206666cc0b2SZachary Turner if (m_start != nullptr) { 207666cc0b2SZachary Turner const DataBuffer *data = m_data_sp.get(); 208666cc0b2SZachary Turner if (data != nullptr) { 209666cc0b2SZachary Turner const uint8_t *data_bytes = data->GetBytes(); 210666cc0b2SZachary Turner if (data_bytes != nullptr) { 211666cc0b2SZachary Turner assert(m_start >= data_bytes); 212666cc0b2SZachary Turner return m_start - data_bytes; 213666cc0b2SZachary Turner } 214666cc0b2SZachary Turner } 215666cc0b2SZachary Turner } 216666cc0b2SZachary Turner return 0; 217666cc0b2SZachary Turner } 218666cc0b2SZachary Turner 21905097246SAdrian Prantl // Set the data with which this object will extract from to data starting at 22005097246SAdrian Prantl // BYTES and set the length of the data to LENGTH bytes long. The data is 22105097246SAdrian Prantl // externally owned must be around at least as long as this object points to 22205097246SAdrian Prantl // the data. No copy of the data is made, this object just refers to this data 22305097246SAdrian Prantl // and can extract from it. If this object refers to any shared data upon 22405097246SAdrian Prantl // entry, the reference to that data will be released. Is SWAP is set to true, 225666cc0b2SZachary Turner // any data extracted will be endian swapped. 226666cc0b2SZachary Turner lldb::offset_t DataExtractor::SetData(const void *bytes, offset_t length, 227666cc0b2SZachary Turner ByteOrder endian) { 228666cc0b2SZachary Turner m_byte_order = endian; 229666cc0b2SZachary Turner m_data_sp.reset(); 230666cc0b2SZachary Turner if (bytes == nullptr || length == 0) { 231666cc0b2SZachary Turner m_start = nullptr; 232666cc0b2SZachary Turner m_end = nullptr; 233666cc0b2SZachary Turner } else { 23465fdb342SRaphael Isemann m_start = const_cast<uint8_t *>(static_cast<const uint8_t *>(bytes)); 235666cc0b2SZachary Turner m_end = m_start + length; 236666cc0b2SZachary Turner } 237666cc0b2SZachary Turner return GetByteSize(); 238666cc0b2SZachary Turner } 239666cc0b2SZachary Turner 24005097246SAdrian Prantl // Assign the data for this object to be a subrange in "data" starting 24105097246SAdrian Prantl // "data_offset" bytes into "data" and ending "data_length" bytes later. If 24205097246SAdrian Prantl // "data_offset" is not a valid offset into "data", then this object will 24305097246SAdrian Prantl // contain no bytes. If "data_offset" is within "data" yet "data_length" is too 24405097246SAdrian Prantl // large, the length will be capped at the number of bytes remaining in "data". 24505097246SAdrian Prantl // If "data" contains a shared pointer to other data, then a ref counted 24605097246SAdrian Prantl // pointer to that data will be made in this object. If "data" doesn't contain 24705097246SAdrian Prantl // a shared pointer to data, then the bytes referred to in "data" will need to 24805097246SAdrian Prantl // exist at least as long as this object refers to those bytes. The address 24905097246SAdrian Prantl // size and endian swap settings are copied from the current values in "data". 250666cc0b2SZachary Turner lldb::offset_t DataExtractor::SetData(const DataExtractor &data, 251666cc0b2SZachary Turner offset_t data_offset, 252666cc0b2SZachary Turner offset_t data_length) { 253666cc0b2SZachary Turner m_addr_size = data.m_addr_size; 254666cc0b2SZachary Turner assert(m_addr_size == 4 || m_addr_size == 8); 255666cc0b2SZachary Turner // If "data" contains shared pointer to data, then we can use that 256666cc0b2SZachary Turner if (data.m_data_sp) { 257666cc0b2SZachary Turner m_byte_order = data.m_byte_order; 258666cc0b2SZachary Turner return SetData(data.m_data_sp, data.GetSharedDataOffset() + data_offset, 259666cc0b2SZachary Turner data_length); 260666cc0b2SZachary Turner } 261666cc0b2SZachary Turner 262666cc0b2SZachary Turner // We have a DataExtractor object that just has a pointer to bytes 263666cc0b2SZachary Turner if (data.ValidOffset(data_offset)) { 264666cc0b2SZachary Turner if (data_length > data.GetByteSize() - data_offset) 265666cc0b2SZachary Turner data_length = data.GetByteSize() - data_offset; 266666cc0b2SZachary Turner return SetData(data.GetDataStart() + data_offset, data_length, 267666cc0b2SZachary Turner data.GetByteOrder()); 268666cc0b2SZachary Turner } 269666cc0b2SZachary Turner return 0; 270666cc0b2SZachary Turner } 271666cc0b2SZachary Turner 27205097246SAdrian Prantl // Assign the data for this object to be a subrange of the shared data in 27305097246SAdrian Prantl // "data_sp" starting "data_offset" bytes into "data_sp" and ending 27405097246SAdrian Prantl // "data_length" bytes later. If "data_offset" is not a valid offset into 27505097246SAdrian Prantl // "data_sp", then this object will contain no bytes. If "data_offset" is 27605097246SAdrian Prantl // within "data_sp" yet "data_length" is too large, the length will be capped 27705097246SAdrian Prantl // at the number of bytes remaining in "data_sp". A ref counted pointer to the 27805097246SAdrian Prantl // data in "data_sp" will be made in this object IF the number of bytes this 27905097246SAdrian Prantl // object refers to in greater than zero (if at least one byte was available 28005097246SAdrian Prantl // starting at "data_offset") to ensure the data stays around as long as it is 28105097246SAdrian Prantl // needed. The address size and endian swap settings will remain unchanged from 28205097246SAdrian Prantl // their current settings. 283666cc0b2SZachary Turner lldb::offset_t DataExtractor::SetData(const DataBufferSP &data_sp, 284666cc0b2SZachary Turner offset_t data_offset, 285666cc0b2SZachary Turner offset_t data_length) { 286666cc0b2SZachary Turner m_start = m_end = nullptr; 287666cc0b2SZachary Turner 288666cc0b2SZachary Turner if (data_length > 0) { 289666cc0b2SZachary Turner m_data_sp = data_sp; 290666cc0b2SZachary Turner if (data_sp) { 291666cc0b2SZachary Turner const size_t data_size = data_sp->GetByteSize(); 292666cc0b2SZachary Turner if (data_offset < data_size) { 293666cc0b2SZachary Turner m_start = data_sp->GetBytes() + data_offset; 294666cc0b2SZachary Turner const size_t bytes_left = data_size - data_offset; 295666cc0b2SZachary Turner // Cap the length of we asked for too many 296666cc0b2SZachary Turner if (data_length <= bytes_left) 297666cc0b2SZachary Turner m_end = m_start + data_length; // We got all the bytes we wanted 298666cc0b2SZachary Turner else 299666cc0b2SZachary Turner m_end = m_start + bytes_left; // Not all the bytes requested were 300666cc0b2SZachary Turner // available in the shared data 301666cc0b2SZachary Turner } 302666cc0b2SZachary Turner } 303666cc0b2SZachary Turner } 304666cc0b2SZachary Turner 305666cc0b2SZachary Turner size_t new_size = GetByteSize(); 306666cc0b2SZachary Turner 30705097246SAdrian Prantl // Don't hold a shared pointer to the data buffer if we don't share any valid 30805097246SAdrian Prantl // bytes in the shared buffer. 309666cc0b2SZachary Turner if (new_size == 0) 310666cc0b2SZachary Turner m_data_sp.reset(); 311666cc0b2SZachary Turner 312666cc0b2SZachary Turner return new_size; 313666cc0b2SZachary Turner } 314666cc0b2SZachary Turner 31505097246SAdrian Prantl // Extract a single unsigned char from the binary data and update the offset 31605097246SAdrian Prantl // pointed to by "offset_ptr". 317666cc0b2SZachary Turner // 318666cc0b2SZachary Turner // RETURNS the byte that was extracted, or zero on failure. 319666cc0b2SZachary Turner uint8_t DataExtractor::GetU8(offset_t *offset_ptr) const { 32024374aefSJonas Devlieghere const uint8_t *data = static_cast<const uint8_t *>(GetData(offset_ptr, 1)); 321666cc0b2SZachary Turner if (data) 322666cc0b2SZachary Turner return *data; 323666cc0b2SZachary Turner return 0; 324666cc0b2SZachary Turner } 325666cc0b2SZachary Turner 32605097246SAdrian Prantl // Extract "count" unsigned chars from the binary data and update the offset 32705097246SAdrian Prantl // pointed to by "offset_ptr". The extracted data is copied into "dst". 328666cc0b2SZachary Turner // 329666cc0b2SZachary Turner // RETURNS the non-nullptr buffer pointer upon successful extraction of 33005097246SAdrian Prantl // all the requested bytes, or nullptr when the data is not available in the 33105097246SAdrian Prantl // buffer due to being out of bounds, or insufficient data. 332666cc0b2SZachary Turner void *DataExtractor::GetU8(offset_t *offset_ptr, void *dst, 333666cc0b2SZachary Turner uint32_t count) const { 33424374aefSJonas Devlieghere const uint8_t *data = 33524374aefSJonas Devlieghere static_cast<const uint8_t *>(GetData(offset_ptr, count)); 336666cc0b2SZachary Turner if (data) { 337666cc0b2SZachary Turner // Copy the data into the buffer 338666cc0b2SZachary Turner memcpy(dst, data, count); 339666cc0b2SZachary Turner // Return a non-nullptr pointer to the converted data as an indicator of 340666cc0b2SZachary Turner // success 341666cc0b2SZachary Turner return dst; 342666cc0b2SZachary Turner } 343666cc0b2SZachary Turner return nullptr; 344666cc0b2SZachary Turner } 345666cc0b2SZachary Turner 34605097246SAdrian Prantl // Extract a single uint16_t from the data and update the offset pointed to by 34705097246SAdrian Prantl // "offset_ptr". 348666cc0b2SZachary Turner // 349666cc0b2SZachary Turner // RETURNS the uint16_t that was extracted, or zero on failure. 350666cc0b2SZachary Turner uint16_t DataExtractor::GetU16(offset_t *offset_ptr) const { 351666cc0b2SZachary Turner uint16_t val = 0; 35224374aefSJonas Devlieghere const uint8_t *data = 35324374aefSJonas Devlieghere static_cast<const uint8_t *>(GetData(offset_ptr, sizeof(val))); 354666cc0b2SZachary Turner if (data) { 355666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) 356666cc0b2SZachary Turner val = ReadSwapInt16(data); 357666cc0b2SZachary Turner else 358666cc0b2SZachary Turner val = ReadInt16(data); 359666cc0b2SZachary Turner } 360666cc0b2SZachary Turner return val; 361666cc0b2SZachary Turner } 362666cc0b2SZachary Turner 363666cc0b2SZachary Turner uint16_t DataExtractor::GetU16_unchecked(offset_t *offset_ptr) const { 364666cc0b2SZachary Turner uint16_t val; 365666cc0b2SZachary Turner if (m_byte_order == endian::InlHostByteOrder()) 366666cc0b2SZachary Turner val = ReadInt16(m_start, *offset_ptr); 367666cc0b2SZachary Turner else 368666cc0b2SZachary Turner val = ReadSwapInt16(m_start, *offset_ptr); 369666cc0b2SZachary Turner *offset_ptr += sizeof(val); 370666cc0b2SZachary Turner return val; 371666cc0b2SZachary Turner } 372666cc0b2SZachary Turner 373666cc0b2SZachary Turner uint32_t DataExtractor::GetU32_unchecked(offset_t *offset_ptr) const { 374666cc0b2SZachary Turner uint32_t val; 375666cc0b2SZachary Turner if (m_byte_order == endian::InlHostByteOrder()) 376666cc0b2SZachary Turner val = ReadInt32(m_start, *offset_ptr); 377666cc0b2SZachary Turner else 378666cc0b2SZachary Turner val = ReadSwapInt32(m_start, *offset_ptr); 379666cc0b2SZachary Turner *offset_ptr += sizeof(val); 380666cc0b2SZachary Turner return val; 381666cc0b2SZachary Turner } 382666cc0b2SZachary Turner 383666cc0b2SZachary Turner uint64_t DataExtractor::GetU64_unchecked(offset_t *offset_ptr) const { 384666cc0b2SZachary Turner uint64_t val; 385666cc0b2SZachary Turner if (m_byte_order == endian::InlHostByteOrder()) 386666cc0b2SZachary Turner val = ReadInt64(m_start, *offset_ptr); 387666cc0b2SZachary Turner else 388666cc0b2SZachary Turner val = ReadSwapInt64(m_start, *offset_ptr); 389666cc0b2SZachary Turner *offset_ptr += sizeof(val); 390666cc0b2SZachary Turner return val; 391666cc0b2SZachary Turner } 392666cc0b2SZachary Turner 39305097246SAdrian Prantl // Extract "count" uint16_t values from the binary data and update the offset 39405097246SAdrian Prantl // pointed to by "offset_ptr". The extracted data is copied into "dst". 395666cc0b2SZachary Turner // 396666cc0b2SZachary Turner // RETURNS the non-nullptr buffer pointer upon successful extraction of 39705097246SAdrian Prantl // all the requested bytes, or nullptr when the data is not available in the 39805097246SAdrian Prantl // buffer due to being out of bounds, or insufficient data. 399666cc0b2SZachary Turner void *DataExtractor::GetU16(offset_t *offset_ptr, void *void_dst, 400666cc0b2SZachary Turner uint32_t count) const { 401666cc0b2SZachary Turner const size_t src_size = sizeof(uint16_t) * count; 40224374aefSJonas Devlieghere const uint16_t *src = 40324374aefSJonas Devlieghere static_cast<const uint16_t *>(GetData(offset_ptr, src_size)); 404666cc0b2SZachary Turner if (src) { 405666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) { 40624374aefSJonas Devlieghere uint16_t *dst_pos = static_cast<uint16_t *>(void_dst); 407666cc0b2SZachary Turner uint16_t *dst_end = dst_pos + count; 408666cc0b2SZachary Turner const uint16_t *src_pos = src; 409666cc0b2SZachary Turner while (dst_pos < dst_end) { 410666cc0b2SZachary Turner *dst_pos = ReadSwapInt16(src_pos); 411666cc0b2SZachary Turner ++dst_pos; 412666cc0b2SZachary Turner ++src_pos; 413666cc0b2SZachary Turner } 414666cc0b2SZachary Turner } else { 415666cc0b2SZachary Turner memcpy(void_dst, src, src_size); 416666cc0b2SZachary Turner } 417666cc0b2SZachary Turner // Return a non-nullptr pointer to the converted data as an indicator of 418666cc0b2SZachary Turner // success 419666cc0b2SZachary Turner return void_dst; 420666cc0b2SZachary Turner } 421666cc0b2SZachary Turner return nullptr; 422666cc0b2SZachary Turner } 423666cc0b2SZachary Turner 42405097246SAdrian Prantl // Extract a single uint32_t from the data and update the offset pointed to by 42505097246SAdrian Prantl // "offset_ptr". 426666cc0b2SZachary Turner // 427666cc0b2SZachary Turner // RETURNS the uint32_t that was extracted, or zero on failure. 428666cc0b2SZachary Turner uint32_t DataExtractor::GetU32(offset_t *offset_ptr) const { 429666cc0b2SZachary Turner uint32_t val = 0; 43024374aefSJonas Devlieghere const uint8_t *data = 43124374aefSJonas Devlieghere static_cast<const uint8_t *>(GetData(offset_ptr, sizeof(val))); 432666cc0b2SZachary Turner if (data) { 433666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) { 434666cc0b2SZachary Turner val = ReadSwapInt32(data); 435666cc0b2SZachary Turner } else { 436666cc0b2SZachary Turner memcpy(&val, data, 4); 437666cc0b2SZachary Turner } 438666cc0b2SZachary Turner } 439666cc0b2SZachary Turner return val; 440666cc0b2SZachary Turner } 441666cc0b2SZachary Turner 44205097246SAdrian Prantl // Extract "count" uint32_t values from the binary data and update the offset 44305097246SAdrian Prantl // pointed to by "offset_ptr". The extracted data is copied into "dst". 444666cc0b2SZachary Turner // 445666cc0b2SZachary Turner // RETURNS the non-nullptr buffer pointer upon successful extraction of 44605097246SAdrian Prantl // all the requested bytes, or nullptr when the data is not available in the 44705097246SAdrian Prantl // buffer due to being out of bounds, or insufficient data. 448666cc0b2SZachary Turner void *DataExtractor::GetU32(offset_t *offset_ptr, void *void_dst, 449666cc0b2SZachary Turner uint32_t count) const { 450666cc0b2SZachary Turner const size_t src_size = sizeof(uint32_t) * count; 45124374aefSJonas Devlieghere const uint32_t *src = 45224374aefSJonas Devlieghere static_cast<const uint32_t *>(GetData(offset_ptr, src_size)); 453666cc0b2SZachary Turner if (src) { 454666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) { 45524374aefSJonas Devlieghere uint32_t *dst_pos = static_cast<uint32_t *>(void_dst); 456666cc0b2SZachary Turner uint32_t *dst_end = dst_pos + count; 457666cc0b2SZachary Turner const uint32_t *src_pos = src; 458666cc0b2SZachary Turner while (dst_pos < dst_end) { 459666cc0b2SZachary Turner *dst_pos = ReadSwapInt32(src_pos); 460666cc0b2SZachary Turner ++dst_pos; 461666cc0b2SZachary Turner ++src_pos; 462666cc0b2SZachary Turner } 463666cc0b2SZachary Turner } else { 464666cc0b2SZachary Turner memcpy(void_dst, src, src_size); 465666cc0b2SZachary Turner } 466666cc0b2SZachary Turner // Return a non-nullptr pointer to the converted data as an indicator of 467666cc0b2SZachary Turner // success 468666cc0b2SZachary Turner return void_dst; 469666cc0b2SZachary Turner } 470666cc0b2SZachary Turner return nullptr; 471666cc0b2SZachary Turner } 472666cc0b2SZachary Turner 47305097246SAdrian Prantl // Extract a single uint64_t from the data and update the offset pointed to by 47405097246SAdrian Prantl // "offset_ptr". 475666cc0b2SZachary Turner // 476666cc0b2SZachary Turner // RETURNS the uint64_t that was extracted, or zero on failure. 477666cc0b2SZachary Turner uint64_t DataExtractor::GetU64(offset_t *offset_ptr) const { 478666cc0b2SZachary Turner uint64_t val = 0; 47924374aefSJonas Devlieghere const uint8_t *data = 48024374aefSJonas Devlieghere static_cast<const uint8_t *>(GetData(offset_ptr, sizeof(val))); 481666cc0b2SZachary Turner if (data) { 482666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) { 483666cc0b2SZachary Turner val = ReadSwapInt64(data); 484666cc0b2SZachary Turner } else { 485666cc0b2SZachary Turner memcpy(&val, data, 8); 486666cc0b2SZachary Turner } 487666cc0b2SZachary Turner } 488666cc0b2SZachary Turner return val; 489666cc0b2SZachary Turner } 490666cc0b2SZachary Turner 491666cc0b2SZachary Turner // GetU64 492666cc0b2SZachary Turner // 49305097246SAdrian Prantl // Get multiple consecutive 64 bit values. Return true if the entire read 49405097246SAdrian Prantl // succeeds and increment the offset pointed to by offset_ptr, else return 49505097246SAdrian Prantl // false and leave the offset pointed to by offset_ptr unchanged. 496666cc0b2SZachary Turner void *DataExtractor::GetU64(offset_t *offset_ptr, void *void_dst, 497666cc0b2SZachary Turner uint32_t count) const { 498666cc0b2SZachary Turner const size_t src_size = sizeof(uint64_t) * count; 49924374aefSJonas Devlieghere const uint64_t *src = 50024374aefSJonas Devlieghere static_cast<const uint64_t *>(GetData(offset_ptr, src_size)); 501666cc0b2SZachary Turner if (src) { 502666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) { 50324374aefSJonas Devlieghere uint64_t *dst_pos = static_cast<uint64_t *>(void_dst); 504666cc0b2SZachary Turner uint64_t *dst_end = dst_pos + count; 505666cc0b2SZachary Turner const uint64_t *src_pos = src; 506666cc0b2SZachary Turner while (dst_pos < dst_end) { 507666cc0b2SZachary Turner *dst_pos = ReadSwapInt64(src_pos); 508666cc0b2SZachary Turner ++dst_pos; 509666cc0b2SZachary Turner ++src_pos; 510666cc0b2SZachary Turner } 511666cc0b2SZachary Turner } else { 512666cc0b2SZachary Turner memcpy(void_dst, src, src_size); 513666cc0b2SZachary Turner } 514666cc0b2SZachary Turner // Return a non-nullptr pointer to the converted data as an indicator of 515666cc0b2SZachary Turner // success 516666cc0b2SZachary Turner return void_dst; 517666cc0b2SZachary Turner } 518666cc0b2SZachary Turner return nullptr; 519666cc0b2SZachary Turner } 520666cc0b2SZachary Turner 521666cc0b2SZachary Turner uint32_t DataExtractor::GetMaxU32(offset_t *offset_ptr, 522666cc0b2SZachary Turner size_t byte_size) const { 523dbd7c338SPetr Pavlu lldbassert(byte_size > 0 && byte_size <= 4 && "GetMaxU32 invalid byte_size!"); 524dbd7c338SPetr Pavlu return GetMaxU64(offset_ptr, byte_size); 525dbd7c338SPetr Pavlu } 526dbd7c338SPetr Pavlu 527dbd7c338SPetr Pavlu uint64_t DataExtractor::GetMaxU64(offset_t *offset_ptr, 528dbd7c338SPetr Pavlu size_t byte_size) const { 529dbd7c338SPetr Pavlu lldbassert(byte_size > 0 && byte_size <= 8 && "GetMaxU64 invalid byte_size!"); 530666cc0b2SZachary Turner switch (byte_size) { 531666cc0b2SZachary Turner case 1: 532666cc0b2SZachary Turner return GetU8(offset_ptr); 533666cc0b2SZachary Turner case 2: 534666cc0b2SZachary Turner return GetU16(offset_ptr); 535666cc0b2SZachary Turner case 4: 536666cc0b2SZachary Turner return GetU32(offset_ptr); 537666cc0b2SZachary Turner case 8: 538666cc0b2SZachary Turner return GetU64(offset_ptr); 539dbd7c338SPetr Pavlu default: { 540dbd7c338SPetr Pavlu // General case. 541dbd7c338SPetr Pavlu const uint8_t *data = 542dbd7c338SPetr Pavlu static_cast<const uint8_t *>(GetData(offset_ptr, byte_size)); 543dbd7c338SPetr Pavlu if (data == nullptr) 544dbd7c338SPetr Pavlu return 0; 545dbd7c338SPetr Pavlu return ReadMaxInt64(data, byte_size, m_byte_order); 546dbd7c338SPetr Pavlu } 547666cc0b2SZachary Turner } 548666cc0b2SZachary Turner return 0; 549666cc0b2SZachary Turner } 550666cc0b2SZachary Turner 551666cc0b2SZachary Turner uint64_t DataExtractor::GetMaxU64_unchecked(offset_t *offset_ptr, 552dbd7c338SPetr Pavlu size_t byte_size) const { 553dbd7c338SPetr Pavlu switch (byte_size) { 554666cc0b2SZachary Turner case 1: 555666cc0b2SZachary Turner return GetU8_unchecked(offset_ptr); 556666cc0b2SZachary Turner case 2: 557666cc0b2SZachary Turner return GetU16_unchecked(offset_ptr); 558666cc0b2SZachary Turner case 4: 559666cc0b2SZachary Turner return GetU32_unchecked(offset_ptr); 560666cc0b2SZachary Turner case 8: 561666cc0b2SZachary Turner return GetU64_unchecked(offset_ptr); 562dbd7c338SPetr Pavlu default: { 563dbd7c338SPetr Pavlu uint64_t res = ReadMaxInt64(&m_start[*offset_ptr], byte_size, m_byte_order); 564dbd7c338SPetr Pavlu *offset_ptr += byte_size; 565dbd7c338SPetr Pavlu return res; 566dbd7c338SPetr Pavlu } 567666cc0b2SZachary Turner } 568666cc0b2SZachary Turner return 0; 569666cc0b2SZachary Turner } 570666cc0b2SZachary Turner 571dbd7c338SPetr Pavlu int64_t DataExtractor::GetMaxS64(offset_t *offset_ptr, size_t byte_size) const { 572dbd7c338SPetr Pavlu uint64_t u64 = GetMaxU64(offset_ptr, byte_size); 573dbd7c338SPetr Pavlu return llvm::SignExtend64(u64, 8 * byte_size); 574666cc0b2SZachary Turner } 575666cc0b2SZachary Turner 576666cc0b2SZachary Turner uint64_t DataExtractor::GetMaxU64Bitfield(offset_t *offset_ptr, size_t size, 577666cc0b2SZachary Turner uint32_t bitfield_bit_size, 578666cc0b2SZachary Turner uint32_t bitfield_bit_offset) const { 579fffd7029Sshafik assert(bitfield_bit_size <= 64); 580666cc0b2SZachary Turner uint64_t uval64 = GetMaxU64(offset_ptr, size); 581fffd7029Sshafik 582fffd7029Sshafik if (bitfield_bit_size == 0) 583fffd7029Sshafik return uval64; 584fffd7029Sshafik 585666cc0b2SZachary Turner int32_t lsbcount = bitfield_bit_offset; 586666cc0b2SZachary Turner if (m_byte_order == eByteOrderBig) 587666cc0b2SZachary Turner lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size; 588fffd7029Sshafik 589666cc0b2SZachary Turner if (lsbcount > 0) 590666cc0b2SZachary Turner uval64 >>= lsbcount; 591fffd7029Sshafik 592fffd7029Sshafik uint64_t bitfield_mask = 593fffd7029Sshafik (bitfield_bit_size == 64 594fffd7029Sshafik ? std::numeric_limits<uint64_t>::max() 595fffd7029Sshafik : ((static_cast<uint64_t>(1) << bitfield_bit_size) - 1)); 596666cc0b2SZachary Turner if (!bitfield_mask && bitfield_bit_offset == 0 && bitfield_bit_size == 64) 597666cc0b2SZachary Turner return uval64; 598fffd7029Sshafik 599666cc0b2SZachary Turner uval64 &= bitfield_mask; 600fffd7029Sshafik 601666cc0b2SZachary Turner return uval64; 602666cc0b2SZachary Turner } 603666cc0b2SZachary Turner 604666cc0b2SZachary Turner int64_t DataExtractor::GetMaxS64Bitfield(offset_t *offset_ptr, size_t size, 605666cc0b2SZachary Turner uint32_t bitfield_bit_size, 606666cc0b2SZachary Turner uint32_t bitfield_bit_offset) const { 6077b90cdedSVedant Kumar assert(size >= 1 && "GetMaxS64Bitfield size must be >= 1"); 6087b90cdedSVedant Kumar assert(size <= 8 && "GetMaxS64Bitfield size must be <= 8"); 609666cc0b2SZachary Turner int64_t sval64 = GetMaxS64(offset_ptr, size); 610*bb6646ceSVedant Kumar if (bitfield_bit_size == 0) 611*bb6646ceSVedant Kumar return sval64; 612666cc0b2SZachary Turner int32_t lsbcount = bitfield_bit_offset; 613666cc0b2SZachary Turner if (m_byte_order == eByteOrderBig) 614666cc0b2SZachary Turner lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size; 615666cc0b2SZachary Turner if (lsbcount > 0) 616666cc0b2SZachary Turner sval64 >>= lsbcount; 617*bb6646ceSVedant Kumar uint64_t bitfield_mask = llvm::maskTrailingOnes<uint64_t>(bitfield_bit_size); 618666cc0b2SZachary Turner sval64 &= bitfield_mask; 619666cc0b2SZachary Turner // sign extend if needed 62024374aefSJonas Devlieghere if (sval64 & ((static_cast<uint64_t>(1)) << (bitfield_bit_size - 1))) 621666cc0b2SZachary Turner sval64 |= ~bitfield_mask; 622666cc0b2SZachary Turner return sval64; 623666cc0b2SZachary Turner } 624666cc0b2SZachary Turner 625666cc0b2SZachary Turner float DataExtractor::GetFloat(offset_t *offset_ptr) const { 626666cc0b2SZachary Turner typedef float float_type; 627666cc0b2SZachary Turner float_type val = 0.0; 628666cc0b2SZachary Turner const size_t src_size = sizeof(float_type); 62924374aefSJonas Devlieghere const float_type *src = 63024374aefSJonas Devlieghere static_cast<const float_type *>(GetData(offset_ptr, src_size)); 631666cc0b2SZachary Turner if (src) { 632666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) { 63324374aefSJonas Devlieghere const uint8_t *src_data = reinterpret_cast<const uint8_t *>(src); 63424374aefSJonas Devlieghere uint8_t *dst_data = reinterpret_cast<uint8_t *>(&val); 635666cc0b2SZachary Turner for (size_t i = 0; i < sizeof(float_type); ++i) 636666cc0b2SZachary Turner dst_data[sizeof(float_type) - 1 - i] = src_data[i]; 637666cc0b2SZachary Turner } else { 638666cc0b2SZachary Turner val = *src; 639666cc0b2SZachary Turner } 640666cc0b2SZachary Turner } 641666cc0b2SZachary Turner return val; 642666cc0b2SZachary Turner } 643666cc0b2SZachary Turner 644666cc0b2SZachary Turner double DataExtractor::GetDouble(offset_t *offset_ptr) const { 645666cc0b2SZachary Turner typedef double float_type; 646666cc0b2SZachary Turner float_type val = 0.0; 647666cc0b2SZachary Turner const size_t src_size = sizeof(float_type); 64824374aefSJonas Devlieghere const float_type *src = 64924374aefSJonas Devlieghere static_cast<const float_type *>(GetData(offset_ptr, src_size)); 650666cc0b2SZachary Turner if (src) { 651666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) { 65224374aefSJonas Devlieghere const uint8_t *src_data = reinterpret_cast<const uint8_t *>(src); 65324374aefSJonas Devlieghere uint8_t *dst_data = reinterpret_cast<uint8_t *>(&val); 654666cc0b2SZachary Turner for (size_t i = 0; i < sizeof(float_type); ++i) 655666cc0b2SZachary Turner dst_data[sizeof(float_type) - 1 - i] = src_data[i]; 656666cc0b2SZachary Turner } else { 657666cc0b2SZachary Turner val = *src; 658666cc0b2SZachary Turner } 659666cc0b2SZachary Turner } 660666cc0b2SZachary Turner return val; 661666cc0b2SZachary Turner } 662666cc0b2SZachary Turner 663666cc0b2SZachary Turner long double DataExtractor::GetLongDouble(offset_t *offset_ptr) const { 664666cc0b2SZachary Turner long double val = 0.0; 665666cc0b2SZachary Turner #if defined(__i386__) || defined(__amd64__) || defined(__x86_64__) || \ 666666cc0b2SZachary Turner defined(_M_IX86) || defined(_M_IA64) || defined(_M_X64) 667666cc0b2SZachary Turner *offset_ptr += CopyByteOrderedData(*offset_ptr, 10, &val, sizeof(val), 668666cc0b2SZachary Turner endian::InlHostByteOrder()); 669666cc0b2SZachary Turner #else 670666cc0b2SZachary Turner *offset_ptr += CopyByteOrderedData(*offset_ptr, sizeof(val), &val, 671666cc0b2SZachary Turner sizeof(val), endian::InlHostByteOrder()); 672666cc0b2SZachary Turner #endif 673666cc0b2SZachary Turner return val; 674666cc0b2SZachary Turner } 675666cc0b2SZachary Turner 67605097246SAdrian Prantl // Extract a single address from the data and update the offset pointed to by 67705097246SAdrian Prantl // "offset_ptr". The size of the extracted address comes from the 67805097246SAdrian Prantl // "this->m_addr_size" member variable and should be set correctly prior to 67905097246SAdrian Prantl // extracting any address values. 680666cc0b2SZachary Turner // 681666cc0b2SZachary Turner // RETURNS the address that was extracted, or zero on failure. 682666cc0b2SZachary Turner uint64_t DataExtractor::GetAddress(offset_t *offset_ptr) const { 683666cc0b2SZachary Turner assert(m_addr_size == 4 || m_addr_size == 8); 684666cc0b2SZachary Turner return GetMaxU64(offset_ptr, m_addr_size); 685666cc0b2SZachary Turner } 686666cc0b2SZachary Turner 687666cc0b2SZachary Turner uint64_t DataExtractor::GetAddress_unchecked(offset_t *offset_ptr) const { 688666cc0b2SZachary Turner assert(m_addr_size == 4 || m_addr_size == 8); 689666cc0b2SZachary Turner return GetMaxU64_unchecked(offset_ptr, m_addr_size); 690666cc0b2SZachary Turner } 691666cc0b2SZachary Turner 69205097246SAdrian Prantl // Extract a single pointer from the data and update the offset pointed to by 69305097246SAdrian Prantl // "offset_ptr". The size of the extracted pointer comes from the 69405097246SAdrian Prantl // "this->m_addr_size" member variable and should be set correctly prior to 69505097246SAdrian Prantl // extracting any pointer values. 696666cc0b2SZachary Turner // 697666cc0b2SZachary Turner // RETURNS the pointer that was extracted, or zero on failure. 698666cc0b2SZachary Turner uint64_t DataExtractor::GetPointer(offset_t *offset_ptr) const { 699666cc0b2SZachary Turner assert(m_addr_size == 4 || m_addr_size == 8); 700666cc0b2SZachary Turner return GetMaxU64(offset_ptr, m_addr_size); 701666cc0b2SZachary Turner } 702666cc0b2SZachary Turner 703666cc0b2SZachary Turner size_t DataExtractor::ExtractBytes(offset_t offset, offset_t length, 704666cc0b2SZachary Turner ByteOrder dst_byte_order, void *dst) const { 705666cc0b2SZachary Turner const uint8_t *src = PeekData(offset, length); 706666cc0b2SZachary Turner if (src) { 707666cc0b2SZachary Turner if (dst_byte_order != GetByteOrder()) { 708666cc0b2SZachary Turner // Validate that only a word- or register-sized dst is byte swapped 709666cc0b2SZachary Turner assert(length == 1 || length == 2 || length == 4 || length == 8 || 710666cc0b2SZachary Turner length == 10 || length == 16 || length == 32); 711666cc0b2SZachary Turner 712666cc0b2SZachary Turner for (uint32_t i = 0; i < length; ++i) 71324374aefSJonas Devlieghere (static_cast<uint8_t *>(dst))[i] = src[length - i - 1]; 714666cc0b2SZachary Turner } else 715666cc0b2SZachary Turner ::memcpy(dst, src, length); 716666cc0b2SZachary Turner return length; 717666cc0b2SZachary Turner } 718666cc0b2SZachary Turner return 0; 719666cc0b2SZachary Turner } 720666cc0b2SZachary Turner 721666cc0b2SZachary Turner // Extract data as it exists in target memory 722666cc0b2SZachary Turner lldb::offset_t DataExtractor::CopyData(offset_t offset, offset_t length, 723666cc0b2SZachary Turner void *dst) const { 724666cc0b2SZachary Turner const uint8_t *src = PeekData(offset, length); 725666cc0b2SZachary Turner if (src) { 726666cc0b2SZachary Turner ::memcpy(dst, src, length); 727666cc0b2SZachary Turner return length; 728666cc0b2SZachary Turner } 729666cc0b2SZachary Turner return 0; 730666cc0b2SZachary Turner } 731666cc0b2SZachary Turner 732666cc0b2SZachary Turner // Extract data and swap if needed when doing the copy 733666cc0b2SZachary Turner lldb::offset_t 734666cc0b2SZachary Turner DataExtractor::CopyByteOrderedData(offset_t src_offset, offset_t src_len, 735666cc0b2SZachary Turner void *dst_void_ptr, offset_t dst_len, 736666cc0b2SZachary Turner ByteOrder dst_byte_order) const { 737666cc0b2SZachary Turner // Validate the source info 738666cc0b2SZachary Turner if (!ValidOffsetForDataOfSize(src_offset, src_len)) 739666cc0b2SZachary Turner assert(ValidOffsetForDataOfSize(src_offset, src_len)); 740666cc0b2SZachary Turner assert(src_len > 0); 741666cc0b2SZachary Turner assert(m_byte_order == eByteOrderBig || m_byte_order == eByteOrderLittle); 742666cc0b2SZachary Turner 743666cc0b2SZachary Turner // Validate the destination info 744666cc0b2SZachary Turner assert(dst_void_ptr != nullptr); 745666cc0b2SZachary Turner assert(dst_len > 0); 746666cc0b2SZachary Turner assert(dst_byte_order == eByteOrderBig || dst_byte_order == eByteOrderLittle); 747666cc0b2SZachary Turner 748666cc0b2SZachary Turner // Validate that only a word- or register-sized dst is byte swapped 749666cc0b2SZachary Turner assert(dst_byte_order == m_byte_order || dst_len == 1 || dst_len == 2 || 750666cc0b2SZachary Turner dst_len == 4 || dst_len == 8 || dst_len == 10 || dst_len == 16 || 751666cc0b2SZachary Turner dst_len == 32); 752666cc0b2SZachary Turner 753666cc0b2SZachary Turner // Must have valid byte orders set in this object and for destination 754666cc0b2SZachary Turner if (!(dst_byte_order == eByteOrderBig || 755666cc0b2SZachary Turner dst_byte_order == eByteOrderLittle) || 756666cc0b2SZachary Turner !(m_byte_order == eByteOrderBig || m_byte_order == eByteOrderLittle)) 757666cc0b2SZachary Turner return 0; 758666cc0b2SZachary Turner 75924374aefSJonas Devlieghere uint8_t *dst = static_cast<uint8_t *>(dst_void_ptr); 76024374aefSJonas Devlieghere const uint8_t *src = PeekData(src_offset, src_len); 761666cc0b2SZachary Turner if (src) { 762666cc0b2SZachary Turner if (dst_len >= src_len) { 76305097246SAdrian Prantl // We are copying the entire value from src into dst. Calculate how many, 76405097246SAdrian Prantl // if any, zeroes we need for the most significant bytes if "dst_len" is 76505097246SAdrian Prantl // greater than "src_len"... 766666cc0b2SZachary Turner const size_t num_zeroes = dst_len - src_len; 767666cc0b2SZachary Turner if (dst_byte_order == eByteOrderBig) { 768666cc0b2SZachary Turner // Big endian, so we lead with zeroes... 769666cc0b2SZachary Turner if (num_zeroes > 0) 770666cc0b2SZachary Turner ::memset(dst, 0, num_zeroes); 771666cc0b2SZachary Turner // Then either copy or swap the rest 772666cc0b2SZachary Turner if (m_byte_order == eByteOrderBig) { 773666cc0b2SZachary Turner ::memcpy(dst + num_zeroes, src, src_len); 774666cc0b2SZachary Turner } else { 775666cc0b2SZachary Turner for (uint32_t i = 0; i < src_len; ++i) 776666cc0b2SZachary Turner dst[i + num_zeroes] = src[src_len - 1 - i]; 777666cc0b2SZachary Turner } 778666cc0b2SZachary Turner } else { 779666cc0b2SZachary Turner // Little endian destination, so we lead the value bytes 780666cc0b2SZachary Turner if (m_byte_order == eByteOrderBig) { 781666cc0b2SZachary Turner for (uint32_t i = 0; i < src_len; ++i) 782666cc0b2SZachary Turner dst[i] = src[src_len - 1 - i]; 783666cc0b2SZachary Turner } else { 784666cc0b2SZachary Turner ::memcpy(dst, src, src_len); 785666cc0b2SZachary Turner } 786666cc0b2SZachary Turner // And zero the rest... 787666cc0b2SZachary Turner if (num_zeroes > 0) 788666cc0b2SZachary Turner ::memset(dst + src_len, 0, num_zeroes); 789666cc0b2SZachary Turner } 790666cc0b2SZachary Turner return src_len; 791666cc0b2SZachary Turner } else { 792666cc0b2SZachary Turner // We are only copying some of the value from src into dst.. 793666cc0b2SZachary Turner 794666cc0b2SZachary Turner if (dst_byte_order == eByteOrderBig) { 795666cc0b2SZachary Turner // Big endian dst 796666cc0b2SZachary Turner if (m_byte_order == eByteOrderBig) { 797666cc0b2SZachary Turner // Big endian dst, with big endian src 798666cc0b2SZachary Turner ::memcpy(dst, src + (src_len - dst_len), dst_len); 799666cc0b2SZachary Turner } else { 800666cc0b2SZachary Turner // Big endian dst, with little endian src 801666cc0b2SZachary Turner for (uint32_t i = 0; i < dst_len; ++i) 802666cc0b2SZachary Turner dst[i] = src[dst_len - 1 - i]; 803666cc0b2SZachary Turner } 804666cc0b2SZachary Turner } else { 805666cc0b2SZachary Turner // Little endian dst 806666cc0b2SZachary Turner if (m_byte_order == eByteOrderBig) { 807666cc0b2SZachary Turner // Little endian dst, with big endian src 808666cc0b2SZachary Turner for (uint32_t i = 0; i < dst_len; ++i) 809666cc0b2SZachary Turner dst[i] = src[src_len - 1 - i]; 810666cc0b2SZachary Turner } else { 811666cc0b2SZachary Turner // Little endian dst, with big endian src 812666cc0b2SZachary Turner ::memcpy(dst, src, dst_len); 813666cc0b2SZachary Turner } 814666cc0b2SZachary Turner } 815666cc0b2SZachary Turner return dst_len; 816666cc0b2SZachary Turner } 817666cc0b2SZachary Turner } 818666cc0b2SZachary Turner return 0; 819666cc0b2SZachary Turner } 820666cc0b2SZachary Turner 82105097246SAdrian Prantl // Extracts a variable length NULL terminated C string from the data at the 82205097246SAdrian Prantl // offset pointed to by "offset_ptr". The "offset_ptr" will be updated with 82305097246SAdrian Prantl // the offset of the byte that follows the NULL terminator byte. 824666cc0b2SZachary Turner // 82505097246SAdrian Prantl // If the offset pointed to by "offset_ptr" is out of bounds, or if "length" is 82605097246SAdrian Prantl // non-zero and there aren't enough available bytes, nullptr will be returned 82705097246SAdrian Prantl // and "offset_ptr" will not be updated. 828666cc0b2SZachary Turner const char *DataExtractor::GetCStr(offset_t *offset_ptr) const { 829067bb1f5SRaphael Isemann const char *start = reinterpret_cast<const char *>(PeekData(*offset_ptr, 1)); 830067bb1f5SRaphael Isemann // Already at the end of the data. 831067bb1f5SRaphael Isemann if (!start) 832666cc0b2SZachary Turner return nullptr; 833067bb1f5SRaphael Isemann 834067bb1f5SRaphael Isemann const char *end = reinterpret_cast<const char *>(m_end); 835067bb1f5SRaphael Isemann 836067bb1f5SRaphael Isemann // Check all bytes for a null terminator that terminates a C string. 837067bb1f5SRaphael Isemann const char *terminator_or_end = std::find(start, end, '\0'); 838067bb1f5SRaphael Isemann 839067bb1f5SRaphael Isemann // We didn't find a null terminator, so return nullptr to indicate that there 840067bb1f5SRaphael Isemann // is no valid C string at that offset. 841067bb1f5SRaphael Isemann if (terminator_or_end == end) 842067bb1f5SRaphael Isemann return nullptr; 843067bb1f5SRaphael Isemann 844067bb1f5SRaphael Isemann // Update offset_ptr for the caller to point to the data behind the 845067bb1f5SRaphael Isemann // terminator (which is 1 byte long). 846067bb1f5SRaphael Isemann *offset_ptr += (terminator_or_end - start + 1UL); 847067bb1f5SRaphael Isemann return start; 848666cc0b2SZachary Turner } 849666cc0b2SZachary Turner 85005097246SAdrian Prantl // Extracts a NULL terminated C string from the fixed length field of length 85105097246SAdrian Prantl // "len" at the offset pointed to by "offset_ptr". The "offset_ptr" will be 85205097246SAdrian Prantl // updated with the offset of the byte that follows the fixed length field. 853666cc0b2SZachary Turner // 85405097246SAdrian Prantl // If the offset pointed to by "offset_ptr" is out of bounds, or if the offset 85505097246SAdrian Prantl // plus the length of the field is out of bounds, or if the field does not 85605097246SAdrian Prantl // contain a NULL terminator byte, nullptr will be returned and "offset_ptr" 85705097246SAdrian Prantl // will not be updated. 858666cc0b2SZachary Turner const char *DataExtractor::GetCStr(offset_t *offset_ptr, offset_t len) const { 85924374aefSJonas Devlieghere const char *cstr = reinterpret_cast<const char *>(PeekData(*offset_ptr, len)); 860666cc0b2SZachary Turner if (cstr != nullptr) { 861666cc0b2SZachary Turner if (memchr(cstr, '\0', len) == nullptr) { 862666cc0b2SZachary Turner return nullptr; 863666cc0b2SZachary Turner } 864666cc0b2SZachary Turner *offset_ptr += len; 865666cc0b2SZachary Turner return cstr; 866666cc0b2SZachary Turner } 867666cc0b2SZachary Turner return nullptr; 868666cc0b2SZachary Turner } 869666cc0b2SZachary Turner 87005097246SAdrian Prantl // Peeks at a string in the contained data. No verification is done to make 87105097246SAdrian Prantl // sure the entire string lies within the bounds of this object's data, only 87205097246SAdrian Prantl // "offset" is verified to be a valid offset. 873666cc0b2SZachary Turner // 87405097246SAdrian Prantl // Returns a valid C string pointer if "offset" is a valid offset in this 87505097246SAdrian Prantl // object's data, else nullptr is returned. 876666cc0b2SZachary Turner const char *DataExtractor::PeekCStr(offset_t offset) const { 87724374aefSJonas Devlieghere return reinterpret_cast<const char *>(PeekData(offset, 1)); 878666cc0b2SZachary Turner } 879666cc0b2SZachary Turner 88005097246SAdrian Prantl // Extracts an unsigned LEB128 number from this object's data starting at the 88105097246SAdrian Prantl // offset pointed to by "offset_ptr". The offset pointed to by "offset_ptr" 88205097246SAdrian Prantl // will be updated with the offset of the byte following the last extracted 88305097246SAdrian Prantl // byte. 884666cc0b2SZachary Turner // 885666cc0b2SZachary Turner // Returned the extracted integer value. 886666cc0b2SZachary Turner uint64_t DataExtractor::GetULEB128(offset_t *offset_ptr) const { 88724374aefSJonas Devlieghere const uint8_t *src = PeekData(*offset_ptr, 1); 888666cc0b2SZachary Turner if (src == nullptr) 889666cc0b2SZachary Turner return 0; 890666cc0b2SZachary Turner 891666cc0b2SZachary Turner const uint8_t *end = m_end; 892666cc0b2SZachary Turner 893666cc0b2SZachary Turner if (src < end) { 894666cc0b2SZachary Turner uint64_t result = *src++; 895666cc0b2SZachary Turner if (result >= 0x80) { 896666cc0b2SZachary Turner result &= 0x7f; 897666cc0b2SZachary Turner int shift = 7; 898666cc0b2SZachary Turner while (src < end) { 899666cc0b2SZachary Turner uint8_t byte = *src++; 90024374aefSJonas Devlieghere result |= static_cast<uint64_t>(byte & 0x7f) << shift; 901666cc0b2SZachary Turner if ((byte & 0x80) == 0) 902666cc0b2SZachary Turner break; 903666cc0b2SZachary Turner shift += 7; 904666cc0b2SZachary Turner } 905666cc0b2SZachary Turner } 906666cc0b2SZachary Turner *offset_ptr = src - m_start; 907666cc0b2SZachary Turner return result; 908666cc0b2SZachary Turner } 909666cc0b2SZachary Turner 910666cc0b2SZachary Turner return 0; 911666cc0b2SZachary Turner } 912666cc0b2SZachary Turner 91305097246SAdrian Prantl // Extracts an signed LEB128 number from this object's data starting at the 91405097246SAdrian Prantl // offset pointed to by "offset_ptr". The offset pointed to by "offset_ptr" 91505097246SAdrian Prantl // will be updated with the offset of the byte following the last extracted 91605097246SAdrian Prantl // byte. 917666cc0b2SZachary Turner // 918666cc0b2SZachary Turner // Returned the extracted integer value. 919666cc0b2SZachary Turner int64_t DataExtractor::GetSLEB128(offset_t *offset_ptr) const { 92024374aefSJonas Devlieghere const uint8_t *src = PeekData(*offset_ptr, 1); 921666cc0b2SZachary Turner if (src == nullptr) 922666cc0b2SZachary Turner return 0; 923666cc0b2SZachary Turner 924666cc0b2SZachary Turner const uint8_t *end = m_end; 925666cc0b2SZachary Turner 926666cc0b2SZachary Turner if (src < end) { 927666cc0b2SZachary Turner int64_t result = 0; 928666cc0b2SZachary Turner int shift = 0; 929666cc0b2SZachary Turner int size = sizeof(int64_t) * 8; 930666cc0b2SZachary Turner 931666cc0b2SZachary Turner uint8_t byte = 0; 932666cc0b2SZachary Turner int bytecount = 0; 933666cc0b2SZachary Turner 934666cc0b2SZachary Turner while (src < end) { 935666cc0b2SZachary Turner bytecount++; 936666cc0b2SZachary Turner byte = *src++; 93724374aefSJonas Devlieghere result |= static_cast<int64_t>(byte & 0x7f) << shift; 938666cc0b2SZachary Turner shift += 7; 939666cc0b2SZachary Turner if ((byte & 0x80) == 0) 940666cc0b2SZachary Turner break; 941666cc0b2SZachary Turner } 942666cc0b2SZachary Turner 943666cc0b2SZachary Turner // Sign bit of byte is 2nd high order bit (0x40) 944666cc0b2SZachary Turner if (shift < size && (byte & 0x40)) 945666cc0b2SZachary Turner result |= -(1 << shift); 946666cc0b2SZachary Turner 947666cc0b2SZachary Turner *offset_ptr += bytecount; 948666cc0b2SZachary Turner return result; 949666cc0b2SZachary Turner } 950666cc0b2SZachary Turner return 0; 951666cc0b2SZachary Turner } 952666cc0b2SZachary Turner 95305097246SAdrian Prantl // Skips a ULEB128 number (signed or unsigned) from this object's data starting 95405097246SAdrian Prantl // at the offset pointed to by "offset_ptr". The offset pointed to by 95505097246SAdrian Prantl // "offset_ptr" will be updated with the offset of the byte following the last 95605097246SAdrian Prantl // extracted byte. 957666cc0b2SZachary Turner // 958666cc0b2SZachary Turner // Returns the number of bytes consumed during the extraction. 959666cc0b2SZachary Turner uint32_t DataExtractor::Skip_LEB128(offset_t *offset_ptr) const { 960666cc0b2SZachary Turner uint32_t bytes_consumed = 0; 96124374aefSJonas Devlieghere const uint8_t *src = PeekData(*offset_ptr, 1); 962666cc0b2SZachary Turner if (src == nullptr) 963666cc0b2SZachary Turner return 0; 964666cc0b2SZachary Turner 965666cc0b2SZachary Turner const uint8_t *end = m_end; 966666cc0b2SZachary Turner 967666cc0b2SZachary Turner if (src < end) { 968666cc0b2SZachary Turner const uint8_t *src_pos = src; 969666cc0b2SZachary Turner while ((src_pos < end) && (*src_pos++ & 0x80)) 970666cc0b2SZachary Turner ++bytes_consumed; 971666cc0b2SZachary Turner *offset_ptr += src_pos - src; 972666cc0b2SZachary Turner } 973666cc0b2SZachary Turner return bytes_consumed; 974666cc0b2SZachary Turner } 975666cc0b2SZachary Turner 976666cc0b2SZachary Turner // Dumps bytes from this object's data to the stream "s" starting 97705097246SAdrian Prantl // "start_offset" bytes into this data, and ending with the byte before 97805097246SAdrian Prantl // "end_offset". "base_addr" will be added to the offset into the dumped data 97905097246SAdrian Prantl // when showing the offset into the data in the output information. 98005097246SAdrian Prantl // "num_per_line" objects of type "type" will be dumped with the option to 98105097246SAdrian Prantl // override the format for each object with "type_format". "type_format" is a 98205097246SAdrian Prantl // printf style formatting string. If "type_format" is nullptr, then an 98305097246SAdrian Prantl // appropriate format string will be used for the supplied "type". If the 98405097246SAdrian Prantl // stream "s" is nullptr, then the output will be send to Log(). 985666cc0b2SZachary Turner lldb::offset_t DataExtractor::PutToLog(Log *log, offset_t start_offset, 986666cc0b2SZachary Turner offset_t length, uint64_t base_addr, 987666cc0b2SZachary Turner uint32_t num_per_line, 988b6e2cf32SRaphael Isemann DataExtractor::Type type) const { 989666cc0b2SZachary Turner if (log == nullptr) 990666cc0b2SZachary Turner return start_offset; 991666cc0b2SZachary Turner 992666cc0b2SZachary Turner offset_t offset; 993666cc0b2SZachary Turner offset_t end_offset; 994666cc0b2SZachary Turner uint32_t count; 995666cc0b2SZachary Turner StreamString sstr; 996666cc0b2SZachary Turner for (offset = start_offset, end_offset = offset + length, count = 0; 997666cc0b2SZachary Turner ValidOffset(offset) && offset < end_offset; ++count) { 998666cc0b2SZachary Turner if ((count % num_per_line) == 0) { 999666cc0b2SZachary Turner // Print out any previous string 1000666cc0b2SZachary Turner if (sstr.GetSize() > 0) { 1001666cc0b2SZachary Turner log->PutString(sstr.GetString()); 1002666cc0b2SZachary Turner sstr.Clear(); 1003666cc0b2SZachary Turner } 1004666cc0b2SZachary Turner // Reset string offset and fill the current line string with address: 1005666cc0b2SZachary Turner if (base_addr != LLDB_INVALID_ADDRESS) 1006666cc0b2SZachary Turner sstr.Printf("0x%8.8" PRIx64 ":", 100724374aefSJonas Devlieghere static_cast<uint64_t>(base_addr + (offset - start_offset))); 1008666cc0b2SZachary Turner } 1009666cc0b2SZachary Turner 1010666cc0b2SZachary Turner switch (type) { 1011666cc0b2SZachary Turner case TypeUInt8: 1012b6e2cf32SRaphael Isemann sstr.Printf(" %2.2x", GetU8(&offset)); 1013666cc0b2SZachary Turner break; 1014666cc0b2SZachary Turner case TypeChar: { 1015666cc0b2SZachary Turner char ch = GetU8(&offset); 1016b6e2cf32SRaphael Isemann sstr.Printf(" %c", isprint(ch) ? ch : ' '); 1017666cc0b2SZachary Turner } break; 1018666cc0b2SZachary Turner case TypeUInt16: 1019b6e2cf32SRaphael Isemann sstr.Printf(" %4.4x", GetU16(&offset)); 1020666cc0b2SZachary Turner break; 1021666cc0b2SZachary Turner case TypeUInt32: 1022b6e2cf32SRaphael Isemann sstr.Printf(" %8.8x", GetU32(&offset)); 1023666cc0b2SZachary Turner break; 1024666cc0b2SZachary Turner case TypeUInt64: 1025b6e2cf32SRaphael Isemann sstr.Printf(" %16.16" PRIx64, GetU64(&offset)); 1026666cc0b2SZachary Turner break; 1027666cc0b2SZachary Turner case TypePointer: 1028b6e2cf32SRaphael Isemann sstr.Printf(" 0x%" PRIx64, GetAddress(&offset)); 1029666cc0b2SZachary Turner break; 1030666cc0b2SZachary Turner case TypeULEB128: 1031b6e2cf32SRaphael Isemann sstr.Printf(" 0x%" PRIx64, GetULEB128(&offset)); 1032666cc0b2SZachary Turner break; 1033666cc0b2SZachary Turner case TypeSLEB128: 1034b6e2cf32SRaphael Isemann sstr.Printf(" %" PRId64, GetSLEB128(&offset)); 1035666cc0b2SZachary Turner break; 1036666cc0b2SZachary Turner } 1037666cc0b2SZachary Turner } 1038666cc0b2SZachary Turner 1039666cc0b2SZachary Turner if (!sstr.Empty()) 1040666cc0b2SZachary Turner log->PutString(sstr.GetString()); 1041666cc0b2SZachary Turner 1042666cc0b2SZachary Turner return offset; // Return the offset at which we ended up 1043666cc0b2SZachary Turner } 1044666cc0b2SZachary Turner 1045666cc0b2SZachary Turner size_t DataExtractor::Copy(DataExtractor &dest_data) const { 1046666cc0b2SZachary Turner if (m_data_sp) { 1047666cc0b2SZachary Turner // we can pass along the SP to the data 1048666cc0b2SZachary Turner dest_data.SetData(m_data_sp); 1049666cc0b2SZachary Turner } else { 1050666cc0b2SZachary Turner const uint8_t *base_ptr = m_start; 1051666cc0b2SZachary Turner size_t data_size = GetByteSize(); 1052666cc0b2SZachary Turner dest_data.SetData(DataBufferSP(new DataBufferHeap(base_ptr, data_size))); 1053666cc0b2SZachary Turner } 1054666cc0b2SZachary Turner return GetByteSize(); 1055666cc0b2SZachary Turner } 1056666cc0b2SZachary Turner 1057666cc0b2SZachary Turner bool DataExtractor::Append(DataExtractor &rhs) { 1058666cc0b2SZachary Turner if (rhs.GetByteOrder() != GetByteOrder()) 1059666cc0b2SZachary Turner return false; 1060666cc0b2SZachary Turner 1061666cc0b2SZachary Turner if (rhs.GetByteSize() == 0) 1062666cc0b2SZachary Turner return true; 1063666cc0b2SZachary Turner 1064666cc0b2SZachary Turner if (GetByteSize() == 0) 1065666cc0b2SZachary Turner return (rhs.Copy(*this) > 0); 1066666cc0b2SZachary Turner 1067666cc0b2SZachary Turner size_t bytes = GetByteSize() + rhs.GetByteSize(); 1068666cc0b2SZachary Turner 1069666cc0b2SZachary Turner DataBufferHeap *buffer_heap_ptr = nullptr; 1070666cc0b2SZachary Turner DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0)); 1071666cc0b2SZachary Turner 1072666cc0b2SZachary Turner if (!buffer_sp || buffer_heap_ptr == nullptr) 1073666cc0b2SZachary Turner return false; 1074666cc0b2SZachary Turner 1075666cc0b2SZachary Turner uint8_t *bytes_ptr = buffer_heap_ptr->GetBytes(); 1076666cc0b2SZachary Turner 1077666cc0b2SZachary Turner memcpy(bytes_ptr, GetDataStart(), GetByteSize()); 1078666cc0b2SZachary Turner memcpy(bytes_ptr + GetByteSize(), rhs.GetDataStart(), rhs.GetByteSize()); 1079666cc0b2SZachary Turner 1080666cc0b2SZachary Turner SetData(buffer_sp); 1081666cc0b2SZachary Turner 1082666cc0b2SZachary Turner return true; 1083666cc0b2SZachary Turner } 1084666cc0b2SZachary Turner 1085666cc0b2SZachary Turner bool DataExtractor::Append(void *buf, offset_t length) { 1086666cc0b2SZachary Turner if (buf == nullptr) 1087666cc0b2SZachary Turner return false; 1088666cc0b2SZachary Turner 1089666cc0b2SZachary Turner if (length == 0) 1090666cc0b2SZachary Turner return true; 1091666cc0b2SZachary Turner 1092666cc0b2SZachary Turner size_t bytes = GetByteSize() + length; 1093666cc0b2SZachary Turner 1094666cc0b2SZachary Turner DataBufferHeap *buffer_heap_ptr = nullptr; 1095666cc0b2SZachary Turner DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0)); 1096666cc0b2SZachary Turner 1097666cc0b2SZachary Turner if (!buffer_sp || buffer_heap_ptr == nullptr) 1098666cc0b2SZachary Turner return false; 1099666cc0b2SZachary Turner 1100666cc0b2SZachary Turner uint8_t *bytes_ptr = buffer_heap_ptr->GetBytes(); 1101666cc0b2SZachary Turner 1102666cc0b2SZachary Turner if (GetByteSize() > 0) 1103666cc0b2SZachary Turner memcpy(bytes_ptr, GetDataStart(), GetByteSize()); 1104666cc0b2SZachary Turner 1105666cc0b2SZachary Turner memcpy(bytes_ptr + GetByteSize(), buf, length); 1106666cc0b2SZachary Turner 1107666cc0b2SZachary Turner SetData(buffer_sp); 1108666cc0b2SZachary Turner 1109666cc0b2SZachary Turner return true; 1110666cc0b2SZachary Turner } 1111666cc0b2SZachary Turner 1112666cc0b2SZachary Turner void DataExtractor::Checksum(llvm::SmallVectorImpl<uint8_t> &dest, 1113666cc0b2SZachary Turner uint64_t max_data) { 1114666cc0b2SZachary Turner if (max_data == 0) 1115666cc0b2SZachary Turner max_data = GetByteSize(); 1116666cc0b2SZachary Turner else 1117666cc0b2SZachary Turner max_data = std::min(max_data, GetByteSize()); 1118666cc0b2SZachary Turner 1119666cc0b2SZachary Turner llvm::MD5 md5; 1120666cc0b2SZachary Turner 1121666cc0b2SZachary Turner const llvm::ArrayRef<uint8_t> data(GetDataStart(), max_data); 1122666cc0b2SZachary Turner md5.update(data); 1123666cc0b2SZachary Turner 1124666cc0b2SZachary Turner llvm::MD5::MD5Result result; 1125666cc0b2SZachary Turner md5.final(result); 1126666cc0b2SZachary Turner 112782a0c97bSZachary Turner dest.clear(); 112882a0c97bSZachary Turner dest.append(result.Bytes.begin(), result.Bytes.end()); 1129666cc0b2SZachary Turner } 1130