1254721Semaste//===-- ObjCLanguageRuntime.cpp ---------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste#include "clang/AST/Type.h" 10254721Semaste 11254721Semaste#include "lldb/Core/Log.h" 12254721Semaste#include "lldb/Core/MappedHash.h" 13254721Semaste#include "lldb/Core/Module.h" 14254721Semaste#include "lldb/Core/PluginManager.h" 15254721Semaste#include "lldb/Core/Timer.h" 16254721Semaste#include "lldb/Core/ValueObject.h" 17254721Semaste#include "lldb/Symbol/ClangASTContext.h" 18254721Semaste#include "lldb/Symbol/Type.h" 19254721Semaste#include "lldb/Symbol/TypeList.h" 20254721Semaste#include "lldb/Target/ObjCLanguageRuntime.h" 21254721Semaste#include "lldb/Target/Target.h" 22254721Semaste 23254721Semaste#include "llvm/ADT/StringRef.h" 24254721Semaste 25254721Semasteusing namespace lldb; 26254721Semasteusing namespace lldb_private; 27254721Semaste 28254721Semaste//---------------------------------------------------------------------- 29254721Semaste// Destructor 30254721Semaste//---------------------------------------------------------------------- 31254721SemasteObjCLanguageRuntime::~ObjCLanguageRuntime() 32254721Semaste{ 33254721Semaste} 34254721Semaste 35254721SemasteObjCLanguageRuntime::ObjCLanguageRuntime (Process *process) : 36254721Semaste LanguageRuntime (process), 37254721Semaste m_has_new_literals_and_indexing (eLazyBoolCalculate), 38254721Semaste m_isa_to_descriptor(), 39254721Semaste m_isa_to_descriptor_stop_id (UINT32_MAX) 40254721Semaste{ 41254721Semaste 42254721Semaste} 43254721Semaste 44254721Semastebool 45254721SemasteObjCLanguageRuntime::AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, const char *class_name) 46254721Semaste{ 47254721Semaste if (isa != 0) 48254721Semaste { 49254721Semaste m_isa_to_descriptor[isa] = descriptor_sp; 50254721Semaste // class_name is assumed to be valid 51254721Semaste m_hash_to_isa_map.insert(std::make_pair(MappedHash::HashStringUsingDJB(class_name), isa)); 52254721Semaste return true; 53254721Semaste } 54254721Semaste return false; 55254721Semaste} 56254721Semaste 57254721Semastevoid 58254721SemasteObjCLanguageRuntime::AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t selector, lldb::addr_t impl_addr) 59254721Semaste{ 60254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 61254721Semaste if (log) 62254721Semaste { 63254721Semaste log->Printf ("Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 " implementation 0x%" PRIx64 ".", class_addr, selector, impl_addr); 64254721Semaste } 65254721Semaste m_impl_cache.insert (std::pair<ClassAndSel,lldb::addr_t> (ClassAndSel(class_addr, selector), impl_addr)); 66254721Semaste} 67254721Semaste 68254721Semastelldb::addr_t 69254721SemasteObjCLanguageRuntime::LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t selector) 70254721Semaste{ 71254721Semaste MsgImplMap::iterator pos, end = m_impl_cache.end(); 72254721Semaste pos = m_impl_cache.find (ClassAndSel(class_addr, selector)); 73254721Semaste if (pos != end) 74254721Semaste return (*pos).second; 75254721Semaste return LLDB_INVALID_ADDRESS; 76254721Semaste} 77254721Semaste 78254721Semaste 79254721Semastelldb::TypeSP 80254721SemasteObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name) 81254721Semaste{ 82254721Semaste CompleteClassMap::iterator complete_class_iter = m_complete_class_cache.find(name); 83254721Semaste 84254721Semaste if (complete_class_iter != m_complete_class_cache.end()) 85254721Semaste { 86254721Semaste // Check the weak pointer to make sure the type hasn't been unloaded 87254721Semaste TypeSP complete_type_sp (complete_class_iter->second.lock()); 88254721Semaste 89254721Semaste if (complete_type_sp) 90254721Semaste return complete_type_sp; 91254721Semaste else 92254721Semaste m_complete_class_cache.erase(name); 93254721Semaste } 94254721Semaste 95254721Semaste if (m_negative_complete_class_cache.count(name) > 0) 96254721Semaste return TypeSP(); 97254721Semaste 98254721Semaste const ModuleList &modules = m_process->GetTarget().GetImages(); 99254721Semaste 100254721Semaste SymbolContextList sc_list; 101254721Semaste const size_t matching_symbols = modules.FindSymbolsWithNameAndType (name, 102254721Semaste eSymbolTypeObjCClass, 103254721Semaste sc_list); 104254721Semaste 105254721Semaste if (matching_symbols) 106254721Semaste { 107254721Semaste SymbolContext sc; 108254721Semaste 109254721Semaste sc_list.GetContextAtIndex(0, sc); 110254721Semaste 111254721Semaste ModuleSP module_sp(sc.module_sp); 112254721Semaste 113254721Semaste if (!module_sp) 114254721Semaste return TypeSP(); 115254721Semaste 116254721Semaste const SymbolContext null_sc; 117254721Semaste const bool exact_match = true; 118254721Semaste const uint32_t max_matches = UINT32_MAX; 119254721Semaste TypeList types; 120254721Semaste 121254721Semaste const uint32_t num_types = module_sp->FindTypes (null_sc, 122254721Semaste name, 123254721Semaste exact_match, 124254721Semaste max_matches, 125254721Semaste types); 126254721Semaste 127254721Semaste if (num_types) 128254721Semaste { 129254721Semaste uint32_t i; 130254721Semaste for (i = 0; i < num_types; ++i) 131254721Semaste { 132254721Semaste TypeSP type_sp (types.GetTypeAtIndex(i)); 133254721Semaste 134254721Semaste if (type_sp->GetClangForwardType().IsObjCObjectOrInterfaceType()) 135254721Semaste { 136254721Semaste if (type_sp->IsCompleteObjCClass()) 137254721Semaste { 138254721Semaste m_complete_class_cache[name] = type_sp; 139254721Semaste return type_sp; 140254721Semaste } 141254721Semaste } 142254721Semaste } 143254721Semaste } 144254721Semaste } 145254721Semaste m_negative_complete_class_cache.insert(name); 146254721Semaste return TypeSP(); 147254721Semaste} 148254721Semaste 149254721Semastesize_t 150254721SemasteObjCLanguageRuntime::GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name) 151254721Semaste{ 152254721Semaste return LLDB_INVALID_IVAR_OFFSET; 153254721Semaste} 154254721Semaste 155254721Semastevoid 156254721SemasteObjCLanguageRuntime::MethodName::Clear() 157254721Semaste{ 158254721Semaste m_full.Clear(); 159254721Semaste m_class.Clear(); 160254721Semaste m_category.Clear(); 161254721Semaste m_selector.Clear(); 162254721Semaste m_type = eTypeUnspecified; 163254721Semaste m_category_is_valid = false; 164254721Semaste} 165254721Semaste 166254721Semaste//bool 167254721Semaste//ObjCLanguageRuntime::MethodName::SetName (const char *name, bool strict) 168254721Semaste//{ 169254721Semaste// Clear(); 170254721Semaste// if (name && name[0]) 171254721Semaste// { 172254721Semaste// // If "strict" is true. then the method must be specified with a 173254721Semaste// // '+' or '-' at the beginning. If "strict" is false, then the '+' 174254721Semaste// // or '-' can be omitted 175254721Semaste// bool valid_prefix = false; 176254721Semaste// 177254721Semaste// if (name[0] == '+' || name[0] == '-') 178254721Semaste// { 179254721Semaste// valid_prefix = name[1] == '['; 180254721Semaste// } 181254721Semaste// else if (!strict) 182254721Semaste// { 183254721Semaste// // "strict" is false, the name just needs to start with '[' 184254721Semaste// valid_prefix = name[0] == '['; 185254721Semaste// } 186254721Semaste// 187254721Semaste// if (valid_prefix) 188254721Semaste// { 189254721Semaste// static RegularExpression g_regex("^([-+]?)\\[([A-Za-z_][A-Za-z_0-9]*)(\\([A-Za-z_][A-Za-z_0-9]*\\))? ([A-Za-z_][A-Za-z_0-9:]*)\\]$"); 190254721Semaste// llvm::StringRef matches[4]; 191254721Semaste// // Since we are using a global regular expression, we must use the threadsafe version of execute 192254721Semaste// if (g_regex.ExecuteThreadSafe(name, matches, 4)) 193254721Semaste// { 194254721Semaste// m_full.SetCString(name); 195254721Semaste// if (matches[0].empty()) 196254721Semaste// m_type = eTypeUnspecified; 197254721Semaste// else if (matches[0][0] == '+') 198254721Semaste// m_type = eTypeClassMethod; 199254721Semaste// else 200254721Semaste// m_type = eTypeInstanceMethod; 201254721Semaste// m_class.SetString(matches[1]); 202254721Semaste// m_selector.SetString(matches[3]); 203254721Semaste// if (!matches[2].empty()) 204254721Semaste// m_category.SetString(matches[2]); 205254721Semaste// } 206254721Semaste// } 207254721Semaste// } 208254721Semaste// return IsValid(strict); 209254721Semaste//} 210254721Semaste 211254721Semastebool 212254721SemasteObjCLanguageRuntime::MethodName::SetName (const char *name, bool strict) 213254721Semaste{ 214254721Semaste Clear(); 215254721Semaste if (name && name[0]) 216254721Semaste { 217254721Semaste // If "strict" is true. then the method must be specified with a 218254721Semaste // '+' or '-' at the beginning. If "strict" is false, then the '+' 219254721Semaste // or '-' can be omitted 220254721Semaste bool valid_prefix = false; 221254721Semaste 222254721Semaste if (name[0] == '+' || name[0] == '-') 223254721Semaste { 224254721Semaste valid_prefix = name[1] == '['; 225254721Semaste if (name[0] == '+') 226254721Semaste m_type = eTypeClassMethod; 227254721Semaste else 228254721Semaste m_type = eTypeInstanceMethod; 229254721Semaste } 230254721Semaste else if (!strict) 231254721Semaste { 232254721Semaste // "strict" is false, the name just needs to start with '[' 233254721Semaste valid_prefix = name[0] == '['; 234254721Semaste } 235254721Semaste 236254721Semaste if (valid_prefix) 237254721Semaste { 238254721Semaste int name_len = strlen (name); 239254721Semaste // Objective C methods must have at least: 240254721Semaste // "-[" or "+[" prefix 241254721Semaste // One character for a class name 242254721Semaste // One character for the space between the class name 243254721Semaste // One character for the method name 244254721Semaste // "]" suffix 245254721Semaste if (name_len >= (5 + (strict ? 1 : 0)) && name[name_len - 1] == ']') 246254721Semaste { 247254721Semaste m_full.SetCStringWithLength(name, name_len); 248254721Semaste } 249254721Semaste } 250254721Semaste } 251254721Semaste return IsValid(strict); 252254721Semaste} 253254721Semaste 254254721Semasteconst ConstString & 255254721SemasteObjCLanguageRuntime::MethodName::GetClassName () 256254721Semaste{ 257254721Semaste if (!m_class) 258254721Semaste { 259254721Semaste if (IsValid(false)) 260254721Semaste { 261254721Semaste const char *full = m_full.GetCString(); 262254721Semaste const char *class_start = (full[0] == '[' ? full + 1 : full + 2); 263254721Semaste const char *paren_pos = strchr (class_start, '('); 264254721Semaste if (paren_pos) 265254721Semaste { 266254721Semaste m_class.SetCStringWithLength (class_start, paren_pos - class_start); 267254721Semaste } 268254721Semaste else 269254721Semaste { 270254721Semaste // No '(' was found in the full name, we can definitively say 271254721Semaste // that our category was valid (and empty). 272254721Semaste m_category_is_valid = true; 273254721Semaste const char *space_pos = strchr (full, ' '); 274254721Semaste if (space_pos) 275254721Semaste { 276254721Semaste m_class.SetCStringWithLength (class_start, space_pos - class_start); 277254721Semaste if (!m_class_category) 278254721Semaste { 279254721Semaste // No category in name, so we can also fill in the m_class_category 280254721Semaste m_class_category = m_class; 281254721Semaste } 282254721Semaste } 283254721Semaste } 284254721Semaste } 285254721Semaste } 286254721Semaste return m_class; 287254721Semaste} 288254721Semaste 289254721Semasteconst ConstString & 290254721SemasteObjCLanguageRuntime::MethodName::GetClassNameWithCategory () 291254721Semaste{ 292254721Semaste if (!m_class_category) 293254721Semaste { 294254721Semaste if (IsValid(false)) 295254721Semaste { 296254721Semaste const char *full = m_full.GetCString(); 297254721Semaste const char *class_start = (full[0] == '[' ? full + 1 : full + 2); 298254721Semaste const char *space_pos = strchr (full, ' '); 299254721Semaste if (space_pos) 300254721Semaste { 301254721Semaste m_class_category.SetCStringWithLength (class_start, space_pos - class_start); 302254721Semaste // If m_class hasn't been filled in and the class with category doesn't 303254721Semaste // contain a '(', then we can also fill in the m_class 304254721Semaste if (!m_class && strchr (m_class_category.GetCString(), '(') == NULL) 305254721Semaste { 306254721Semaste m_class = m_class_category; 307254721Semaste // No '(' was found in the full name, we can definitively say 308254721Semaste // that our category was valid (and empty). 309254721Semaste m_category_is_valid = true; 310254721Semaste 311254721Semaste } 312254721Semaste } 313254721Semaste } 314254721Semaste } 315254721Semaste return m_class_category; 316254721Semaste} 317254721Semaste 318254721Semasteconst ConstString & 319254721SemasteObjCLanguageRuntime::MethodName::GetSelector () 320254721Semaste{ 321254721Semaste if (!m_selector) 322254721Semaste { 323254721Semaste if (IsValid(false)) 324254721Semaste { 325254721Semaste const char *full = m_full.GetCString(); 326254721Semaste const char *space_pos = strchr (full, ' '); 327254721Semaste if (space_pos) 328254721Semaste { 329254721Semaste ++space_pos; // skip the space 330254721Semaste m_selector.SetCStringWithLength (space_pos, m_full.GetLength() - (space_pos - full) - 1); 331254721Semaste } 332254721Semaste } 333254721Semaste } 334254721Semaste return m_selector; 335254721Semaste} 336254721Semaste 337254721Semasteconst ConstString & 338254721SemasteObjCLanguageRuntime::MethodName::GetCategory () 339254721Semaste{ 340254721Semaste if (!m_category_is_valid && !m_category) 341254721Semaste { 342254721Semaste if (IsValid(false)) 343254721Semaste { 344254721Semaste m_category_is_valid = true; 345254721Semaste const char *full = m_full.GetCString(); 346254721Semaste const char *class_start = (full[0] == '[' ? full + 1 : full + 2); 347254721Semaste const char *open_paren_pos = strchr (class_start, '('); 348254721Semaste if (open_paren_pos) 349254721Semaste { 350254721Semaste ++open_paren_pos; // Skip the open paren 351254721Semaste const char *close_paren_pos = strchr (open_paren_pos, ')'); 352254721Semaste if (close_paren_pos) 353254721Semaste m_category.SetCStringWithLength (open_paren_pos, close_paren_pos - open_paren_pos); 354254721Semaste } 355254721Semaste } 356254721Semaste } 357254721Semaste return m_category; 358254721Semaste} 359254721Semaste 360254721SemasteConstString 361254721SemasteObjCLanguageRuntime::MethodName::GetFullNameWithoutCategory (bool empty_if_no_category) 362254721Semaste{ 363254721Semaste if (IsValid(false)) 364254721Semaste { 365254721Semaste if (HasCategory()) 366254721Semaste { 367254721Semaste StreamString strm; 368254721Semaste if (m_type == eTypeClassMethod) 369254721Semaste strm.PutChar('+'); 370254721Semaste else if (m_type == eTypeInstanceMethod) 371254721Semaste strm.PutChar('-'); 372254721Semaste strm.Printf("[%s %s]", GetClassName().GetCString(), GetSelector().GetCString()); 373254721Semaste return ConstString(strm.GetString().c_str()); 374254721Semaste } 375254721Semaste 376254721Semaste if (!empty_if_no_category) 377254721Semaste { 378254721Semaste // Just return the full name since it doesn't have a category 379254721Semaste return GetFullName(); 380254721Semaste } 381254721Semaste } 382254721Semaste return ConstString(); 383254721Semaste} 384254721Semaste 385254721Semastesize_t 386254721SemasteObjCLanguageRuntime::MethodName::GetFullNames (std::vector<ConstString> &names, bool append) 387254721Semaste{ 388254721Semaste if (!append) 389254721Semaste names.clear(); 390254721Semaste if (IsValid(false)) 391254721Semaste { 392254721Semaste StreamString strm; 393254721Semaste const bool is_class_method = m_type == eTypeClassMethod; 394254721Semaste const bool is_instance_method = m_type == eTypeInstanceMethod; 395254721Semaste const ConstString &category = GetCategory(); 396254721Semaste if (is_class_method || is_instance_method) 397254721Semaste { 398254721Semaste names.push_back (m_full); 399254721Semaste if (category) 400254721Semaste { 401254721Semaste strm.Printf("%c[%s %s]", 402254721Semaste is_class_method ? '+' : '-', 403254721Semaste GetClassName().GetCString(), 404254721Semaste GetSelector().GetCString()); 405254721Semaste names.push_back(ConstString(strm.GetString().c_str())); 406254721Semaste } 407254721Semaste } 408254721Semaste else 409254721Semaste { 410254721Semaste const ConstString &class_name = GetClassName(); 411254721Semaste const ConstString &selector = GetSelector(); 412254721Semaste strm.Printf("+[%s %s]", class_name.GetCString(), selector.GetCString()); 413254721Semaste names.push_back(ConstString(strm.GetString().c_str())); 414254721Semaste strm.Clear(); 415254721Semaste strm.Printf("-[%s %s]", class_name.GetCString(), selector.GetCString()); 416254721Semaste names.push_back(ConstString(strm.GetString().c_str())); 417254721Semaste strm.Clear(); 418254721Semaste if (category) 419254721Semaste { 420254721Semaste strm.Printf("+[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString()); 421254721Semaste names.push_back(ConstString(strm.GetString().c_str())); 422254721Semaste strm.Clear(); 423254721Semaste strm.Printf("-[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString()); 424254721Semaste names.push_back(ConstString(strm.GetString().c_str())); 425254721Semaste } 426254721Semaste } 427254721Semaste } 428254721Semaste return names.size(); 429254721Semaste} 430254721Semaste 431254721Semaste 432254721Semastebool 433254721SemasteObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value, 434254721Semaste uint32_t ptr_size, 435254721Semaste bool allow_NULLs, 436254721Semaste bool allow_tagged, 437254721Semaste bool check_version_specific) const 438254721Semaste{ 439254721Semaste if (!value) 440254721Semaste return allow_NULLs; 441254721Semaste if ( (value % 2) == 1 && allow_tagged) 442254721Semaste return true; 443254721Semaste if ((value % ptr_size) == 0) 444254721Semaste return (check_version_specific ? CheckPointer(value,ptr_size) : true); 445254721Semaste else 446254721Semaste return false; 447254721Semaste} 448254721Semaste 449254721SemasteObjCLanguageRuntime::ObjCISA 450254721SemasteObjCLanguageRuntime::GetISA(const ConstString &name) 451254721Semaste{ 452254721Semaste ISAToDescriptorIterator pos = GetDescriptorIterator (name); 453254721Semaste if (pos != m_isa_to_descriptor.end()) 454254721Semaste return pos->first; 455254721Semaste return 0; 456254721Semaste} 457254721Semaste 458254721SemasteObjCLanguageRuntime::ISAToDescriptorIterator 459254721SemasteObjCLanguageRuntime::GetDescriptorIterator (const ConstString &name) 460254721Semaste{ 461254721Semaste ISAToDescriptorIterator end = m_isa_to_descriptor.end(); 462254721Semaste 463254721Semaste if (name) 464254721Semaste { 465254721Semaste UpdateISAToDescriptorMap(); 466254721Semaste if (m_hash_to_isa_map.empty()) 467254721Semaste { 468254721Semaste // No name hashes were provided, we need to just linearly power through the 469254721Semaste // names and find a match 470254721Semaste for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin(); pos != end; ++pos) 471254721Semaste { 472254721Semaste if (pos->second->GetClassName() == name) 473254721Semaste return pos; 474254721Semaste } 475254721Semaste } 476254721Semaste else 477254721Semaste { 478254721Semaste // Name hashes were provided, so use them to efficiently lookup name to isa/descriptor 479254721Semaste const uint32_t name_hash = MappedHash::HashStringUsingDJB (name.GetCString()); 480254721Semaste std::pair <HashToISAIterator, HashToISAIterator> range = m_hash_to_isa_map.equal_range(name_hash); 481254721Semaste for (HashToISAIterator range_pos = range.first; range_pos != range.second; ++range_pos) 482254721Semaste { 483254721Semaste ISAToDescriptorIterator pos = m_isa_to_descriptor.find (range_pos->second); 484254721Semaste if (pos != m_isa_to_descriptor.end()) 485254721Semaste { 486254721Semaste if (pos->second->GetClassName() == name) 487254721Semaste return pos; 488254721Semaste } 489254721Semaste } 490254721Semaste } 491254721Semaste } 492254721Semaste return end; 493254721Semaste} 494254721Semaste 495254721Semaste 496254721SemasteObjCLanguageRuntime::ObjCISA 497254721SemasteObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa) 498254721Semaste{ 499254721Semaste ClassDescriptorSP objc_class_sp (GetClassDescriptorFromISA(isa)); 500254721Semaste if (objc_class_sp) 501254721Semaste { 502254721Semaste ClassDescriptorSP objc_super_class_sp (objc_class_sp->GetSuperclass()); 503254721Semaste if (objc_super_class_sp) 504254721Semaste return objc_super_class_sp->GetISA(); 505254721Semaste } 506254721Semaste return 0; 507254721Semaste} 508254721Semaste 509254721SemasteConstString 510254721SemasteObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) 511254721Semaste{ 512254721Semaste ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor(isa)); 513254721Semaste if (objc_class_sp) 514254721Semaste return objc_class_sp->GetClassName(); 515254721Semaste return ConstString(); 516254721Semaste} 517254721Semaste 518254721SemasteObjCLanguageRuntime::ClassDescriptorSP 519254721SemasteObjCLanguageRuntime::GetClassDescriptorFromClassName (const ConstString &class_name) 520254721Semaste{ 521254721Semaste ISAToDescriptorIterator pos = GetDescriptorIterator (class_name); 522254721Semaste if (pos != m_isa_to_descriptor.end()) 523254721Semaste return pos->second; 524254721Semaste return ClassDescriptorSP(); 525254721Semaste 526254721Semaste} 527254721Semaste 528254721SemasteObjCLanguageRuntime::ClassDescriptorSP 529254721SemasteObjCLanguageRuntime::GetClassDescriptor (ValueObject& valobj) 530254721Semaste{ 531254721Semaste ClassDescriptorSP objc_class_sp; 532254721Semaste // if we get an invalid VO (which might still happen when playing around 533254721Semaste // with pointers returned by the expression parser, don't consider this 534254721Semaste // a valid ObjC object) 535254721Semaste if (valobj.GetClangType().IsValid()) 536254721Semaste { 537254721Semaste addr_t isa_pointer = valobj.GetPointerValue(); 538254721Semaste if (isa_pointer != LLDB_INVALID_ADDRESS) 539254721Semaste { 540254721Semaste ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); 541254721Semaste 542254721Semaste Process *process = exe_ctx.GetProcessPtr(); 543254721Semaste if (process) 544254721Semaste { 545254721Semaste Error error; 546254721Semaste ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error); 547254721Semaste if (isa != LLDB_INVALID_ADDRESS) 548254721Semaste objc_class_sp = GetClassDescriptorFromISA (isa); 549254721Semaste } 550254721Semaste } 551254721Semaste } 552254721Semaste return objc_class_sp; 553254721Semaste} 554254721Semaste 555254721SemasteObjCLanguageRuntime::ClassDescriptorSP 556254721SemasteObjCLanguageRuntime::GetNonKVOClassDescriptor (ValueObject& valobj) 557254721Semaste{ 558254721Semaste ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (GetClassDescriptor (valobj)); 559254721Semaste if (objc_class_sp) 560254721Semaste { 561254721Semaste if (!objc_class_sp->IsKVO()) 562254721Semaste return objc_class_sp; 563254721Semaste 564254721Semaste ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass()); 565254721Semaste if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid()) 566254721Semaste return non_kvo_objc_class_sp; 567254721Semaste } 568254721Semaste return ClassDescriptorSP(); 569254721Semaste} 570254721Semaste 571254721Semaste 572254721SemasteObjCLanguageRuntime::ClassDescriptorSP 573254721SemasteObjCLanguageRuntime::GetClassDescriptorFromISA (ObjCISA isa) 574254721Semaste{ 575254721Semaste if (isa) 576254721Semaste { 577254721Semaste UpdateISAToDescriptorMap(); 578254721Semaste ObjCLanguageRuntime::ISAToDescriptorIterator pos = m_isa_to_descriptor.find(isa); 579254721Semaste if (pos != m_isa_to_descriptor.end()) 580254721Semaste return pos->second; 581254721Semaste } 582254721Semaste return ClassDescriptorSP(); 583254721Semaste} 584254721Semaste 585254721SemasteObjCLanguageRuntime::ClassDescriptorSP 586254721SemasteObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa) 587254721Semaste{ 588254721Semaste if (isa) 589254721Semaste { 590254721Semaste ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA (isa); 591254721Semaste if (objc_class_sp && objc_class_sp->IsValid()) 592254721Semaste { 593254721Semaste if (!objc_class_sp->IsKVO()) 594254721Semaste return objc_class_sp; 595254721Semaste 596254721Semaste ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass()); 597254721Semaste if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid()) 598254721Semaste return non_kvo_objc_class_sp; 599254721Semaste } 600254721Semaste } 601254721Semaste return ClassDescriptorSP(); 602254721Semaste} 603254721Semaste 604254721Semaste 605254721Semaste 606