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