blob: 2b37cb06c225a1388b457b89f4c12314c32e5215 [file] [log] [blame]
Greg Clayton9b8ff512012-02-01 01:46:19 +00001//===-- ObjCLanguageRuntime.cpp ---------------------------------*- C++ -*-===//
Jim Ingham642036f2010-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 Ingham324067b2010-09-30 00:54:27 +00009#include "clang/AST/Type.h"
Jim Ingham642036f2010-09-23 02:01:19 +000010
Jim Inghamb66cd072010-09-28 01:25:32 +000011#include "lldb/Core/Log.h"
Greg Clayton49ce8962012-08-29 21:13:06 +000012#include "lldb/Core/Module.h"
Jim Ingham642036f2010-09-23 02:01:19 +000013#include "lldb/Core/PluginManager.h"
Jim Ingham324067b2010-09-30 00:54:27 +000014#include "lldb/Core/ValueObject.h"
15#include "lldb/Symbol/ClangASTContext.h"
Jim Inghamef80aab2011-05-02 18:13:59 +000016#include "lldb/Symbol/Type.h"
Greg Clayton49ce8962012-08-29 21:13:06 +000017#include "lldb/Symbol/TypeList.h"
Jim Inghamb66cd072010-09-28 01:25:32 +000018#include "lldb/Target/ObjCLanguageRuntime.h"
Sean Callanan931acec2012-02-22 23:57:45 +000019#include "lldb/Target/Target.h"
Jim Ingham642036f2010-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 Callanan6e12c7a2012-03-08 02:39:03 +000032 LanguageRuntime (process),
Sean Callanan6fe8d362012-09-15 01:05:12 +000033 m_has_new_literals_and_indexing (eLazyBoolCalculate),
Greg Claytona5104372012-10-11 18:07:21 +000034 m_isa_to_descriptor_cache(),
Greg Clayton90c6cd52012-10-25 16:54:22 +000035 m_isa_to_descriptor_cache_stop_id (UINT32_MAX)
Jim Ingham642036f2010-09-23 02:01:19 +000036{
37
Jim Inghamb66cd072010-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 Claytone005f2c2010-11-06 01:53:30 +000043 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Inghamb66cd072010-09-28 01:25:32 +000044 if (log)
45 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +000046 log->Printf ("Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 " implementation 0x%" PRIx64 ".", class_addr, selector, impl_addr);
Jim Inghamb66cd072010-09-28 01:25:32 +000047 }
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 Inghamef80aab2011-05-02 18:13:59 +000060
Jim Ingham58513662011-06-24 22:03:24 +000061
Sean Callanan931acec2012-02-22 23:57:45 +000062lldb::TypeSP
63ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name)
64{
65 CompleteClassMap::iterator complete_class_iter = m_complete_class_cache.find(name);
66
67 if (complete_class_iter != m_complete_class_cache.end())
68 {
Greg Claytonef22b902012-10-23 22:41:19 +000069 // Check the weak pointer to make sure the type hasn't been unloaded
70 TypeSP complete_type_sp (complete_class_iter->second.lock());
Sean Callanan931acec2012-02-22 23:57:45 +000071
Greg Claytonef22b902012-10-23 22:41:19 +000072 if (complete_type_sp)
73 return complete_type_sp;
Sean Callanan931acec2012-02-22 23:57:45 +000074 else
Greg Claytonef22b902012-10-23 22:41:19 +000075 m_complete_class_cache.erase(name);
Sean Callanan931acec2012-02-22 23:57:45 +000076 }
77
Enrico Granata146d9522012-11-08 02:22:02 +000078 const ModuleList &modules = m_process->GetTarget().GetImages();
Greg Claytonef22b902012-10-23 22:41:19 +000079
Sean Callanan931acec2012-02-22 23:57:45 +000080 SymbolContextList sc_list;
Greg Claytonef22b902012-10-23 22:41:19 +000081 const size_t matching_symbols = modules.FindSymbolsWithNameAndType (name,
82 eSymbolTypeObjCClass,
83 sc_list);
Sean Callanan931acec2012-02-22 23:57:45 +000084
Greg Claytonef22b902012-10-23 22:41:19 +000085 if (matching_symbols)
Sean Callanan931acec2012-02-22 23:57:45 +000086 {
Greg Claytonef22b902012-10-23 22:41:19 +000087 SymbolContext sc;
Sean Callanan931acec2012-02-22 23:57:45 +000088
Greg Claytonef22b902012-10-23 22:41:19 +000089 sc_list.GetContextAtIndex(0, sc);
90
91 ModuleSP module_sp(sc.module_sp);
92
93 if (!module_sp)
Sean Callanan931acec2012-02-22 23:57:45 +000094 return TypeSP();
Sean Callanan931acec2012-02-22 23:57:45 +000095
Greg Claytonef22b902012-10-23 22:41:19 +000096 const SymbolContext null_sc;
97 const bool exact_match = true;
98 const uint32_t max_matches = UINT32_MAX;
99 TypeList types;
100
101 const uint32_t num_types = module_sp->FindTypes (null_sc,
102 name,
103 exact_match,
104 max_matches,
105 types);
106
107 if (num_types)
Sean Callanan931acec2012-02-22 23:57:45 +0000108 {
Greg Claytonef22b902012-10-23 22:41:19 +0000109 TypeSP incomplete_type_sp;
110
111 uint32_t i;
112 for (i = 0; i < num_types; ++i)
113 {
114 TypeSP type_sp (types.GetTypeAtIndex(i));
115
116 if (ClangASTContext::IsObjCClassType(type_sp->GetClangForwardType()))
117 {
118 if (type_sp->IsCompleteObjCClass())
119 {
120 m_complete_class_cache[name] = type_sp;
121 return type_sp;
122 }
123 else if (!incomplete_type_sp)
124 incomplete_type_sp = type_sp;
125 }
126 }
Sean Callanan931acec2012-02-22 23:57:45 +0000127 }
128 }
Sean Callanan931acec2012-02-22 23:57:45 +0000129 return TypeSP();
130}
131
Jim Ingham58513662011-06-24 22:03:24 +0000132size_t
133ObjCLanguageRuntime::GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name)
134{
135 return LLDB_INVALID_IVAR_OFFSET;
136}
137
Jim Ingham3ad4da02011-08-15 01:32:22 +0000138
Greg Clayton662e5672012-01-19 03:24:53 +0000139uint32_t
Jim Ingham3ad4da02011-08-15 01:32:22 +0000140ObjCLanguageRuntime::ParseMethodName (const char *name,
Greg Claytone14d3d32012-01-19 00:52:59 +0000141 ConstString *class_name, // Class name (with category if any)
142 ConstString *selector_name, // selector on its own
143 ConstString *name_sans_category, // Full function prototype with no category
144 ConstString *class_name_sans_category)// Class name with no category (or empty if no category as answer will be in "class_name"
Jim Ingham3ad4da02011-08-15 01:32:22 +0000145{
Greg Claytone14d3d32012-01-19 00:52:59 +0000146 if (class_name)
147 class_name->Clear();
148 if (selector_name)
149 selector_name->Clear();
150 if (name_sans_category)
151 name_sans_category->Clear();
152 if (class_name_sans_category)
153 class_name_sans_category->Clear();
Jim Ingham3ad4da02011-08-15 01:32:22 +0000154
Greg Clayton662e5672012-01-19 03:24:53 +0000155 uint32_t result = 0;
156
Jim Inghamfdf24ef2011-09-08 22:13:49 +0000157 if (IsPossibleObjCMethodName (name))
Jim Ingham3ad4da02011-08-15 01:32:22 +0000158 {
159 int name_len = strlen (name);
160 // Objective C methods must have at least:
161 // "-[" or "+[" prefix
162 // One character for a class name
163 // One character for the space between the class name
164 // One character for the method name
165 // "]" suffix
166 if (name_len >= 6 && name[name_len - 1] == ']')
167 {
Greg Claytone14d3d32012-01-19 00:52:59 +0000168 const char *selector_name_ptr = strchr (name, ' ');
Greg Clayton00db2152011-10-04 22:41:51 +0000169 if (selector_name_ptr)
Jim Ingham3ad4da02011-08-15 01:32:22 +0000170 {
171 if (class_name)
Greg Clayton662e5672012-01-19 03:24:53 +0000172 {
Greg Clayton00db2152011-10-04 22:41:51 +0000173 class_name->SetCStringWithLength (name + 2, selector_name_ptr - name - 2);
Greg Clayton662e5672012-01-19 03:24:53 +0000174 ++result;
175 }
Jim Ingham3ad4da02011-08-15 01:32:22 +0000176
177 // Skip the space
Greg Clayton00db2152011-10-04 22:41:51 +0000178 ++selector_name_ptr;
Jim Ingham3ad4da02011-08-15 01:32:22 +0000179 // Extract the objective C basename and add it to the
180 // accelerator tables
Greg Clayton00db2152011-10-04 22:41:51 +0000181 size_t selector_name_len = name_len - (selector_name_ptr - name) - 1;
182 if (selector_name)
Greg Clayton662e5672012-01-19 03:24:53 +0000183 {
Greg Clayton00db2152011-10-04 22:41:51 +0000184 selector_name->SetCStringWithLength (selector_name_ptr, selector_name_len);
Greg Clayton662e5672012-01-19 03:24:53 +0000185 ++result;
186 }
Jim Ingham3ad4da02011-08-15 01:32:22 +0000187
188 // Also see if this is a "category" on our class. If so strip off the category name,
189 // and add the class name without it to the basename table.
190
Greg Claytone14d3d32012-01-19 00:52:59 +0000191 if (name_sans_category || class_name_sans_category)
Jim Ingham3ad4da02011-08-15 01:32:22 +0000192 {
Greg Claytone14d3d32012-01-19 00:52:59 +0000193 const char *open_paren = strchr (name, '(');
Greg Claytone14d3d32012-01-19 00:52:59 +0000194 if (open_paren)
Jim Ingham3ad4da02011-08-15 01:32:22 +0000195 {
Greg Claytone14d3d32012-01-19 00:52:59 +0000196 if (class_name_sans_category)
Greg Clayton662e5672012-01-19 03:24:53 +0000197 {
Greg Claytone14d3d32012-01-19 00:52:59 +0000198 class_name_sans_category->SetCStringWithLength (name + 2, open_paren - name - 2);
Greg Clayton662e5672012-01-19 03:24:53 +0000199 ++result;
200 }
Sean Callananc1cd3792012-01-19 01:10:27 +0000201
202 if (name_sans_category)
Jim Ingham3ad4da02011-08-15 01:32:22 +0000203 {
Greg Clayton662e5672012-01-19 03:24:53 +0000204 const char *close_paren = strchr (open_paren, ')');
205 if (open_paren < close_paren)
Sean Callananc1cd3792012-01-19 01:10:27 +0000206 {
207 std::string buffer (name, open_paren - name);
208 buffer.append (close_paren + 1);
209 name_sans_category->SetCString (buffer.c_str());
Greg Clayton662e5672012-01-19 03:24:53 +0000210 ++result;
Sean Callananc1cd3792012-01-19 01:10:27 +0000211 }
Jim Ingham3ad4da02011-08-15 01:32:22 +0000212 }
213 }
214 }
215 }
Jim Ingham3ad4da02011-08-15 01:32:22 +0000216 }
Jim Ingham3ad4da02011-08-15 01:32:22 +0000217 }
Greg Clayton662e5672012-01-19 03:24:53 +0000218 return result;
Jim Ingham3ad4da02011-08-15 01:32:22 +0000219}
Enrico Granataae2ae942012-09-04 18:47:54 +0000220
221bool
222ObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value,
223 uint32_t ptr_size,
224 bool allow_NULLs,
225 bool allow_tagged,
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000226 bool check_version_specific) const
Enrico Granataae2ae942012-09-04 18:47:54 +0000227{
228 if (!value)
229 return allow_NULLs;
230 if ( (value % 2) == 1 && allow_tagged)
231 return true;
232 if ((value % ptr_size) == 0)
233 return (check_version_specific ? CheckPointer(value,ptr_size) : true);
234 else
235 return false;
236}
237
238ObjCLanguageRuntime::ObjCISA
Sean Callananc718b962012-09-11 21:44:01 +0000239ObjCLanguageRuntime::GetISA(const ConstString &name)
240{
Sean Callanan6fe8d362012-09-15 01:05:12 +0000241 UpdateISAToDescriptorMap();
Sean Callananc718b962012-09-11 21:44:01 +0000242 for (const ISAToDescriptorMap::value_type &val : m_isa_to_descriptor_cache)
243 if (val.second && val.second->GetClassName() == name)
244 return val.first;
Sean Callananc718b962012-09-11 21:44:01 +0000245 return 0;
246}
247
248ObjCLanguageRuntime::ObjCISA
Enrico Granataae2ae942012-09-04 18:47:54 +0000249ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
250{
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000251 ClassDescriptorSP objc_class_sp (GetClassDescriptor(isa));
252 if (objc_class_sp)
Enrico Granataae2ae942012-09-04 18:47:54 +0000253 {
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000254 ClassDescriptorSP objc_super_class_sp (objc_class_sp->GetSuperclass());
255 if (objc_super_class_sp)
256 return objc_super_class_sp->GetISA();
Enrico Granataae2ae942012-09-04 18:47:54 +0000257 }
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000258 return 0;
Enrico Granataae2ae942012-09-04 18:47:54 +0000259}
260
Enrico Granataae2ae942012-09-04 18:47:54 +0000261ConstString
262ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
263{
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000264 ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor(isa));
265 if (objc_class_sp)
266 return objc_class_sp->GetClassName();
267 return ConstString();
Enrico Granataae2ae942012-09-04 18:47:54 +0000268}
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000269
270ObjCLanguageRuntime::ClassDescriptorSP
Greg Claytona5104372012-10-11 18:07:21 +0000271ObjCLanguageRuntime::GetClassDescriptor (const ConstString &class_name)
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000272{
Greg Claytona5104372012-10-11 18:07:21 +0000273 UpdateISAToDescriptorMap();
274 for (const ISAToDescriptorMap::value_type &val : m_isa_to_descriptor_cache)
275 if (val.second && val.second->GetClassName() == class_name)
276 return val.second;
277 return ClassDescriptorSP();
278
279}
280
281ObjCLanguageRuntime::ClassDescriptorSP
282ObjCLanguageRuntime::GetClassDescriptor (ValueObject& valobj)
283{
284 ClassDescriptorSP objc_class_sp;
285 // if we get an invalid VO (which might still happen when playing around
286 // with pointers returned by the expression parser, don't consider this
287 // a valid ObjC object)
288 if (valobj.GetValue().GetContextType() != Value::eContextTypeInvalid)
289 {
290 addr_t isa_pointer = valobj.GetPointerValue();
291 if (isa_pointer != LLDB_INVALID_ADDRESS)
292 {
293 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
294
295 Process *process = exe_ctx.GetProcessPtr();
296 if (process)
297 {
298 Error error;
299 ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
300 if (isa != LLDB_INVALID_ADDRESS)
301 objc_class_sp = GetClassDescriptor (isa);
302 }
303 }
304 }
305 return objc_class_sp;
306}
307
308ObjCLanguageRuntime::ClassDescriptorSP
309ObjCLanguageRuntime::GetNonKVOClassDescriptor (ValueObject& valobj)
310{
311 ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (GetClassDescriptor (valobj));
312 if (objc_class_sp)
313 {
314 if (!objc_class_sp->IsKVO())
315 return objc_class_sp;
316
317 ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
318 if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
319 return non_kvo_objc_class_sp;
320 }
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000321 return ClassDescriptorSP();
322}
323
Greg Claytona5104372012-10-11 18:07:21 +0000324
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000325ObjCLanguageRuntime::ClassDescriptorSP
326ObjCLanguageRuntime::GetClassDescriptor (ObjCISA isa)
327{
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000328 if (isa)
329 {
Greg Claytona5104372012-10-11 18:07:21 +0000330 UpdateISAToDescriptorMap();
331 ObjCLanguageRuntime::ISAToDescriptorIterator pos = m_isa_to_descriptor_cache.find(isa);
332 if (pos != m_isa_to_descriptor_cache.end())
333 return pos->second;
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000334 }
Greg Claytona5104372012-10-11 18:07:21 +0000335 return ClassDescriptorSP();
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000336}
337
338ObjCLanguageRuntime::ClassDescriptorSP
339ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa)
340{
341 if (isa)
342 {
343 ClassDescriptorSP objc_class_sp = GetClassDescriptor (isa);
344 if (objc_class_sp && objc_class_sp->IsValid())
345 {
Greg Claytona5104372012-10-11 18:07:21 +0000346 if (!objc_class_sp->IsKVO())
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000347 return objc_class_sp;
Greg Claytona5104372012-10-11 18:07:21 +0000348
349 ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
350 if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
351 return non_kvo_objc_class_sp;
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000352 }
353 }
354 return ClassDescriptorSP();
355}
356
357
358