blob: ad4ca9a9d11744d3eae08c121fec09941b8499e7 [file] [log] [blame]
Greg Clayton05e8d192012-02-01 01:46:19 +00001//===-- ObjCLanguageRuntime.cpp ---------------------------------*- C++ -*-===//
Jim Ingham22777012010-09-23 02:01:19 +00002//
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//===----------------------------------------------------------------------===//
Jim Ingham6c68fb42010-09-30 00:54:27 +00009#include "clang/AST/Type.h"
Jim Ingham22777012010-09-23 02:01:19 +000010
Jim Ingham5a369122010-09-28 01:25:32 +000011#include "lldb/Core/Log.h"
Greg Claytona66c4d92013-02-13 22:56:14 +000012#include "lldb/Core/MappedHash.h"
Greg Clayton1f746072012-08-29 21:13:06 +000013#include "lldb/Core/Module.h"
Jim Ingham22777012010-09-23 02:01:19 +000014#include "lldb/Core/PluginManager.h"
Greg Clayton1b3815c2013-01-30 00:18:29 +000015#include "lldb/Core/Timer.h"
Jim Ingham6c68fb42010-09-30 00:54:27 +000016#include "lldb/Core/ValueObject.h"
17#include "lldb/Symbol/ClangASTContext.h"
Zachary Turner32abc6e2015-03-03 19:23:09 +000018#include "lldb/Symbol/SymbolContext.h"
Jim Ingham61be0902011-05-02 18:13:59 +000019#include "lldb/Symbol/Type.h"
Greg Clayton1f746072012-08-29 21:13:06 +000020#include "lldb/Symbol/TypeList.h"
Jim Ingham5a369122010-09-28 01:25:32 +000021#include "lldb/Target/ObjCLanguageRuntime.h"
Sean Callanan72772842012-02-22 23:57:45 +000022#include "lldb/Target/Target.h"
Jim Ingham22777012010-09-23 02:01:19 +000023
Greg Clayton1b3815c2013-01-30 00:18:29 +000024#include "llvm/ADT/StringRef.h"
25
Jim Ingham22777012010-09-23 02:01:19 +000026using namespace lldb;
27using namespace lldb_private;
28
29//----------------------------------------------------------------------
30// Destructor
31//----------------------------------------------------------------------
32ObjCLanguageRuntime::~ObjCLanguageRuntime()
33{
34}
35
36ObjCLanguageRuntime::ObjCLanguageRuntime (Process *process) :
Sean Callanan226b70c2012-03-08 02:39:03 +000037 LanguageRuntime (process),
Enrico Granata3842b9f2015-01-28 00:45:42 +000038 m_impl_cache(),
Sean Callananc09d9d82012-09-15 01:05:12 +000039 m_has_new_literals_and_indexing (eLazyBoolCalculate),
Greg Claytona66c4d92013-02-13 22:56:14 +000040 m_isa_to_descriptor(),
Enrico Granata3842b9f2015-01-28 00:45:42 +000041 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()
Jim Ingham22777012010-09-23 02:01:19 +000046{
Jim Ingham5a369122010-09-28 01:25:32 +000047}
48
Greg Claytona66c4d92013-02-13 22:56:14 +000049bool
50ObjCLanguageRuntime::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
Jim Ingham5a369122010-09-28 01:25:32 +000062void
63ObjCLanguageRuntime::AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t selector, lldb::addr_t impl_addr)
64{
Greg Clayton5160ce52013-03-27 23:08:40 +000065 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Ingham5a369122010-09-28 01:25:32 +000066 if (log)
67 {
Daniel Malead01b2952012-11-29 21:49:15 +000068 log->Printf ("Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 " implementation 0x%" PRIx64 ".", class_addr, selector, impl_addr);
Jim Ingham5a369122010-09-28 01:25:32 +000069 }
70 m_impl_cache.insert (std::pair<ClassAndSel,lldb::addr_t> (ClassAndSel(class_addr, selector), impl_addr));
71}
72
73lldb::addr_t
74ObjCLanguageRuntime::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}
Jim Ingham61be0902011-05-02 18:13:59 +000082
Jim Inghamd555bac2011-06-24 22:03:24 +000083
Sean Callanan72772842012-02-22 23:57:45 +000084lldb::TypeSP
85ObjCLanguageRuntime::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 {
Greg Claytond64dd122012-10-23 22:41:19 +000091 // Check the weak pointer to make sure the type hasn't been unloaded
92 TypeSP complete_type_sp (complete_class_iter->second.lock());
Sean Callanan72772842012-02-22 23:57:45 +000093
Greg Claytond64dd122012-10-23 22:41:19 +000094 if (complete_type_sp)
95 return complete_type_sp;
Sean Callanan72772842012-02-22 23:57:45 +000096 else
Greg Claytond64dd122012-10-23 22:41:19 +000097 m_complete_class_cache.erase(name);
Sean Callanan72772842012-02-22 23:57:45 +000098 }
99
Enrico Granataf15ee4e2013-04-05 18:49:06 +0000100 if (m_negative_complete_class_cache.count(name) > 0)
101 return TypeSP();
102
Enrico Granata17598482012-11-08 02:22:02 +0000103 const ModuleList &modules = m_process->GetTarget().GetImages();
Greg Claytond64dd122012-10-23 22:41:19 +0000104
Sean Callanan72772842012-02-22 23:57:45 +0000105 SymbolContextList sc_list;
Greg Claytond64dd122012-10-23 22:41:19 +0000106 const size_t matching_symbols = modules.FindSymbolsWithNameAndType (name,
107 eSymbolTypeObjCClass,
108 sc_list);
Sean Callanan72772842012-02-22 23:57:45 +0000109
Greg Claytond64dd122012-10-23 22:41:19 +0000110 if (matching_symbols)
Sean Callanan72772842012-02-22 23:57:45 +0000111 {
Greg Claytond64dd122012-10-23 22:41:19 +0000112 SymbolContext sc;
Sean Callanan72772842012-02-22 23:57:45 +0000113
Greg Claytond64dd122012-10-23 22:41:19 +0000114 sc_list.GetContextAtIndex(0, sc);
115
116 ModuleSP module_sp(sc.module_sp);
117
118 if (!module_sp)
Sean Callanan72772842012-02-22 23:57:45 +0000119 return TypeSP();
Sean Callanan72772842012-02-22 23:57:45 +0000120
Greg Claytond64dd122012-10-23 22:41:19 +0000121 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)
Sean Callanan7be70e82012-12-19 23:05:01 +0000133 {
Greg Claytond64dd122012-10-23 22:41:19 +0000134 uint32_t i;
135 for (i = 0; i < num_types; ++i)
136 {
137 TypeSP type_sp (types.GetTypeAtIndex(i));
138
Greg Clayton99558cc42015-08-24 23:46:31 +0000139 if (ClangASTContext::IsObjCObjectOrInterfaceType(type_sp->GetForwardCompilerType ()))
Greg Claytond64dd122012-10-23 22:41:19 +0000140 {
141 if (type_sp->IsCompleteObjCClass())
142 {
143 m_complete_class_cache[name] = type_sp;
144 return type_sp;
145 }
Greg Claytond64dd122012-10-23 22:41:19 +0000146 }
147 }
Sean Callanan72772842012-02-22 23:57:45 +0000148 }
149 }
Enrico Granataf15ee4e2013-04-05 18:49:06 +0000150 m_negative_complete_class_cache.insert(name);
Sean Callanan72772842012-02-22 23:57:45 +0000151 return TypeSP();
152}
153
Jim Inghamd555bac2011-06-24 22:03:24 +0000154size_t
Greg Claytona1e5dc82015-08-11 22:53:00 +0000155ObjCLanguageRuntime::GetByteOffsetForIvar (CompilerType &parent_qual_type, const char *ivar_name)
Jim Inghamd555bac2011-06-24 22:03:24 +0000156{
157 return LLDB_INVALID_IVAR_OFFSET;
158}
159
Enrico Granata3467d802012-09-04 18:47:54 +0000160bool
161ObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value,
162 uint32_t ptr_size,
163 bool allow_NULLs,
164 bool allow_tagged,
Greg Clayton77fbc812012-10-09 17:51:53 +0000165 bool check_version_specific) const
Enrico Granata3467d802012-09-04 18:47:54 +0000166{
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
177ObjCLanguageRuntime::ObjCISA
Sean Callananbc47dfc2012-09-11 21:44:01 +0000178ObjCLanguageRuntime::GetISA(const ConstString &name)
179{
Greg Claytona66c4d92013-02-13 22:56:14 +0000180 ISAToDescriptorIterator pos = GetDescriptorIterator (name);
181 if (pos != m_isa_to_descriptor.end())
182 return pos->first;
Sean Callananbc47dfc2012-09-11 21:44:01 +0000183 return 0;
184}
185
Greg Claytona66c4d92013-02-13 22:56:14 +0000186ObjCLanguageRuntime::ISAToDescriptorIterator
187ObjCLanguageRuntime::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
Enrico Granataba4b8b02015-05-06 21:01:07 +0000223std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,ObjCLanguageRuntime::ISAToDescriptorIterator>
224ObjCLanguageRuntime::GetDescriptorIteratorPair (bool update_if_needed)
225{
226 if (update_if_needed)
227 UpdateISAToDescriptorMapIfNeeded();
Colin Riley5de42512015-05-08 12:17:27 +0000228
229 return std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,
230 ObjCLanguageRuntime::ISAToDescriptorIterator>(
231 m_isa_to_descriptor.begin(),
232 m_isa_to_descriptor.end());
Enrico Granataba4b8b02015-05-06 21:01:07 +0000233}
234
Greg Claytona66c4d92013-02-13 22:56:14 +0000235
Sean Callananbc47dfc2012-09-11 21:44:01 +0000236ObjCLanguageRuntime::ObjCISA
Enrico Granata3467d802012-09-04 18:47:54 +0000237ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
238{
Greg Clayton03da4cc2013-04-19 21:31:16 +0000239 ClassDescriptorSP objc_class_sp (GetClassDescriptorFromISA(isa));
Greg Clayton77fbc812012-10-09 17:51:53 +0000240 if (objc_class_sp)
Enrico Granata3467d802012-09-04 18:47:54 +0000241 {
Greg Clayton77fbc812012-10-09 17:51:53 +0000242 ClassDescriptorSP objc_super_class_sp (objc_class_sp->GetSuperclass());
243 if (objc_super_class_sp)
244 return objc_super_class_sp->GetISA();
Enrico Granata3467d802012-09-04 18:47:54 +0000245 }
Greg Clayton77fbc812012-10-09 17:51:53 +0000246 return 0;
Enrico Granata3467d802012-09-04 18:47:54 +0000247}
248
Enrico Granata3467d802012-09-04 18:47:54 +0000249ConstString
250ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
251{
Greg Clayton77fbc812012-10-09 17:51:53 +0000252 ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor(isa));
253 if (objc_class_sp)
254 return objc_class_sp->GetClassName();
255 return ConstString();
Enrico Granata3467d802012-09-04 18:47:54 +0000256}
Greg Clayton77fbc812012-10-09 17:51:53 +0000257
258ObjCLanguageRuntime::ClassDescriptorSP
Greg Clayton03da4cc2013-04-19 21:31:16 +0000259ObjCLanguageRuntime::GetClassDescriptorFromClassName (const ConstString &class_name)
Greg Clayton77fbc812012-10-09 17:51:53 +0000260{
Greg Claytona66c4d92013-02-13 22:56:14 +0000261 ISAToDescriptorIterator pos = GetDescriptorIterator (class_name);
262 if (pos != m_isa_to_descriptor.end())
263 return pos->second;
Greg Claytonf0246d12012-10-11 18:07:21 +0000264 return ClassDescriptorSP();
265
266}
267
268ObjCLanguageRuntime::ClassDescriptorSP
269ObjCLanguageRuntime::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)
Greg Clayton99558cc42015-08-24 23:46:31 +0000275 if (valobj.GetCompilerType().IsValid())
Greg Claytonf0246d12012-10-11 18:07:21 +0000276 {
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)
Greg Clayton03da4cc2013-04-19 21:31:16 +0000288 objc_class_sp = GetClassDescriptorFromISA (isa);
Greg Claytonf0246d12012-10-11 18:07:21 +0000289 }
290 }
291 }
292 return objc_class_sp;
293}
294
295ObjCLanguageRuntime::ClassDescriptorSP
296ObjCLanguageRuntime::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 }
Greg Clayton77fbc812012-10-09 17:51:53 +0000308 return ClassDescriptorSP();
309}
310
Greg Claytonf0246d12012-10-11 18:07:21 +0000311
Greg Clayton77fbc812012-10-09 17:51:53 +0000312ObjCLanguageRuntime::ClassDescriptorSP
Greg Clayton03da4cc2013-04-19 21:31:16 +0000313ObjCLanguageRuntime::GetClassDescriptorFromISA (ObjCISA isa)
Greg Clayton77fbc812012-10-09 17:51:53 +0000314{
Greg Clayton77fbc812012-10-09 17:51:53 +0000315 if (isa)
316 {
Greg Claytonf0246d12012-10-11 18:07:21 +0000317 UpdateISAToDescriptorMap();
Greg Claytona66c4d92013-02-13 22:56:14 +0000318 ObjCLanguageRuntime::ISAToDescriptorIterator pos = m_isa_to_descriptor.find(isa);
319 if (pos != m_isa_to_descriptor.end())
Greg Claytonf0246d12012-10-11 18:07:21 +0000320 return pos->second;
Greg Clayton77fbc812012-10-09 17:51:53 +0000321 }
Greg Claytonf0246d12012-10-11 18:07:21 +0000322 return ClassDescriptorSP();
Greg Clayton77fbc812012-10-09 17:51:53 +0000323}
324
325ObjCLanguageRuntime::ClassDescriptorSP
326ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa)
327{
328 if (isa)
329 {
Greg Clayton03da4cc2013-04-19 21:31:16 +0000330 ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA (isa);
Greg Clayton77fbc812012-10-09 17:51:53 +0000331 if (objc_class_sp && objc_class_sp->IsValid())
332 {
Greg Claytonf0246d12012-10-11 18:07:21 +0000333 if (!objc_class_sp->IsKVO())
Greg Clayton77fbc812012-10-09 17:51:53 +0000334 return objc_class_sp;
Greg Claytonf0246d12012-10-11 18:07:21 +0000335
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;
Greg Clayton77fbc812012-10-09 17:51:53 +0000339 }
340 }
341 return ClassDescriptorSP();
342}
343
344
Greg Claytona1e5dc82015-08-11 22:53:00 +0000345CompilerType
Sean Callanana3309332014-10-31 18:02:30 +0000346ObjCLanguageRuntime::EncodingToType::RealizeType (const char* name, bool for_expression)
Enrico Granata5d84a692014-08-19 21:46:37 +0000347{
348 if (m_scratch_ast_ctx_ap)
Sean Callanana3309332014-10-31 18:02:30 +0000349 return RealizeType(*m_scratch_ast_ctx_ap, name, for_expression);
Greg Claytona1e5dc82015-08-11 22:53:00 +0000350 return CompilerType();
Enrico Granata5d84a692014-08-19 21:46:37 +0000351}
Greg Clayton77fbc812012-10-09 17:51:53 +0000352
Greg Claytona1e5dc82015-08-11 22:53:00 +0000353CompilerType
Sean Callanana3309332014-10-31 18:02:30 +0000354ObjCLanguageRuntime::EncodingToType::RealizeType (ClangASTContext& ast_ctx, const char* name, bool for_expression)
Enrico Granata5d84a692014-08-19 21:46:37 +0000355{
356 clang::ASTContext *clang_ast = ast_ctx.getASTContext();
357 if (!clang_ast)
Greg Claytona1e5dc82015-08-11 22:53:00 +0000358 return CompilerType();
Sean Callanana3309332014-10-31 18:02:30 +0000359 return RealizeType(*clang_ast, name, for_expression);
Enrico Granata5d84a692014-08-19 21:46:37 +0000360}
361
362ObjCLanguageRuntime::EncodingToType::~EncodingToType() {}
363
364ObjCLanguageRuntime::EncodingToTypeSP
365ObjCLanguageRuntime::GetEncodingToType ()
366{
367 return nullptr;
368}
Enrico Granata3842b9f2015-01-28 00:45:42 +0000369
370bool
Bruce Mitchener3ad353f2015-09-24 03:54:50 +0000371ObjCLanguageRuntime::GetTypeBitSize (const CompilerType& compiler_type,
Enrico Granata3842b9f2015-01-28 00:45:42 +0000372 uint64_t &size)
373{
Bruce Mitchener3ad353f2015-09-24 03:54:50 +0000374 void *opaque_ptr = compiler_type.GetOpaqueQualType();
Enrico Granata3842b9f2015-01-28 00:45:42 +0000375 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
Bruce Mitchener3ad353f2015-09-24 03:54:50 +0000380 ClassDescriptorSP class_descriptor_sp = GetClassDescriptorFromClassName(compiler_type.GetTypeName());
Enrico Granata3842b9f2015-01-28 00:45:42 +0000381 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}
Jim Inghama72b31c2015-04-22 19:42:18 +0000408
409//------------------------------------------------------------------
410// Exception breakpoint Precondition class for ObjC:
411//------------------------------------------------------------------
412void
413ObjCLanguageRuntime::ObjCExceptionPrecondition::AddClassName(const char *class_name)
414{
415 m_class_names.insert(class_name);
416}
417
418ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition()
419{
420}
421
422bool
423ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition(StoppointCallbackContext &context)
424{
425 return true;
426}
427
428void
429ObjCLanguageRuntime::ObjCExceptionPrecondition::DescribePrecondition(Stream &stream, lldb::DescriptionLevel level)
430{
431}
432
433Error
434ObjCLanguageRuntime::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}