180814287SRaphael Isemann //===-- ObjCLanguageRuntime.cpp -------------------------------------------===// 2b5701710SAlex Langford // 3b5701710SAlex Langford // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4b5701710SAlex Langford // See https://llvm.org/LICENSE.txt for license information. 5b5701710SAlex Langford // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6b5701710SAlex Langford // 7b5701710SAlex Langford //===----------------------------------------------------------------------===// 8b5701710SAlex Langford #include "clang/AST/Type.h" 9b5701710SAlex Langford 10b5701710SAlex Langford #include "ObjCLanguageRuntime.h" 11b5701710SAlex Langford 128be30215SAlex Langford #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 13b5701710SAlex Langford #include "lldb/Core/Module.h" 14b5701710SAlex Langford #include "lldb/Core/PluginManager.h" 15b5701710SAlex Langford #include "lldb/Symbol/SymbolContext.h" 16b5701710SAlex Langford #include "lldb/Symbol/SymbolFile.h" 17b5701710SAlex Langford #include "lldb/Symbol/Type.h" 18b5701710SAlex Langford #include "lldb/Symbol/TypeList.h" 19b5701710SAlex Langford #include "lldb/Symbol/Variable.h" 208bac9e36SJonas Devlieghere #include "lldb/Target/ABI.h" 21c34698a8SPavel Labath #include "lldb/Target/Target.h" 22c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h" 23b5701710SAlex Langford #include "lldb/Utility/Log.h" 24b5701710SAlex Langford #include "lldb/Utility/Timer.h" 25*b852fb1eSJonas Devlieghere #include "lldb/ValueObject/ValueObject.h" 26b5701710SAlex Langford 27b5701710SAlex Langford #include "llvm/ADT/StringRef.h" 28b5701710SAlex Langford #include "llvm/Support/DJB.h" 29f190ce62SKazu Hirata #include <optional> 30b5701710SAlex Langford 31b5701710SAlex Langford using namespace lldb; 32b5701710SAlex Langford using namespace lldb_private; 33b5701710SAlex Langford 34b5701710SAlex Langford char ObjCLanguageRuntime::ID = 0; 35b5701710SAlex Langford 36b5701710SAlex Langford // Destructor 37fd2433e1SJonas Devlieghere ObjCLanguageRuntime::~ObjCLanguageRuntime() = default; 38b5701710SAlex Langford 39b5701710SAlex Langford ObjCLanguageRuntime::ObjCLanguageRuntime(Process *process) 40833882b3SJim Ingham : LanguageRuntime(process), m_impl_cache(), m_impl_str_cache(), 41b5701710SAlex Langford m_has_new_literals_and_indexing(eLazyBoolCalculate), 42b5701710SAlex Langford m_isa_to_descriptor(), m_hash_to_isa_map(), m_type_size_cache(), 43b5701710SAlex Langford m_isa_to_descriptor_stop_id(UINT32_MAX), m_complete_class_cache(), 44b5701710SAlex Langford m_negative_complete_class_cache() {} 45b5701710SAlex Langford 46efb328f6SEric Christopher bool ObjCLanguageRuntime::IsAllowedRuntimeValue(ConstString name) { 47b5701710SAlex Langford static ConstString g_self = ConstString("self"); 48b5701710SAlex Langford static ConstString g_cmd = ConstString("_cmd"); 49b5701710SAlex Langford return name == g_self || name == g_cmd; 50b5701710SAlex Langford } 51b5701710SAlex Langford 52b5701710SAlex Langford bool ObjCLanguageRuntime::AddClass(ObjCISA isa, 53b5701710SAlex Langford const ClassDescriptorSP &descriptor_sp, 54b5701710SAlex Langford const char *class_name) { 55b5701710SAlex Langford if (isa != 0) { 56b5701710SAlex Langford m_isa_to_descriptor[isa] = descriptor_sp; 57b5701710SAlex Langford // class_name is assumed to be valid 58b5701710SAlex Langford m_hash_to_isa_map.insert(std::make_pair(llvm::djbHash(class_name), isa)); 59b5701710SAlex Langford return true; 60b5701710SAlex Langford } 61b5701710SAlex Langford return false; 62b5701710SAlex Langford } 63b5701710SAlex Langford 64b5701710SAlex Langford void ObjCLanguageRuntime::AddToMethodCache(lldb::addr_t class_addr, 65b5701710SAlex Langford lldb::addr_t selector, 66b5701710SAlex Langford lldb::addr_t impl_addr) { 67a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Step); 68b5701710SAlex Langford if (log) { 6963e5fb76SJonas Devlieghere LLDB_LOGF(log, 7063e5fb76SJonas Devlieghere "Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 71b5701710SAlex Langford " implementation 0x%" PRIx64 ".", 72b5701710SAlex Langford class_addr, selector, impl_addr); 73b5701710SAlex Langford } 74b5701710SAlex Langford m_impl_cache.insert(std::pair<ClassAndSel, lldb::addr_t>( 75b5701710SAlex Langford ClassAndSel(class_addr, selector), impl_addr)); 76b5701710SAlex Langford } 77b5701710SAlex Langford 78833882b3SJim Ingham void ObjCLanguageRuntime::AddToMethodCache(lldb::addr_t class_addr, 79833882b3SJim Ingham llvm::StringRef sel_str, 80833882b3SJim Ingham lldb::addr_t impl_addr) { 81833882b3SJim Ingham Log *log = GetLog(LLDBLog::Step); 82833882b3SJim Ingham 83833882b3SJim Ingham LLDB_LOG(log, "Caching: class {0} selector {1} implementation {2}.", 84833882b3SJim Ingham class_addr, sel_str, impl_addr); 85833882b3SJim Ingham 86833882b3SJim Ingham m_impl_str_cache.insert(std::pair<ClassAndSelStr, lldb::addr_t>( 87833882b3SJim Ingham ClassAndSelStr(class_addr, sel_str), impl_addr)); 88833882b3SJim Ingham } 89833882b3SJim Ingham 90b5701710SAlex Langford lldb::addr_t ObjCLanguageRuntime::LookupInMethodCache(lldb::addr_t class_addr, 91b5701710SAlex Langford lldb::addr_t selector) { 92b5701710SAlex Langford MsgImplMap::iterator pos, end = m_impl_cache.end(); 93b5701710SAlex Langford pos = m_impl_cache.find(ClassAndSel(class_addr, selector)); 94b5701710SAlex Langford if (pos != end) 95b5701710SAlex Langford return (*pos).second; 96b5701710SAlex Langford return LLDB_INVALID_ADDRESS; 97b5701710SAlex Langford } 98b5701710SAlex Langford 99833882b3SJim Ingham lldb::addr_t ObjCLanguageRuntime::LookupInMethodCache(lldb::addr_t class_addr, 100833882b3SJim Ingham llvm::StringRef sel_str) { 101833882b3SJim Ingham MsgImplStrMap::iterator pos, end = m_impl_str_cache.end(); 102833882b3SJim Ingham pos = m_impl_str_cache.find(ClassAndSelStr(class_addr, sel_str)); 103833882b3SJim Ingham if (pos != end) 104833882b3SJim Ingham return (*pos).second; 105833882b3SJim Ingham return LLDB_INVALID_ADDRESS; 106833882b3SJim Ingham } 107833882b3SJim Ingham 108b5701710SAlex Langford lldb::TypeSP 109b5701710SAlex Langford ObjCLanguageRuntime::LookupInCompleteClassCache(ConstString &name) { 110b5701710SAlex Langford CompleteClassMap::iterator complete_class_iter = 111b5701710SAlex Langford m_complete_class_cache.find(name); 112b5701710SAlex Langford 113b5701710SAlex Langford if (complete_class_iter != m_complete_class_cache.end()) { 114b5701710SAlex Langford // Check the weak pointer to make sure the type hasn't been unloaded 115b5701710SAlex Langford TypeSP complete_type_sp(complete_class_iter->second.lock()); 116b5701710SAlex Langford 117b5701710SAlex Langford if (complete_type_sp) 118b5701710SAlex Langford return complete_type_sp; 119b5701710SAlex Langford else 120b5701710SAlex Langford m_complete_class_cache.erase(name); 121b5701710SAlex Langford } 122b5701710SAlex Langford 123b5701710SAlex Langford if (m_negative_complete_class_cache.count(name) > 0) 124b5701710SAlex Langford return TypeSP(); 125b5701710SAlex Langford 126b5701710SAlex Langford const ModuleList &modules = m_process->GetTarget().GetImages(); 127b5701710SAlex Langford 128b5701710SAlex Langford SymbolContextList sc_list; 129b5701710SAlex Langford modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list); 1301ad655e2SAdrian Prantl const size_t matching_symbols = sc_list.GetSize(); 131b5701710SAlex Langford 132b5701710SAlex Langford if (matching_symbols) { 133b5701710SAlex Langford SymbolContext sc; 134b5701710SAlex Langford 135b5701710SAlex Langford sc_list.GetContextAtIndex(0, sc); 136b5701710SAlex Langford 137b5701710SAlex Langford ModuleSP module_sp(sc.module_sp); 138b5701710SAlex Langford 139b5701710SAlex Langford if (!module_sp) 140b5701710SAlex Langford return TypeSP(); 141b5701710SAlex Langford 142dd958779SGreg Clayton TypeQuery query(name.GetStringRef(), TypeQueryOptions::e_exact_match); 143dd958779SGreg Clayton TypeResults results; 144dd958779SGreg Clayton module_sp->FindTypes(query, results); 145dd958779SGreg Clayton for (const TypeSP &type_sp : results.GetTypeMap().Types()) { 1466e3b0cc2SRaphael Isemann if (TypeSystemClang::IsObjCObjectOrInterfaceType( 147b5701710SAlex Langford type_sp->GetForwardCompilerType())) { 1487b06cb45SAdrian Prantl if (TypePayloadClang(type_sp->GetPayload()).IsCompleteObjCClass()) { 149b5701710SAlex Langford m_complete_class_cache[name] = type_sp; 150b5701710SAlex Langford return type_sp; 151b5701710SAlex Langford } 152b5701710SAlex Langford } 153b5701710SAlex Langford } 154b5701710SAlex Langford } 155b5701710SAlex Langford m_negative_complete_class_cache.insert(name); 156b5701710SAlex Langford return TypeSP(); 157b5701710SAlex Langford } 158b5701710SAlex Langford 159b5701710SAlex Langford size_t ObjCLanguageRuntime::GetByteOffsetForIvar(CompilerType &parent_qual_type, 160b5701710SAlex Langford const char *ivar_name) { 161b5701710SAlex Langford return LLDB_INVALID_IVAR_OFFSET; 162b5701710SAlex Langford } 163b5701710SAlex Langford 164b5701710SAlex Langford bool ObjCLanguageRuntime::ClassDescriptor::IsPointerValid( 165b5701710SAlex Langford lldb::addr_t value, uint32_t ptr_size, bool allow_NULLs, bool allow_tagged, 166b5701710SAlex Langford bool check_version_specific) const { 167b5701710SAlex Langford if (!value) 168b5701710SAlex Langford return allow_NULLs; 169b5701710SAlex Langford if ((value % 2) == 1 && allow_tagged) 170b5701710SAlex Langford return true; 171b5701710SAlex Langford if ((value % ptr_size) == 0) 172b5701710SAlex Langford return (check_version_specific ? CheckPointer(value, ptr_size) : true); 173b5701710SAlex Langford else 174b5701710SAlex Langford return false; 175b5701710SAlex Langford } 176b5701710SAlex Langford 177b5701710SAlex Langford ObjCLanguageRuntime::ObjCISA 178b5701710SAlex Langford ObjCLanguageRuntime::GetISA(ConstString name) { 179b5701710SAlex Langford ISAToDescriptorIterator pos = GetDescriptorIterator(name); 180b5701710SAlex Langford if (pos != m_isa_to_descriptor.end()) 181b5701710SAlex Langford return pos->first; 182b5701710SAlex Langford return 0; 183b5701710SAlex Langford } 184b5701710SAlex Langford 185b5701710SAlex Langford ObjCLanguageRuntime::ISAToDescriptorIterator 186b5701710SAlex Langford ObjCLanguageRuntime::GetDescriptorIterator(ConstString name) { 187b5701710SAlex Langford ISAToDescriptorIterator end = m_isa_to_descriptor.end(); 188b5701710SAlex Langford 189b5701710SAlex Langford if (name) { 190b5701710SAlex Langford UpdateISAToDescriptorMap(); 191b5701710SAlex Langford if (m_hash_to_isa_map.empty()) { 192b5701710SAlex Langford // No name hashes were provided, we need to just linearly power through 193b5701710SAlex Langford // the names and find a match 194b5701710SAlex Langford for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin(); 195b5701710SAlex Langford pos != end; ++pos) { 196b5701710SAlex Langford if (pos->second->GetClassName() == name) 197b5701710SAlex Langford return pos; 198b5701710SAlex Langford } 199b5701710SAlex Langford } else { 200b5701710SAlex Langford // Name hashes were provided, so use them to efficiently lookup name to 201b5701710SAlex Langford // isa/descriptor 202b5701710SAlex Langford const uint32_t name_hash = llvm::djbHash(name.GetStringRef()); 203b5701710SAlex Langford std::pair<HashToISAIterator, HashToISAIterator> range = 204b5701710SAlex Langford m_hash_to_isa_map.equal_range(name_hash); 205b5701710SAlex Langford for (HashToISAIterator range_pos = range.first; range_pos != range.second; 206b5701710SAlex Langford ++range_pos) { 207b5701710SAlex Langford ISAToDescriptorIterator pos = 208b5701710SAlex Langford m_isa_to_descriptor.find(range_pos->second); 209b5701710SAlex Langford if (pos != m_isa_to_descriptor.end()) { 210b5701710SAlex Langford if (pos->second->GetClassName() == name) 211b5701710SAlex Langford return pos; 212b5701710SAlex Langford } 213b5701710SAlex Langford } 214b5701710SAlex Langford } 215b5701710SAlex Langford } 216b5701710SAlex Langford return end; 217b5701710SAlex Langford } 218b5701710SAlex Langford 219b5701710SAlex Langford std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator, 220b5701710SAlex Langford ObjCLanguageRuntime::ISAToDescriptorIterator> 221b5701710SAlex Langford ObjCLanguageRuntime::GetDescriptorIteratorPair(bool update_if_needed) { 222b5701710SAlex Langford if (update_if_needed) 223b5701710SAlex Langford UpdateISAToDescriptorMapIfNeeded(); 224b5701710SAlex Langford 225b5701710SAlex Langford return std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator, 226b5701710SAlex Langford ObjCLanguageRuntime::ISAToDescriptorIterator>( 227b5701710SAlex Langford m_isa_to_descriptor.begin(), m_isa_to_descriptor.end()); 228b5701710SAlex Langford } 229b5701710SAlex Langford 2300b626473SStefan Gränitz void ObjCLanguageRuntime::ReadObjCLibraryIfNeeded( 2310b626473SStefan Gränitz const ModuleList &module_list) { 2320b626473SStefan Gränitz if (!HasReadObjCLibrary()) { 2330b626473SStefan Gränitz std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex()); 2340b626473SStefan Gränitz 2350b626473SStefan Gränitz size_t num_modules = module_list.GetSize(); 2360b626473SStefan Gränitz for (size_t i = 0; i < num_modules; i++) { 2370b626473SStefan Gränitz auto mod = module_list.GetModuleAtIndex(i); 2380b626473SStefan Gränitz if (IsModuleObjCLibrary(mod)) { 2390b626473SStefan Gränitz ReadObjCLibrary(mod); 2400b626473SStefan Gränitz break; 2410b626473SStefan Gränitz } 2420b626473SStefan Gränitz } 2430b626473SStefan Gränitz } 2440b626473SStefan Gränitz } 2450b626473SStefan Gränitz 246b5701710SAlex Langford ObjCLanguageRuntime::ObjCISA 247b5701710SAlex Langford ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa) { 248b5701710SAlex Langford ClassDescriptorSP objc_class_sp(GetClassDescriptorFromISA(isa)); 249b5701710SAlex Langford if (objc_class_sp) { 250b5701710SAlex Langford ClassDescriptorSP objc_super_class_sp(objc_class_sp->GetSuperclass()); 251b5701710SAlex Langford if (objc_super_class_sp) 252b5701710SAlex Langford return objc_super_class_sp->GetISA(); 253b5701710SAlex Langford } 254b5701710SAlex Langford return 0; 255b5701710SAlex Langford } 256b5701710SAlex Langford 257b5701710SAlex Langford ObjCLanguageRuntime::ClassDescriptorSP 258b5701710SAlex Langford ObjCLanguageRuntime::GetClassDescriptorFromClassName( 259b5701710SAlex Langford ConstString class_name) { 260b5701710SAlex Langford ISAToDescriptorIterator pos = GetDescriptorIterator(class_name); 261b5701710SAlex Langford if (pos != m_isa_to_descriptor.end()) 262b5701710SAlex Langford return pos->second; 263b5701710SAlex Langford return ClassDescriptorSP(); 264b5701710SAlex Langford } 265b5701710SAlex Langford 266b5701710SAlex Langford ObjCLanguageRuntime::ClassDescriptorSP 267b5701710SAlex Langford ObjCLanguageRuntime::GetClassDescriptor(ValueObject &valobj) { 268b5701710SAlex Langford ClassDescriptorSP objc_class_sp; 269b5701710SAlex Langford // if we get an invalid VO (which might still happen when playing around with 270b5701710SAlex Langford // pointers returned by the expression parser, don't consider this a valid 271b5701710SAlex Langford // ObjC object) 272b5701710SAlex Langford if (valobj.GetCompilerType().IsValid()) { 273b5701710SAlex Langford addr_t isa_pointer = valobj.GetPointerValue(); 274b5701710SAlex Langford if (isa_pointer != LLDB_INVALID_ADDRESS) { 275b5701710SAlex Langford ExecutionContext exe_ctx(valobj.GetExecutionContextRef()); 276b5701710SAlex Langford 277b5701710SAlex Langford Process *process = exe_ctx.GetProcessPtr(); 278b5701710SAlex Langford if (process) { 279b5701710SAlex Langford Status error; 280b5701710SAlex Langford ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error); 281b5701710SAlex Langford if (isa != LLDB_INVALID_ADDRESS) 282b5701710SAlex Langford objc_class_sp = GetClassDescriptorFromISA(isa); 283b5701710SAlex Langford } 284b5701710SAlex Langford } 285b5701710SAlex Langford } 286b5701710SAlex Langford return objc_class_sp; 287b5701710SAlex Langford } 288b5701710SAlex Langford 289b5701710SAlex Langford ObjCLanguageRuntime::ClassDescriptorSP 290b5701710SAlex Langford ObjCLanguageRuntime::GetNonKVOClassDescriptor(ValueObject &valobj) { 291b5701710SAlex Langford ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp( 292b5701710SAlex Langford GetClassDescriptor(valobj)); 293b5701710SAlex Langford if (objc_class_sp) { 294b5701710SAlex Langford if (!objc_class_sp->IsKVO()) 295b5701710SAlex Langford return objc_class_sp; 296b5701710SAlex Langford 297b5701710SAlex Langford ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass()); 298b5701710SAlex Langford if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid()) 299b5701710SAlex Langford return non_kvo_objc_class_sp; 300b5701710SAlex Langford } 301b5701710SAlex Langford return ClassDescriptorSP(); 302b5701710SAlex Langford } 303b5701710SAlex Langford 304b5701710SAlex Langford ObjCLanguageRuntime::ClassDescriptorSP 305b5701710SAlex Langford ObjCLanguageRuntime::GetClassDescriptorFromISA(ObjCISA isa) { 306b5701710SAlex Langford if (isa) { 307b5701710SAlex Langford UpdateISAToDescriptorMap(); 3088bac9e36SJonas Devlieghere 309b5701710SAlex Langford ObjCLanguageRuntime::ISAToDescriptorIterator pos = 310b5701710SAlex Langford m_isa_to_descriptor.find(isa); 311b5701710SAlex Langford if (pos != m_isa_to_descriptor.end()) 312b5701710SAlex Langford return pos->second; 3138bac9e36SJonas Devlieghere 3148bac9e36SJonas Devlieghere if (ABISP abi_sp = m_process->GetABI()) { 3158bac9e36SJonas Devlieghere pos = m_isa_to_descriptor.find(abi_sp->FixCodeAddress(isa)); 3168bac9e36SJonas Devlieghere if (pos != m_isa_to_descriptor.end()) 3178bac9e36SJonas Devlieghere return pos->second; 3188bac9e36SJonas Devlieghere } 319b5701710SAlex Langford } 320b5701710SAlex Langford return ClassDescriptorSP(); 321b5701710SAlex Langford } 322b5701710SAlex Langford 323b5701710SAlex Langford ObjCLanguageRuntime::ClassDescriptorSP 324b5701710SAlex Langford ObjCLanguageRuntime::GetNonKVOClassDescriptor(ObjCISA isa) { 325b5701710SAlex Langford if (isa) { 326b5701710SAlex Langford ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA(isa); 327b5701710SAlex Langford if (objc_class_sp && objc_class_sp->IsValid()) { 328b5701710SAlex Langford if (!objc_class_sp->IsKVO()) 329b5701710SAlex Langford return objc_class_sp; 330b5701710SAlex Langford 331b5701710SAlex Langford ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass()); 332b5701710SAlex Langford if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid()) 333b5701710SAlex Langford return non_kvo_objc_class_sp; 334b5701710SAlex Langford } 335b5701710SAlex Langford } 336b5701710SAlex Langford return ClassDescriptorSP(); 337b5701710SAlex Langford } 338b5701710SAlex Langford 339b5701710SAlex Langford CompilerType 340b5701710SAlex Langford ObjCLanguageRuntime::EncodingToType::RealizeType(const char *name, 341b5701710SAlex Langford bool for_expression) { 3426eaedbb5SAdrian Prantl if (m_scratch_ast_ctx_sp) 3436eaedbb5SAdrian Prantl return RealizeType(*m_scratch_ast_ctx_sp, name, for_expression); 344b5701710SAlex Langford return CompilerType(); 345b5701710SAlex Langford } 346b5701710SAlex Langford 347fd2433e1SJonas Devlieghere ObjCLanguageRuntime::EncodingToType::~EncodingToType() = default; 348b5701710SAlex Langford 349b5701710SAlex Langford ObjCLanguageRuntime::EncodingToTypeSP ObjCLanguageRuntime::GetEncodingToType() { 350b5701710SAlex Langford return nullptr; 351b5701710SAlex Langford } 352b5701710SAlex Langford 3535e9f247cSJonas Devlieghere std::optional<uint64_t> 3545e9f247cSJonas Devlieghere ObjCLanguageRuntime::GetTypeBitSize(const CompilerType &compiler_type) { 355b5701710SAlex Langford void *opaque_ptr = compiler_type.GetOpaqueQualType(); 3565e9f247cSJonas Devlieghere uint64_t cached_size = m_type_size_cache.Lookup(opaque_ptr); 3575e9f247cSJonas Devlieghere if (cached_size > 0) 3585e9f247cSJonas Devlieghere return cached_size; 359b5701710SAlex Langford 360b5701710SAlex Langford ClassDescriptorSP class_descriptor_sp = 361b5701710SAlex Langford GetClassDescriptorFromClassName(compiler_type.GetTypeName()); 362b5701710SAlex Langford if (!class_descriptor_sp) 3635e9f247cSJonas Devlieghere return {}; 364b5701710SAlex Langford 365b5701710SAlex Langford int32_t max_offset = INT32_MIN; 366b5701710SAlex Langford uint64_t sizeof_max = 0; 367b5701710SAlex Langford bool found = false; 368b5701710SAlex Langford 369b5701710SAlex Langford for (size_t idx = 0; idx < class_descriptor_sp->GetNumIVars(); idx++) { 370b5701710SAlex Langford const auto &ivar = class_descriptor_sp->GetIVarAtIndex(idx); 371b5701710SAlex Langford int32_t cur_offset = ivar.m_offset; 372b5701710SAlex Langford if (cur_offset > max_offset) { 373b5701710SAlex Langford max_offset = cur_offset; 374b5701710SAlex Langford sizeof_max = ivar.m_size; 375b5701710SAlex Langford found = true; 376b5701710SAlex Langford } 377b5701710SAlex Langford } 378b5701710SAlex Langford 3795e9f247cSJonas Devlieghere uint64_t size = 8 * (max_offset + sizeof_max); 3805e9f247cSJonas Devlieghere if (found && size > 0) { 381b5701710SAlex Langford m_type_size_cache.Insert(opaque_ptr, size); 3825e9f247cSJonas Devlieghere return size; 3835e9f247cSJonas Devlieghere } 384b5701710SAlex Langford 3855e9f247cSJonas Devlieghere return {}; 386b5701710SAlex Langford } 387b5701710SAlex Langford 388b5701710SAlex Langford lldb::BreakpointPreconditionSP 389b5701710SAlex Langford ObjCLanguageRuntime::GetBreakpointExceptionPrecondition(LanguageType language, 390b5701710SAlex Langford bool throw_bp) { 391b5701710SAlex Langford if (language != eLanguageTypeObjC) 392b5701710SAlex Langford return lldb::BreakpointPreconditionSP(); 393b5701710SAlex Langford if (!throw_bp) 394b5701710SAlex Langford return lldb::BreakpointPreconditionSP(); 395b5701710SAlex Langford BreakpointPreconditionSP precondition_sp( 396b5701710SAlex Langford new ObjCLanguageRuntime::ObjCExceptionPrecondition()); 397b5701710SAlex Langford return precondition_sp; 398b5701710SAlex Langford } 399b5701710SAlex Langford 400b5701710SAlex Langford // Exception breakpoint Precondition class for ObjC: 401b5701710SAlex Langford void ObjCLanguageRuntime::ObjCExceptionPrecondition::AddClassName( 402b5701710SAlex Langford const char *class_name) { 403b5701710SAlex Langford m_class_names.insert(class_name); 404b5701710SAlex Langford } 405b5701710SAlex Langford 406fd2433e1SJonas Devlieghere ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition() = 407fd2433e1SJonas Devlieghere default; 408b5701710SAlex Langford 409b5701710SAlex Langford bool ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition( 410b5701710SAlex Langford StoppointCallbackContext &context) { 411b5701710SAlex Langford return true; 412b5701710SAlex Langford } 413b5701710SAlex Langford 414b5701710SAlex Langford void ObjCLanguageRuntime::ObjCExceptionPrecondition::GetDescription( 415b5701710SAlex Langford Stream &stream, lldb::DescriptionLevel level) {} 416b5701710SAlex Langford 417b5701710SAlex Langford Status ObjCLanguageRuntime::ObjCExceptionPrecondition::ConfigurePrecondition( 418b5701710SAlex Langford Args &args) { 419b5701710SAlex Langford Status error; 420b5701710SAlex Langford if (args.GetArgumentCount() > 0) 4210642cd76SAdrian Prantl error = Status::FromErrorString( 422b5701710SAlex Langford "The ObjC Exception breakpoint doesn't support extra options."); 423b5701710SAlex Langford return error; 424b5701710SAlex Langford } 425b5701710SAlex Langford 4262fe83274SKazu Hirata std::optional<CompilerType> 427b5701710SAlex Langford ObjCLanguageRuntime::GetRuntimeType(CompilerType base_type) { 428b5701710SAlex Langford CompilerType class_type; 429b5701710SAlex Langford bool is_pointer_type = false; 430b5701710SAlex Langford 4316e3b0cc2SRaphael Isemann if (TypeSystemClang::IsObjCObjectPointerType(base_type, &class_type)) 432b5701710SAlex Langford is_pointer_type = true; 4336e3b0cc2SRaphael Isemann else if (TypeSystemClang::IsObjCObjectOrInterfaceType(base_type)) 434b5701710SAlex Langford class_type = base_type; 435b5701710SAlex Langford else 436343523d0SKazu Hirata return std::nullopt; 437b5701710SAlex Langford 438b5701710SAlex Langford if (!class_type) 439343523d0SKazu Hirata return std::nullopt; 440b5701710SAlex Langford 44130ce956aSRaphael Isemann ConstString class_name(class_type.GetTypeName()); 442b5701710SAlex Langford if (!class_name) 443343523d0SKazu Hirata return std::nullopt; 444b5701710SAlex Langford 445b5701710SAlex Langford TypeSP complete_objc_class_type_sp = LookupInCompleteClassCache(class_name); 446b5701710SAlex Langford if (!complete_objc_class_type_sp) 447343523d0SKazu Hirata return std::nullopt; 448b5701710SAlex Langford 449b5701710SAlex Langford CompilerType complete_class( 450b5701710SAlex Langford complete_objc_class_type_sp->GetFullCompilerType()); 451b5701710SAlex Langford if (complete_class.GetCompleteType()) { 452b5701710SAlex Langford if (is_pointer_type) 453b5701710SAlex Langford return complete_class.GetPointerType(); 454b5701710SAlex Langford else 455b5701710SAlex Langford return complete_class; 456b5701710SAlex Langford } 457b5701710SAlex Langford 458343523d0SKazu Hirata return std::nullopt; 459b5701710SAlex Langford } 460