xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Language/ObjC/CFBasicHash.cpp (revision dda2819751e49c83612958492e38917049128b41)
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*dda28197Spatrick bool 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*dda28197Spatrick bool 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*dda28197Spatrick bool 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*dda28197Spatrick size_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*dda28197Spatrick size_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*dda28197Spatrick addr_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*dda28197Spatrick addr_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