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