diff options
Diffstat (limited to 'lldb/source/Utility/DataExtractor.cpp')
-rw-r--r-- | lldb/source/Utility/DataExtractor.cpp | 147 |
1 files changed, 34 insertions, 113 deletions
diff --git a/lldb/source/Utility/DataExtractor.cpp b/lldb/source/Utility/DataExtractor.cpp index fed2a1326b865..64b878d7dee74 100644 --- a/lldb/source/Utility/DataExtractor.cpp +++ b/lldb/source/Utility/DataExtractor.cpp @@ -1,4 +1,4 @@ -//===-- DataExtractor.cpp ---------------------------------------*- C++ -*-===// +//===-- DataExtractor.cpp -------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -15,7 +15,6 @@ #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/Endian.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Stream.h" @@ -24,6 +23,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/MD5.h" #include "llvm/Support/MathExtras.h" @@ -133,7 +133,7 @@ DataExtractor::DataExtractor(const void *data, offset_t length, m_end(const_cast<uint8_t *>(static_cast<const uint8_t *>(data)) + length), m_byte_order(endian), m_addr_size(addr_size), m_data_sp(), m_target_byte_size(target_byte_size) { - assert(addr_size == 4 || addr_size == 8); + assert(addr_size >= 1 && addr_size <= 8); } // Make a shared pointer reference to the shared data in "data_sp" and set the @@ -146,7 +146,7 @@ DataExtractor::DataExtractor(const DataBufferSP &data_sp, ByteOrder endian, : m_start(nullptr), m_end(nullptr), m_byte_order(endian), m_addr_size(addr_size), m_data_sp(), m_target_byte_size(target_byte_size) { - assert(addr_size == 4 || addr_size == 8); + assert(addr_size >= 1 && addr_size <= 8); SetData(data_sp); } @@ -160,7 +160,7 @@ DataExtractor::DataExtractor(const DataExtractor &data, offset_t offset, : m_start(nullptr), m_end(nullptr), m_byte_order(data.m_byte_order), m_addr_size(data.m_addr_size), m_data_sp(), m_target_byte_size(target_byte_size) { - assert(m_addr_size == 4 || m_addr_size == 8); + assert(m_addr_size >= 1 && m_addr_size <= 8); if (data.ValidOffset(offset)) { offset_t bytes_available = data.GetByteSize() - offset; if (length > bytes_available) @@ -173,7 +173,7 @@ DataExtractor::DataExtractor(const DataExtractor &rhs) : m_start(rhs.m_start), m_end(rhs.m_end), m_byte_order(rhs.m_byte_order), m_addr_size(rhs.m_addr_size), m_data_sp(rhs.m_data_sp), m_target_byte_size(rhs.m_target_byte_size) { - assert(m_addr_size == 4 || m_addr_size == 8); + assert(m_addr_size >= 1 && m_addr_size <= 8); } // Assignment operator @@ -251,7 +251,7 @@ lldb::offset_t DataExtractor::SetData(const DataExtractor &data, offset_t data_offset, offset_t data_length) { m_addr_size = data.m_addr_size; - assert(m_addr_size == 4 || m_addr_size == 8); + assert(m_addr_size >= 1 && m_addr_size <= 8); // If "data" contains shared pointer to data, then we can use that if (data.m_data_sp) { m_byte_order = data.m_byte_order; @@ -604,59 +604,30 @@ uint64_t DataExtractor::GetMaxU64Bitfield(offset_t *offset_ptr, size_t size, int64_t DataExtractor::GetMaxS64Bitfield(offset_t *offset_ptr, size_t size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset) const { + assert(size >= 1 && "GetMaxS64Bitfield size must be >= 1"); + assert(size <= 8 && "GetMaxS64Bitfield size must be <= 8"); int64_t sval64 = GetMaxS64(offset_ptr, size); - if (bitfield_bit_size > 0) { - int32_t lsbcount = bitfield_bit_offset; - if (m_byte_order == eByteOrderBig) - lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size; - if (lsbcount > 0) - sval64 >>= lsbcount; - uint64_t bitfield_mask = - ((static_cast<uint64_t>(1)) << bitfield_bit_size) - 1; - sval64 &= bitfield_mask; - // sign extend if needed - if (sval64 & ((static_cast<uint64_t>(1)) << (bitfield_bit_size - 1))) - sval64 |= ~bitfield_mask; - } + if (bitfield_bit_size == 0) + return sval64; + int32_t lsbcount = bitfield_bit_offset; + if (m_byte_order == eByteOrderBig) + lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size; + if (lsbcount > 0) + sval64 >>= lsbcount; + uint64_t bitfield_mask = llvm::maskTrailingOnes<uint64_t>(bitfield_bit_size); + sval64 &= bitfield_mask; + // sign extend if needed + if (sval64 & ((static_cast<uint64_t>(1)) << (bitfield_bit_size - 1))) + sval64 |= ~bitfield_mask; return sval64; } float DataExtractor::GetFloat(offset_t *offset_ptr) const { - typedef float float_type; - float_type val = 0.0; - const size_t src_size = sizeof(float_type); - const float_type *src = - static_cast<const float_type *>(GetData(offset_ptr, src_size)); - if (src) { - if (m_byte_order != endian::InlHostByteOrder()) { - const uint8_t *src_data = reinterpret_cast<const uint8_t *>(src); - uint8_t *dst_data = reinterpret_cast<uint8_t *>(&val); - for (size_t i = 0; i < sizeof(float_type); ++i) - dst_data[sizeof(float_type) - 1 - i] = src_data[i]; - } else { - val = *src; - } - } - return val; + return Get<float>(offset_ptr, 0.0f); } double DataExtractor::GetDouble(offset_t *offset_ptr) const { - typedef double float_type; - float_type val = 0.0; - const size_t src_size = sizeof(float_type); - const float_type *src = - static_cast<const float_type *>(GetData(offset_ptr, src_size)); - if (src) { - if (m_byte_order != endian::InlHostByteOrder()) { - const uint8_t *src_data = reinterpret_cast<const uint8_t *>(src); - uint8_t *dst_data = reinterpret_cast<uint8_t *>(&val); - for (size_t i = 0; i < sizeof(float_type); ++i) - dst_data[sizeof(float_type) - 1 - i] = src_data[i]; - } else { - val = *src; - } - } - return val; + return Get<double>(offset_ptr, 0.0); } long double DataExtractor::GetLongDouble(offset_t *offset_ptr) const { @@ -679,26 +650,15 @@ long double DataExtractor::GetLongDouble(offset_t *offset_ptr) const { // // RETURNS the address that was extracted, or zero on failure. uint64_t DataExtractor::GetAddress(offset_t *offset_ptr) const { - assert(m_addr_size == 4 || m_addr_size == 8); + assert(m_addr_size >= 1 && m_addr_size <= 8); return GetMaxU64(offset_ptr, m_addr_size); } uint64_t DataExtractor::GetAddress_unchecked(offset_t *offset_ptr) const { - assert(m_addr_size == 4 || m_addr_size == 8); + assert(m_addr_size >= 1 && m_addr_size <= 8); return GetMaxU64_unchecked(offset_ptr, m_addr_size); } -// Extract a single pointer from the data and update the offset pointed to by -// "offset_ptr". The size of the extracted pointer comes from the -// "this->m_addr_size" member variable and should be set correctly prior to -// extracting any pointer values. -// -// RETURNS the pointer that was extracted, or zero on failure. -uint64_t DataExtractor::GetPointer(offset_t *offset_ptr) const { - assert(m_addr_size == 4 || m_addr_size == 8); - return GetMaxU64(offset_ptr, m_addr_size); -} - size_t DataExtractor::ExtractBytes(offset_t offset, offset_t length, ByteOrder dst_byte_order, void *dst) const { const uint8_t *src = PeekData(offset, length); @@ -887,26 +847,10 @@ uint64_t DataExtractor::GetULEB128(offset_t *offset_ptr) const { if (src == nullptr) return 0; - const uint8_t *end = m_end; - - if (src < end) { - uint64_t result = *src++; - if (result >= 0x80) { - result &= 0x7f; - int shift = 7; - while (src < end) { - uint8_t byte = *src++; - result |= static_cast<uint64_t>(byte & 0x7f) << shift; - if ((byte & 0x80) == 0) - break; - shift += 7; - } - } - *offset_ptr = src - m_start; - return result; - } - - return 0; + unsigned byte_count = 0; + uint64_t result = llvm::decodeULEB128(src, &byte_count, m_end); + *offset_ptr += byte_count; + return result; } // Extracts an signed LEB128 number from this object's data starting at the @@ -920,33 +864,10 @@ int64_t DataExtractor::GetSLEB128(offset_t *offset_ptr) const { if (src == nullptr) return 0; - const uint8_t *end = m_end; - - if (src < end) { - int64_t result = 0; - int shift = 0; - int size = sizeof(int64_t) * 8; - - uint8_t byte = 0; - int bytecount = 0; - - while (src < end) { - bytecount++; - byte = *src++; - result |= static_cast<int64_t>(byte & 0x7f) << shift; - shift += 7; - if ((byte & 0x80) == 0) - break; - } - - // Sign bit of byte is 2nd high order bit (0x40) - if (shift < size && (byte & 0x40)) - result |= -(1 << shift); - - *offset_ptr += bytecount; - return result; - } - return 0; + unsigned byte_count = 0; + int64_t result = llvm::decodeSLEB128(src, &byte_count, m_end); + *offset_ptr += byte_count; + return result; } // Skips a ULEB128 number (signed or unsigned) from this object's data starting @@ -1012,7 +933,7 @@ lldb::offset_t DataExtractor::PutToLog(Log *log, offset_t start_offset, break; case TypeChar: { char ch = GetU8(&offset); - sstr.Printf(" %c", isprint(ch) ? ch : ' '); + sstr.Printf(" %c", llvm::isPrint(ch) ? ch : ' '); } break; case TypeUInt16: sstr.Printf(" %4.4x", GetU16(&offset)); |