1 //===-- ObjCLanguageRuntime.cpp ---------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #include "clang/AST/Type.h" 10 11 #include "lldb/Core/Log.h" 12 #include "lldb/Core/MappedHash.h" 13 #include "lldb/Core/Module.h" 14 #include "lldb/Core/PluginManager.h" 15 #include "lldb/Core/Timer.h" 16 #include "lldb/Core/ValueObject.h" 17 #include "lldb/Symbol/ClangASTContext.h" 18 #include "lldb/Symbol/SymbolContext.h" 19 #include "lldb/Symbol/SymbolFile.h" 20 #include "lldb/Symbol/Type.h" 21 #include "lldb/Symbol/TypeList.h" 22 #include "lldb/Target/ObjCLanguageRuntime.h" 23 #include "lldb/Target/Target.h" 24 25 #include "llvm/ADT/StringRef.h" 26 27 using namespace lldb; 28 using namespace lldb_private; 29 30 //---------------------------------------------------------------------- 31 // Destructor 32 //---------------------------------------------------------------------- 33 ObjCLanguageRuntime::~ObjCLanguageRuntime() 34 { 35 } 36 37 ObjCLanguageRuntime::ObjCLanguageRuntime (Process *process) : 38 LanguageRuntime (process), 39 m_impl_cache(), 40 m_has_new_literals_and_indexing (eLazyBoolCalculate), 41 m_isa_to_descriptor(), 42 m_hash_to_isa_map(), 43 m_type_size_cache(), 44 m_isa_to_descriptor_stop_id (UINT32_MAX), 45 m_complete_class_cache(), 46 m_negative_complete_class_cache() 47 { 48 } 49 50 bool 51 ObjCLanguageRuntime::AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, const char *class_name) 52 { 53 if (isa != 0) 54 { 55 m_isa_to_descriptor[isa] = descriptor_sp; 56 // class_name is assumed to be valid 57 m_hash_to_isa_map.insert(std::make_pair(MappedHash::HashStringUsingDJB(class_name), isa)); 58 return true; 59 } 60 return false; 61 } 62 63 void 64 ObjCLanguageRuntime::AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t selector, lldb::addr_t impl_addr) 65 { 66 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 67 if (log) 68 { 69 log->Printf ("Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 " implementation 0x%" PRIx64 ".", class_addr, selector, impl_addr); 70 } 71 m_impl_cache.insert (std::pair<ClassAndSel,lldb::addr_t> (ClassAndSel(class_addr, selector), impl_addr)); 72 } 73 74 lldb::addr_t 75 ObjCLanguageRuntime::LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t selector) 76 { 77 MsgImplMap::iterator pos, end = m_impl_cache.end(); 78 pos = m_impl_cache.find (ClassAndSel(class_addr, selector)); 79 if (pos != end) 80 return (*pos).second; 81 return LLDB_INVALID_ADDRESS; 82 } 83 84 85 lldb::TypeSP 86 ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name) 87 { 88 CompleteClassMap::iterator complete_class_iter = m_complete_class_cache.find(name); 89 90 if (complete_class_iter != m_complete_class_cache.end()) 91 { 92 // Check the weak pointer to make sure the type hasn't been unloaded 93 TypeSP complete_type_sp (complete_class_iter->second.lock()); 94 95 if (complete_type_sp) 96 return complete_type_sp; 97 else 98 m_complete_class_cache.erase(name); 99 } 100 101 if (m_negative_complete_class_cache.count(name) > 0) 102 return TypeSP(); 103 104 const ModuleList &modules = m_process->GetTarget().GetImages(); 105 106 SymbolContextList sc_list; 107 const size_t matching_symbols = modules.FindSymbolsWithNameAndType (name, 108 eSymbolTypeObjCClass, 109 sc_list); 110 111 if (matching_symbols) 112 { 113 SymbolContext sc; 114 115 sc_list.GetContextAtIndex(0, sc); 116 117 ModuleSP module_sp(sc.module_sp); 118 119 if (!module_sp) 120 return TypeSP(); 121 122 const SymbolContext null_sc; 123 const bool exact_match = true; 124 const uint32_t max_matches = UINT32_MAX; 125 TypeList types; 126 127 llvm::DenseSet<SymbolFile *> searched_symbol_files; 128 const uint32_t num_types = module_sp->FindTypes (null_sc, 129 name, 130 exact_match, 131 max_matches, 132 searched_symbol_files, 133 types); 134 135 if (num_types) 136 { 137 uint32_t i; 138 for (i = 0; i < num_types; ++i) 139 { 140 TypeSP type_sp (types.GetTypeAtIndex(i)); 141 142 if (ClangASTContext::IsObjCObjectOrInterfaceType(type_sp->GetForwardCompilerType ())) 143 { 144 if (type_sp->IsCompleteObjCClass()) 145 { 146 m_complete_class_cache[name] = type_sp; 147 return type_sp; 148 } 149 } 150 } 151 } 152 } 153 m_negative_complete_class_cache.insert(name); 154 return TypeSP(); 155 } 156 157 size_t 158 ObjCLanguageRuntime::GetByteOffsetForIvar (CompilerType &parent_qual_type, const char *ivar_name) 159 { 160 return LLDB_INVALID_IVAR_OFFSET; 161 } 162 163 bool 164 ObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value, 165 uint32_t ptr_size, 166 bool allow_NULLs, 167 bool allow_tagged, 168 bool check_version_specific) const 169 { 170 if (!value) 171 return allow_NULLs; 172 if ( (value % 2) == 1 && allow_tagged) 173 return true; 174 if ((value % ptr_size) == 0) 175 return (check_version_specific ? CheckPointer(value,ptr_size) : true); 176 else 177 return false; 178 } 179 180 ObjCLanguageRuntime::ObjCISA 181 ObjCLanguageRuntime::GetISA(const ConstString &name) 182 { 183 ISAToDescriptorIterator pos = GetDescriptorIterator (name); 184 if (pos != m_isa_to_descriptor.end()) 185 return pos->first; 186 return 0; 187 } 188 189 ObjCLanguageRuntime::ISAToDescriptorIterator 190 ObjCLanguageRuntime::GetDescriptorIterator (const ConstString &name) 191 { 192 ISAToDescriptorIterator end = m_isa_to_descriptor.end(); 193 194 if (name) 195 { 196 UpdateISAToDescriptorMap(); 197 if (m_hash_to_isa_map.empty()) 198 { 199 // No name hashes were provided, we need to just linearly power through the 200 // names and find a match 201 for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin(); pos != end; ++pos) 202 { 203 if (pos->second->GetClassName() == name) 204 return pos; 205 } 206 } 207 else 208 { 209 // Name hashes were provided, so use them to efficiently lookup name to isa/descriptor 210 const uint32_t name_hash = MappedHash::HashStringUsingDJB (name.GetCString()); 211 std::pair <HashToISAIterator, HashToISAIterator> range = m_hash_to_isa_map.equal_range(name_hash); 212 for (HashToISAIterator range_pos = range.first; range_pos != range.second; ++range_pos) 213 { 214 ISAToDescriptorIterator pos = m_isa_to_descriptor.find (range_pos->second); 215 if (pos != m_isa_to_descriptor.end()) 216 { 217 if (pos->second->GetClassName() == name) 218 return pos; 219 } 220 } 221 } 222 } 223 return end; 224 } 225 226 std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,ObjCLanguageRuntime::ISAToDescriptorIterator> 227 ObjCLanguageRuntime::GetDescriptorIteratorPair (bool update_if_needed) 228 { 229 if (update_if_needed) 230 UpdateISAToDescriptorMapIfNeeded(); 231 232 return std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator, 233 ObjCLanguageRuntime::ISAToDescriptorIterator>( 234 m_isa_to_descriptor.begin(), 235 m_isa_to_descriptor.end()); 236 } 237 238 239 ObjCLanguageRuntime::ObjCISA 240 ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa) 241 { 242 ClassDescriptorSP objc_class_sp (GetClassDescriptorFromISA(isa)); 243 if (objc_class_sp) 244 { 245 ClassDescriptorSP objc_super_class_sp (objc_class_sp->GetSuperclass()); 246 if (objc_super_class_sp) 247 return objc_super_class_sp->GetISA(); 248 } 249 return 0; 250 } 251 252 ConstString 253 ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) 254 { 255 ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor(isa)); 256 if (objc_class_sp) 257 return objc_class_sp->GetClassName(); 258 return ConstString(); 259 } 260 261 ObjCLanguageRuntime::ClassDescriptorSP 262 ObjCLanguageRuntime::GetClassDescriptorFromClassName (const ConstString &class_name) 263 { 264 ISAToDescriptorIterator pos = GetDescriptorIterator (class_name); 265 if (pos != m_isa_to_descriptor.end()) 266 return pos->second; 267 return ClassDescriptorSP(); 268 269 } 270 271 ObjCLanguageRuntime::ClassDescriptorSP 272 ObjCLanguageRuntime::GetClassDescriptor (ValueObject& valobj) 273 { 274 ClassDescriptorSP objc_class_sp; 275 // if we get an invalid VO (which might still happen when playing around 276 // with pointers returned by the expression parser, don't consider this 277 // a valid ObjC object) 278 if (valobj.GetCompilerType().IsValid()) 279 { 280 addr_t isa_pointer = valobj.GetPointerValue(); 281 if (isa_pointer != LLDB_INVALID_ADDRESS) 282 { 283 ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); 284 285 Process *process = exe_ctx.GetProcessPtr(); 286 if (process) 287 { 288 Error error; 289 ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error); 290 if (isa != LLDB_INVALID_ADDRESS) 291 objc_class_sp = GetClassDescriptorFromISA (isa); 292 } 293 } 294 } 295 return objc_class_sp; 296 } 297 298 ObjCLanguageRuntime::ClassDescriptorSP 299 ObjCLanguageRuntime::GetNonKVOClassDescriptor (ValueObject& valobj) 300 { 301 ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (GetClassDescriptor (valobj)); 302 if (objc_class_sp) 303 { 304 if (!objc_class_sp->IsKVO()) 305 return objc_class_sp; 306 307 ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass()); 308 if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid()) 309 return non_kvo_objc_class_sp; 310 } 311 return ClassDescriptorSP(); 312 } 313 314 315 ObjCLanguageRuntime::ClassDescriptorSP 316 ObjCLanguageRuntime::GetClassDescriptorFromISA (ObjCISA isa) 317 { 318 if (isa) 319 { 320 UpdateISAToDescriptorMap(); 321 ObjCLanguageRuntime::ISAToDescriptorIterator pos = m_isa_to_descriptor.find(isa); 322 if (pos != m_isa_to_descriptor.end()) 323 return pos->second; 324 } 325 return ClassDescriptorSP(); 326 } 327 328 ObjCLanguageRuntime::ClassDescriptorSP 329 ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa) 330 { 331 if (isa) 332 { 333 ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA (isa); 334 if (objc_class_sp && objc_class_sp->IsValid()) 335 { 336 if (!objc_class_sp->IsKVO()) 337 return objc_class_sp; 338 339 ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass()); 340 if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid()) 341 return non_kvo_objc_class_sp; 342 } 343 } 344 return ClassDescriptorSP(); 345 } 346 347 348 CompilerType 349 ObjCLanguageRuntime::EncodingToType::RealizeType (const char* name, bool for_expression) 350 { 351 if (m_scratch_ast_ctx_ap) 352 return RealizeType(*m_scratch_ast_ctx_ap, name, for_expression); 353 return CompilerType(); 354 } 355 356 CompilerType 357 ObjCLanguageRuntime::EncodingToType::RealizeType (ClangASTContext& ast_ctx, const char* name, bool for_expression) 358 { 359 clang::ASTContext *clang_ast = ast_ctx.getASTContext(); 360 if (!clang_ast) 361 return CompilerType(); 362 return RealizeType(*clang_ast, name, for_expression); 363 } 364 365 ObjCLanguageRuntime::EncodingToType::~EncodingToType() {} 366 367 ObjCLanguageRuntime::EncodingToTypeSP 368 ObjCLanguageRuntime::GetEncodingToType () 369 { 370 return nullptr; 371 } 372 373 bool 374 ObjCLanguageRuntime::GetTypeBitSize (const CompilerType& compiler_type, 375 uint64_t &size) 376 { 377 void *opaque_ptr = compiler_type.GetOpaqueQualType(); 378 size = m_type_size_cache.Lookup(opaque_ptr); 379 // an ObjC object will at least have an ISA, so 0 is definitely not OK 380 if (size > 0) 381 return true; 382 383 ClassDescriptorSP class_descriptor_sp = GetClassDescriptorFromClassName(compiler_type.GetTypeName()); 384 if (!class_descriptor_sp) 385 return false; 386 387 int32_t max_offset = INT32_MIN; 388 uint64_t sizeof_max = 0; 389 bool found = false; 390 391 for (size_t idx = 0; 392 idx < class_descriptor_sp->GetNumIVars(); 393 idx++) 394 { 395 const auto& ivar = class_descriptor_sp->GetIVarAtIndex(idx); 396 int32_t cur_offset = ivar.m_offset; 397 if (cur_offset > max_offset) 398 { 399 max_offset = cur_offset; 400 sizeof_max = ivar.m_size; 401 found = true; 402 } 403 } 404 405 size = 8 * (max_offset + sizeof_max); 406 if (found) 407 m_type_size_cache.Insert(opaque_ptr, size); 408 409 return found; 410 } 411 412 //------------------------------------------------------------------ 413 // Exception breakpoint Precondition class for ObjC: 414 //------------------------------------------------------------------ 415 void 416 ObjCLanguageRuntime::ObjCExceptionPrecondition::AddClassName(const char *class_name) 417 { 418 m_class_names.insert(class_name); 419 } 420 421 ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition() 422 { 423 } 424 425 bool 426 ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition(StoppointCallbackContext &context) 427 { 428 return true; 429 } 430 431 void 432 ObjCLanguageRuntime::ObjCExceptionPrecondition::GetDescription(Stream &stream, lldb::DescriptionLevel level) 433 { 434 } 435 436 Error 437 ObjCLanguageRuntime::ObjCExceptionPrecondition::ConfigurePrecondition(Args &args) 438 { 439 Error error; 440 if (args.GetArgumentCount() > 0) 441 error.SetErrorString("The ObjC Exception breakpoint doesn't support extra options."); 442 return error; 443 } 444