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