blob: 64ddfcc6c7969c7c67b4e4a59abefbf8270e9d2d [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 Claytonce490e32013-02-13 22:56:14 +000012#include "lldb/Core/MappedHash.h"
Greg Clayton49ce8962012-08-29 21:13:06 +000013#include "lldb/Core/Module.h"
Jim Ingham642036f2010-09-23 02:01:19 +000014#include "lldb/Core/PluginManager.h"
Greg Claytonf892c422013-01-30 00:18:29 +000015#include "lldb/Core/Timer.h"
Jim Ingham324067b2010-09-30 00:54:27 +000016#include "lldb/Core/ValueObject.h"
17#include "lldb/Symbol/ClangASTContext.h"
Jim Inghamef80aab2011-05-02 18:13:59 +000018#include "lldb/Symbol/Type.h"
Greg Clayton49ce8962012-08-29 21:13:06 +000019#include "lldb/Symbol/TypeList.h"
Jim Inghamb66cd072010-09-28 01:25:32 +000020#include "lldb/Target/ObjCLanguageRuntime.h"
Sean Callanan931acec2012-02-22 23:57:45 +000021#include "lldb/Target/Target.h"
Jim Ingham642036f2010-09-23 02:01:19 +000022
Greg Claytonf892c422013-01-30 00:18:29 +000023#include "llvm/ADT/StringRef.h"
24
Jim Ingham642036f2010-09-23 02:01:19 +000025using namespace lldb;
26using namespace lldb_private;
27
28//----------------------------------------------------------------------
29// Destructor
30//----------------------------------------------------------------------
31ObjCLanguageRuntime::~ObjCLanguageRuntime()
32{
33}
34
35ObjCLanguageRuntime::ObjCLanguageRuntime (Process *process) :
Sean Callanan6e12c7a2012-03-08 02:39:03 +000036 LanguageRuntime (process),
Sean Callanan6fe8d362012-09-15 01:05:12 +000037 m_has_new_literals_and_indexing (eLazyBoolCalculate),
Greg Claytonce490e32013-02-13 22:56:14 +000038 m_isa_to_descriptor(),
39 m_isa_to_descriptor_stop_id (UINT32_MAX)
Jim Ingham642036f2010-09-23 02:01:19 +000040{
41
Jim Inghamb66cd072010-09-28 01:25:32 +000042}
43
Greg Claytonce490e32013-02-13 22:56:14 +000044bool
45ObjCLanguageRuntime::AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, const char *class_name)
46{
47 if (isa != 0)
48 {
49 m_isa_to_descriptor[isa] = descriptor_sp;
50 // class_name is assumed to be valid
51 m_hash_to_isa_map.insert(std::make_pair(MappedHash::HashStringUsingDJB(class_name), isa));
52 return true;
53 }
54 return false;
55}
56
Jim Inghamb66cd072010-09-28 01:25:32 +000057void
58ObjCLanguageRuntime::AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t selector, lldb::addr_t impl_addr)
59{
Greg Clayton952e9dc2013-03-27 23:08:40 +000060 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Inghamb66cd072010-09-28 01:25:32 +000061 if (log)
62 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +000063 log->Printf ("Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 " implementation 0x%" PRIx64 ".", class_addr, selector, impl_addr);
Jim Inghamb66cd072010-09-28 01:25:32 +000064 }
65 m_impl_cache.insert (std::pair<ClassAndSel,lldb::addr_t> (ClassAndSel(class_addr, selector), impl_addr));
66}
67
68lldb::addr_t
69ObjCLanguageRuntime::LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t selector)
70{
71 MsgImplMap::iterator pos, end = m_impl_cache.end();
72 pos = m_impl_cache.find (ClassAndSel(class_addr, selector));
73 if (pos != end)
74 return (*pos).second;
75 return LLDB_INVALID_ADDRESS;
76}
Jim Inghamef80aab2011-05-02 18:13:59 +000077
Jim Ingham58513662011-06-24 22:03:24 +000078
Sean Callanan931acec2012-02-22 23:57:45 +000079lldb::TypeSP
80ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name)
81{
82 CompleteClassMap::iterator complete_class_iter = m_complete_class_cache.find(name);
83
84 if (complete_class_iter != m_complete_class_cache.end())
85 {
Greg Claytonef22b902012-10-23 22:41:19 +000086 // Check the weak pointer to make sure the type hasn't been unloaded
87 TypeSP complete_type_sp (complete_class_iter->second.lock());
Sean Callanan931acec2012-02-22 23:57:45 +000088
Greg Claytonef22b902012-10-23 22:41:19 +000089 if (complete_type_sp)
90 return complete_type_sp;
Sean Callanan931acec2012-02-22 23:57:45 +000091 else
Greg Claytonef22b902012-10-23 22:41:19 +000092 m_complete_class_cache.erase(name);
Sean Callanan931acec2012-02-22 23:57:45 +000093 }
94
Enrico Granata12fbcf52013-04-05 18:49:06 +000095 if (m_negative_complete_class_cache.count(name) > 0)
96 return TypeSP();
97
Enrico Granata146d9522012-11-08 02:22:02 +000098 const ModuleList &modules = m_process->GetTarget().GetImages();
Greg Claytonef22b902012-10-23 22:41:19 +000099
Sean Callanan931acec2012-02-22 23:57:45 +0000100 SymbolContextList sc_list;
Greg Claytonef22b902012-10-23 22:41:19 +0000101 const size_t matching_symbols = modules.FindSymbolsWithNameAndType (name,
102 eSymbolTypeObjCClass,
103 sc_list);
Sean Callanan931acec2012-02-22 23:57:45 +0000104
Greg Claytonef22b902012-10-23 22:41:19 +0000105 if (matching_symbols)
Sean Callanan931acec2012-02-22 23:57:45 +0000106 {
Greg Claytonef22b902012-10-23 22:41:19 +0000107 SymbolContext sc;
Sean Callanan931acec2012-02-22 23:57:45 +0000108
Greg Claytonef22b902012-10-23 22:41:19 +0000109 sc_list.GetContextAtIndex(0, sc);
110
111 ModuleSP module_sp(sc.module_sp);
112
113 if (!module_sp)
Sean Callanan931acec2012-02-22 23:57:45 +0000114 return TypeSP();
Sean Callanan931acec2012-02-22 23:57:45 +0000115
Greg Claytonef22b902012-10-23 22:41:19 +0000116 const SymbolContext null_sc;
117 const bool exact_match = true;
118 const uint32_t max_matches = UINT32_MAX;
119 TypeList types;
120
121 const uint32_t num_types = module_sp->FindTypes (null_sc,
122 name,
123 exact_match,
124 max_matches,
125 types);
126
127 if (num_types)
Sean Callanan282c22c2012-12-19 23:05:01 +0000128 {
Greg Claytonef22b902012-10-23 22:41:19 +0000129 uint32_t i;
130 for (i = 0; i < num_types; ++i)
131 {
132 TypeSP type_sp (types.GetTypeAtIndex(i));
133
Greg Clayton52f79232013-07-11 22:46:58 +0000134 if (type_sp->GetClangForwardType().IsObjCObjectOrInterfaceType())
Greg Claytonef22b902012-10-23 22:41:19 +0000135 {
136 if (type_sp->IsCompleteObjCClass())
137 {
138 m_complete_class_cache[name] = type_sp;
139 return type_sp;
140 }
Greg Claytonef22b902012-10-23 22:41:19 +0000141 }
142 }
Sean Callanan931acec2012-02-22 23:57:45 +0000143 }
144 }
Enrico Granata12fbcf52013-04-05 18:49:06 +0000145 m_negative_complete_class_cache.insert(name);
Sean Callanan931acec2012-02-22 23:57:45 +0000146 return TypeSP();
147}
148
Jim Ingham58513662011-06-24 22:03:24 +0000149size_t
150ObjCLanguageRuntime::GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name)
151{
152 return LLDB_INVALID_IVAR_OFFSET;
153}
154
Greg Claytonf892c422013-01-30 00:18:29 +0000155void
156ObjCLanguageRuntime::MethodName::Clear()
Jim Ingham3ad4da02011-08-15 01:32:22 +0000157{
Greg Claytonf892c422013-01-30 00:18:29 +0000158 m_full.Clear();
159 m_class.Clear();
160 m_category.Clear();
161 m_selector.Clear();
162 m_type = eTypeUnspecified;
163 m_category_is_valid = false;
164}
Greg Clayton662e5672012-01-19 03:24:53 +0000165
Greg Claytonf892c422013-01-30 00:18:29 +0000166//bool
167//ObjCLanguageRuntime::MethodName::SetName (const char *name, bool strict)
168//{
169// Clear();
170// if (name && name[0])
171// {
172// // If "strict" is true. then the method must be specified with a
173// // '+' or '-' at the beginning. If "strict" is false, then the '+'
174// // or '-' can be omitted
175// bool valid_prefix = false;
176//
177// if (name[0] == '+' || name[0] == '-')
178// {
179// valid_prefix = name[1] == '[';
180// }
181// else if (!strict)
182// {
183// // "strict" is false, the name just needs to start with '['
184// valid_prefix = name[0] == '[';
185// }
186//
187// if (valid_prefix)
188// {
189// static RegularExpression g_regex("^([-+]?)\\[([A-Za-z_][A-Za-z_0-9]*)(\\([A-Za-z_][A-Za-z_0-9]*\\))? ([A-Za-z_][A-Za-z_0-9:]*)\\]$");
190// llvm::StringRef matches[4];
191// // Since we are using a global regular expression, we must use the threadsafe version of execute
192// if (g_regex.ExecuteThreadSafe(name, matches, 4))
193// {
194// m_full.SetCString(name);
195// if (matches[0].empty())
196// m_type = eTypeUnspecified;
197// else if (matches[0][0] == '+')
198// m_type = eTypeClassMethod;
199// else
200// m_type = eTypeInstanceMethod;
201// m_class.SetString(matches[1]);
202// m_selector.SetString(matches[3]);
203// if (!matches[2].empty())
204// m_category.SetString(matches[2]);
205// }
206// }
207// }
208// return IsValid(strict);
209//}
210
211bool
212ObjCLanguageRuntime::MethodName::SetName (const char *name, bool strict)
213{
214 Clear();
215 if (name && name[0])
Jim Ingham3ad4da02011-08-15 01:32:22 +0000216 {
Greg Claytonf892c422013-01-30 00:18:29 +0000217 // If "strict" is true. then the method must be specified with a
218 // '+' or '-' at the beginning. If "strict" is false, then the '+'
219 // or '-' can be omitted
220 bool valid_prefix = false;
221
222 if (name[0] == '+' || name[0] == '-')
Jim Ingham3ad4da02011-08-15 01:32:22 +0000223 {
Greg Claytonf892c422013-01-30 00:18:29 +0000224 valid_prefix = name[1] == '[';
225 if (name[0] == '+')
226 m_type = eTypeClassMethod;
227 else
228 m_type = eTypeInstanceMethod;
229 }
230 else if (!strict)
231 {
232 // "strict" is false, the name just needs to start with '['
233 valid_prefix = name[0] == '[';
234 }
235
236 if (valid_prefix)
237 {
238 int name_len = strlen (name);
239 // Objective C methods must have at least:
240 // "-[" or "+[" prefix
241 // One character for a class name
242 // One character for the space between the class name
243 // One character for the method name
244 // "]" suffix
245 if (name_len >= (5 + (strict ? 1 : 0)) && name[name_len - 1] == ']')
Jim Ingham3ad4da02011-08-15 01:32:22 +0000246 {
Greg Claytonf892c422013-01-30 00:18:29 +0000247 m_full.SetCStringWithLength(name, name_len);
248 }
249 }
250 }
251 return IsValid(strict);
252}
253
254const ConstString &
255ObjCLanguageRuntime::MethodName::GetClassName ()
256{
257 if (!m_class)
258 {
259 if (IsValid(false))
260 {
261 const char *full = m_full.GetCString();
262 const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
263 const char *paren_pos = strchr (class_start, '(');
264 if (paren_pos)
265 {
266 m_class.SetCStringWithLength (class_start, paren_pos - class_start);
267 }
268 else
269 {
270 // No '(' was found in the full name, we can definitively say
271 // that our category was valid (and empty).
272 m_category_is_valid = true;
273 const char *space_pos = strchr (full, ' ');
274 if (space_pos)
Greg Clayton662e5672012-01-19 03:24:53 +0000275 {
Greg Claytonf892c422013-01-30 00:18:29 +0000276 m_class.SetCStringWithLength (class_start, space_pos - class_start);
277 if (!m_class_category)
Jim Ingham3ad4da02011-08-15 01:32:22 +0000278 {
Greg Claytonf892c422013-01-30 00:18:29 +0000279 // No category in name, so we can also fill in the m_class_category
280 m_class_category = m_class;
Jim Ingham3ad4da02011-08-15 01:32:22 +0000281 }
282 }
283 }
Jim Ingham3ad4da02011-08-15 01:32:22 +0000284 }
Jim Ingham3ad4da02011-08-15 01:32:22 +0000285 }
Greg Claytonf892c422013-01-30 00:18:29 +0000286 return m_class;
Jim Ingham3ad4da02011-08-15 01:32:22 +0000287}
Enrico Granataae2ae942012-09-04 18:47:54 +0000288
Greg Claytonf892c422013-01-30 00:18:29 +0000289const ConstString &
290ObjCLanguageRuntime::MethodName::GetClassNameWithCategory ()
291{
292 if (!m_class_category)
293 {
294 if (IsValid(false))
295 {
296 const char *full = m_full.GetCString();
297 const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
298 const char *space_pos = strchr (full, ' ');
299 if (space_pos)
300 {
301 m_class_category.SetCStringWithLength (class_start, space_pos - class_start);
302 // If m_class hasn't been filled in and the class with category doesn't
303 // contain a '(', then we can also fill in the m_class
304 if (!m_class && strchr (m_class_category.GetCString(), '(') == NULL)
305 {
306 m_class = m_class_category;
307 // No '(' was found in the full name, we can definitively say
308 // that our category was valid (and empty).
309 m_category_is_valid = true;
310
311 }
312 }
313 }
314 }
315 return m_class_category;
316}
317
318const ConstString &
319ObjCLanguageRuntime::MethodName::GetSelector ()
320{
321 if (!m_selector)
322 {
323 if (IsValid(false))
324 {
325 const char *full = m_full.GetCString();
326 const char *space_pos = strchr (full, ' ');
327 if (space_pos)
328 {
329 ++space_pos; // skip the space
330 m_selector.SetCStringWithLength (space_pos, m_full.GetLength() - (space_pos - full) - 1);
331 }
332 }
333 }
334 return m_selector;
335}
336
337const ConstString &
338ObjCLanguageRuntime::MethodName::GetCategory ()
339{
340 if (!m_category_is_valid && !m_category)
341 {
342 if (IsValid(false))
343 {
344 m_category_is_valid = true;
345 const char *full = m_full.GetCString();
346 const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
347 const char *open_paren_pos = strchr (class_start, '(');
348 if (open_paren_pos)
349 {
350 ++open_paren_pos; // Skip the open paren
351 const char *close_paren_pos = strchr (open_paren_pos, ')');
352 if (close_paren_pos)
353 m_category.SetCStringWithLength (open_paren_pos, close_paren_pos - open_paren_pos);
354 }
355 }
356 }
357 return m_category;
358}
359
360ConstString
361ObjCLanguageRuntime::MethodName::GetFullNameWithoutCategory (bool empty_if_no_category)
362{
363 if (IsValid(false))
364 {
365 if (HasCategory())
366 {
367 StreamString strm;
368 if (m_type == eTypeClassMethod)
369 strm.PutChar('+');
370 else if (m_type == eTypeInstanceMethod)
371 strm.PutChar('-');
372 strm.Printf("[%s %s]", GetClassName().GetCString(), GetSelector().GetCString());
373 return ConstString(strm.GetString().c_str());
374 }
375
376 if (!empty_if_no_category)
377 {
378 // Just return the full name since it doesn't have a category
379 return GetFullName();
380 }
381 }
382 return ConstString();
383}
384
385size_t
386ObjCLanguageRuntime::MethodName::GetFullNames (std::vector<ConstString> &names, bool append)
387{
388 if (!append)
389 names.clear();
390 if (IsValid(false))
391 {
392 StreamString strm;
393 const bool is_class_method = m_type == eTypeClassMethod;
394 const bool is_instance_method = m_type == eTypeInstanceMethod;
395 const ConstString &category = GetCategory();
396 if (is_class_method || is_instance_method)
397 {
398 names.push_back (m_full);
399 if (category)
400 {
401 strm.Printf("%c[%s %s]",
402 is_class_method ? '+' : '-',
403 GetClassName().GetCString(),
404 GetSelector().GetCString());
405 names.push_back(ConstString(strm.GetString().c_str()));
406 }
407 }
408 else
409 {
410 const ConstString &class_name = GetClassName();
411 const ConstString &selector = GetSelector();
412 strm.Printf("+[%s %s]", class_name.GetCString(), selector.GetCString());
413 names.push_back(ConstString(strm.GetString().c_str()));
414 strm.Clear();
415 strm.Printf("-[%s %s]", class_name.GetCString(), selector.GetCString());
416 names.push_back(ConstString(strm.GetString().c_str()));
417 strm.Clear();
418 if (category)
419 {
420 strm.Printf("+[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
421 names.push_back(ConstString(strm.GetString().c_str()));
422 strm.Clear();
423 strm.Printf("-[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
424 names.push_back(ConstString(strm.GetString().c_str()));
425 }
426 }
427 }
428 return names.size();
429}
430
431
Enrico Granataae2ae942012-09-04 18:47:54 +0000432bool
433ObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value,
434 uint32_t ptr_size,
435 bool allow_NULLs,
436 bool allow_tagged,
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000437 bool check_version_specific) const
Enrico Granataae2ae942012-09-04 18:47:54 +0000438{
439 if (!value)
440 return allow_NULLs;
441 if ( (value % 2) == 1 && allow_tagged)
442 return true;
443 if ((value % ptr_size) == 0)
444 return (check_version_specific ? CheckPointer(value,ptr_size) : true);
445 else
446 return false;
447}
448
449ObjCLanguageRuntime::ObjCISA
Sean Callananc718b962012-09-11 21:44:01 +0000450ObjCLanguageRuntime::GetISA(const ConstString &name)
451{
Greg Claytonce490e32013-02-13 22:56:14 +0000452 ISAToDescriptorIterator pos = GetDescriptorIterator (name);
453 if (pos != m_isa_to_descriptor.end())
454 return pos->first;
Sean Callananc718b962012-09-11 21:44:01 +0000455 return 0;
456}
457
Greg Claytonce490e32013-02-13 22:56:14 +0000458ObjCLanguageRuntime::ISAToDescriptorIterator
459ObjCLanguageRuntime::GetDescriptorIterator (const ConstString &name)
460{
461 ISAToDescriptorIterator end = m_isa_to_descriptor.end();
462
463 if (name)
464 {
465 UpdateISAToDescriptorMap();
466 if (m_hash_to_isa_map.empty())
467 {
468 // No name hashes were provided, we need to just linearly power through the
469 // names and find a match
470 for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin(); pos != end; ++pos)
471 {
472 if (pos->second->GetClassName() == name)
473 return pos;
474 }
475 }
476 else
477 {
478 // Name hashes were provided, so use them to efficiently lookup name to isa/descriptor
479 const uint32_t name_hash = MappedHash::HashStringUsingDJB (name.GetCString());
480 std::pair <HashToISAIterator, HashToISAIterator> range = m_hash_to_isa_map.equal_range(name_hash);
481 for (HashToISAIterator range_pos = range.first; range_pos != range.second; ++range_pos)
482 {
483 ISAToDescriptorIterator pos = m_isa_to_descriptor.find (range_pos->second);
484 if (pos != m_isa_to_descriptor.end())
485 {
486 if (pos->second->GetClassName() == name)
487 return pos;
488 }
489 }
490 }
491 }
492 return end;
493}
494
495
Sean Callananc718b962012-09-11 21:44:01 +0000496ObjCLanguageRuntime::ObjCISA
Enrico Granataae2ae942012-09-04 18:47:54 +0000497ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
498{
Greg Claytond387b462013-04-19 21:31:16 +0000499 ClassDescriptorSP objc_class_sp (GetClassDescriptorFromISA(isa));
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000500 if (objc_class_sp)
Enrico Granataae2ae942012-09-04 18:47:54 +0000501 {
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000502 ClassDescriptorSP objc_super_class_sp (objc_class_sp->GetSuperclass());
503 if (objc_super_class_sp)
504 return objc_super_class_sp->GetISA();
Enrico Granataae2ae942012-09-04 18:47:54 +0000505 }
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000506 return 0;
Enrico Granataae2ae942012-09-04 18:47:54 +0000507}
508
Enrico Granataae2ae942012-09-04 18:47:54 +0000509ConstString
510ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
511{
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000512 ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor(isa));
513 if (objc_class_sp)
514 return objc_class_sp->GetClassName();
515 return ConstString();
Enrico Granataae2ae942012-09-04 18:47:54 +0000516}
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000517
518ObjCLanguageRuntime::ClassDescriptorSP
Greg Claytond387b462013-04-19 21:31:16 +0000519ObjCLanguageRuntime::GetClassDescriptorFromClassName (const ConstString &class_name)
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000520{
Greg Claytonce490e32013-02-13 22:56:14 +0000521 ISAToDescriptorIterator pos = GetDescriptorIterator (class_name);
522 if (pos != m_isa_to_descriptor.end())
523 return pos->second;
Greg Claytona5104372012-10-11 18:07:21 +0000524 return ClassDescriptorSP();
525
526}
527
528ObjCLanguageRuntime::ClassDescriptorSP
529ObjCLanguageRuntime::GetClassDescriptor (ValueObject& valobj)
530{
531 ClassDescriptorSP objc_class_sp;
532 // if we get an invalid VO (which might still happen when playing around
533 // with pointers returned by the expression parser, don't consider this
534 // a valid ObjC object)
Greg Clayton52f79232013-07-11 22:46:58 +0000535 if (valobj.GetClangType().IsValid())
Greg Claytona5104372012-10-11 18:07:21 +0000536 {
537 addr_t isa_pointer = valobj.GetPointerValue();
538 if (isa_pointer != LLDB_INVALID_ADDRESS)
539 {
540 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
541
542 Process *process = exe_ctx.GetProcessPtr();
543 if (process)
544 {
545 Error error;
546 ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
547 if (isa != LLDB_INVALID_ADDRESS)
Greg Claytond387b462013-04-19 21:31:16 +0000548 objc_class_sp = GetClassDescriptorFromISA (isa);
Greg Claytona5104372012-10-11 18:07:21 +0000549 }
550 }
551 }
552 return objc_class_sp;
553}
554
555ObjCLanguageRuntime::ClassDescriptorSP
556ObjCLanguageRuntime::GetNonKVOClassDescriptor (ValueObject& valobj)
557{
558 ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (GetClassDescriptor (valobj));
559 if (objc_class_sp)
560 {
561 if (!objc_class_sp->IsKVO())
562 return objc_class_sp;
563
564 ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
565 if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
566 return non_kvo_objc_class_sp;
567 }
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000568 return ClassDescriptorSP();
569}
570
Greg Claytona5104372012-10-11 18:07:21 +0000571
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000572ObjCLanguageRuntime::ClassDescriptorSP
Greg Claytond387b462013-04-19 21:31:16 +0000573ObjCLanguageRuntime::GetClassDescriptorFromISA (ObjCISA isa)
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000574{
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000575 if (isa)
576 {
Greg Claytona5104372012-10-11 18:07:21 +0000577 UpdateISAToDescriptorMap();
Greg Claytonce490e32013-02-13 22:56:14 +0000578 ObjCLanguageRuntime::ISAToDescriptorIterator pos = m_isa_to_descriptor.find(isa);
579 if (pos != m_isa_to_descriptor.end())
Greg Claytona5104372012-10-11 18:07:21 +0000580 return pos->second;
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000581 }
Greg Claytona5104372012-10-11 18:07:21 +0000582 return ClassDescriptorSP();
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000583}
584
585ObjCLanguageRuntime::ClassDescriptorSP
586ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa)
587{
588 if (isa)
589 {
Greg Claytond387b462013-04-19 21:31:16 +0000590 ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA (isa);
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000591 if (objc_class_sp && objc_class_sp->IsValid())
592 {
Greg Claytona5104372012-10-11 18:07:21 +0000593 if (!objc_class_sp->IsKVO())
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000594 return objc_class_sp;
Greg Claytona5104372012-10-11 18:07:21 +0000595
596 ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
597 if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
598 return non_kvo_objc_class_sp;
Greg Claytonbe2f3aa2012-10-09 17:51:53 +0000599 }
600 }
601 return ClassDescriptorSP();
602}
603
604
605