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