blob: fa80e0951e977e1552a7f8392032441a71f5e668 [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 Callanan282c22c2012-12-19 23:05:01 +0000108 {
Greg Claytonef22b902012-10-23 22:41:19 +0000109 uint32_t i;
110 for (i = 0; i < num_types; ++i)
111 {
112 TypeSP type_sp (types.GetTypeAtIndex(i));
113
114 if (ClangASTContext::IsObjCClassType(type_sp->GetClangForwardType()))
115 {
116 if (type_sp->IsCompleteObjCClass())
117 {
118 m_complete_class_cache[name] = type_sp;
119 return type_sp;
120 }
Greg Claytonef22b902012-10-23 22:41:19 +0000121 }
122 }
Sean Callanan931acec2012-02-22 23:57:45 +0000123 }
124 }
Sean Callanan931acec2012-02-22 23:57:45 +0000125 return TypeSP();
126}
127
Jim Ingham58513662011-06-24 22:03:24 +0000128size_t
129ObjCLanguageRuntime::GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name)
130{
131 return LLDB_INVALID_IVAR_OFFSET;
132}
133
Jim Ingham3ad4da02011-08-15 01:32:22 +0000134
Greg Clayton662e5672012-01-19 03:24:53 +0000135uint32_t
Jim Ingham3ad4da02011-08-15 01:32:22 +0000136ObjCLanguageRuntime::ParseMethodName (const char *name,
Greg Claytone14d3d32012-01-19 00:52:59 +0000137 ConstString *class_name, // Class name (with category if any)
138 ConstString *selector_name, // selector on its own
139 ConstString *name_sans_category, // Full function prototype with no category
140 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 +0000141{
Greg Claytone14d3d32012-01-19 00:52:59 +0000142 if (class_name)
143 class_name->Clear();
144 if (selector_name)
145 selector_name->Clear();
146 if (name_sans_category)
147 name_sans_category->Clear();
148 if (class_name_sans_category)
149 class_name_sans_category->Clear();
Jim Ingham3ad4da02011-08-15 01:32:22 +0000150
Greg Clayton662e5672012-01-19 03:24:53 +0000151 uint32_t result = 0;
152
Jim Inghamfdf24ef2011-09-08 22:13:49 +0000153 if (IsPossibleObjCMethodName (name))
Jim Ingham3ad4da02011-08-15 01:32:22 +0000154 {
155 int name_len = strlen (name);
156 // Objective C methods must have at least:
157 // "-[" or "+[" prefix
158 // One character for a class name
159 // One character for the space between the class name
160 // One character for the method name
161 // "]" suffix
162 if (name_len >= 6 && name[name_len - 1] == ']')
163 {
Greg Claytone14d3d32012-01-19 00:52:59 +0000164 const char *selector_name_ptr = strchr (name, ' ');
Greg Clayton00db2152011-10-04 22:41:51 +0000165 if (selector_name_ptr)
Jim Ingham3ad4da02011-08-15 01:32:22 +0000166 {
167 if (class_name)
Greg Clayton662e5672012-01-19 03:24:53 +0000168 {
Greg Clayton00db2152011-10-04 22:41:51 +0000169 class_name->SetCStringWithLength (name + 2, selector_name_ptr - name - 2);
Greg Clayton662e5672012-01-19 03:24:53 +0000170 ++result;
171 }
Jim Ingham3ad4da02011-08-15 01:32:22 +0000172
173 // Skip the space
Greg Clayton00db2152011-10-04 22:41:51 +0000174 ++selector_name_ptr;
Jim Ingham3ad4da02011-08-15 01:32:22 +0000175 // Extract the objective C basename and add it to the
176 // accelerator tables
Greg Clayton00db2152011-10-04 22:41:51 +0000177 size_t selector_name_len = name_len - (selector_name_ptr - name) - 1;
178 if (selector_name)
Greg Clayton662e5672012-01-19 03:24:53 +0000179 {
Greg Clayton00db2152011-10-04 22:41:51 +0000180 selector_name->SetCStringWithLength (selector_name_ptr, selector_name_len);
Greg Clayton662e5672012-01-19 03:24:53 +0000181 ++result;
182 }
Jim Ingham3ad4da02011-08-15 01:32:22 +0000183
184 // Also see if this is a "category" on our class. If so strip off the category name,
185 // and add the class name without it to the basename table.
186
Greg Claytone14d3d32012-01-19 00:52:59 +0000187 if (name_sans_category || class_name_sans_category)
Jim Ingham3ad4da02011-08-15 01:32:22 +0000188 {
Greg Claytone14d3d32012-01-19 00:52:59 +0000189 const char *open_paren = strchr (name, '(');
Greg Claytone14d3d32012-01-19 00:52:59 +0000190 if (open_paren)
Jim Ingham3ad4da02011-08-15 01:32:22 +0000191 {
Greg Claytone14d3d32012-01-19 00:52:59 +0000192 if (class_name_sans_category)
Greg Clayton662e5672012-01-19 03:24:53 +0000193 {
Greg Claytone14d3d32012-01-19 00:52:59 +0000194 class_name_sans_category->SetCStringWithLength (name + 2, open_paren - name - 2);
Greg Clayton662e5672012-01-19 03:24:53 +0000195 ++result;
196 }
Sean Callananc1cd3792012-01-19 01:10:27 +0000197
198 if (name_sans_category)
Jim Ingham3ad4da02011-08-15 01:32:22 +0000199 {
Greg Clayton662e5672012-01-19 03:24:53 +0000200 const char *close_paren = strchr (open_paren, ')');
201 if (open_paren < close_paren)
Sean Callananc1cd3792012-01-19 01:10:27 +0000202 {
203 std::string buffer (name, open_paren - name);
204 buffer.append (close_paren + 1);
205 name_sans_category->SetCString (buffer.c_str());
Greg Clayton662e5672012-01-19 03:24:53 +0000206 ++result;
Sean Callananc1cd3792012-01-19 01:10:27 +0000207 }
Jim Ingham3ad4da02011-08-15 01:32:22 +0000208 }
209 }
210 }
211 }
Jim Ingham3ad4da02011-08-15 01:32:22 +0000212 }
Jim Ingham3ad4da02011-08-15 01:32:22 +0000213 }
Greg Clayton662e5672012-01-19 03:24:53 +0000214 return result;
Jim Ingham3ad4da02011-08-15 01:32:22 +0000215}
Enrico Granataae2ae942012-09-04 18:47:54 +0000216
217bool
218ObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value,
219 uint32_t ptr_size,
220 bool allow_NULLs,
221 bool allow_tagged,
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000222 bool check_version_specific) const
Enrico Granataae2ae942012-09-04 18:47:54 +0000223{
224 if (!value)
225 return allow_NULLs;
226 if ( (value % 2) == 1 && allow_tagged)
227 return true;
228 if ((value % ptr_size) == 0)
229 return (check_version_specific ? CheckPointer(value,ptr_size) : true);
230 else
231 return false;
232}
233
234ObjCLanguageRuntime::ObjCISA
Sean Callananc718b962012-09-11 21:44:01 +0000235ObjCLanguageRuntime::GetISA(const ConstString &name)
236{
Sean Callanan6fe8d362012-09-15 01:05:12 +0000237 UpdateISAToDescriptorMap();
Sean Callananc718b962012-09-11 21:44:01 +0000238 for (const ISAToDescriptorMap::value_type &val : m_isa_to_descriptor_cache)
239 if (val.second && val.second->GetClassName() == name)
240 return val.first;
Sean Callananc718b962012-09-11 21:44:01 +0000241 return 0;
242}
243
244ObjCLanguageRuntime::ObjCISA
Enrico Granataae2ae942012-09-04 18:47:54 +0000245ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
246{
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000247 ClassDescriptorSP objc_class_sp (GetClassDescriptor(isa));
248 if (objc_class_sp)
Enrico Granataae2ae942012-09-04 18:47:54 +0000249 {
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000250 ClassDescriptorSP objc_super_class_sp (objc_class_sp->GetSuperclass());
251 if (objc_super_class_sp)
252 return objc_super_class_sp->GetISA();
Enrico Granataae2ae942012-09-04 18:47:54 +0000253 }
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000254 return 0;
Enrico Granataae2ae942012-09-04 18:47:54 +0000255}
256
Enrico Granataae2ae942012-09-04 18:47:54 +0000257ConstString
258ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
259{
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000260 ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor(isa));
261 if (objc_class_sp)
262 return objc_class_sp->GetClassName();
263 return ConstString();
Enrico Granataae2ae942012-09-04 18:47:54 +0000264}
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000265
266ObjCLanguageRuntime::ClassDescriptorSP
Greg Claytona5104372012-10-11 18:07:21 +0000267ObjCLanguageRuntime::GetClassDescriptor (const ConstString &class_name)
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000268{
Greg Claytona5104372012-10-11 18:07:21 +0000269 UpdateISAToDescriptorMap();
270 for (const ISAToDescriptorMap::value_type &val : m_isa_to_descriptor_cache)
271 if (val.second && val.second->GetClassName() == class_name)
272 return val.second;
273 return ClassDescriptorSP();
274
275}
276
277ObjCLanguageRuntime::ClassDescriptorSP
278ObjCLanguageRuntime::GetClassDescriptor (ValueObject& valobj)
279{
280 ClassDescriptorSP objc_class_sp;
281 // if we get an invalid VO (which might still happen when playing around
282 // with pointers returned by the expression parser, don't consider this
283 // a valid ObjC object)
284 if (valobj.GetValue().GetContextType() != Value::eContextTypeInvalid)
285 {
286 addr_t isa_pointer = valobj.GetPointerValue();
287 if (isa_pointer != LLDB_INVALID_ADDRESS)
288 {
289 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
290
291 Process *process = exe_ctx.GetProcessPtr();
292 if (process)
293 {
294 Error error;
295 ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
296 if (isa != LLDB_INVALID_ADDRESS)
297 objc_class_sp = GetClassDescriptor (isa);
298 }
299 }
300 }
301 return objc_class_sp;
302}
303
304ObjCLanguageRuntime::ClassDescriptorSP
305ObjCLanguageRuntime::GetNonKVOClassDescriptor (ValueObject& valobj)
306{
307 ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (GetClassDescriptor (valobj));
308 if (objc_class_sp)
309 {
310 if (!objc_class_sp->IsKVO())
311 return objc_class_sp;
312
313 ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
314 if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
315 return non_kvo_objc_class_sp;
316 }
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000317 return ClassDescriptorSP();
318}
319
Greg Claytona5104372012-10-11 18:07:21 +0000320
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000321ObjCLanguageRuntime::ClassDescriptorSP
322ObjCLanguageRuntime::GetClassDescriptor (ObjCISA isa)
323{
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000324 if (isa)
325 {
Greg Claytona5104372012-10-11 18:07:21 +0000326 UpdateISAToDescriptorMap();
327 ObjCLanguageRuntime::ISAToDescriptorIterator pos = m_isa_to_descriptor_cache.find(isa);
328 if (pos != m_isa_to_descriptor_cache.end())
329 return pos->second;
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000330 }
Greg Claytona5104372012-10-11 18:07:21 +0000331 return ClassDescriptorSP();
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000332}
333
334ObjCLanguageRuntime::ClassDescriptorSP
335ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa)
336{
337 if (isa)
338 {
339 ClassDescriptorSP objc_class_sp = GetClassDescriptor (isa);
340 if (objc_class_sp && objc_class_sp->IsValid())
341 {
Greg Claytona5104372012-10-11 18:07:21 +0000342 if (!objc_class_sp->IsKVO())
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000343 return objc_class_sp;
Greg Claytona5104372012-10-11 18:07:21 +0000344
345 ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
346 if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
347 return non_kvo_objc_class_sp;
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000348 }
349 }
350 return ClassDescriptorSP();
351}
352
353
354