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