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

source code of lldb/source/Plugins/Language/ObjC/CFBasicHash.cpp