15ffd83dbSDimitry Andric //===-- ObjCLanguageRuntime.cpp -------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric #include "clang/AST/Type.h" 90b57cec5SDimitry Andric 100b57cec5SDimitry Andric #include "ObjCLanguageRuntime.h" 110b57cec5SDimitry Andric 125ffd83dbSDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 130b57cec5SDimitry Andric #include "lldb/Core/Module.h" 140b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h" 150b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h" 160b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h" 170b57cec5SDimitry Andric #include "lldb/Symbol/SymbolFile.h" 180b57cec5SDimitry Andric #include "lldb/Symbol/Type.h" 190b57cec5SDimitry Andric #include "lldb/Symbol/TypeList.h" 200b57cec5SDimitry Andric #include "lldb/Symbol/Variable.h" 21349cc55cSDimitry Andric #include "lldb/Target/ABI.h" 2281ad6265SDimitry Andric #include "lldb/Target/Target.h" 2381ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 240b57cec5SDimitry Andric #include "lldb/Utility/Log.h" 250b57cec5SDimitry Andric #include "lldb/Utility/Timer.h" 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 280b57cec5SDimitry Andric #include "llvm/Support/DJB.h" 29bdd1243dSDimitry Andric #include <optional> 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric using namespace lldb; 320b57cec5SDimitry Andric using namespace lldb_private; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric char ObjCLanguageRuntime::ID = 0; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric // Destructor 37fe6060f1SDimitry Andric ObjCLanguageRuntime::~ObjCLanguageRuntime() = default; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric ObjCLanguageRuntime::ObjCLanguageRuntime(Process *process) 4081ad6265SDimitry Andric : LanguageRuntime(process), m_impl_cache(), m_impl_str_cache(), 410b57cec5SDimitry Andric m_has_new_literals_and_indexing(eLazyBoolCalculate), 420b57cec5SDimitry Andric m_isa_to_descriptor(), m_hash_to_isa_map(), m_type_size_cache(), 430b57cec5SDimitry Andric m_isa_to_descriptor_stop_id(UINT32_MAX), m_complete_class_cache(), 440b57cec5SDimitry Andric m_negative_complete_class_cache() {} 450b57cec5SDimitry Andric 465ffd83dbSDimitry Andric bool ObjCLanguageRuntime::IsAllowedRuntimeValue(ConstString name) { 470b57cec5SDimitry Andric static ConstString g_self = ConstString("self"); 480b57cec5SDimitry Andric static ConstString g_cmd = ConstString("_cmd"); 490b57cec5SDimitry Andric return name == g_self || name == g_cmd; 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric bool ObjCLanguageRuntime::AddClass(ObjCISA isa, 530b57cec5SDimitry Andric const ClassDescriptorSP &descriptor_sp, 540b57cec5SDimitry Andric const char *class_name) { 550b57cec5SDimitry Andric if (isa != 0) { 560b57cec5SDimitry Andric m_isa_to_descriptor[isa] = descriptor_sp; 570b57cec5SDimitry Andric // class_name is assumed to be valid 580b57cec5SDimitry Andric m_hash_to_isa_map.insert(std::make_pair(llvm::djbHash(class_name), isa)); 590b57cec5SDimitry Andric return true; 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric return false; 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric void ObjCLanguageRuntime::AddToMethodCache(lldb::addr_t class_addr, 650b57cec5SDimitry Andric lldb::addr_t selector, 660b57cec5SDimitry Andric lldb::addr_t impl_addr) { 6781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 680b57cec5SDimitry Andric if (log) { 699dba64beSDimitry Andric LLDB_LOGF(log, 709dba64beSDimitry Andric "Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 710b57cec5SDimitry Andric " implementation 0x%" PRIx64 ".", 720b57cec5SDimitry Andric class_addr, selector, impl_addr); 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric m_impl_cache.insert(std::pair<ClassAndSel, lldb::addr_t>( 750b57cec5SDimitry Andric ClassAndSel(class_addr, selector), impl_addr)); 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 7881ad6265SDimitry Andric void ObjCLanguageRuntime::AddToMethodCache(lldb::addr_t class_addr, 7981ad6265SDimitry Andric llvm::StringRef sel_str, 8081ad6265SDimitry Andric lldb::addr_t impl_addr) { 8181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 8281ad6265SDimitry Andric 8381ad6265SDimitry Andric LLDB_LOG(log, "Caching: class {0} selector {1} implementation {2}.", 8481ad6265SDimitry Andric class_addr, sel_str, impl_addr); 8581ad6265SDimitry Andric 8681ad6265SDimitry Andric m_impl_str_cache.insert(std::pair<ClassAndSelStr, lldb::addr_t>( 8781ad6265SDimitry Andric ClassAndSelStr(class_addr, sel_str), impl_addr)); 8881ad6265SDimitry Andric } 8981ad6265SDimitry Andric 900b57cec5SDimitry Andric lldb::addr_t ObjCLanguageRuntime::LookupInMethodCache(lldb::addr_t class_addr, 910b57cec5SDimitry Andric lldb::addr_t selector) { 920b57cec5SDimitry Andric MsgImplMap::iterator pos, end = m_impl_cache.end(); 930b57cec5SDimitry Andric pos = m_impl_cache.find(ClassAndSel(class_addr, selector)); 940b57cec5SDimitry Andric if (pos != end) 950b57cec5SDimitry Andric return (*pos).second; 960b57cec5SDimitry Andric return LLDB_INVALID_ADDRESS; 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric 9981ad6265SDimitry Andric lldb::addr_t ObjCLanguageRuntime::LookupInMethodCache(lldb::addr_t class_addr, 10081ad6265SDimitry Andric llvm::StringRef sel_str) { 10181ad6265SDimitry Andric MsgImplStrMap::iterator pos, end = m_impl_str_cache.end(); 10281ad6265SDimitry Andric pos = m_impl_str_cache.find(ClassAndSelStr(class_addr, sel_str)); 10381ad6265SDimitry Andric if (pos != end) 10481ad6265SDimitry Andric return (*pos).second; 10581ad6265SDimitry Andric return LLDB_INVALID_ADDRESS; 10681ad6265SDimitry Andric } 10781ad6265SDimitry Andric 1080b57cec5SDimitry Andric lldb::TypeSP 1090b57cec5SDimitry Andric ObjCLanguageRuntime::LookupInCompleteClassCache(ConstString &name) { 1100b57cec5SDimitry Andric CompleteClassMap::iterator complete_class_iter = 1110b57cec5SDimitry Andric m_complete_class_cache.find(name); 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric if (complete_class_iter != m_complete_class_cache.end()) { 1140b57cec5SDimitry Andric // Check the weak pointer to make sure the type hasn't been unloaded 1150b57cec5SDimitry Andric TypeSP complete_type_sp(complete_class_iter->second.lock()); 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric if (complete_type_sp) 1180b57cec5SDimitry Andric return complete_type_sp; 1190b57cec5SDimitry Andric else 1200b57cec5SDimitry Andric m_complete_class_cache.erase(name); 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric if (m_negative_complete_class_cache.count(name) > 0) 1240b57cec5SDimitry Andric return TypeSP(); 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric const ModuleList &modules = m_process->GetTarget().GetImages(); 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric SymbolContextList sc_list; 1290b57cec5SDimitry Andric modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list); 1309dba64beSDimitry Andric const size_t matching_symbols = sc_list.GetSize(); 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric if (matching_symbols) { 1330b57cec5SDimitry Andric SymbolContext sc; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric sc_list.GetContextAtIndex(0, sc); 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric ModuleSP module_sp(sc.module_sp); 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric if (!module_sp) 1400b57cec5SDimitry Andric return TypeSP(); 1410b57cec5SDimitry Andric 1425f757f3fSDimitry Andric TypeQuery query(name.GetStringRef(), TypeQueryOptions::e_exact_match); 1435f757f3fSDimitry Andric TypeResults results; 1445f757f3fSDimitry Andric module_sp->FindTypes(query, results); 1455f757f3fSDimitry Andric for (const TypeSP &type_sp : results.GetTypeMap().Types()) { 1465ffd83dbSDimitry Andric if (TypeSystemClang::IsObjCObjectOrInterfaceType( 1470b57cec5SDimitry Andric type_sp->GetForwardCompilerType())) { 1485ffd83dbSDimitry Andric if (TypePayloadClang(type_sp->GetPayload()).IsCompleteObjCClass()) { 1490b57cec5SDimitry Andric m_complete_class_cache[name] = type_sp; 1500b57cec5SDimitry Andric return type_sp; 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric m_negative_complete_class_cache.insert(name); 1560b57cec5SDimitry Andric return TypeSP(); 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric size_t ObjCLanguageRuntime::GetByteOffsetForIvar(CompilerType &parent_qual_type, 1600b57cec5SDimitry Andric const char *ivar_name) { 1610b57cec5SDimitry Andric return LLDB_INVALID_IVAR_OFFSET; 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric bool ObjCLanguageRuntime::ClassDescriptor::IsPointerValid( 1650b57cec5SDimitry Andric lldb::addr_t value, uint32_t ptr_size, bool allow_NULLs, bool allow_tagged, 1660b57cec5SDimitry Andric bool check_version_specific) const { 1670b57cec5SDimitry Andric if (!value) 1680b57cec5SDimitry Andric return allow_NULLs; 1690b57cec5SDimitry Andric if ((value % 2) == 1 && allow_tagged) 1700b57cec5SDimitry Andric return true; 1710b57cec5SDimitry Andric if ((value % ptr_size) == 0) 1720b57cec5SDimitry Andric return (check_version_specific ? CheckPointer(value, ptr_size) : true); 1730b57cec5SDimitry Andric else 1740b57cec5SDimitry Andric return false; 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric ObjCLanguageRuntime::ObjCISA 1780b57cec5SDimitry Andric ObjCLanguageRuntime::GetISA(ConstString name) { 1790b57cec5SDimitry Andric ISAToDescriptorIterator pos = GetDescriptorIterator(name); 1800b57cec5SDimitry Andric if (pos != m_isa_to_descriptor.end()) 1810b57cec5SDimitry Andric return pos->first; 1820b57cec5SDimitry Andric return 0; 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric ObjCLanguageRuntime::ISAToDescriptorIterator 1860b57cec5SDimitry Andric ObjCLanguageRuntime::GetDescriptorIterator(ConstString name) { 1870b57cec5SDimitry Andric ISAToDescriptorIterator end = m_isa_to_descriptor.end(); 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric if (name) { 1900b57cec5SDimitry Andric UpdateISAToDescriptorMap(); 1910b57cec5SDimitry Andric if (m_hash_to_isa_map.empty()) { 1920b57cec5SDimitry Andric // No name hashes were provided, we need to just linearly power through 1930b57cec5SDimitry Andric // the names and find a match 1940b57cec5SDimitry Andric for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin(); 1950b57cec5SDimitry Andric pos != end; ++pos) { 1960b57cec5SDimitry Andric if (pos->second->GetClassName() == name) 1970b57cec5SDimitry Andric return pos; 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric } else { 2000b57cec5SDimitry Andric // Name hashes were provided, so use them to efficiently lookup name to 2010b57cec5SDimitry Andric // isa/descriptor 2020b57cec5SDimitry Andric const uint32_t name_hash = llvm::djbHash(name.GetStringRef()); 2030b57cec5SDimitry Andric std::pair<HashToISAIterator, HashToISAIterator> range = 2040b57cec5SDimitry Andric m_hash_to_isa_map.equal_range(name_hash); 2050b57cec5SDimitry Andric for (HashToISAIterator range_pos = range.first; range_pos != range.second; 2060b57cec5SDimitry Andric ++range_pos) { 2070b57cec5SDimitry Andric ISAToDescriptorIterator pos = 2080b57cec5SDimitry Andric m_isa_to_descriptor.find(range_pos->second); 2090b57cec5SDimitry Andric if (pos != m_isa_to_descriptor.end()) { 2100b57cec5SDimitry Andric if (pos->second->GetClassName() == name) 2110b57cec5SDimitry Andric return pos; 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric return end; 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator, 2200b57cec5SDimitry Andric ObjCLanguageRuntime::ISAToDescriptorIterator> 2210b57cec5SDimitry Andric ObjCLanguageRuntime::GetDescriptorIteratorPair(bool update_if_needed) { 2220b57cec5SDimitry Andric if (update_if_needed) 2230b57cec5SDimitry Andric UpdateISAToDescriptorMapIfNeeded(); 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric return std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator, 2260b57cec5SDimitry Andric ObjCLanguageRuntime::ISAToDescriptorIterator>( 2270b57cec5SDimitry Andric m_isa_to_descriptor.begin(), m_isa_to_descriptor.end()); 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric 23006c3fb27SDimitry Andric void ObjCLanguageRuntime::ReadObjCLibraryIfNeeded( 23106c3fb27SDimitry Andric const ModuleList &module_list) { 23206c3fb27SDimitry Andric if (!HasReadObjCLibrary()) { 23306c3fb27SDimitry Andric std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex()); 23406c3fb27SDimitry Andric 23506c3fb27SDimitry Andric size_t num_modules = module_list.GetSize(); 23606c3fb27SDimitry Andric for (size_t i = 0; i < num_modules; i++) { 23706c3fb27SDimitry Andric auto mod = module_list.GetModuleAtIndex(i); 23806c3fb27SDimitry Andric if (IsModuleObjCLibrary(mod)) { 23906c3fb27SDimitry Andric ReadObjCLibrary(mod); 24006c3fb27SDimitry Andric break; 24106c3fb27SDimitry Andric } 24206c3fb27SDimitry Andric } 24306c3fb27SDimitry Andric } 24406c3fb27SDimitry Andric } 24506c3fb27SDimitry Andric 2460b57cec5SDimitry Andric ObjCLanguageRuntime::ObjCISA 2470b57cec5SDimitry Andric ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa) { 2480b57cec5SDimitry Andric ClassDescriptorSP objc_class_sp(GetClassDescriptorFromISA(isa)); 2490b57cec5SDimitry Andric if (objc_class_sp) { 2500b57cec5SDimitry Andric ClassDescriptorSP objc_super_class_sp(objc_class_sp->GetSuperclass()); 2510b57cec5SDimitry Andric if (objc_super_class_sp) 2520b57cec5SDimitry Andric return objc_super_class_sp->GetISA(); 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric return 0; 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP 2580b57cec5SDimitry Andric ObjCLanguageRuntime::GetClassDescriptorFromClassName( 2590b57cec5SDimitry Andric ConstString class_name) { 2600b57cec5SDimitry Andric ISAToDescriptorIterator pos = GetDescriptorIterator(class_name); 2610b57cec5SDimitry Andric if (pos != m_isa_to_descriptor.end()) 2620b57cec5SDimitry Andric return pos->second; 2630b57cec5SDimitry Andric return ClassDescriptorSP(); 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP 2670b57cec5SDimitry Andric ObjCLanguageRuntime::GetClassDescriptor(ValueObject &valobj) { 2680b57cec5SDimitry Andric ClassDescriptorSP objc_class_sp; 2690b57cec5SDimitry Andric // if we get an invalid VO (which might still happen when playing around with 2700b57cec5SDimitry Andric // pointers returned by the expression parser, don't consider this a valid 2710b57cec5SDimitry Andric // ObjC object) 2720b57cec5SDimitry Andric if (valobj.GetCompilerType().IsValid()) { 2730b57cec5SDimitry Andric addr_t isa_pointer = valobj.GetPointerValue(); 2740b57cec5SDimitry Andric if (isa_pointer != LLDB_INVALID_ADDRESS) { 2750b57cec5SDimitry Andric ExecutionContext exe_ctx(valobj.GetExecutionContextRef()); 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 2780b57cec5SDimitry Andric if (process) { 2790b57cec5SDimitry Andric Status error; 2800b57cec5SDimitry Andric ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error); 2810b57cec5SDimitry Andric if (isa != LLDB_INVALID_ADDRESS) 2820b57cec5SDimitry Andric objc_class_sp = GetClassDescriptorFromISA(isa); 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric return objc_class_sp; 2870b57cec5SDimitry Andric } 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP 2900b57cec5SDimitry Andric ObjCLanguageRuntime::GetNonKVOClassDescriptor(ValueObject &valobj) { 2910b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp( 2920b57cec5SDimitry Andric GetClassDescriptor(valobj)); 2930b57cec5SDimitry Andric if (objc_class_sp) { 2940b57cec5SDimitry Andric if (!objc_class_sp->IsKVO()) 2950b57cec5SDimitry Andric return objc_class_sp; 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass()); 2980b57cec5SDimitry Andric if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid()) 2990b57cec5SDimitry Andric return non_kvo_objc_class_sp; 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric return ClassDescriptorSP(); 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP 3050b57cec5SDimitry Andric ObjCLanguageRuntime::GetClassDescriptorFromISA(ObjCISA isa) { 3060b57cec5SDimitry Andric if (isa) { 3070b57cec5SDimitry Andric UpdateISAToDescriptorMap(); 308349cc55cSDimitry Andric 3090b57cec5SDimitry Andric ObjCLanguageRuntime::ISAToDescriptorIterator pos = 3100b57cec5SDimitry Andric m_isa_to_descriptor.find(isa); 3110b57cec5SDimitry Andric if (pos != m_isa_to_descriptor.end()) 3120b57cec5SDimitry Andric return pos->second; 313349cc55cSDimitry Andric 314349cc55cSDimitry Andric if (ABISP abi_sp = m_process->GetABI()) { 315349cc55cSDimitry Andric pos = m_isa_to_descriptor.find(abi_sp->FixCodeAddress(isa)); 316349cc55cSDimitry Andric if (pos != m_isa_to_descriptor.end()) 317349cc55cSDimitry Andric return pos->second; 318349cc55cSDimitry Andric } 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric return ClassDescriptorSP(); 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP 3240b57cec5SDimitry Andric ObjCLanguageRuntime::GetNonKVOClassDescriptor(ObjCISA isa) { 3250b57cec5SDimitry Andric if (isa) { 3260b57cec5SDimitry Andric ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA(isa); 3270b57cec5SDimitry Andric if (objc_class_sp && objc_class_sp->IsValid()) { 3280b57cec5SDimitry Andric if (!objc_class_sp->IsKVO()) 3290b57cec5SDimitry Andric return objc_class_sp; 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass()); 3320b57cec5SDimitry Andric if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid()) 3330b57cec5SDimitry Andric return non_kvo_objc_class_sp; 3340b57cec5SDimitry Andric } 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric return ClassDescriptorSP(); 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric CompilerType 3400b57cec5SDimitry Andric ObjCLanguageRuntime::EncodingToType::RealizeType(const char *name, 3410b57cec5SDimitry Andric bool for_expression) { 342bdd1243dSDimitry Andric if (m_scratch_ast_ctx_sp) 343bdd1243dSDimitry Andric return RealizeType(*m_scratch_ast_ctx_sp, name, for_expression); 3440b57cec5SDimitry Andric return CompilerType(); 3450b57cec5SDimitry Andric } 3460b57cec5SDimitry Andric 347fe6060f1SDimitry Andric ObjCLanguageRuntime::EncodingToType::~EncodingToType() = default; 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric ObjCLanguageRuntime::EncodingToTypeSP ObjCLanguageRuntime::GetEncodingToType() { 3500b57cec5SDimitry Andric return nullptr; 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric 353*0fca6ea1SDimitry Andric std::optional<uint64_t> 354*0fca6ea1SDimitry Andric ObjCLanguageRuntime::GetTypeBitSize(const CompilerType &compiler_type) { 3550b57cec5SDimitry Andric void *opaque_ptr = compiler_type.GetOpaqueQualType(); 356*0fca6ea1SDimitry Andric uint64_t cached_size = m_type_size_cache.Lookup(opaque_ptr); 357*0fca6ea1SDimitry Andric if (cached_size > 0) 358*0fca6ea1SDimitry Andric return cached_size; 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric ClassDescriptorSP class_descriptor_sp = 3610b57cec5SDimitry Andric GetClassDescriptorFromClassName(compiler_type.GetTypeName()); 3620b57cec5SDimitry Andric if (!class_descriptor_sp) 363*0fca6ea1SDimitry Andric return {}; 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric int32_t max_offset = INT32_MIN; 3660b57cec5SDimitry Andric uint64_t sizeof_max = 0; 3670b57cec5SDimitry Andric bool found = false; 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric for (size_t idx = 0; idx < class_descriptor_sp->GetNumIVars(); idx++) { 3700b57cec5SDimitry Andric const auto &ivar = class_descriptor_sp->GetIVarAtIndex(idx); 3710b57cec5SDimitry Andric int32_t cur_offset = ivar.m_offset; 3720b57cec5SDimitry Andric if (cur_offset > max_offset) { 3730b57cec5SDimitry Andric max_offset = cur_offset; 3740b57cec5SDimitry Andric sizeof_max = ivar.m_size; 3750b57cec5SDimitry Andric found = true; 3760b57cec5SDimitry Andric } 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric 379*0fca6ea1SDimitry Andric uint64_t size = 8 * (max_offset + sizeof_max); 380*0fca6ea1SDimitry Andric if (found && size > 0) { 3810b57cec5SDimitry Andric m_type_size_cache.Insert(opaque_ptr, size); 382*0fca6ea1SDimitry Andric return size; 383*0fca6ea1SDimitry Andric } 3840b57cec5SDimitry Andric 385*0fca6ea1SDimitry Andric return {}; 3860b57cec5SDimitry Andric } 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric lldb::BreakpointPreconditionSP 3890b57cec5SDimitry Andric ObjCLanguageRuntime::GetBreakpointExceptionPrecondition(LanguageType language, 3900b57cec5SDimitry Andric bool throw_bp) { 3910b57cec5SDimitry Andric if (language != eLanguageTypeObjC) 3920b57cec5SDimitry Andric return lldb::BreakpointPreconditionSP(); 3930b57cec5SDimitry Andric if (!throw_bp) 3940b57cec5SDimitry Andric return lldb::BreakpointPreconditionSP(); 3950b57cec5SDimitry Andric BreakpointPreconditionSP precondition_sp( 3960b57cec5SDimitry Andric new ObjCLanguageRuntime::ObjCExceptionPrecondition()); 3970b57cec5SDimitry Andric return precondition_sp; 3980b57cec5SDimitry Andric } 3990b57cec5SDimitry Andric 4000b57cec5SDimitry Andric // Exception breakpoint Precondition class for ObjC: 4010b57cec5SDimitry Andric void ObjCLanguageRuntime::ObjCExceptionPrecondition::AddClassName( 4020b57cec5SDimitry Andric const char *class_name) { 4030b57cec5SDimitry Andric m_class_names.insert(class_name); 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric 406fe6060f1SDimitry Andric ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition() = 407fe6060f1SDimitry Andric default; 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric bool ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition( 4100b57cec5SDimitry Andric StoppointCallbackContext &context) { 4110b57cec5SDimitry Andric return true; 4120b57cec5SDimitry Andric } 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric void ObjCLanguageRuntime::ObjCExceptionPrecondition::GetDescription( 4150b57cec5SDimitry Andric Stream &stream, lldb::DescriptionLevel level) {} 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric Status ObjCLanguageRuntime::ObjCExceptionPrecondition::ConfigurePrecondition( 4180b57cec5SDimitry Andric Args &args) { 4190b57cec5SDimitry Andric Status error; 4200b57cec5SDimitry Andric if (args.GetArgumentCount() > 0) 4210b57cec5SDimitry Andric error.SetErrorString( 4220b57cec5SDimitry Andric "The ObjC Exception breakpoint doesn't support extra options."); 4230b57cec5SDimitry Andric return error; 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric 426bdd1243dSDimitry Andric std::optional<CompilerType> 4270b57cec5SDimitry Andric ObjCLanguageRuntime::GetRuntimeType(CompilerType base_type) { 4280b57cec5SDimitry Andric CompilerType class_type; 4290b57cec5SDimitry Andric bool is_pointer_type = false; 4300b57cec5SDimitry Andric 4315ffd83dbSDimitry Andric if (TypeSystemClang::IsObjCObjectPointerType(base_type, &class_type)) 4320b57cec5SDimitry Andric is_pointer_type = true; 4335ffd83dbSDimitry Andric else if (TypeSystemClang::IsObjCObjectOrInterfaceType(base_type)) 4340b57cec5SDimitry Andric class_type = base_type; 4350b57cec5SDimitry Andric else 436bdd1243dSDimitry Andric return std::nullopt; 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric if (!class_type) 439bdd1243dSDimitry Andric return std::nullopt; 4400b57cec5SDimitry Andric 4415ffd83dbSDimitry Andric ConstString class_name(class_type.GetTypeName()); 4420b57cec5SDimitry Andric if (!class_name) 443bdd1243dSDimitry Andric return std::nullopt; 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric TypeSP complete_objc_class_type_sp = LookupInCompleteClassCache(class_name); 4460b57cec5SDimitry Andric if (!complete_objc_class_type_sp) 447bdd1243dSDimitry Andric return std::nullopt; 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric CompilerType complete_class( 4500b57cec5SDimitry Andric complete_objc_class_type_sp->GetFullCompilerType()); 4510b57cec5SDimitry Andric if (complete_class.GetCompleteType()) { 4520b57cec5SDimitry Andric if (is_pointer_type) 4530b57cec5SDimitry Andric return complete_class.GetPointerType(); 4540b57cec5SDimitry Andric else 4550b57cec5SDimitry Andric return complete_class; 4560b57cec5SDimitry Andric } 4570b57cec5SDimitry Andric 458bdd1243dSDimitry Andric return std::nullopt; 4590b57cec5SDimitry Andric } 460