1 #include "CFBasicHash.h" 2 3 #include "lldb/Utility/Endian.h" 4 5 using namespace lldb; 6 using namespace lldb_private; 7 8 bool CFBasicHash::IsValid() const { 9 if (m_address != LLDB_INVALID_ADDRESS) { 10 if (m_ptr_size == 4 && m_ht_32) 11 return true; 12 else if (m_ptr_size == 8 && m_ht_64) 13 return true; 14 else 15 return false; 16 } 17 return false; 18 } 19 20 bool CFBasicHash::Update(addr_t addr, ExecutionContextRef exe_ctx_rf) { 21 if (addr == LLDB_INVALID_ADDRESS || !addr) 22 return false; 23 24 m_address = addr; 25 m_exe_ctx_ref = exe_ctx_rf; 26 m_ptr_size = 27 m_exe_ctx_ref.GetTargetSP()->GetArchitecture().GetAddressByteSize(); 28 m_byte_order = m_exe_ctx_ref.GetTargetSP()->GetArchitecture().GetByteOrder(); 29 30 if (m_ptr_size == 4) 31 return UpdateFor(m_ht_32); 32 else if (m_ptr_size == 8) 33 return UpdateFor(m_ht_64); 34 return false; 35 36 llvm_unreachable( 37 "Unsupported architecture. Only 32bits and 64bits supported."); 38 } 39 40 template <typename T> 41 bool CFBasicHash::UpdateFor(std::unique_ptr<__CFBasicHash<T>> &m_ht) { 42 if (m_byte_order != endian::InlHostByteOrder()) 43 return false; 44 45 Status error; 46 Target *target = m_exe_ctx_ref.GetTargetSP().get(); 47 addr_t addr = m_address.GetLoadAddress(target); 48 size_t size = sizeof(typename __CFBasicHash<T>::RuntimeBase) + 49 sizeof(typename __CFBasicHash<T>::Bits); 50 51 m_ht = std::make_unique<__CFBasicHash<T>>(); 52 m_exe_ctx_ref.GetProcessSP()->ReadMemory(addr, m_ht.get(), 53 size, error); 54 if (error.Fail()) 55 return false; 56 57 m_mutable = !(m_ht->base.cfinfoa & (1 << 6)); 58 m_multi = m_ht->bits.counts_offset; 59 m_type = static_cast<HashType>(m_ht->bits.keys_offset); 60 addr_t ptr_offset = addr + size; 61 size_t ptr_count = GetPointerCount(); 62 size = ptr_count * sizeof(T); 63 64 m_exe_ctx_ref.GetProcessSP()->ReadMemory(ptr_offset, m_ht->pointers, size, 65 error); 66 67 if (error.Fail()) { 68 m_ht = nullptr; 69 return false; 70 } 71 72 return true; 73 } 74 75 size_t CFBasicHash::GetCount() const { 76 if (!IsValid()) 77 return 0; 78 79 if (!m_multi) 80 return (m_ptr_size == 4) ? m_ht_32->bits.used_buckets 81 : m_ht_64->bits.used_buckets; 82 83 // FIXME: Add support for multi 84 return 0; 85 } 86 87 size_t CFBasicHash::GetPointerCount() const { 88 if (!IsValid()) 89 return 0; 90 91 if (m_multi) 92 return 3; // Bits::counts_offset; 93 return (m_type == HashType::dict) + 1; 94 } 95 96 addr_t CFBasicHash::GetKeyPointer() const { 97 if (!IsValid()) 98 return LLDB_INVALID_ADDRESS; 99 100 if (m_ptr_size == 4) 101 return m_ht_32->pointers[m_ht_32->bits.keys_offset]; 102 103 return m_ht_64->pointers[m_ht_64->bits.keys_offset]; 104 } 105 106 addr_t CFBasicHash::GetValuePointer() const { 107 if (!IsValid()) 108 return LLDB_INVALID_ADDRESS; 109 110 if (m_ptr_size == 4) 111 return m_ht_32->pointers[0]; 112 113 return m_ht_64->pointers[0]; 114 } 115