blob: 4fb41c843e5eb7c0743964206100b20172b56fd0 [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 Clayton1f746072012-08-29 21:13:06 +000012#include "lldb/Core/Module.h"
Jim Ingham22777012010-09-23 02:01:19 +000013#include "lldb/Core/PluginManager.h"
Jim Ingham6c68fb42010-09-30 00:54:27 +000014#include "lldb/Core/ValueObject.h"
15#include "lldb/Symbol/ClangASTContext.h"
Jim Ingham61be0902011-05-02 18:13:59 +000016#include "lldb/Symbol/Type.h"
Greg Clayton1f746072012-08-29 21:13:06 +000017#include "lldb/Symbol/TypeList.h"
Jim Ingham5a369122010-09-28 01:25:32 +000018#include "lldb/Target/ObjCLanguageRuntime.h"
Sean Callanan72772842012-02-22 23:57:45 +000019#include "lldb/Target/Target.h"
Jim Ingham22777012010-09-23 02:01:19 +000020
21using namespace lldb;
22using namespace lldb_private;
23
24//----------------------------------------------------------------------
25// Destructor
26//----------------------------------------------------------------------
27ObjCLanguageRuntime::~ObjCLanguageRuntime()
28{
29}
30
31ObjCLanguageRuntime::ObjCLanguageRuntime (Process *process) :
Sean Callanan226b70c2012-03-08 02:39:03 +000032 LanguageRuntime (process),
Sean Callananc09d9d82012-09-15 01:05:12 +000033 m_has_new_literals_and_indexing (eLazyBoolCalculate),
Greg Claytonf0246d12012-10-11 18:07:21 +000034 m_isa_to_descriptor_cache(),
Sean Callananc09d9d82012-09-15 01:05:12 +000035 m_isa_to_descriptor_cache_is_up_to_date (false)
Jim Ingham22777012010-09-23 02:01:19 +000036{
37
Jim Ingham5a369122010-09-28 01:25:32 +000038}
39
40void
41ObjCLanguageRuntime::AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t selector, lldb::addr_t impl_addr)
42{
Greg Clayton2d4edfb2010-11-06 01:53:30 +000043 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Ingham5a369122010-09-28 01:25:32 +000044 if (log)
45 {
46 log->Printf ("Caching: class 0x%llx selector 0x%llx implementation 0x%llx.", class_addr, selector, impl_addr);
47 }
48 m_impl_cache.insert (std::pair<ClassAndSel,lldb::addr_t> (ClassAndSel(class_addr, selector), impl_addr));
49}
50
51lldb::addr_t
52ObjCLanguageRuntime::LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t selector)
53{
54 MsgImplMap::iterator pos, end = m_impl_cache.end();
55 pos = m_impl_cache.find (ClassAndSel(class_addr, selector));
56 if (pos != end)
57 return (*pos).second;
58 return LLDB_INVALID_ADDRESS;
59}
Jim Ingham61be0902011-05-02 18:13:59 +000060
61void
62ObjCLanguageRuntime::AddToClassNameCache (lldb::addr_t class_addr, const char *name, lldb::TypeSP type_sp)
63{
64 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
65 if (log)
66 {
67 log->Printf ("Caching: class 0x%llx name: %s.", class_addr, name);
68 }
69
70 TypeAndOrName class_type_or_name;
71
Greg Clayton85ae2e12011-10-18 23:36:41 +000072 if (type_sp)
Jim Ingham61be0902011-05-02 18:13:59 +000073 class_type_or_name.SetTypeSP (type_sp);
74 else if (name && *name != '\0')
75 class_type_or_name.SetName (name);
76 else
77 return;
78 m_class_name_cache.insert (std::pair<lldb::addr_t,TypeAndOrName> (class_addr, class_type_or_name));
79}
80
81void
82ObjCLanguageRuntime::AddToClassNameCache (lldb::addr_t class_addr, const TypeAndOrName &class_type_or_name)
83{
84 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
85 if (log)
86 {
87 log->Printf ("Caching: class 0x%llx name: %s.", class_addr, class_type_or_name.GetName().AsCString());
88 }
89
90 m_class_name_cache.insert (std::pair<lldb::addr_t,TypeAndOrName> (class_addr, class_type_or_name));
91}
92
93TypeAndOrName
94ObjCLanguageRuntime::LookupInClassNameCache (lldb::addr_t class_addr)
95{
96 ClassNameMap::iterator pos, end = m_class_name_cache.end();
97 pos = m_class_name_cache.find (class_addr);
98 if (pos != end)
99 return (*pos).second;
100 return TypeAndOrName ();
101}
Jim Inghamd555bac2011-06-24 22:03:24 +0000102
Sean Callanan72772842012-02-22 23:57:45 +0000103lldb::TypeSP
104ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name)
105{
106 CompleteClassMap::iterator complete_class_iter = m_complete_class_cache.find(name);
107
108 if (complete_class_iter != m_complete_class_cache.end())
109 {
110 TypeSP ret(complete_class_iter->second);
111
112 if (!ret)
113 m_complete_class_cache.erase(name);
114 else
115 return TypeSP(complete_class_iter->second);
116 }
117
118 ModuleList &modules = m_process->GetTarget().GetImages();
119
120 SymbolContextList sc_list;
121
122 modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list);
123
124 if (sc_list.GetSize() == 0)
125 return TypeSP();
126
127 SymbolContext sc;
128
129 sc_list.GetContextAtIndex(0, sc);
130
131 ModuleSP module_sp(sc.module_sp);
132
133 if (!module_sp)
134 return TypeSP();
135
136 const SymbolContext null_sc;
Greg Clayton84db9102012-03-26 23:03:23 +0000137 const bool exact_match = true;
Sean Callanan72772842012-02-22 23:57:45 +0000138 const uint32_t max_matches = UINT32_MAX;
139 TypeList types;
140
Greg Clayton84db9102012-03-26 23:03:23 +0000141 module_sp->FindTypes (null_sc,
142 name,
143 exact_match,
144 max_matches,
145 types);
Sean Callanan72772842012-02-22 23:57:45 +0000146
147 if (types.GetSize() == 1)
148 {
149 TypeSP candidate_type = types.GetTypeAtIndex(0);
150
151 if (ClangASTContext::IsObjCClassType(candidate_type->GetClangForwardType()))
152 {
153 m_complete_class_cache[name] = TypeWP(candidate_type);
154 return candidate_type;
155 }
156 else
157 {
158 return TypeSP();
159 }
160 }
161
162 for (uint32_t ti = 0, te = types.GetSize();
163 ti < te;
164 ++ti)
165 {
166 TypeSP candidate_type = types.GetTypeAtIndex(ti);
167
168 if (candidate_type->IsCompleteObjCClass() &&
169 ClangASTContext::IsObjCClassType(candidate_type->GetClangForwardType()))
170 {
171 m_complete_class_cache[name] = TypeWP(candidate_type);
172 return candidate_type;
173 }
174 }
175
176 return TypeSP();
177}
178
Jim Inghamd555bac2011-06-24 22:03:24 +0000179size_t
180ObjCLanguageRuntime::GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name)
181{
182 return LLDB_INVALID_IVAR_OFFSET;
183}
184
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000185
Greg Claytone42ae842012-01-19 03:24:53 +0000186uint32_t
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000187ObjCLanguageRuntime::ParseMethodName (const char *name,
Greg Clayton278a16b2012-01-19 00:52:59 +0000188 ConstString *class_name, // Class name (with category if any)
189 ConstString *selector_name, // selector on its own
190 ConstString *name_sans_category, // Full function prototype with no category
191 ConstString *class_name_sans_category)// Class name with no category (or empty if no category as answer will be in "class_name"
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000192{
Greg Clayton278a16b2012-01-19 00:52:59 +0000193 if (class_name)
194 class_name->Clear();
195 if (selector_name)
196 selector_name->Clear();
197 if (name_sans_category)
198 name_sans_category->Clear();
199 if (class_name_sans_category)
200 class_name_sans_category->Clear();
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000201
Greg Claytone42ae842012-01-19 03:24:53 +0000202 uint32_t result = 0;
203
Jim Inghamb7f6b2f2011-09-08 22:13:49 +0000204 if (IsPossibleObjCMethodName (name))
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000205 {
206 int name_len = strlen (name);
207 // Objective C methods must have at least:
208 // "-[" or "+[" prefix
209 // One character for a class name
210 // One character for the space between the class name
211 // One character for the method name
212 // "]" suffix
213 if (name_len >= 6 && name[name_len - 1] == ']')
214 {
Greg Clayton278a16b2012-01-19 00:52:59 +0000215 const char *selector_name_ptr = strchr (name, ' ');
Greg Clayton7f995132011-10-04 22:41:51 +0000216 if (selector_name_ptr)
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000217 {
218 if (class_name)
Greg Claytone42ae842012-01-19 03:24:53 +0000219 {
Greg Clayton7f995132011-10-04 22:41:51 +0000220 class_name->SetCStringWithLength (name + 2, selector_name_ptr - name - 2);
Greg Claytone42ae842012-01-19 03:24:53 +0000221 ++result;
222 }
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000223
224 // Skip the space
Greg Clayton7f995132011-10-04 22:41:51 +0000225 ++selector_name_ptr;
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000226 // Extract the objective C basename and add it to the
227 // accelerator tables
Greg Clayton7f995132011-10-04 22:41:51 +0000228 size_t selector_name_len = name_len - (selector_name_ptr - name) - 1;
229 if (selector_name)
Greg Claytone42ae842012-01-19 03:24:53 +0000230 {
Greg Clayton7f995132011-10-04 22:41:51 +0000231 selector_name->SetCStringWithLength (selector_name_ptr, selector_name_len);
Greg Claytone42ae842012-01-19 03:24:53 +0000232 ++result;
233 }
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000234
235 // Also see if this is a "category" on our class. If so strip off the category name,
236 // and add the class name without it to the basename table.
237
Greg Clayton278a16b2012-01-19 00:52:59 +0000238 if (name_sans_category || class_name_sans_category)
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000239 {
Greg Clayton278a16b2012-01-19 00:52:59 +0000240 const char *open_paren = strchr (name, '(');
Greg Clayton278a16b2012-01-19 00:52:59 +0000241 if (open_paren)
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000242 {
Greg Clayton278a16b2012-01-19 00:52:59 +0000243 if (class_name_sans_category)
Greg Claytone42ae842012-01-19 03:24:53 +0000244 {
Greg Clayton278a16b2012-01-19 00:52:59 +0000245 class_name_sans_category->SetCStringWithLength (name + 2, open_paren - name - 2);
Greg Claytone42ae842012-01-19 03:24:53 +0000246 ++result;
247 }
Sean Callananb811e4b2012-01-19 01:10:27 +0000248
249 if (name_sans_category)
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000250 {
Greg Claytone42ae842012-01-19 03:24:53 +0000251 const char *close_paren = strchr (open_paren, ')');
252 if (open_paren < close_paren)
Sean Callananb811e4b2012-01-19 01:10:27 +0000253 {
254 std::string buffer (name, open_paren - name);
255 buffer.append (close_paren + 1);
256 name_sans_category->SetCString (buffer.c_str());
Greg Claytone42ae842012-01-19 03:24:53 +0000257 ++result;
Sean Callananb811e4b2012-01-19 01:10:27 +0000258 }
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000259 }
260 }
261 }
262 }
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000263 }
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000264 }
Greg Claytone42ae842012-01-19 03:24:53 +0000265 return result;
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000266}
Enrico Granata3467d802012-09-04 18:47:54 +0000267
268bool
269ObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value,
270 uint32_t ptr_size,
271 bool allow_NULLs,
272 bool allow_tagged,
Greg Clayton77fbc812012-10-09 17:51:53 +0000273 bool check_version_specific) const
Enrico Granata3467d802012-09-04 18:47:54 +0000274{
275 if (!value)
276 return allow_NULLs;
277 if ( (value % 2) == 1 && allow_tagged)
278 return true;
279 if ((value % ptr_size) == 0)
280 return (check_version_specific ? CheckPointer(value,ptr_size) : true);
281 else
282 return false;
283}
284
285ObjCLanguageRuntime::ObjCISA
Sean Callananbc47dfc2012-09-11 21:44:01 +0000286ObjCLanguageRuntime::GetISA(const ConstString &name)
287{
Sean Callananc09d9d82012-09-15 01:05:12 +0000288 UpdateISAToDescriptorMap();
Sean Callananbc47dfc2012-09-11 21:44:01 +0000289 for (const ISAToDescriptorMap::value_type &val : m_isa_to_descriptor_cache)
290 if (val.second && val.second->GetClassName() == name)
291 return val.first;
Sean Callananbc47dfc2012-09-11 21:44:01 +0000292 return 0;
293}
294
295ObjCLanguageRuntime::ObjCISA
Enrico Granata3467d802012-09-04 18:47:54 +0000296ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
297{
Greg Clayton77fbc812012-10-09 17:51:53 +0000298 ClassDescriptorSP objc_class_sp (GetClassDescriptor(isa));
299 if (objc_class_sp)
Enrico Granata3467d802012-09-04 18:47:54 +0000300 {
Greg Clayton77fbc812012-10-09 17:51:53 +0000301 ClassDescriptorSP objc_super_class_sp (objc_class_sp->GetSuperclass());
302 if (objc_super_class_sp)
303 return objc_super_class_sp->GetISA();
Enrico Granata3467d802012-09-04 18:47:54 +0000304 }
Greg Clayton77fbc812012-10-09 17:51:53 +0000305 return 0;
Enrico Granata3467d802012-09-04 18:47:54 +0000306}
307
Enrico Granata3467d802012-09-04 18:47:54 +0000308ConstString
309ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
310{
Greg Clayton77fbc812012-10-09 17:51:53 +0000311 ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor(isa));
312 if (objc_class_sp)
313 return objc_class_sp->GetClassName();
314 return ConstString();
Enrico Granata3467d802012-09-04 18:47:54 +0000315}
Greg Clayton77fbc812012-10-09 17:51:53 +0000316
317ObjCLanguageRuntime::ClassDescriptorSP
Greg Claytonf0246d12012-10-11 18:07:21 +0000318ObjCLanguageRuntime::GetClassDescriptor (const ConstString &class_name)
Greg Clayton77fbc812012-10-09 17:51:53 +0000319{
Greg Claytonf0246d12012-10-11 18:07:21 +0000320 UpdateISAToDescriptorMap();
321 for (const ISAToDescriptorMap::value_type &val : m_isa_to_descriptor_cache)
322 if (val.second && val.second->GetClassName() == class_name)
323 return val.second;
324 return ClassDescriptorSP();
325
326}
327
328ObjCLanguageRuntime::ClassDescriptorSP
329ObjCLanguageRuntime::GetClassDescriptor (ValueObject& valobj)
330{
331 ClassDescriptorSP objc_class_sp;
332 // if we get an invalid VO (which might still happen when playing around
333 // with pointers returned by the expression parser, don't consider this
334 // a valid ObjC object)
335 if (valobj.GetValue().GetContextType() != Value::eContextTypeInvalid)
336 {
337 addr_t isa_pointer = valobj.GetPointerValue();
338 if (isa_pointer != LLDB_INVALID_ADDRESS)
339 {
340 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
341
342 Process *process = exe_ctx.GetProcessPtr();
343 if (process)
344 {
345 Error error;
346 ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
347 if (isa != LLDB_INVALID_ADDRESS)
348 objc_class_sp = GetClassDescriptor (isa);
349 }
350 }
351 }
352 return objc_class_sp;
353}
354
355ObjCLanguageRuntime::ClassDescriptorSP
356ObjCLanguageRuntime::GetNonKVOClassDescriptor (ValueObject& valobj)
357{
358 ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (GetClassDescriptor (valobj));
359 if (objc_class_sp)
360 {
361 if (!objc_class_sp->IsKVO())
362 return objc_class_sp;
363
364 ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
365 if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
366 return non_kvo_objc_class_sp;
367 }
Greg Clayton77fbc812012-10-09 17:51:53 +0000368 return ClassDescriptorSP();
369}
370
Greg Claytonf0246d12012-10-11 18:07:21 +0000371
Greg Clayton77fbc812012-10-09 17:51:53 +0000372ObjCLanguageRuntime::ClassDescriptorSP
373ObjCLanguageRuntime::GetClassDescriptor (ObjCISA isa)
374{
Greg Clayton77fbc812012-10-09 17:51:53 +0000375 if (isa)
376 {
Greg Claytonf0246d12012-10-11 18:07:21 +0000377 UpdateISAToDescriptorMap();
378 ObjCLanguageRuntime::ISAToDescriptorIterator pos = m_isa_to_descriptor_cache.find(isa);
379 if (pos != m_isa_to_descriptor_cache.end())
380 return pos->second;
Greg Clayton77fbc812012-10-09 17:51:53 +0000381 }
Greg Claytonf0246d12012-10-11 18:07:21 +0000382 return ClassDescriptorSP();
Greg Clayton77fbc812012-10-09 17:51:53 +0000383}
384
385ObjCLanguageRuntime::ClassDescriptorSP
386ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa)
387{
388 if (isa)
389 {
390 ClassDescriptorSP objc_class_sp = GetClassDescriptor (isa);
391 if (objc_class_sp && objc_class_sp->IsValid())
392 {
Greg Claytonf0246d12012-10-11 18:07:21 +0000393 if (!objc_class_sp->IsKVO())
Greg Clayton77fbc812012-10-09 17:51:53 +0000394 return objc_class_sp;
Greg Claytonf0246d12012-10-11 18:07:21 +0000395
396 ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
397 if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
398 return non_kvo_objc_class_sp;
Greg Clayton77fbc812012-10-09 17:51:53 +0000399 }
400 }
401 return ClassDescriptorSP();
402}
403
404
405