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