1666cc0b2SZachary Turner //===-- DataExtractor.cpp ---------------------------------------*- C++ -*-===// 2666cc0b2SZachary Turner // 3666cc0b2SZachary Turner // The LLVM Compiler Infrastructure 4666cc0b2SZachary Turner // 5666cc0b2SZachary Turner // This file is distributed under the University of Illinois Open Source 6666cc0b2SZachary Turner // License. See LICENSE.TXT for details. 7666cc0b2SZachary Turner // 8666cc0b2SZachary Turner //===----------------------------------------------------------------------===// 9666cc0b2SZachary Turner 104479ac15SZachary Turner #include "lldb/Utility/DataExtractor.h" 11666cc0b2SZachary Turner 124479ac15SZachary Turner #include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS 134479ac15SZachary Turner #include "lldb/lldb-enumerations.h" // for ByteOrder::eByteOrderBig 144479ac15SZachary Turner #include "lldb/lldb-forward.h" // for DataBufferSP 154479ac15SZachary Turner #include "lldb/lldb-types.h" // for offset_t 164479ac15SZachary Turner 17666cc0b2SZachary Turner #include "lldb/Utility/DataBuffer.h" 18666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h" 19666cc0b2SZachary Turner #include "lldb/Utility/Endian.h" 20*dbd7c338SPetr Pavlu #include "lldb/Utility/LLDBAssert.h" 21666cc0b2SZachary Turner #include "lldb/Utility/Log.h" 22666cc0b2SZachary Turner #include "lldb/Utility/Stream.h" 23666cc0b2SZachary Turner #include "lldb/Utility/StreamString.h" 24666cc0b2SZachary Turner #include "lldb/Utility/UUID.h" 25666cc0b2SZachary Turner 26666cc0b2SZachary Turner #include "llvm/ADT/ArrayRef.h" 27666cc0b2SZachary Turner #include "llvm/ADT/SmallVector.h" 28666cc0b2SZachary Turner #include "llvm/Support/MD5.h" 29666cc0b2SZachary Turner #include "llvm/Support/MathExtras.h" 30666cc0b2SZachary Turner 314479ac15SZachary Turner #include <algorithm> // for min 324479ac15SZachary Turner #include <array> // for array 334479ac15SZachary Turner #include <cassert> 344479ac15SZachary Turner #include <cstdint> // for uint8_t, uint32_t, uint64_t 354479ac15SZachary Turner #include <string> 364479ac15SZachary Turner 374479ac15SZachary Turner #include <ctype.h> // for isprint 384479ac15SZachary Turner #include <inttypes.h> // for PRIx64, PRId64 394479ac15SZachary Turner #include <string.h> // for memcpy, memset, memchr 404479ac15SZachary Turner 41666cc0b2SZachary Turner using namespace lldb; 42666cc0b2SZachary Turner using namespace lldb_private; 43666cc0b2SZachary Turner 44666cc0b2SZachary Turner static inline uint16_t ReadInt16(const unsigned char *ptr, offset_t offset) { 45666cc0b2SZachary Turner uint16_t value; 46666cc0b2SZachary Turner memcpy(&value, ptr + offset, 2); 47666cc0b2SZachary Turner return value; 48666cc0b2SZachary Turner } 49666cc0b2SZachary Turner 50666cc0b2SZachary Turner static inline uint32_t ReadInt32(const unsigned char *ptr, 51666cc0b2SZachary Turner offset_t offset = 0) { 52666cc0b2SZachary Turner uint32_t value; 53666cc0b2SZachary Turner memcpy(&value, ptr + offset, 4); 54666cc0b2SZachary Turner return value; 55666cc0b2SZachary Turner } 56666cc0b2SZachary Turner 57666cc0b2SZachary Turner static inline uint64_t ReadInt64(const unsigned char *ptr, 58666cc0b2SZachary Turner offset_t offset = 0) { 59666cc0b2SZachary Turner uint64_t value; 60666cc0b2SZachary Turner memcpy(&value, ptr + offset, 8); 61666cc0b2SZachary Turner return value; 62666cc0b2SZachary Turner } 63666cc0b2SZachary Turner 64666cc0b2SZachary Turner static inline uint16_t ReadInt16(const void *ptr) { 65666cc0b2SZachary Turner uint16_t value; 66666cc0b2SZachary Turner memcpy(&value, ptr, 2); 67666cc0b2SZachary Turner return value; 68666cc0b2SZachary Turner } 69666cc0b2SZachary Turner 70666cc0b2SZachary Turner static inline uint16_t ReadSwapInt16(const unsigned char *ptr, 71666cc0b2SZachary Turner offset_t offset) { 72666cc0b2SZachary Turner uint16_t value; 73666cc0b2SZachary Turner memcpy(&value, ptr + offset, 2); 74666cc0b2SZachary Turner return llvm::ByteSwap_16(value); 75666cc0b2SZachary Turner } 76666cc0b2SZachary Turner 77666cc0b2SZachary Turner static inline uint32_t ReadSwapInt32(const unsigned char *ptr, 78666cc0b2SZachary Turner offset_t offset) { 79666cc0b2SZachary Turner uint32_t value; 80666cc0b2SZachary Turner memcpy(&value, ptr + offset, 4); 81666cc0b2SZachary Turner return llvm::ByteSwap_32(value); 82666cc0b2SZachary Turner } 83666cc0b2SZachary Turner 84666cc0b2SZachary Turner static inline uint64_t ReadSwapInt64(const unsigned char *ptr, 85666cc0b2SZachary Turner offset_t offset) { 86666cc0b2SZachary Turner uint64_t value; 87666cc0b2SZachary Turner memcpy(&value, ptr + offset, 8); 88666cc0b2SZachary Turner return llvm::ByteSwap_64(value); 89666cc0b2SZachary Turner } 90666cc0b2SZachary Turner 91666cc0b2SZachary Turner static inline uint16_t ReadSwapInt16(const void *ptr) { 92666cc0b2SZachary Turner uint16_t value; 93666cc0b2SZachary Turner memcpy(&value, ptr, 2); 94666cc0b2SZachary Turner return llvm::ByteSwap_16(value); 95666cc0b2SZachary Turner } 96666cc0b2SZachary Turner 97666cc0b2SZachary Turner static inline uint32_t ReadSwapInt32(const void *ptr) { 98666cc0b2SZachary Turner uint32_t value; 99666cc0b2SZachary Turner memcpy(&value, ptr, 4); 100666cc0b2SZachary Turner return llvm::ByteSwap_32(value); 101666cc0b2SZachary Turner } 102666cc0b2SZachary Turner 103666cc0b2SZachary Turner static inline uint64_t ReadSwapInt64(const void *ptr) { 104666cc0b2SZachary Turner uint64_t value; 105666cc0b2SZachary Turner memcpy(&value, ptr, 8); 106666cc0b2SZachary Turner return llvm::ByteSwap_64(value); 107666cc0b2SZachary Turner } 108666cc0b2SZachary Turner 109*dbd7c338SPetr Pavlu static inline uint64_t ReadMaxInt64(const uint8_t *data, size_t byte_size, 110*dbd7c338SPetr Pavlu ByteOrder byte_order) { 111*dbd7c338SPetr Pavlu uint64_t res = 0; 112*dbd7c338SPetr Pavlu if (byte_order == eByteOrderBig) 113*dbd7c338SPetr Pavlu for (size_t i = 0; i < byte_size; ++i) 114*dbd7c338SPetr Pavlu res = (res << 8) | data[i]; 115*dbd7c338SPetr Pavlu else { 116*dbd7c338SPetr Pavlu assert(byte_order == eByteOrderLittle); 117*dbd7c338SPetr Pavlu for (size_t i = 0; i < byte_size; ++i) 118*dbd7c338SPetr Pavlu res = (res << 8) | data[byte_size - 1 - i]; 119*dbd7c338SPetr Pavlu } 120*dbd7c338SPetr Pavlu return res; 121*dbd7c338SPetr Pavlu } 122*dbd7c338SPetr Pavlu 123666cc0b2SZachary Turner DataExtractor::DataExtractor() 124666cc0b2SZachary Turner : m_start(nullptr), m_end(nullptr), 125666cc0b2SZachary Turner m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)), 126666cc0b2SZachary Turner m_data_sp(), m_target_byte_size(1) {} 127666cc0b2SZachary Turner 128666cc0b2SZachary Turner //---------------------------------------------------------------------- 129666cc0b2SZachary Turner // This constructor allows us to use data that is owned by someone else. 130666cc0b2SZachary Turner // The data must stay around as long as this object is valid. 131666cc0b2SZachary Turner //---------------------------------------------------------------------- 132666cc0b2SZachary Turner DataExtractor::DataExtractor(const void *data, offset_t length, 133666cc0b2SZachary Turner ByteOrder endian, uint32_t addr_size, 134666cc0b2SZachary Turner uint32_t target_byte_size /*=1*/) 135666cc0b2SZachary Turner : m_start(const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(data))), 136666cc0b2SZachary Turner m_end(const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(data)) + 137666cc0b2SZachary Turner length), 138666cc0b2SZachary Turner m_byte_order(endian), m_addr_size(addr_size), m_data_sp(), 139666cc0b2SZachary Turner m_target_byte_size(target_byte_size) { 140666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG 141666cc0b2SZachary Turner assert(addr_size == 4 || addr_size == 8); 142666cc0b2SZachary Turner #endif 143666cc0b2SZachary Turner } 144666cc0b2SZachary Turner 145666cc0b2SZachary Turner //---------------------------------------------------------------------- 146666cc0b2SZachary Turner // Make a shared pointer reference to the shared data in "data_sp" and 147666cc0b2SZachary Turner // set the endian swapping setting to "swap", and the address size to 148666cc0b2SZachary Turner // "addr_size". The shared data reference will ensure the data lives 149666cc0b2SZachary Turner // as long as any DataExtractor objects exist that have a reference to 150666cc0b2SZachary Turner // this data. 151666cc0b2SZachary Turner //---------------------------------------------------------------------- 152666cc0b2SZachary Turner DataExtractor::DataExtractor(const DataBufferSP &data_sp, ByteOrder endian, 153666cc0b2SZachary Turner uint32_t addr_size, 154666cc0b2SZachary Turner uint32_t target_byte_size /*=1*/) 155666cc0b2SZachary Turner : m_start(nullptr), m_end(nullptr), m_byte_order(endian), 156666cc0b2SZachary Turner m_addr_size(addr_size), m_data_sp(), 157666cc0b2SZachary Turner m_target_byte_size(target_byte_size) { 158666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG 159666cc0b2SZachary Turner assert(addr_size == 4 || addr_size == 8); 160666cc0b2SZachary Turner #endif 161666cc0b2SZachary Turner SetData(data_sp); 162666cc0b2SZachary Turner } 163666cc0b2SZachary Turner 164666cc0b2SZachary Turner //---------------------------------------------------------------------- 165666cc0b2SZachary Turner // Initialize this object with a subset of the data bytes in "data". 166666cc0b2SZachary Turner // If "data" contains shared data, then a reference to this shared 167666cc0b2SZachary Turner // data will added and the shared data will stay around as long 168666cc0b2SZachary Turner // as any object contains a reference to that data. The endian 169666cc0b2SZachary Turner // swap and address size settings are copied from "data". 170666cc0b2SZachary Turner //---------------------------------------------------------------------- 171666cc0b2SZachary Turner DataExtractor::DataExtractor(const DataExtractor &data, offset_t offset, 172666cc0b2SZachary Turner offset_t length, uint32_t target_byte_size /*=1*/) 173666cc0b2SZachary Turner : m_start(nullptr), m_end(nullptr), m_byte_order(data.m_byte_order), 174666cc0b2SZachary Turner m_addr_size(data.m_addr_size), m_data_sp(), 175666cc0b2SZachary Turner m_target_byte_size(target_byte_size) { 176666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG 177666cc0b2SZachary Turner assert(m_addr_size == 4 || m_addr_size == 8); 178666cc0b2SZachary Turner #endif 179666cc0b2SZachary Turner if (data.ValidOffset(offset)) { 180666cc0b2SZachary Turner offset_t bytes_available = data.GetByteSize() - offset; 181666cc0b2SZachary Turner if (length > bytes_available) 182666cc0b2SZachary Turner length = bytes_available; 183666cc0b2SZachary Turner SetData(data, offset, length); 184666cc0b2SZachary Turner } 185666cc0b2SZachary Turner } 186666cc0b2SZachary Turner 187666cc0b2SZachary Turner DataExtractor::DataExtractor(const DataExtractor &rhs) 188666cc0b2SZachary Turner : m_start(rhs.m_start), m_end(rhs.m_end), m_byte_order(rhs.m_byte_order), 189666cc0b2SZachary Turner m_addr_size(rhs.m_addr_size), m_data_sp(rhs.m_data_sp), 190666cc0b2SZachary Turner m_target_byte_size(rhs.m_target_byte_size) { 191666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG 192666cc0b2SZachary Turner assert(m_addr_size == 4 || m_addr_size == 8); 193666cc0b2SZachary Turner #endif 194666cc0b2SZachary Turner } 195666cc0b2SZachary Turner 196666cc0b2SZachary Turner //---------------------------------------------------------------------- 197666cc0b2SZachary Turner // Assignment operator 198666cc0b2SZachary Turner //---------------------------------------------------------------------- 199666cc0b2SZachary Turner const DataExtractor &DataExtractor::operator=(const DataExtractor &rhs) { 200666cc0b2SZachary Turner if (this != &rhs) { 201666cc0b2SZachary Turner m_start = rhs.m_start; 202666cc0b2SZachary Turner m_end = rhs.m_end; 203666cc0b2SZachary Turner m_byte_order = rhs.m_byte_order; 204666cc0b2SZachary Turner m_addr_size = rhs.m_addr_size; 205666cc0b2SZachary Turner m_data_sp = rhs.m_data_sp; 206666cc0b2SZachary Turner } 207666cc0b2SZachary Turner return *this; 208666cc0b2SZachary Turner } 209666cc0b2SZachary Turner 210666cc0b2SZachary Turner DataExtractor::~DataExtractor() = default; 211666cc0b2SZachary Turner 212666cc0b2SZachary Turner //------------------------------------------------------------------ 213666cc0b2SZachary Turner // Clears the object contents back to a default invalid state, and 214666cc0b2SZachary Turner // release any references to shared data that this object may 215666cc0b2SZachary Turner // contain. 216666cc0b2SZachary Turner //------------------------------------------------------------------ 217666cc0b2SZachary Turner void DataExtractor::Clear() { 218666cc0b2SZachary Turner m_start = nullptr; 219666cc0b2SZachary Turner m_end = nullptr; 220666cc0b2SZachary Turner m_byte_order = endian::InlHostByteOrder(); 221666cc0b2SZachary Turner m_addr_size = sizeof(void *); 222666cc0b2SZachary Turner m_data_sp.reset(); 223666cc0b2SZachary Turner } 224666cc0b2SZachary Turner 225666cc0b2SZachary Turner //------------------------------------------------------------------ 226666cc0b2SZachary Turner // If this object contains shared data, this function returns the 227666cc0b2SZachary Turner // offset into that shared data. Else zero is returned. 228666cc0b2SZachary Turner //------------------------------------------------------------------ 229666cc0b2SZachary Turner size_t DataExtractor::GetSharedDataOffset() const { 230666cc0b2SZachary Turner if (m_start != nullptr) { 231666cc0b2SZachary Turner const DataBuffer *data = m_data_sp.get(); 232666cc0b2SZachary Turner if (data != nullptr) { 233666cc0b2SZachary Turner const uint8_t *data_bytes = data->GetBytes(); 234666cc0b2SZachary Turner if (data_bytes != nullptr) { 235666cc0b2SZachary Turner assert(m_start >= data_bytes); 236666cc0b2SZachary Turner return m_start - data_bytes; 237666cc0b2SZachary Turner } 238666cc0b2SZachary Turner } 239666cc0b2SZachary Turner } 240666cc0b2SZachary Turner return 0; 241666cc0b2SZachary Turner } 242666cc0b2SZachary Turner 243666cc0b2SZachary Turner //---------------------------------------------------------------------- 244666cc0b2SZachary Turner // Set the data with which this object will extract from to data 245666cc0b2SZachary Turner // starting at BYTES and set the length of the data to LENGTH bytes 246666cc0b2SZachary Turner // long. The data is externally owned must be around at least as 247666cc0b2SZachary Turner // long as this object points to the data. No copy of the data is 248666cc0b2SZachary Turner // made, this object just refers to this data and can extract from 249666cc0b2SZachary Turner // it. If this object refers to any shared data upon entry, the 250666cc0b2SZachary Turner // reference to that data will be released. Is SWAP is set to true, 251666cc0b2SZachary Turner // any data extracted will be endian swapped. 252666cc0b2SZachary Turner //---------------------------------------------------------------------- 253666cc0b2SZachary Turner lldb::offset_t DataExtractor::SetData(const void *bytes, offset_t length, 254666cc0b2SZachary Turner ByteOrder endian) { 255666cc0b2SZachary Turner m_byte_order = endian; 256666cc0b2SZachary Turner m_data_sp.reset(); 257666cc0b2SZachary Turner if (bytes == nullptr || length == 0) { 258666cc0b2SZachary Turner m_start = nullptr; 259666cc0b2SZachary Turner m_end = nullptr; 260666cc0b2SZachary Turner } else { 261666cc0b2SZachary Turner m_start = const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(bytes)); 262666cc0b2SZachary Turner m_end = m_start + length; 263666cc0b2SZachary Turner } 264666cc0b2SZachary Turner return GetByteSize(); 265666cc0b2SZachary Turner } 266666cc0b2SZachary Turner 267666cc0b2SZachary Turner //---------------------------------------------------------------------- 268666cc0b2SZachary Turner // Assign the data for this object to be a subrange in "data" 269666cc0b2SZachary Turner // starting "data_offset" bytes into "data" and ending "data_length" 270666cc0b2SZachary Turner // bytes later. If "data_offset" is not a valid offset into "data", 271666cc0b2SZachary Turner // then this object will contain no bytes. If "data_offset" is 272666cc0b2SZachary Turner // within "data" yet "data_length" is too large, the length will be 273666cc0b2SZachary Turner // capped at the number of bytes remaining in "data". If "data" 274666cc0b2SZachary Turner // contains a shared pointer to other data, then a ref counted 275666cc0b2SZachary Turner // pointer to that data will be made in this object. If "data" 276666cc0b2SZachary Turner // doesn't contain a shared pointer to data, then the bytes referred 277666cc0b2SZachary Turner // to in "data" will need to exist at least as long as this object 278666cc0b2SZachary Turner // refers to those bytes. The address size and endian swap settings 279666cc0b2SZachary Turner // are copied from the current values in "data". 280666cc0b2SZachary Turner //---------------------------------------------------------------------- 281666cc0b2SZachary Turner lldb::offset_t DataExtractor::SetData(const DataExtractor &data, 282666cc0b2SZachary Turner offset_t data_offset, 283666cc0b2SZachary Turner offset_t data_length) { 284666cc0b2SZachary Turner m_addr_size = data.m_addr_size; 285666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG 286666cc0b2SZachary Turner assert(m_addr_size == 4 || m_addr_size == 8); 287666cc0b2SZachary Turner #endif 288666cc0b2SZachary Turner // If "data" contains shared pointer to data, then we can use that 289666cc0b2SZachary Turner if (data.m_data_sp) { 290666cc0b2SZachary Turner m_byte_order = data.m_byte_order; 291666cc0b2SZachary Turner return SetData(data.m_data_sp, data.GetSharedDataOffset() + data_offset, 292666cc0b2SZachary Turner data_length); 293666cc0b2SZachary Turner } 294666cc0b2SZachary Turner 295666cc0b2SZachary Turner // We have a DataExtractor object that just has a pointer to bytes 296666cc0b2SZachary Turner if (data.ValidOffset(data_offset)) { 297666cc0b2SZachary Turner if (data_length > data.GetByteSize() - data_offset) 298666cc0b2SZachary Turner data_length = data.GetByteSize() - data_offset; 299666cc0b2SZachary Turner return SetData(data.GetDataStart() + data_offset, data_length, 300666cc0b2SZachary Turner data.GetByteOrder()); 301666cc0b2SZachary Turner } 302666cc0b2SZachary Turner return 0; 303666cc0b2SZachary Turner } 304666cc0b2SZachary Turner 305666cc0b2SZachary Turner //---------------------------------------------------------------------- 306666cc0b2SZachary Turner // Assign the data for this object to be a subrange of the shared 307666cc0b2SZachary Turner // data in "data_sp" starting "data_offset" bytes into "data_sp" 308666cc0b2SZachary Turner // and ending "data_length" bytes later. If "data_offset" is not 309666cc0b2SZachary Turner // a valid offset into "data_sp", then this object will contain no 310666cc0b2SZachary Turner // bytes. If "data_offset" is within "data_sp" yet "data_length" is 311666cc0b2SZachary Turner // too large, the length will be capped at the number of bytes 312666cc0b2SZachary Turner // remaining in "data_sp". A ref counted pointer to the data in 313666cc0b2SZachary Turner // "data_sp" will be made in this object IF the number of bytes this 314666cc0b2SZachary Turner // object refers to in greater than zero (if at least one byte was 315666cc0b2SZachary Turner // available starting at "data_offset") to ensure the data stays 316666cc0b2SZachary Turner // around as long as it is needed. The address size and endian swap 317666cc0b2SZachary Turner // settings will remain unchanged from their current settings. 318666cc0b2SZachary Turner //---------------------------------------------------------------------- 319666cc0b2SZachary Turner lldb::offset_t DataExtractor::SetData(const DataBufferSP &data_sp, 320666cc0b2SZachary Turner offset_t data_offset, 321666cc0b2SZachary Turner offset_t data_length) { 322666cc0b2SZachary Turner m_start = m_end = nullptr; 323666cc0b2SZachary Turner 324666cc0b2SZachary Turner if (data_length > 0) { 325666cc0b2SZachary Turner m_data_sp = data_sp; 326666cc0b2SZachary Turner if (data_sp) { 327666cc0b2SZachary Turner const size_t data_size = data_sp->GetByteSize(); 328666cc0b2SZachary Turner if (data_offset < data_size) { 329666cc0b2SZachary Turner m_start = data_sp->GetBytes() + data_offset; 330666cc0b2SZachary Turner const size_t bytes_left = data_size - data_offset; 331666cc0b2SZachary Turner // Cap the length of we asked for too many 332666cc0b2SZachary Turner if (data_length <= bytes_left) 333666cc0b2SZachary Turner m_end = m_start + data_length; // We got all the bytes we wanted 334666cc0b2SZachary Turner else 335666cc0b2SZachary Turner m_end = m_start + bytes_left; // Not all the bytes requested were 336666cc0b2SZachary Turner // available in the shared data 337666cc0b2SZachary Turner } 338666cc0b2SZachary Turner } 339666cc0b2SZachary Turner } 340666cc0b2SZachary Turner 341666cc0b2SZachary Turner size_t new_size = GetByteSize(); 342666cc0b2SZachary Turner 343666cc0b2SZachary Turner // Don't hold a shared pointer to the data buffer if we don't share 344666cc0b2SZachary Turner // any valid bytes in the shared buffer. 345666cc0b2SZachary Turner if (new_size == 0) 346666cc0b2SZachary Turner m_data_sp.reset(); 347666cc0b2SZachary Turner 348666cc0b2SZachary Turner return new_size; 349666cc0b2SZachary Turner } 350666cc0b2SZachary Turner 351666cc0b2SZachary Turner //---------------------------------------------------------------------- 352666cc0b2SZachary Turner // Extract a single unsigned char from the binary data and update 353666cc0b2SZachary Turner // the offset pointed to by "offset_ptr". 354666cc0b2SZachary Turner // 355666cc0b2SZachary Turner // RETURNS the byte that was extracted, or zero on failure. 356666cc0b2SZachary Turner //---------------------------------------------------------------------- 357666cc0b2SZachary Turner uint8_t DataExtractor::GetU8(offset_t *offset_ptr) const { 358666cc0b2SZachary Turner const uint8_t *data = (const uint8_t *)GetData(offset_ptr, 1); 359666cc0b2SZachary Turner if (data) 360666cc0b2SZachary Turner return *data; 361666cc0b2SZachary Turner return 0; 362666cc0b2SZachary Turner } 363666cc0b2SZachary Turner 364666cc0b2SZachary Turner //---------------------------------------------------------------------- 365666cc0b2SZachary Turner // Extract "count" unsigned chars from the binary data and update the 366666cc0b2SZachary Turner // offset pointed to by "offset_ptr". The extracted data is copied into 367666cc0b2SZachary Turner // "dst". 368666cc0b2SZachary Turner // 369666cc0b2SZachary Turner // RETURNS the non-nullptr buffer pointer upon successful extraction of 370666cc0b2SZachary Turner // all the requested bytes, or nullptr when the data is not available in 371666cc0b2SZachary Turner // the buffer due to being out of bounds, or insufficient data. 372666cc0b2SZachary Turner //---------------------------------------------------------------------- 373666cc0b2SZachary Turner void *DataExtractor::GetU8(offset_t *offset_ptr, void *dst, 374666cc0b2SZachary Turner uint32_t count) const { 375666cc0b2SZachary Turner const uint8_t *data = (const uint8_t *)GetData(offset_ptr, count); 376666cc0b2SZachary Turner if (data) { 377666cc0b2SZachary Turner // Copy the data into the buffer 378666cc0b2SZachary Turner memcpy(dst, data, count); 379666cc0b2SZachary Turner // Return a non-nullptr pointer to the converted data as an indicator of 380666cc0b2SZachary Turner // success 381666cc0b2SZachary Turner return dst; 382666cc0b2SZachary Turner } 383666cc0b2SZachary Turner return nullptr; 384666cc0b2SZachary Turner } 385666cc0b2SZachary Turner 386666cc0b2SZachary Turner //---------------------------------------------------------------------- 387666cc0b2SZachary Turner // Extract a single uint16_t from the data and update the offset 388666cc0b2SZachary Turner // pointed to by "offset_ptr". 389666cc0b2SZachary Turner // 390666cc0b2SZachary Turner // RETURNS the uint16_t that was extracted, or zero on failure. 391666cc0b2SZachary Turner //---------------------------------------------------------------------- 392666cc0b2SZachary Turner uint16_t DataExtractor::GetU16(offset_t *offset_ptr) const { 393666cc0b2SZachary Turner uint16_t val = 0; 394666cc0b2SZachary Turner const uint8_t *data = (const uint8_t *)GetData(offset_ptr, sizeof(val)); 395666cc0b2SZachary Turner if (data) { 396666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) 397666cc0b2SZachary Turner val = ReadSwapInt16(data); 398666cc0b2SZachary Turner else 399666cc0b2SZachary Turner val = ReadInt16(data); 400666cc0b2SZachary Turner } 401666cc0b2SZachary Turner return val; 402666cc0b2SZachary Turner } 403666cc0b2SZachary Turner 404666cc0b2SZachary Turner uint16_t DataExtractor::GetU16_unchecked(offset_t *offset_ptr) const { 405666cc0b2SZachary Turner uint16_t val; 406666cc0b2SZachary Turner if (m_byte_order == endian::InlHostByteOrder()) 407666cc0b2SZachary Turner val = ReadInt16(m_start, *offset_ptr); 408666cc0b2SZachary Turner else 409666cc0b2SZachary Turner val = ReadSwapInt16(m_start, *offset_ptr); 410666cc0b2SZachary Turner *offset_ptr += sizeof(val); 411666cc0b2SZachary Turner return val; 412666cc0b2SZachary Turner } 413666cc0b2SZachary Turner 414666cc0b2SZachary Turner uint32_t DataExtractor::GetU32_unchecked(offset_t *offset_ptr) const { 415666cc0b2SZachary Turner uint32_t val; 416666cc0b2SZachary Turner if (m_byte_order == endian::InlHostByteOrder()) 417666cc0b2SZachary Turner val = ReadInt32(m_start, *offset_ptr); 418666cc0b2SZachary Turner else 419666cc0b2SZachary Turner val = ReadSwapInt32(m_start, *offset_ptr); 420666cc0b2SZachary Turner *offset_ptr += sizeof(val); 421666cc0b2SZachary Turner return val; 422666cc0b2SZachary Turner } 423666cc0b2SZachary Turner 424666cc0b2SZachary Turner uint64_t DataExtractor::GetU64_unchecked(offset_t *offset_ptr) const { 425666cc0b2SZachary Turner uint64_t val; 426666cc0b2SZachary Turner if (m_byte_order == endian::InlHostByteOrder()) 427666cc0b2SZachary Turner val = ReadInt64(m_start, *offset_ptr); 428666cc0b2SZachary Turner else 429666cc0b2SZachary Turner val = ReadSwapInt64(m_start, *offset_ptr); 430666cc0b2SZachary Turner *offset_ptr += sizeof(val); 431666cc0b2SZachary Turner return val; 432666cc0b2SZachary Turner } 433666cc0b2SZachary Turner 434666cc0b2SZachary Turner //---------------------------------------------------------------------- 435666cc0b2SZachary Turner // Extract "count" uint16_t values from the binary data and update 436666cc0b2SZachary Turner // the offset pointed to by "offset_ptr". The extracted data is 437666cc0b2SZachary Turner // copied into "dst". 438666cc0b2SZachary Turner // 439666cc0b2SZachary Turner // RETURNS the non-nullptr buffer pointer upon successful extraction of 440666cc0b2SZachary Turner // all the requested bytes, or nullptr when the data is not available 441666cc0b2SZachary Turner // in the buffer due to being out of bounds, or insufficient data. 442666cc0b2SZachary Turner //---------------------------------------------------------------------- 443666cc0b2SZachary Turner void *DataExtractor::GetU16(offset_t *offset_ptr, void *void_dst, 444666cc0b2SZachary Turner uint32_t count) const { 445666cc0b2SZachary Turner const size_t src_size = sizeof(uint16_t) * count; 446666cc0b2SZachary Turner const uint16_t *src = (const uint16_t *)GetData(offset_ptr, src_size); 447666cc0b2SZachary Turner if (src) { 448666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) { 449666cc0b2SZachary Turner uint16_t *dst_pos = (uint16_t *)void_dst; 450666cc0b2SZachary Turner uint16_t *dst_end = dst_pos + count; 451666cc0b2SZachary Turner const uint16_t *src_pos = src; 452666cc0b2SZachary Turner while (dst_pos < dst_end) { 453666cc0b2SZachary Turner *dst_pos = ReadSwapInt16(src_pos); 454666cc0b2SZachary Turner ++dst_pos; 455666cc0b2SZachary Turner ++src_pos; 456666cc0b2SZachary Turner } 457666cc0b2SZachary Turner } else { 458666cc0b2SZachary Turner memcpy(void_dst, src, src_size); 459666cc0b2SZachary Turner } 460666cc0b2SZachary Turner // Return a non-nullptr pointer to the converted data as an indicator of 461666cc0b2SZachary Turner // success 462666cc0b2SZachary Turner return void_dst; 463666cc0b2SZachary Turner } 464666cc0b2SZachary Turner return nullptr; 465666cc0b2SZachary Turner } 466666cc0b2SZachary Turner 467666cc0b2SZachary Turner //---------------------------------------------------------------------- 468666cc0b2SZachary Turner // Extract a single uint32_t from the data and update the offset 469666cc0b2SZachary Turner // pointed to by "offset_ptr". 470666cc0b2SZachary Turner // 471666cc0b2SZachary Turner // RETURNS the uint32_t that was extracted, or zero on failure. 472666cc0b2SZachary Turner //---------------------------------------------------------------------- 473666cc0b2SZachary Turner uint32_t DataExtractor::GetU32(offset_t *offset_ptr) const { 474666cc0b2SZachary Turner uint32_t val = 0; 475666cc0b2SZachary Turner const uint8_t *data = (const uint8_t *)GetData(offset_ptr, sizeof(val)); 476666cc0b2SZachary Turner if (data) { 477666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) { 478666cc0b2SZachary Turner val = ReadSwapInt32(data); 479666cc0b2SZachary Turner } else { 480666cc0b2SZachary Turner memcpy(&val, data, 4); 481666cc0b2SZachary Turner } 482666cc0b2SZachary Turner } 483666cc0b2SZachary Turner return val; 484666cc0b2SZachary Turner } 485666cc0b2SZachary Turner 486666cc0b2SZachary Turner //---------------------------------------------------------------------- 487666cc0b2SZachary Turner // Extract "count" uint32_t values from the binary data and update 488666cc0b2SZachary Turner // the offset pointed to by "offset_ptr". The extracted data is 489666cc0b2SZachary Turner // copied into "dst". 490666cc0b2SZachary Turner // 491666cc0b2SZachary Turner // RETURNS the non-nullptr buffer pointer upon successful extraction of 492666cc0b2SZachary Turner // all the requested bytes, or nullptr when the data is not available 493666cc0b2SZachary Turner // in the buffer due to being out of bounds, or insufficient data. 494666cc0b2SZachary Turner //---------------------------------------------------------------------- 495666cc0b2SZachary Turner void *DataExtractor::GetU32(offset_t *offset_ptr, void *void_dst, 496666cc0b2SZachary Turner uint32_t count) const { 497666cc0b2SZachary Turner const size_t src_size = sizeof(uint32_t) * count; 498666cc0b2SZachary Turner const uint32_t *src = (const uint32_t *)GetData(offset_ptr, src_size); 499666cc0b2SZachary Turner if (src) { 500666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) { 501666cc0b2SZachary Turner uint32_t *dst_pos = (uint32_t *)void_dst; 502666cc0b2SZachary Turner uint32_t *dst_end = dst_pos + count; 503666cc0b2SZachary Turner const uint32_t *src_pos = src; 504666cc0b2SZachary Turner while (dst_pos < dst_end) { 505666cc0b2SZachary Turner *dst_pos = ReadSwapInt32(src_pos); 506666cc0b2SZachary Turner ++dst_pos; 507666cc0b2SZachary Turner ++src_pos; 508666cc0b2SZachary Turner } 509666cc0b2SZachary Turner } else { 510666cc0b2SZachary Turner memcpy(void_dst, src, src_size); 511666cc0b2SZachary Turner } 512666cc0b2SZachary Turner // Return a non-nullptr pointer to the converted data as an indicator of 513666cc0b2SZachary Turner // success 514666cc0b2SZachary Turner return void_dst; 515666cc0b2SZachary Turner } 516666cc0b2SZachary Turner return nullptr; 517666cc0b2SZachary Turner } 518666cc0b2SZachary Turner 519666cc0b2SZachary Turner //---------------------------------------------------------------------- 520666cc0b2SZachary Turner // Extract a single uint64_t from the data and update the offset 521666cc0b2SZachary Turner // pointed to by "offset_ptr". 522666cc0b2SZachary Turner // 523666cc0b2SZachary Turner // RETURNS the uint64_t that was extracted, or zero on failure. 524666cc0b2SZachary Turner //---------------------------------------------------------------------- 525666cc0b2SZachary Turner uint64_t DataExtractor::GetU64(offset_t *offset_ptr) const { 526666cc0b2SZachary Turner uint64_t val = 0; 527666cc0b2SZachary Turner const uint8_t *data = (const uint8_t *)GetData(offset_ptr, sizeof(val)); 528666cc0b2SZachary Turner if (data) { 529666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) { 530666cc0b2SZachary Turner val = ReadSwapInt64(data); 531666cc0b2SZachary Turner } else { 532666cc0b2SZachary Turner memcpy(&val, data, 8); 533666cc0b2SZachary Turner } 534666cc0b2SZachary Turner } 535666cc0b2SZachary Turner return val; 536666cc0b2SZachary Turner } 537666cc0b2SZachary Turner 538666cc0b2SZachary Turner //---------------------------------------------------------------------- 539666cc0b2SZachary Turner // GetU64 540666cc0b2SZachary Turner // 541666cc0b2SZachary Turner // Get multiple consecutive 64 bit values. Return true if the entire 542666cc0b2SZachary Turner // read succeeds and increment the offset pointed to by offset_ptr, else 543666cc0b2SZachary Turner // return false and leave the offset pointed to by offset_ptr unchanged. 544666cc0b2SZachary Turner //---------------------------------------------------------------------- 545666cc0b2SZachary Turner void *DataExtractor::GetU64(offset_t *offset_ptr, void *void_dst, 546666cc0b2SZachary Turner uint32_t count) const { 547666cc0b2SZachary Turner const size_t src_size = sizeof(uint64_t) * count; 548666cc0b2SZachary Turner const uint64_t *src = (const uint64_t *)GetData(offset_ptr, src_size); 549666cc0b2SZachary Turner if (src) { 550666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) { 551666cc0b2SZachary Turner uint64_t *dst_pos = (uint64_t *)void_dst; 552666cc0b2SZachary Turner uint64_t *dst_end = dst_pos + count; 553666cc0b2SZachary Turner const uint64_t *src_pos = src; 554666cc0b2SZachary Turner while (dst_pos < dst_end) { 555666cc0b2SZachary Turner *dst_pos = ReadSwapInt64(src_pos); 556666cc0b2SZachary Turner ++dst_pos; 557666cc0b2SZachary Turner ++src_pos; 558666cc0b2SZachary Turner } 559666cc0b2SZachary Turner } else { 560666cc0b2SZachary Turner memcpy(void_dst, src, src_size); 561666cc0b2SZachary Turner } 562666cc0b2SZachary Turner // Return a non-nullptr pointer to the converted data as an indicator of 563666cc0b2SZachary Turner // success 564666cc0b2SZachary Turner return void_dst; 565666cc0b2SZachary Turner } 566666cc0b2SZachary Turner return nullptr; 567666cc0b2SZachary Turner } 568666cc0b2SZachary Turner 569666cc0b2SZachary Turner uint32_t DataExtractor::GetMaxU32(offset_t *offset_ptr, 570666cc0b2SZachary Turner size_t byte_size) const { 571*dbd7c338SPetr Pavlu lldbassert(byte_size > 0 && byte_size <= 4 && "GetMaxU32 invalid byte_size!"); 572*dbd7c338SPetr Pavlu return GetMaxU64(offset_ptr, byte_size); 573*dbd7c338SPetr Pavlu } 574*dbd7c338SPetr Pavlu 575*dbd7c338SPetr Pavlu uint64_t DataExtractor::GetMaxU64(offset_t *offset_ptr, 576*dbd7c338SPetr Pavlu size_t byte_size) const { 577*dbd7c338SPetr Pavlu lldbassert(byte_size > 0 && byte_size <= 8 && "GetMaxU64 invalid byte_size!"); 578666cc0b2SZachary Turner switch (byte_size) { 579666cc0b2SZachary Turner case 1: 580666cc0b2SZachary Turner return GetU8(offset_ptr); 581666cc0b2SZachary Turner case 2: 582666cc0b2SZachary Turner return GetU16(offset_ptr); 583666cc0b2SZachary Turner case 4: 584666cc0b2SZachary Turner return GetU32(offset_ptr); 585666cc0b2SZachary Turner case 8: 586666cc0b2SZachary Turner return GetU64(offset_ptr); 587*dbd7c338SPetr Pavlu default: { 588*dbd7c338SPetr Pavlu // General case. 589*dbd7c338SPetr Pavlu const uint8_t *data = 590*dbd7c338SPetr Pavlu static_cast<const uint8_t *>(GetData(offset_ptr, byte_size)); 591*dbd7c338SPetr Pavlu if (data == nullptr) 592*dbd7c338SPetr Pavlu return 0; 593*dbd7c338SPetr Pavlu return ReadMaxInt64(data, byte_size, m_byte_order); 594*dbd7c338SPetr Pavlu } 595666cc0b2SZachary Turner } 596666cc0b2SZachary Turner return 0; 597666cc0b2SZachary Turner } 598666cc0b2SZachary Turner 599666cc0b2SZachary Turner uint64_t DataExtractor::GetMaxU64_unchecked(offset_t *offset_ptr, 600*dbd7c338SPetr Pavlu size_t byte_size) const { 601*dbd7c338SPetr Pavlu switch (byte_size) { 602666cc0b2SZachary Turner case 1: 603666cc0b2SZachary Turner return GetU8_unchecked(offset_ptr); 604666cc0b2SZachary Turner case 2: 605666cc0b2SZachary Turner return GetU16_unchecked(offset_ptr); 606666cc0b2SZachary Turner case 4: 607666cc0b2SZachary Turner return GetU32_unchecked(offset_ptr); 608666cc0b2SZachary Turner case 8: 609666cc0b2SZachary Turner return GetU64_unchecked(offset_ptr); 610*dbd7c338SPetr Pavlu default: { 611*dbd7c338SPetr Pavlu uint64_t res = ReadMaxInt64(&m_start[*offset_ptr], byte_size, m_byte_order); 612*dbd7c338SPetr Pavlu *offset_ptr += byte_size; 613*dbd7c338SPetr Pavlu return res; 614*dbd7c338SPetr Pavlu } 615666cc0b2SZachary Turner } 616666cc0b2SZachary Turner return 0; 617666cc0b2SZachary Turner } 618666cc0b2SZachary Turner 619*dbd7c338SPetr Pavlu int64_t DataExtractor::GetMaxS64(offset_t *offset_ptr, size_t byte_size) const { 620*dbd7c338SPetr Pavlu uint64_t u64 = GetMaxU64(offset_ptr, byte_size); 621*dbd7c338SPetr Pavlu return llvm::SignExtend64(u64, 8 * byte_size); 622666cc0b2SZachary Turner } 623666cc0b2SZachary Turner 624666cc0b2SZachary Turner uint64_t DataExtractor::GetMaxU64Bitfield(offset_t *offset_ptr, size_t size, 625666cc0b2SZachary Turner uint32_t bitfield_bit_size, 626666cc0b2SZachary Turner uint32_t bitfield_bit_offset) const { 627666cc0b2SZachary Turner uint64_t uval64 = GetMaxU64(offset_ptr, size); 628666cc0b2SZachary Turner if (bitfield_bit_size > 0) { 629666cc0b2SZachary Turner int32_t lsbcount = bitfield_bit_offset; 630666cc0b2SZachary Turner if (m_byte_order == eByteOrderBig) 631666cc0b2SZachary Turner lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size; 632666cc0b2SZachary Turner if (lsbcount > 0) 633666cc0b2SZachary Turner uval64 >>= lsbcount; 634666cc0b2SZachary Turner uint64_t bitfield_mask = ((1ul << bitfield_bit_size) - 1); 635666cc0b2SZachary Turner if (!bitfield_mask && bitfield_bit_offset == 0 && bitfield_bit_size == 64) 636666cc0b2SZachary Turner return uval64; 637666cc0b2SZachary Turner uval64 &= bitfield_mask; 638666cc0b2SZachary Turner } 639666cc0b2SZachary Turner return uval64; 640666cc0b2SZachary Turner } 641666cc0b2SZachary Turner 642666cc0b2SZachary Turner int64_t DataExtractor::GetMaxS64Bitfield(offset_t *offset_ptr, size_t size, 643666cc0b2SZachary Turner uint32_t bitfield_bit_size, 644666cc0b2SZachary Turner uint32_t bitfield_bit_offset) const { 645666cc0b2SZachary Turner int64_t sval64 = GetMaxS64(offset_ptr, size); 646666cc0b2SZachary Turner if (bitfield_bit_size > 0) { 647666cc0b2SZachary Turner int32_t lsbcount = bitfield_bit_offset; 648666cc0b2SZachary Turner if (m_byte_order == eByteOrderBig) 649666cc0b2SZachary Turner lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size; 650666cc0b2SZachary Turner if (lsbcount > 0) 651666cc0b2SZachary Turner sval64 >>= lsbcount; 652666cc0b2SZachary Turner uint64_t bitfield_mask = (((uint64_t)1) << bitfield_bit_size) - 1; 653666cc0b2SZachary Turner sval64 &= bitfield_mask; 654666cc0b2SZachary Turner // sign extend if needed 655666cc0b2SZachary Turner if (sval64 & (((uint64_t)1) << (bitfield_bit_size - 1))) 656666cc0b2SZachary Turner sval64 |= ~bitfield_mask; 657666cc0b2SZachary Turner } 658666cc0b2SZachary Turner return sval64; 659666cc0b2SZachary Turner } 660666cc0b2SZachary Turner 661666cc0b2SZachary Turner float DataExtractor::GetFloat(offset_t *offset_ptr) const { 662666cc0b2SZachary Turner typedef float float_type; 663666cc0b2SZachary Turner float_type val = 0.0; 664666cc0b2SZachary Turner const size_t src_size = sizeof(float_type); 665666cc0b2SZachary Turner const float_type *src = (const float_type *)GetData(offset_ptr, src_size); 666666cc0b2SZachary Turner if (src) { 667666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) { 668666cc0b2SZachary Turner const uint8_t *src_data = (const uint8_t *)src; 669666cc0b2SZachary Turner uint8_t *dst_data = (uint8_t *)&val; 670666cc0b2SZachary Turner for (size_t i = 0; i < sizeof(float_type); ++i) 671666cc0b2SZachary Turner dst_data[sizeof(float_type) - 1 - i] = src_data[i]; 672666cc0b2SZachary Turner } else { 673666cc0b2SZachary Turner val = *src; 674666cc0b2SZachary Turner } 675666cc0b2SZachary Turner } 676666cc0b2SZachary Turner return val; 677666cc0b2SZachary Turner } 678666cc0b2SZachary Turner 679666cc0b2SZachary Turner double DataExtractor::GetDouble(offset_t *offset_ptr) const { 680666cc0b2SZachary Turner typedef double float_type; 681666cc0b2SZachary Turner float_type val = 0.0; 682666cc0b2SZachary Turner const size_t src_size = sizeof(float_type); 683666cc0b2SZachary Turner const float_type *src = (const float_type *)GetData(offset_ptr, src_size); 684666cc0b2SZachary Turner if (src) { 685666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) { 686666cc0b2SZachary Turner const uint8_t *src_data = (const uint8_t *)src; 687666cc0b2SZachary Turner uint8_t *dst_data = (uint8_t *)&val; 688666cc0b2SZachary Turner for (size_t i = 0; i < sizeof(float_type); ++i) 689666cc0b2SZachary Turner dst_data[sizeof(float_type) - 1 - i] = src_data[i]; 690666cc0b2SZachary Turner } else { 691666cc0b2SZachary Turner val = *src; 692666cc0b2SZachary Turner } 693666cc0b2SZachary Turner } 694666cc0b2SZachary Turner return val; 695666cc0b2SZachary Turner } 696666cc0b2SZachary Turner 697666cc0b2SZachary Turner long double DataExtractor::GetLongDouble(offset_t *offset_ptr) const { 698666cc0b2SZachary Turner long double val = 0.0; 699666cc0b2SZachary Turner #if defined(__i386__) || defined(__amd64__) || defined(__x86_64__) || \ 700666cc0b2SZachary Turner defined(_M_IX86) || defined(_M_IA64) || defined(_M_X64) 701666cc0b2SZachary Turner *offset_ptr += CopyByteOrderedData(*offset_ptr, 10, &val, sizeof(val), 702666cc0b2SZachary Turner endian::InlHostByteOrder()); 703666cc0b2SZachary Turner #else 704666cc0b2SZachary Turner *offset_ptr += CopyByteOrderedData(*offset_ptr, sizeof(val), &val, 705666cc0b2SZachary Turner sizeof(val), endian::InlHostByteOrder()); 706666cc0b2SZachary Turner #endif 707666cc0b2SZachary Turner return val; 708666cc0b2SZachary Turner } 709666cc0b2SZachary Turner 710666cc0b2SZachary Turner //------------------------------------------------------------------ 711666cc0b2SZachary Turner // Extract a single address from the data and update the offset 712666cc0b2SZachary Turner // pointed to by "offset_ptr". The size of the extracted address 713666cc0b2SZachary Turner // comes from the "this->m_addr_size" member variable and should be 714666cc0b2SZachary Turner // set correctly prior to extracting any address values. 715666cc0b2SZachary Turner // 716666cc0b2SZachary Turner // RETURNS the address that was extracted, or zero on failure. 717666cc0b2SZachary Turner //------------------------------------------------------------------ 718666cc0b2SZachary Turner uint64_t DataExtractor::GetAddress(offset_t *offset_ptr) const { 719666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG 720666cc0b2SZachary Turner assert(m_addr_size == 4 || m_addr_size == 8); 721666cc0b2SZachary Turner #endif 722666cc0b2SZachary Turner return GetMaxU64(offset_ptr, m_addr_size); 723666cc0b2SZachary Turner } 724666cc0b2SZachary Turner 725666cc0b2SZachary Turner uint64_t DataExtractor::GetAddress_unchecked(offset_t *offset_ptr) const { 726666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG 727666cc0b2SZachary Turner assert(m_addr_size == 4 || m_addr_size == 8); 728666cc0b2SZachary Turner #endif 729666cc0b2SZachary Turner return GetMaxU64_unchecked(offset_ptr, m_addr_size); 730666cc0b2SZachary Turner } 731666cc0b2SZachary Turner 732666cc0b2SZachary Turner //------------------------------------------------------------------ 733666cc0b2SZachary Turner // Extract a single pointer from the data and update the offset 734666cc0b2SZachary Turner // pointed to by "offset_ptr". The size of the extracted pointer 735666cc0b2SZachary Turner // comes from the "this->m_addr_size" member variable and should be 736666cc0b2SZachary Turner // set correctly prior to extracting any pointer values. 737666cc0b2SZachary Turner // 738666cc0b2SZachary Turner // RETURNS the pointer that was extracted, or zero on failure. 739666cc0b2SZachary Turner //------------------------------------------------------------------ 740666cc0b2SZachary Turner uint64_t DataExtractor::GetPointer(offset_t *offset_ptr) const { 741666cc0b2SZachary Turner #ifdef LLDB_CONFIGURATION_DEBUG 742666cc0b2SZachary Turner assert(m_addr_size == 4 || m_addr_size == 8); 743666cc0b2SZachary Turner #endif 744666cc0b2SZachary Turner return GetMaxU64(offset_ptr, m_addr_size); 745666cc0b2SZachary Turner } 746666cc0b2SZachary Turner 747666cc0b2SZachary Turner size_t DataExtractor::ExtractBytes(offset_t offset, offset_t length, 748666cc0b2SZachary Turner ByteOrder dst_byte_order, void *dst) const { 749666cc0b2SZachary Turner const uint8_t *src = PeekData(offset, length); 750666cc0b2SZachary Turner if (src) { 751666cc0b2SZachary Turner if (dst_byte_order != GetByteOrder()) { 752666cc0b2SZachary Turner // Validate that only a word- or register-sized dst is byte swapped 753666cc0b2SZachary Turner assert(length == 1 || length == 2 || length == 4 || length == 8 || 754666cc0b2SZachary Turner length == 10 || length == 16 || length == 32); 755666cc0b2SZachary Turner 756666cc0b2SZachary Turner for (uint32_t i = 0; i < length; ++i) 757666cc0b2SZachary Turner ((uint8_t *)dst)[i] = src[length - i - 1]; 758666cc0b2SZachary Turner } else 759666cc0b2SZachary Turner ::memcpy(dst, src, length); 760666cc0b2SZachary Turner return length; 761666cc0b2SZachary Turner } 762666cc0b2SZachary Turner return 0; 763666cc0b2SZachary Turner } 764666cc0b2SZachary Turner 765666cc0b2SZachary Turner // Extract data as it exists in target memory 766666cc0b2SZachary Turner lldb::offset_t DataExtractor::CopyData(offset_t offset, offset_t length, 767666cc0b2SZachary Turner void *dst) const { 768666cc0b2SZachary Turner const uint8_t *src = PeekData(offset, length); 769666cc0b2SZachary Turner if (src) { 770666cc0b2SZachary Turner ::memcpy(dst, src, length); 771666cc0b2SZachary Turner return length; 772666cc0b2SZachary Turner } 773666cc0b2SZachary Turner return 0; 774666cc0b2SZachary Turner } 775666cc0b2SZachary Turner 776666cc0b2SZachary Turner // Extract data and swap if needed when doing the copy 777666cc0b2SZachary Turner lldb::offset_t 778666cc0b2SZachary Turner DataExtractor::CopyByteOrderedData(offset_t src_offset, offset_t src_len, 779666cc0b2SZachary Turner void *dst_void_ptr, offset_t dst_len, 780666cc0b2SZachary Turner ByteOrder dst_byte_order) const { 781666cc0b2SZachary Turner // Validate the source info 782666cc0b2SZachary Turner if (!ValidOffsetForDataOfSize(src_offset, src_len)) 783666cc0b2SZachary Turner assert(ValidOffsetForDataOfSize(src_offset, src_len)); 784666cc0b2SZachary Turner assert(src_len > 0); 785666cc0b2SZachary Turner assert(m_byte_order == eByteOrderBig || m_byte_order == eByteOrderLittle); 786666cc0b2SZachary Turner 787666cc0b2SZachary Turner // Validate the destination info 788666cc0b2SZachary Turner assert(dst_void_ptr != nullptr); 789666cc0b2SZachary Turner assert(dst_len > 0); 790666cc0b2SZachary Turner assert(dst_byte_order == eByteOrderBig || dst_byte_order == eByteOrderLittle); 791666cc0b2SZachary Turner 792666cc0b2SZachary Turner // Validate that only a word- or register-sized dst is byte swapped 793666cc0b2SZachary Turner assert(dst_byte_order == m_byte_order || dst_len == 1 || dst_len == 2 || 794666cc0b2SZachary Turner dst_len == 4 || dst_len == 8 || dst_len == 10 || dst_len == 16 || 795666cc0b2SZachary Turner dst_len == 32); 796666cc0b2SZachary Turner 797666cc0b2SZachary Turner // Must have valid byte orders set in this object and for destination 798666cc0b2SZachary Turner if (!(dst_byte_order == eByteOrderBig || 799666cc0b2SZachary Turner dst_byte_order == eByteOrderLittle) || 800666cc0b2SZachary Turner !(m_byte_order == eByteOrderBig || m_byte_order == eByteOrderLittle)) 801666cc0b2SZachary Turner return 0; 802666cc0b2SZachary Turner 803666cc0b2SZachary Turner uint8_t *dst = (uint8_t *)dst_void_ptr; 804666cc0b2SZachary Turner const uint8_t *src = (const uint8_t *)PeekData(src_offset, src_len); 805666cc0b2SZachary Turner if (src) { 806666cc0b2SZachary Turner if (dst_len >= src_len) { 807666cc0b2SZachary Turner // We are copying the entire value from src into dst. 808666cc0b2SZachary Turner // Calculate how many, if any, zeroes we need for the most 809666cc0b2SZachary Turner // significant bytes if "dst_len" is greater than "src_len"... 810666cc0b2SZachary Turner const size_t num_zeroes = dst_len - src_len; 811666cc0b2SZachary Turner if (dst_byte_order == eByteOrderBig) { 812666cc0b2SZachary Turner // Big endian, so we lead with zeroes... 813666cc0b2SZachary Turner if (num_zeroes > 0) 814666cc0b2SZachary Turner ::memset(dst, 0, num_zeroes); 815666cc0b2SZachary Turner // Then either copy or swap the rest 816666cc0b2SZachary Turner if (m_byte_order == eByteOrderBig) { 817666cc0b2SZachary Turner ::memcpy(dst + num_zeroes, src, src_len); 818666cc0b2SZachary Turner } else { 819666cc0b2SZachary Turner for (uint32_t i = 0; i < src_len; ++i) 820666cc0b2SZachary Turner dst[i + num_zeroes] = src[src_len - 1 - i]; 821666cc0b2SZachary Turner } 822666cc0b2SZachary Turner } else { 823666cc0b2SZachary Turner // Little endian destination, so we lead the value bytes 824666cc0b2SZachary Turner if (m_byte_order == eByteOrderBig) { 825666cc0b2SZachary Turner for (uint32_t i = 0; i < src_len; ++i) 826666cc0b2SZachary Turner dst[i] = src[src_len - 1 - i]; 827666cc0b2SZachary Turner } else { 828666cc0b2SZachary Turner ::memcpy(dst, src, src_len); 829666cc0b2SZachary Turner } 830666cc0b2SZachary Turner // And zero the rest... 831666cc0b2SZachary Turner if (num_zeroes > 0) 832666cc0b2SZachary Turner ::memset(dst + src_len, 0, num_zeroes); 833666cc0b2SZachary Turner } 834666cc0b2SZachary Turner return src_len; 835666cc0b2SZachary Turner } else { 836666cc0b2SZachary Turner // We are only copying some of the value from src into dst.. 837666cc0b2SZachary Turner 838666cc0b2SZachary Turner if (dst_byte_order == eByteOrderBig) { 839666cc0b2SZachary Turner // Big endian dst 840666cc0b2SZachary Turner if (m_byte_order == eByteOrderBig) { 841666cc0b2SZachary Turner // Big endian dst, with big endian src 842666cc0b2SZachary Turner ::memcpy(dst, src + (src_len - dst_len), dst_len); 843666cc0b2SZachary Turner } else { 844666cc0b2SZachary Turner // Big endian dst, with little endian src 845666cc0b2SZachary Turner for (uint32_t i = 0; i < dst_len; ++i) 846666cc0b2SZachary Turner dst[i] = src[dst_len - 1 - i]; 847666cc0b2SZachary Turner } 848666cc0b2SZachary Turner } else { 849666cc0b2SZachary Turner // Little endian dst 850666cc0b2SZachary Turner if (m_byte_order == eByteOrderBig) { 851666cc0b2SZachary Turner // Little endian dst, with big endian src 852666cc0b2SZachary Turner for (uint32_t i = 0; i < dst_len; ++i) 853666cc0b2SZachary Turner dst[i] = src[src_len - 1 - i]; 854666cc0b2SZachary Turner } else { 855666cc0b2SZachary Turner // Little endian dst, with big endian src 856666cc0b2SZachary Turner ::memcpy(dst, src, dst_len); 857666cc0b2SZachary Turner } 858666cc0b2SZachary Turner } 859666cc0b2SZachary Turner return dst_len; 860666cc0b2SZachary Turner } 861666cc0b2SZachary Turner } 862666cc0b2SZachary Turner return 0; 863666cc0b2SZachary Turner } 864666cc0b2SZachary Turner 865666cc0b2SZachary Turner //---------------------------------------------------------------------- 866666cc0b2SZachary Turner // Extracts a variable length NULL terminated C string from 867666cc0b2SZachary Turner // the data at the offset pointed to by "offset_ptr". The 868666cc0b2SZachary Turner // "offset_ptr" will be updated with the offset of the byte that 869666cc0b2SZachary Turner // follows the NULL terminator byte. 870666cc0b2SZachary Turner // 871666cc0b2SZachary Turner // If the offset pointed to by "offset_ptr" is out of bounds, or if 872666cc0b2SZachary Turner // "length" is non-zero and there aren't enough available 873666cc0b2SZachary Turner // bytes, nullptr will be returned and "offset_ptr" will not be 874666cc0b2SZachary Turner // updated. 875666cc0b2SZachary Turner //---------------------------------------------------------------------- 876666cc0b2SZachary Turner const char *DataExtractor::GetCStr(offset_t *offset_ptr) const { 877666cc0b2SZachary Turner const char *cstr = (const char *)PeekData(*offset_ptr, 1); 878666cc0b2SZachary Turner if (cstr) { 879666cc0b2SZachary Turner const char *cstr_end = cstr; 880666cc0b2SZachary Turner const char *end = (const char *)m_end; 881666cc0b2SZachary Turner while (cstr_end < end && *cstr_end) 882666cc0b2SZachary Turner ++cstr_end; 883666cc0b2SZachary Turner 884666cc0b2SZachary Turner // Now we are either at the end of the data or we point to the 885666cc0b2SZachary Turner // NULL C string terminator with cstr_end... 886666cc0b2SZachary Turner if (*cstr_end == '\0') { 887666cc0b2SZachary Turner // Advance the offset with one extra byte for the NULL terminator 888666cc0b2SZachary Turner *offset_ptr += (cstr_end - cstr + 1); 889666cc0b2SZachary Turner return cstr; 890666cc0b2SZachary Turner } 891666cc0b2SZachary Turner 892666cc0b2SZachary Turner // We reached the end of the data without finding a NULL C string 893666cc0b2SZachary Turner // terminator. Fall through and return nullptr otherwise anyone that 894666cc0b2SZachary Turner // would have used the result as a C string can wander into 895666cc0b2SZachary Turner // unknown memory... 896666cc0b2SZachary Turner } 897666cc0b2SZachary Turner return nullptr; 898666cc0b2SZachary Turner } 899666cc0b2SZachary Turner 900666cc0b2SZachary Turner //---------------------------------------------------------------------- 901666cc0b2SZachary Turner // Extracts a NULL terminated C string from the fixed length field of 902666cc0b2SZachary Turner // length "len" at the offset pointed to by "offset_ptr". 903666cc0b2SZachary Turner // The "offset_ptr" will be updated with the offset of the byte that 904666cc0b2SZachary Turner // follows the fixed length field. 905666cc0b2SZachary Turner // 906666cc0b2SZachary Turner // If the offset pointed to by "offset_ptr" is out of bounds, or if 907666cc0b2SZachary Turner // the offset plus the length of the field is out of bounds, or if the 908666cc0b2SZachary Turner // field does not contain a NULL terminator byte, nullptr will be returned 909666cc0b2SZachary Turner // and "offset_ptr" will not be updated. 910666cc0b2SZachary Turner //---------------------------------------------------------------------- 911666cc0b2SZachary Turner const char *DataExtractor::GetCStr(offset_t *offset_ptr, offset_t len) const { 912666cc0b2SZachary Turner const char *cstr = (const char *)PeekData(*offset_ptr, len); 913666cc0b2SZachary Turner if (cstr != nullptr) { 914666cc0b2SZachary Turner if (memchr(cstr, '\0', len) == nullptr) { 915666cc0b2SZachary Turner return nullptr; 916666cc0b2SZachary Turner } 917666cc0b2SZachary Turner *offset_ptr += len; 918666cc0b2SZachary Turner return cstr; 919666cc0b2SZachary Turner } 920666cc0b2SZachary Turner return nullptr; 921666cc0b2SZachary Turner } 922666cc0b2SZachary Turner 923666cc0b2SZachary Turner //------------------------------------------------------------------ 924666cc0b2SZachary Turner // Peeks at a string in the contained data. No verification is done 925666cc0b2SZachary Turner // to make sure the entire string lies within the bounds of this 926666cc0b2SZachary Turner // object's data, only "offset" is verified to be a valid offset. 927666cc0b2SZachary Turner // 928666cc0b2SZachary Turner // Returns a valid C string pointer if "offset" is a valid offset in 929666cc0b2SZachary Turner // this object's data, else nullptr is returned. 930666cc0b2SZachary Turner //------------------------------------------------------------------ 931666cc0b2SZachary Turner const char *DataExtractor::PeekCStr(offset_t offset) const { 932666cc0b2SZachary Turner return (const char *)PeekData(offset, 1); 933666cc0b2SZachary Turner } 934666cc0b2SZachary Turner 935666cc0b2SZachary Turner //---------------------------------------------------------------------- 936666cc0b2SZachary Turner // Extracts an unsigned LEB128 number from this object's data 937666cc0b2SZachary Turner // starting at the offset pointed to by "offset_ptr". The offset 938666cc0b2SZachary Turner // pointed to by "offset_ptr" will be updated with the offset of the 939666cc0b2SZachary Turner // byte following the last extracted byte. 940666cc0b2SZachary Turner // 941666cc0b2SZachary Turner // Returned the extracted integer value. 942666cc0b2SZachary Turner //---------------------------------------------------------------------- 943666cc0b2SZachary Turner uint64_t DataExtractor::GetULEB128(offset_t *offset_ptr) const { 944666cc0b2SZachary Turner const uint8_t *src = (const uint8_t *)PeekData(*offset_ptr, 1); 945666cc0b2SZachary Turner if (src == nullptr) 946666cc0b2SZachary Turner return 0; 947666cc0b2SZachary Turner 948666cc0b2SZachary Turner const uint8_t *end = m_end; 949666cc0b2SZachary Turner 950666cc0b2SZachary Turner if (src < end) { 951666cc0b2SZachary Turner uint64_t result = *src++; 952666cc0b2SZachary Turner if (result >= 0x80) { 953666cc0b2SZachary Turner result &= 0x7f; 954666cc0b2SZachary Turner int shift = 7; 955666cc0b2SZachary Turner while (src < end) { 956666cc0b2SZachary Turner uint8_t byte = *src++; 957666cc0b2SZachary Turner result |= (uint64_t)(byte & 0x7f) << shift; 958666cc0b2SZachary Turner if ((byte & 0x80) == 0) 959666cc0b2SZachary Turner break; 960666cc0b2SZachary Turner shift += 7; 961666cc0b2SZachary Turner } 962666cc0b2SZachary Turner } 963666cc0b2SZachary Turner *offset_ptr = src - m_start; 964666cc0b2SZachary Turner return result; 965666cc0b2SZachary Turner } 966666cc0b2SZachary Turner 967666cc0b2SZachary Turner return 0; 968666cc0b2SZachary Turner } 969666cc0b2SZachary Turner 970666cc0b2SZachary Turner //---------------------------------------------------------------------- 971666cc0b2SZachary Turner // Extracts an signed LEB128 number from this object's data 972666cc0b2SZachary Turner // starting at the offset pointed to by "offset_ptr". The offset 973666cc0b2SZachary Turner // pointed to by "offset_ptr" will be updated with the offset of the 974666cc0b2SZachary Turner // byte following the last extracted byte. 975666cc0b2SZachary Turner // 976666cc0b2SZachary Turner // Returned the extracted integer value. 977666cc0b2SZachary Turner //---------------------------------------------------------------------- 978666cc0b2SZachary Turner int64_t DataExtractor::GetSLEB128(offset_t *offset_ptr) const { 979666cc0b2SZachary Turner const uint8_t *src = (const uint8_t *)PeekData(*offset_ptr, 1); 980666cc0b2SZachary Turner if (src == nullptr) 981666cc0b2SZachary Turner return 0; 982666cc0b2SZachary Turner 983666cc0b2SZachary Turner const uint8_t *end = m_end; 984666cc0b2SZachary Turner 985666cc0b2SZachary Turner if (src < end) { 986666cc0b2SZachary Turner int64_t result = 0; 987666cc0b2SZachary Turner int shift = 0; 988666cc0b2SZachary Turner int size = sizeof(int64_t) * 8; 989666cc0b2SZachary Turner 990666cc0b2SZachary Turner uint8_t byte = 0; 991666cc0b2SZachary Turner int bytecount = 0; 992666cc0b2SZachary Turner 993666cc0b2SZachary Turner while (src < end) { 994666cc0b2SZachary Turner bytecount++; 995666cc0b2SZachary Turner byte = *src++; 996666cc0b2SZachary Turner result |= (int64_t)(byte & 0x7f) << shift; 997666cc0b2SZachary Turner shift += 7; 998666cc0b2SZachary Turner if ((byte & 0x80) == 0) 999666cc0b2SZachary Turner break; 1000666cc0b2SZachary Turner } 1001666cc0b2SZachary Turner 1002666cc0b2SZachary Turner // Sign bit of byte is 2nd high order bit (0x40) 1003666cc0b2SZachary Turner if (shift < size && (byte & 0x40)) 1004666cc0b2SZachary Turner result |= -(1 << shift); 1005666cc0b2SZachary Turner 1006666cc0b2SZachary Turner *offset_ptr += bytecount; 1007666cc0b2SZachary Turner return result; 1008666cc0b2SZachary Turner } 1009666cc0b2SZachary Turner return 0; 1010666cc0b2SZachary Turner } 1011666cc0b2SZachary Turner 1012666cc0b2SZachary Turner //---------------------------------------------------------------------- 1013666cc0b2SZachary Turner // Skips a ULEB128 number (signed or unsigned) from this object's 1014666cc0b2SZachary Turner // data starting at the offset pointed to by "offset_ptr". The 1015666cc0b2SZachary Turner // offset pointed to by "offset_ptr" will be updated with the offset 1016666cc0b2SZachary Turner // of the byte following the last extracted byte. 1017666cc0b2SZachary Turner // 1018666cc0b2SZachary Turner // Returns the number of bytes consumed during the extraction. 1019666cc0b2SZachary Turner //---------------------------------------------------------------------- 1020666cc0b2SZachary Turner uint32_t DataExtractor::Skip_LEB128(offset_t *offset_ptr) const { 1021666cc0b2SZachary Turner uint32_t bytes_consumed = 0; 1022666cc0b2SZachary Turner const uint8_t *src = (const uint8_t *)PeekData(*offset_ptr, 1); 1023666cc0b2SZachary Turner if (src == nullptr) 1024666cc0b2SZachary Turner return 0; 1025666cc0b2SZachary Turner 1026666cc0b2SZachary Turner const uint8_t *end = m_end; 1027666cc0b2SZachary Turner 1028666cc0b2SZachary Turner if (src < end) { 1029666cc0b2SZachary Turner const uint8_t *src_pos = src; 1030666cc0b2SZachary Turner while ((src_pos < end) && (*src_pos++ & 0x80)) 1031666cc0b2SZachary Turner ++bytes_consumed; 1032666cc0b2SZachary Turner *offset_ptr += src_pos - src; 1033666cc0b2SZachary Turner } 1034666cc0b2SZachary Turner return bytes_consumed; 1035666cc0b2SZachary Turner } 1036666cc0b2SZachary Turner 1037666cc0b2SZachary Turner //---------------------------------------------------------------------- 1038666cc0b2SZachary Turner // Dumps bytes from this object's data to the stream "s" starting 1039666cc0b2SZachary Turner // "start_offset" bytes into this data, and ending with the byte 1040666cc0b2SZachary Turner // before "end_offset". "base_addr" will be added to the offset 1041666cc0b2SZachary Turner // into the dumped data when showing the offset into the data in the 1042666cc0b2SZachary Turner // output information. "num_per_line" objects of type "type" will 1043666cc0b2SZachary Turner // be dumped with the option to override the format for each object 1044666cc0b2SZachary Turner // with "type_format". "type_format" is a printf style formatting 1045666cc0b2SZachary Turner // string. If "type_format" is nullptr, then an appropriate format 1046666cc0b2SZachary Turner // string will be used for the supplied "type". If the stream "s" 1047666cc0b2SZachary Turner // is nullptr, then the output will be send to Log(). 1048666cc0b2SZachary Turner //---------------------------------------------------------------------- 1049666cc0b2SZachary Turner lldb::offset_t DataExtractor::PutToLog(Log *log, offset_t start_offset, 1050666cc0b2SZachary Turner offset_t length, uint64_t base_addr, 1051666cc0b2SZachary Turner uint32_t num_per_line, 1052666cc0b2SZachary Turner DataExtractor::Type type, 1053666cc0b2SZachary Turner const char *format) const { 1054666cc0b2SZachary Turner if (log == nullptr) 1055666cc0b2SZachary Turner return start_offset; 1056666cc0b2SZachary Turner 1057666cc0b2SZachary Turner offset_t offset; 1058666cc0b2SZachary Turner offset_t end_offset; 1059666cc0b2SZachary Turner uint32_t count; 1060666cc0b2SZachary Turner StreamString sstr; 1061666cc0b2SZachary Turner for (offset = start_offset, end_offset = offset + length, count = 0; 1062666cc0b2SZachary Turner ValidOffset(offset) && offset < end_offset; ++count) { 1063666cc0b2SZachary Turner if ((count % num_per_line) == 0) { 1064666cc0b2SZachary Turner // Print out any previous string 1065666cc0b2SZachary Turner if (sstr.GetSize() > 0) { 1066666cc0b2SZachary Turner log->PutString(sstr.GetString()); 1067666cc0b2SZachary Turner sstr.Clear(); 1068666cc0b2SZachary Turner } 1069666cc0b2SZachary Turner // Reset string offset and fill the current line string with address: 1070666cc0b2SZachary Turner if (base_addr != LLDB_INVALID_ADDRESS) 1071666cc0b2SZachary Turner sstr.Printf("0x%8.8" PRIx64 ":", 1072666cc0b2SZachary Turner (uint64_t)(base_addr + (offset - start_offset))); 1073666cc0b2SZachary Turner } 1074666cc0b2SZachary Turner 1075666cc0b2SZachary Turner switch (type) { 1076666cc0b2SZachary Turner case TypeUInt8: 1077666cc0b2SZachary Turner sstr.Printf(format ? format : " %2.2x", GetU8(&offset)); 1078666cc0b2SZachary Turner break; 1079666cc0b2SZachary Turner case TypeChar: { 1080666cc0b2SZachary Turner char ch = GetU8(&offset); 1081666cc0b2SZachary Turner sstr.Printf(format ? format : " %c", isprint(ch) ? ch : ' '); 1082666cc0b2SZachary Turner } break; 1083666cc0b2SZachary Turner case TypeUInt16: 1084666cc0b2SZachary Turner sstr.Printf(format ? format : " %4.4x", GetU16(&offset)); 1085666cc0b2SZachary Turner break; 1086666cc0b2SZachary Turner case TypeUInt32: 1087666cc0b2SZachary Turner sstr.Printf(format ? format : " %8.8x", GetU32(&offset)); 1088666cc0b2SZachary Turner break; 1089666cc0b2SZachary Turner case TypeUInt64: 1090666cc0b2SZachary Turner sstr.Printf(format ? format : " %16.16" PRIx64, GetU64(&offset)); 1091666cc0b2SZachary Turner break; 1092666cc0b2SZachary Turner case TypePointer: 1093666cc0b2SZachary Turner sstr.Printf(format ? format : " 0x%" PRIx64, GetAddress(&offset)); 1094666cc0b2SZachary Turner break; 1095666cc0b2SZachary Turner case TypeULEB128: 1096666cc0b2SZachary Turner sstr.Printf(format ? format : " 0x%" PRIx64, GetULEB128(&offset)); 1097666cc0b2SZachary Turner break; 1098666cc0b2SZachary Turner case TypeSLEB128: 1099666cc0b2SZachary Turner sstr.Printf(format ? format : " %" PRId64, GetSLEB128(&offset)); 1100666cc0b2SZachary Turner break; 1101666cc0b2SZachary Turner } 1102666cc0b2SZachary Turner } 1103666cc0b2SZachary Turner 1104666cc0b2SZachary Turner if (!sstr.Empty()) 1105666cc0b2SZachary Turner log->PutString(sstr.GetString()); 1106666cc0b2SZachary Turner 1107666cc0b2SZachary Turner return offset; // Return the offset at which we ended up 1108666cc0b2SZachary Turner } 1109666cc0b2SZachary Turner 1110666cc0b2SZachary Turner //---------------------------------------------------------------------- 1111666cc0b2SZachary Turner // DumpUUID 1112666cc0b2SZachary Turner // 1113666cc0b2SZachary Turner // Dump out a UUID starting at 'offset' bytes into the buffer 1114666cc0b2SZachary Turner //---------------------------------------------------------------------- 1115666cc0b2SZachary Turner void DataExtractor::DumpUUID(Stream *s, offset_t offset) const { 1116666cc0b2SZachary Turner if (s) { 1117666cc0b2SZachary Turner const uint8_t *uuid_data = PeekData(offset, 16); 1118666cc0b2SZachary Turner if (uuid_data) { 1119666cc0b2SZachary Turner lldb_private::UUID uuid(uuid_data, 16); 1120666cc0b2SZachary Turner uuid.Dump(s); 1121666cc0b2SZachary Turner } else { 1122666cc0b2SZachary Turner s->Printf("<not enough data for UUID at offset 0x%8.8" PRIx64 ">", 1123666cc0b2SZachary Turner offset); 1124666cc0b2SZachary Turner } 1125666cc0b2SZachary Turner } 1126666cc0b2SZachary Turner } 1127666cc0b2SZachary Turner 1128666cc0b2SZachary Turner size_t DataExtractor::Copy(DataExtractor &dest_data) const { 1129666cc0b2SZachary Turner if (m_data_sp) { 1130666cc0b2SZachary Turner // we can pass along the SP to the data 1131666cc0b2SZachary Turner dest_data.SetData(m_data_sp); 1132666cc0b2SZachary Turner } else { 1133666cc0b2SZachary Turner const uint8_t *base_ptr = m_start; 1134666cc0b2SZachary Turner size_t data_size = GetByteSize(); 1135666cc0b2SZachary Turner dest_data.SetData(DataBufferSP(new DataBufferHeap(base_ptr, data_size))); 1136666cc0b2SZachary Turner } 1137666cc0b2SZachary Turner return GetByteSize(); 1138666cc0b2SZachary Turner } 1139666cc0b2SZachary Turner 1140666cc0b2SZachary Turner bool DataExtractor::Append(DataExtractor &rhs) { 1141666cc0b2SZachary Turner if (rhs.GetByteOrder() != GetByteOrder()) 1142666cc0b2SZachary Turner return false; 1143666cc0b2SZachary Turner 1144666cc0b2SZachary Turner if (rhs.GetByteSize() == 0) 1145666cc0b2SZachary Turner return true; 1146666cc0b2SZachary Turner 1147666cc0b2SZachary Turner if (GetByteSize() == 0) 1148666cc0b2SZachary Turner return (rhs.Copy(*this) > 0); 1149666cc0b2SZachary Turner 1150666cc0b2SZachary Turner size_t bytes = GetByteSize() + rhs.GetByteSize(); 1151666cc0b2SZachary Turner 1152666cc0b2SZachary Turner DataBufferHeap *buffer_heap_ptr = nullptr; 1153666cc0b2SZachary Turner DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0)); 1154666cc0b2SZachary Turner 1155666cc0b2SZachary Turner if (!buffer_sp || buffer_heap_ptr == nullptr) 1156666cc0b2SZachary Turner return false; 1157666cc0b2SZachary Turner 1158666cc0b2SZachary Turner uint8_t *bytes_ptr = buffer_heap_ptr->GetBytes(); 1159666cc0b2SZachary Turner 1160666cc0b2SZachary Turner memcpy(bytes_ptr, GetDataStart(), GetByteSize()); 1161666cc0b2SZachary Turner memcpy(bytes_ptr + GetByteSize(), rhs.GetDataStart(), rhs.GetByteSize()); 1162666cc0b2SZachary Turner 1163666cc0b2SZachary Turner SetData(buffer_sp); 1164666cc0b2SZachary Turner 1165666cc0b2SZachary Turner return true; 1166666cc0b2SZachary Turner } 1167666cc0b2SZachary Turner 1168666cc0b2SZachary Turner bool DataExtractor::Append(void *buf, offset_t length) { 1169666cc0b2SZachary Turner if (buf == nullptr) 1170666cc0b2SZachary Turner return false; 1171666cc0b2SZachary Turner 1172666cc0b2SZachary Turner if (length == 0) 1173666cc0b2SZachary Turner return true; 1174666cc0b2SZachary Turner 1175666cc0b2SZachary Turner size_t bytes = GetByteSize() + length; 1176666cc0b2SZachary Turner 1177666cc0b2SZachary Turner DataBufferHeap *buffer_heap_ptr = nullptr; 1178666cc0b2SZachary Turner DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0)); 1179666cc0b2SZachary Turner 1180666cc0b2SZachary Turner if (!buffer_sp || buffer_heap_ptr == nullptr) 1181666cc0b2SZachary Turner return false; 1182666cc0b2SZachary Turner 1183666cc0b2SZachary Turner uint8_t *bytes_ptr = buffer_heap_ptr->GetBytes(); 1184666cc0b2SZachary Turner 1185666cc0b2SZachary Turner if (GetByteSize() > 0) 1186666cc0b2SZachary Turner memcpy(bytes_ptr, GetDataStart(), GetByteSize()); 1187666cc0b2SZachary Turner 1188666cc0b2SZachary Turner memcpy(bytes_ptr + GetByteSize(), buf, length); 1189666cc0b2SZachary Turner 1190666cc0b2SZachary Turner SetData(buffer_sp); 1191666cc0b2SZachary Turner 1192666cc0b2SZachary Turner return true; 1193666cc0b2SZachary Turner } 1194666cc0b2SZachary Turner 1195666cc0b2SZachary Turner void DataExtractor::Checksum(llvm::SmallVectorImpl<uint8_t> &dest, 1196666cc0b2SZachary Turner uint64_t max_data) { 1197666cc0b2SZachary Turner if (max_data == 0) 1198666cc0b2SZachary Turner max_data = GetByteSize(); 1199666cc0b2SZachary Turner else 1200666cc0b2SZachary Turner max_data = std::min(max_data, GetByteSize()); 1201666cc0b2SZachary Turner 1202666cc0b2SZachary Turner llvm::MD5 md5; 1203666cc0b2SZachary Turner 1204666cc0b2SZachary Turner const llvm::ArrayRef<uint8_t> data(GetDataStart(), max_data); 1205666cc0b2SZachary Turner md5.update(data); 1206666cc0b2SZachary Turner 1207666cc0b2SZachary Turner llvm::MD5::MD5Result result; 1208666cc0b2SZachary Turner md5.final(result); 1209666cc0b2SZachary Turner 121082a0c97bSZachary Turner dest.clear(); 121182a0c97bSZachary Turner dest.append(result.Bytes.begin(), result.Bytes.end()); 1212666cc0b2SZachary Turner } 1213