summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Language/ObjC/CFBasicHash.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Language/ObjC/CFBasicHash.cpp')
-rw-r--r--lldb/source/Plugins/Language/ObjC/CFBasicHash.cpp114
1 files changed, 114 insertions, 0 deletions
diff --git a/lldb/source/Plugins/Language/ObjC/CFBasicHash.cpp b/lldb/source/Plugins/Language/ObjC/CFBasicHash.cpp
new file mode 100644
index 0000000000000..42cda0146f2e0
--- /dev/null
+++ b/lldb/source/Plugins/Language/ObjC/CFBasicHash.cpp
@@ -0,0 +1,114 @@
+#include "CFBasicHash.h"
+
+#include "lldb/Utility/Endian.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+bool CFBasicHash::IsValid() const {
+ if (m_address != LLDB_INVALID_ADDRESS) {
+ if (m_ptr_size == 4 && m_ht_32)
+ return true;
+ else if (m_ptr_size == 8 && m_ht_64)
+ return true;
+ else
+ return false;
+ }
+ return false;
+}
+
+bool CFBasicHash::Update(addr_t addr, ExecutionContextRef exe_ctx_rf) {
+ if (addr == LLDB_INVALID_ADDRESS || !addr)
+ return false;
+
+ m_address = addr;
+ m_exe_ctx_ref = exe_ctx_rf;
+ m_ptr_size =
+ m_exe_ctx_ref.GetTargetSP()->GetArchitecture().GetAddressByteSize();
+ m_byte_order = m_exe_ctx_ref.GetTargetSP()->GetArchitecture().GetByteOrder();
+
+ if (m_ptr_size == 4)
+ return UpdateFor(m_ht_32);
+ else if (m_ptr_size == 8)
+ return UpdateFor(m_ht_64);
+ return false;
+
+ llvm_unreachable(
+ "Unsupported architecture. Only 32bits and 64bits supported.");
+}
+
+template <typename T>
+bool CFBasicHash::UpdateFor(std::unique_ptr<__CFBasicHash<T>> &m_ht) {
+ if (m_byte_order != endian::InlHostByteOrder())
+ return false;
+
+ Status error;
+ Target *target = m_exe_ctx_ref.GetTargetSP().get();
+ addr_t addr = m_address.GetLoadAddress(target);
+ size_t size = sizeof(typename __CFBasicHash<T>::RuntimeBase) +
+ sizeof(typename __CFBasicHash<T>::Bits);
+
+ m_ht = std::make_unique<__CFBasicHash<T>>();
+ m_exe_ctx_ref.GetProcessSP()->ReadMemory(addr, m_ht.get(),
+ size, error);
+ if (error.Fail())
+ return false;
+
+ m_mutable = !(m_ht->base.cfinfoa & (1 << 6));
+ m_multi = m_ht->bits.counts_offset;
+ m_type = static_cast<HashType>(m_ht->bits.keys_offset);
+ addr_t ptr_offset = addr + size;
+ size_t ptr_count = GetPointerCount();
+ size = ptr_count * sizeof(T);
+
+ m_exe_ctx_ref.GetProcessSP()->ReadMemory(ptr_offset, m_ht->pointers, size,
+ error);
+
+ if (error.Fail()) {
+ m_ht = nullptr;
+ return false;
+ }
+
+ return true;
+}
+
+size_t CFBasicHash::GetCount() const {
+ if (!IsValid())
+ return 0;
+
+ if (!m_multi)
+ return (m_ptr_size == 4) ? m_ht_32->bits.used_buckets
+ : m_ht_64->bits.used_buckets;
+
+ // FIXME: Add support for multi
+ return 0;
+}
+
+size_t CFBasicHash::GetPointerCount() const {
+ if (!IsValid())
+ return 0;
+
+ if (m_multi)
+ return 3; // Bits::counts_offset;
+ return (m_type == HashType::dict) + 1;
+}
+
+addr_t CFBasicHash::GetKeyPointer() const {
+ if (!IsValid())
+ return LLDB_INVALID_ADDRESS;
+
+ if (m_ptr_size == 4)
+ return m_ht_32->pointers[m_ht_32->bits.keys_offset];
+
+ return m_ht_64->pointers[m_ht_64->bits.keys_offset];
+}
+
+addr_t CFBasicHash::GetValuePointer() const {
+ if (!IsValid())
+ return LLDB_INVALID_ADDRESS;
+
+ if (m_ptr_size == 4)
+ return m_ht_32->pointers[0];
+
+ return m_ht_64->pointers[0];
+}