blob: 9ed2f26f7861187c9c763472cc358c9adfc61729 [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{
47
Jim Ingham5a369122010-09-28 01:25:32 +000048}
49
Greg Claytona66c4d92013-02-13 22:56:14 +000050bool
51ObjCLanguageRuntime::AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, const char *class_name)
52{
53 if (isa != 0)
54 {
55 m_isa_to_descriptor[isa] = descriptor_sp;
56 // class_name is assumed to be valid
57 m_hash_to_isa_map.insert(std::make_pair(MappedHash::HashStringUsingDJB(class_name), isa));
58 return true;
59 }
60 return false;
61}
62
Jim Ingham5a369122010-09-28 01:25:32 +000063void
64ObjCLanguageRuntime::AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t selector, lldb::addr_t impl_addr)
65{
Greg Clayton5160ce52013-03-27 23:08:40 +000066 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Ingham5a369122010-09-28 01:25:32 +000067 if (log)
68 {
Daniel Malead01b2952012-11-29 21:49:15 +000069 log->Printf ("Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 " implementation 0x%" PRIx64 ".", class_addr, selector, impl_addr);
Jim Ingham5a369122010-09-28 01:25:32 +000070 }
71 m_impl_cache.insert (std::pair<ClassAndSel,lldb::addr_t> (ClassAndSel(class_addr, selector), impl_addr));
72}
73
74lldb::addr_t
75ObjCLanguageRuntime::LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t selector)
76{
77 MsgImplMap::iterator pos, end = m_impl_cache.end();
78 pos = m_impl_cache.find (ClassAndSel(class_addr, selector));
79 if (pos != end)
80 return (*pos).second;
81 return LLDB_INVALID_ADDRESS;
82}
Jim Ingham61be0902011-05-02 18:13:59 +000083
Jim Inghamd555bac2011-06-24 22:03:24 +000084
Sean Callanan72772842012-02-22 23:57:45 +000085lldb::TypeSP
86ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name)
87{
88 CompleteClassMap::iterator complete_class_iter = m_complete_class_cache.find(name);
89
90 if (complete_class_iter != m_complete_class_cache.end())
91 {
Greg Claytond64dd122012-10-23 22:41:19 +000092 // Check the weak pointer to make sure the type hasn't been unloaded
93 TypeSP complete_type_sp (complete_class_iter->second.lock());
Sean Callanan72772842012-02-22 23:57:45 +000094
Greg Claytond64dd122012-10-23 22:41:19 +000095 if (complete_type_sp)
96 return complete_type_sp;
Sean Callanan72772842012-02-22 23:57:45 +000097 else
Greg Claytond64dd122012-10-23 22:41:19 +000098 m_complete_class_cache.erase(name);
Sean Callanan72772842012-02-22 23:57:45 +000099 }
100
Enrico Granataf15ee4e2013-04-05 18:49:06 +0000101 if (m_negative_complete_class_cache.count(name) > 0)
102 return TypeSP();
103
Enrico Granata17598482012-11-08 02:22:02 +0000104 const ModuleList &modules = m_process->GetTarget().GetImages();
Greg Claytond64dd122012-10-23 22:41:19 +0000105
Sean Callanan72772842012-02-22 23:57:45 +0000106 SymbolContextList sc_list;
Greg Claytond64dd122012-10-23 22:41:19 +0000107 const size_t matching_symbols = modules.FindSymbolsWithNameAndType (name,
108 eSymbolTypeObjCClass,
109 sc_list);
Sean Callanan72772842012-02-22 23:57:45 +0000110
Greg Claytond64dd122012-10-23 22:41:19 +0000111 if (matching_symbols)
Sean Callanan72772842012-02-22 23:57:45 +0000112 {
Greg Claytond64dd122012-10-23 22:41:19 +0000113 SymbolContext sc;
Sean Callanan72772842012-02-22 23:57:45 +0000114
Greg Claytond64dd122012-10-23 22:41:19 +0000115 sc_list.GetContextAtIndex(0, sc);
116
117 ModuleSP module_sp(sc.module_sp);
118
119 if (!module_sp)
Sean Callanan72772842012-02-22 23:57:45 +0000120 return TypeSP();
Sean Callanan72772842012-02-22 23:57:45 +0000121
Greg Claytond64dd122012-10-23 22:41:19 +0000122 const SymbolContext null_sc;
123 const bool exact_match = true;
124 const uint32_t max_matches = UINT32_MAX;
125 TypeList types;
126
127 const uint32_t num_types = module_sp->FindTypes (null_sc,
128 name,
129 exact_match,
130 max_matches,
131 types);
132
133 if (num_types)
Sean Callanan7be70e82012-12-19 23:05:01 +0000134 {
Greg Claytond64dd122012-10-23 22:41:19 +0000135 uint32_t i;
136 for (i = 0; i < num_types; ++i)
137 {
138 TypeSP type_sp (types.GetTypeAtIndex(i));
139
Greg Clayton57ee3062013-07-11 22:46:58 +0000140 if (type_sp->GetClangForwardType().IsObjCObjectOrInterfaceType())
Greg Claytond64dd122012-10-23 22:41:19 +0000141 {
142 if (type_sp->IsCompleteObjCClass())
143 {
144 m_complete_class_cache[name] = type_sp;
145 return type_sp;
146 }
Greg Claytond64dd122012-10-23 22:41:19 +0000147 }
148 }
Sean Callanan72772842012-02-22 23:57:45 +0000149 }
150 }
Enrico Granataf15ee4e2013-04-05 18:49:06 +0000151 m_negative_complete_class_cache.insert(name);
Sean Callanan72772842012-02-22 23:57:45 +0000152 return TypeSP();
153}
154
Jim Inghamd555bac2011-06-24 22:03:24 +0000155size_t
156ObjCLanguageRuntime::GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name)
157{
158 return LLDB_INVALID_IVAR_OFFSET;
159}
160
Greg Clayton1b3815c2013-01-30 00:18:29 +0000161void
162ObjCLanguageRuntime::MethodName::Clear()
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000163{
Greg Clayton1b3815c2013-01-30 00:18:29 +0000164 m_full.Clear();
165 m_class.Clear();
166 m_category.Clear();
167 m_selector.Clear();
168 m_type = eTypeUnspecified;
169 m_category_is_valid = false;
170}
Greg Claytone42ae842012-01-19 03:24:53 +0000171
Greg Clayton1b3815c2013-01-30 00:18:29 +0000172//bool
173//ObjCLanguageRuntime::MethodName::SetName (const char *name, bool strict)
174//{
175// Clear();
176// if (name && name[0])
177// {
178// // If "strict" is true. then the method must be specified with a
179// // '+' or '-' at the beginning. If "strict" is false, then the '+'
180// // or '-' can be omitted
181// bool valid_prefix = false;
182//
183// if (name[0] == '+' || name[0] == '-')
184// {
185// valid_prefix = name[1] == '[';
186// }
187// else if (!strict)
188// {
189// // "strict" is false, the name just needs to start with '['
190// valid_prefix = name[0] == '[';
191// }
192//
193// if (valid_prefix)
194// {
195// 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:]*)\\]$");
196// llvm::StringRef matches[4];
197// // Since we are using a global regular expression, we must use the threadsafe version of execute
198// if (g_regex.ExecuteThreadSafe(name, matches, 4))
199// {
200// m_full.SetCString(name);
201// if (matches[0].empty())
202// m_type = eTypeUnspecified;
203// else if (matches[0][0] == '+')
204// m_type = eTypeClassMethod;
205// else
206// m_type = eTypeInstanceMethod;
207// m_class.SetString(matches[1]);
208// m_selector.SetString(matches[3]);
209// if (!matches[2].empty())
210// m_category.SetString(matches[2]);
211// }
212// }
213// }
214// return IsValid(strict);
215//}
216
217bool
218ObjCLanguageRuntime::MethodName::SetName (const char *name, bool strict)
219{
220 Clear();
221 if (name && name[0])
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000222 {
Greg Clayton1b3815c2013-01-30 00:18:29 +0000223 // If "strict" is true. then the method must be specified with a
224 // '+' or '-' at the beginning. If "strict" is false, then the '+'
225 // or '-' can be omitted
226 bool valid_prefix = false;
227
228 if (name[0] == '+' || name[0] == '-')
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000229 {
Greg Clayton1b3815c2013-01-30 00:18:29 +0000230 valid_prefix = name[1] == '[';
231 if (name[0] == '+')
232 m_type = eTypeClassMethod;
233 else
234 m_type = eTypeInstanceMethod;
235 }
236 else if (!strict)
237 {
238 // "strict" is false, the name just needs to start with '['
239 valid_prefix = name[0] == '[';
240 }
241
242 if (valid_prefix)
243 {
244 int name_len = strlen (name);
245 // Objective C methods must have at least:
246 // "-[" or "+[" prefix
247 // One character for a class name
248 // One character for the space between the class name
249 // One character for the method name
250 // "]" suffix
251 if (name_len >= (5 + (strict ? 1 : 0)) && name[name_len - 1] == ']')
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000252 {
Greg Clayton1b3815c2013-01-30 00:18:29 +0000253 m_full.SetCStringWithLength(name, name_len);
254 }
255 }
256 }
257 return IsValid(strict);
258}
259
260const ConstString &
261ObjCLanguageRuntime::MethodName::GetClassName ()
262{
263 if (!m_class)
264 {
265 if (IsValid(false))
266 {
267 const char *full = m_full.GetCString();
268 const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
269 const char *paren_pos = strchr (class_start, '(');
270 if (paren_pos)
271 {
272 m_class.SetCStringWithLength (class_start, paren_pos - class_start);
273 }
274 else
275 {
276 // No '(' was found in the full name, we can definitively say
277 // that our category was valid (and empty).
278 m_category_is_valid = true;
279 const char *space_pos = strchr (full, ' ');
280 if (space_pos)
Greg Claytone42ae842012-01-19 03:24:53 +0000281 {
Greg Clayton1b3815c2013-01-30 00:18:29 +0000282 m_class.SetCStringWithLength (class_start, space_pos - class_start);
283 if (!m_class_category)
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000284 {
Greg Clayton1b3815c2013-01-30 00:18:29 +0000285 // No category in name, so we can also fill in the m_class_category
286 m_class_category = m_class;
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000287 }
288 }
289 }
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000290 }
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000291 }
Greg Clayton1b3815c2013-01-30 00:18:29 +0000292 return m_class;
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000293}
Enrico Granata3467d802012-09-04 18:47:54 +0000294
Greg Clayton1b3815c2013-01-30 00:18:29 +0000295const ConstString &
296ObjCLanguageRuntime::MethodName::GetClassNameWithCategory ()
297{
298 if (!m_class_category)
299 {
300 if (IsValid(false))
301 {
302 const char *full = m_full.GetCString();
303 const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
304 const char *space_pos = strchr (full, ' ');
305 if (space_pos)
306 {
307 m_class_category.SetCStringWithLength (class_start, space_pos - class_start);
308 // If m_class hasn't been filled in and the class with category doesn't
309 // contain a '(', then we can also fill in the m_class
310 if (!m_class && strchr (m_class_category.GetCString(), '(') == NULL)
311 {
312 m_class = m_class_category;
313 // No '(' was found in the full name, we can definitively say
314 // that our category was valid (and empty).
315 m_category_is_valid = true;
316
317 }
318 }
319 }
320 }
321 return m_class_category;
322}
323
324const ConstString &
325ObjCLanguageRuntime::MethodName::GetSelector ()
326{
327 if (!m_selector)
328 {
329 if (IsValid(false))
330 {
331 const char *full = m_full.GetCString();
332 const char *space_pos = strchr (full, ' ');
333 if (space_pos)
334 {
335 ++space_pos; // skip the space
336 m_selector.SetCStringWithLength (space_pos, m_full.GetLength() - (space_pos - full) - 1);
337 }
338 }
339 }
340 return m_selector;
341}
342
343const ConstString &
344ObjCLanguageRuntime::MethodName::GetCategory ()
345{
346 if (!m_category_is_valid && !m_category)
347 {
348 if (IsValid(false))
349 {
350 m_category_is_valid = true;
351 const char *full = m_full.GetCString();
352 const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
353 const char *open_paren_pos = strchr (class_start, '(');
354 if (open_paren_pos)
355 {
356 ++open_paren_pos; // Skip the open paren
357 const char *close_paren_pos = strchr (open_paren_pos, ')');
358 if (close_paren_pos)
359 m_category.SetCStringWithLength (open_paren_pos, close_paren_pos - open_paren_pos);
360 }
361 }
362 }
363 return m_category;
364}
365
366ConstString
367ObjCLanguageRuntime::MethodName::GetFullNameWithoutCategory (bool empty_if_no_category)
368{
369 if (IsValid(false))
370 {
371 if (HasCategory())
372 {
373 StreamString strm;
374 if (m_type == eTypeClassMethod)
375 strm.PutChar('+');
376 else if (m_type == eTypeInstanceMethod)
377 strm.PutChar('-');
378 strm.Printf("[%s %s]", GetClassName().GetCString(), GetSelector().GetCString());
379 return ConstString(strm.GetString().c_str());
380 }
381
382 if (!empty_if_no_category)
383 {
384 // Just return the full name since it doesn't have a category
385 return GetFullName();
386 }
387 }
388 return ConstString();
389}
390
391size_t
392ObjCLanguageRuntime::MethodName::GetFullNames (std::vector<ConstString> &names, bool append)
393{
394 if (!append)
395 names.clear();
396 if (IsValid(false))
397 {
398 StreamString strm;
399 const bool is_class_method = m_type == eTypeClassMethod;
400 const bool is_instance_method = m_type == eTypeInstanceMethod;
401 const ConstString &category = GetCategory();
402 if (is_class_method || is_instance_method)
403 {
404 names.push_back (m_full);
405 if (category)
406 {
407 strm.Printf("%c[%s %s]",
408 is_class_method ? '+' : '-',
409 GetClassName().GetCString(),
410 GetSelector().GetCString());
411 names.push_back(ConstString(strm.GetString().c_str()));
412 }
413 }
414 else
415 {
416 const ConstString &class_name = GetClassName();
417 const ConstString &selector = GetSelector();
418 strm.Printf("+[%s %s]", class_name.GetCString(), selector.GetCString());
419 names.push_back(ConstString(strm.GetString().c_str()));
420 strm.Clear();
421 strm.Printf("-[%s %s]", class_name.GetCString(), selector.GetCString());
422 names.push_back(ConstString(strm.GetString().c_str()));
423 strm.Clear();
424 if (category)
425 {
426 strm.Printf("+[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
427 names.push_back(ConstString(strm.GetString().c_str()));
428 strm.Clear();
429 strm.Printf("-[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
430 names.push_back(ConstString(strm.GetString().c_str()));
431 }
432 }
433 }
434 return names.size();
435}
436
437
Enrico Granata3467d802012-09-04 18:47:54 +0000438bool
439ObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value,
440 uint32_t ptr_size,
441 bool allow_NULLs,
442 bool allow_tagged,
Greg Clayton77fbc812012-10-09 17:51:53 +0000443 bool check_version_specific) const
Enrico Granata3467d802012-09-04 18:47:54 +0000444{
445 if (!value)
446 return allow_NULLs;
447 if ( (value % 2) == 1 && allow_tagged)
448 return true;
449 if ((value % ptr_size) == 0)
450 return (check_version_specific ? CheckPointer(value,ptr_size) : true);
451 else
452 return false;
453}
454
455ObjCLanguageRuntime::ObjCISA
Sean Callananbc47dfc2012-09-11 21:44:01 +0000456ObjCLanguageRuntime::GetISA(const ConstString &name)
457{
Greg Claytona66c4d92013-02-13 22:56:14 +0000458 ISAToDescriptorIterator pos = GetDescriptorIterator (name);
459 if (pos != m_isa_to_descriptor.end())
460 return pos->first;
Sean Callananbc47dfc2012-09-11 21:44:01 +0000461 return 0;
462}
463
Greg Claytona66c4d92013-02-13 22:56:14 +0000464ObjCLanguageRuntime::ISAToDescriptorIterator
465ObjCLanguageRuntime::GetDescriptorIterator (const ConstString &name)
466{
467 ISAToDescriptorIterator end = m_isa_to_descriptor.end();
468
469 if (name)
470 {
471 UpdateISAToDescriptorMap();
472 if (m_hash_to_isa_map.empty())
473 {
474 // No name hashes were provided, we need to just linearly power through the
475 // names and find a match
476 for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin(); pos != end; ++pos)
477 {
478 if (pos->second->GetClassName() == name)
479 return pos;
480 }
481 }
482 else
483 {
484 // Name hashes were provided, so use them to efficiently lookup name to isa/descriptor
485 const uint32_t name_hash = MappedHash::HashStringUsingDJB (name.GetCString());
486 std::pair <HashToISAIterator, HashToISAIterator> range = m_hash_to_isa_map.equal_range(name_hash);
487 for (HashToISAIterator range_pos = range.first; range_pos != range.second; ++range_pos)
488 {
489 ISAToDescriptorIterator pos = m_isa_to_descriptor.find (range_pos->second);
490 if (pos != m_isa_to_descriptor.end())
491 {
492 if (pos->second->GetClassName() == name)
493 return pos;
494 }
495 }
496 }
497 }
498 return end;
499}
500
501
Sean Callananbc47dfc2012-09-11 21:44:01 +0000502ObjCLanguageRuntime::ObjCISA
Enrico Granata3467d802012-09-04 18:47:54 +0000503ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
504{
Greg Clayton03da4cc2013-04-19 21:31:16 +0000505 ClassDescriptorSP objc_class_sp (GetClassDescriptorFromISA(isa));
Greg Clayton77fbc812012-10-09 17:51:53 +0000506 if (objc_class_sp)
Enrico Granata3467d802012-09-04 18:47:54 +0000507 {
Greg Clayton77fbc812012-10-09 17:51:53 +0000508 ClassDescriptorSP objc_super_class_sp (objc_class_sp->GetSuperclass());
509 if (objc_super_class_sp)
510 return objc_super_class_sp->GetISA();
Enrico Granata3467d802012-09-04 18:47:54 +0000511 }
Greg Clayton77fbc812012-10-09 17:51:53 +0000512 return 0;
Enrico Granata3467d802012-09-04 18:47:54 +0000513}
514
Enrico Granata3467d802012-09-04 18:47:54 +0000515ConstString
516ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
517{
Greg Clayton77fbc812012-10-09 17:51:53 +0000518 ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor(isa));
519 if (objc_class_sp)
520 return objc_class_sp->GetClassName();
521 return ConstString();
Enrico Granata3467d802012-09-04 18:47:54 +0000522}
Greg Clayton77fbc812012-10-09 17:51:53 +0000523
524ObjCLanguageRuntime::ClassDescriptorSP
Greg Clayton03da4cc2013-04-19 21:31:16 +0000525ObjCLanguageRuntime::GetClassDescriptorFromClassName (const ConstString &class_name)
Greg Clayton77fbc812012-10-09 17:51:53 +0000526{
Greg Claytona66c4d92013-02-13 22:56:14 +0000527 ISAToDescriptorIterator pos = GetDescriptorIterator (class_name);
528 if (pos != m_isa_to_descriptor.end())
529 return pos->second;
Greg Claytonf0246d12012-10-11 18:07:21 +0000530 return ClassDescriptorSP();
531
532}
533
534ObjCLanguageRuntime::ClassDescriptorSP
535ObjCLanguageRuntime::GetClassDescriptor (ValueObject& valobj)
536{
537 ClassDescriptorSP objc_class_sp;
538 // if we get an invalid VO (which might still happen when playing around
539 // with pointers returned by the expression parser, don't consider this
540 // a valid ObjC object)
Greg Clayton57ee3062013-07-11 22:46:58 +0000541 if (valobj.GetClangType().IsValid())
Greg Claytonf0246d12012-10-11 18:07:21 +0000542 {
543 addr_t isa_pointer = valobj.GetPointerValue();
544 if (isa_pointer != LLDB_INVALID_ADDRESS)
545 {
546 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
547
548 Process *process = exe_ctx.GetProcessPtr();
549 if (process)
550 {
551 Error error;
552 ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
553 if (isa != LLDB_INVALID_ADDRESS)
Greg Clayton03da4cc2013-04-19 21:31:16 +0000554 objc_class_sp = GetClassDescriptorFromISA (isa);
Greg Claytonf0246d12012-10-11 18:07:21 +0000555 }
556 }
557 }
558 return objc_class_sp;
559}
560
561ObjCLanguageRuntime::ClassDescriptorSP
562ObjCLanguageRuntime::GetNonKVOClassDescriptor (ValueObject& valobj)
563{
564 ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (GetClassDescriptor (valobj));
565 if (objc_class_sp)
566 {
567 if (!objc_class_sp->IsKVO())
568 return objc_class_sp;
569
570 ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
571 if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
572 return non_kvo_objc_class_sp;
573 }
Greg Clayton77fbc812012-10-09 17:51:53 +0000574 return ClassDescriptorSP();
575}
576
Greg Claytonf0246d12012-10-11 18:07:21 +0000577
Greg Clayton77fbc812012-10-09 17:51:53 +0000578ObjCLanguageRuntime::ClassDescriptorSP
Greg Clayton03da4cc2013-04-19 21:31:16 +0000579ObjCLanguageRuntime::GetClassDescriptorFromISA (ObjCISA isa)
Greg Clayton77fbc812012-10-09 17:51:53 +0000580{
Greg Clayton77fbc812012-10-09 17:51:53 +0000581 if (isa)
582 {
Greg Claytonf0246d12012-10-11 18:07:21 +0000583 UpdateISAToDescriptorMap();
Greg Claytona66c4d92013-02-13 22:56:14 +0000584 ObjCLanguageRuntime::ISAToDescriptorIterator pos = m_isa_to_descriptor.find(isa);
585 if (pos != m_isa_to_descriptor.end())
Greg Claytonf0246d12012-10-11 18:07:21 +0000586 return pos->second;
Greg Clayton77fbc812012-10-09 17:51:53 +0000587 }
Greg Claytonf0246d12012-10-11 18:07:21 +0000588 return ClassDescriptorSP();
Greg Clayton77fbc812012-10-09 17:51:53 +0000589}
590
591ObjCLanguageRuntime::ClassDescriptorSP
592ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa)
593{
594 if (isa)
595 {
Greg Clayton03da4cc2013-04-19 21:31:16 +0000596 ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA (isa);
Greg Clayton77fbc812012-10-09 17:51:53 +0000597 if (objc_class_sp && objc_class_sp->IsValid())
598 {
Greg Claytonf0246d12012-10-11 18:07:21 +0000599 if (!objc_class_sp->IsKVO())
Greg Clayton77fbc812012-10-09 17:51:53 +0000600 return objc_class_sp;
Greg Claytonf0246d12012-10-11 18:07:21 +0000601
602 ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
603 if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
604 return non_kvo_objc_class_sp;
Greg Clayton77fbc812012-10-09 17:51:53 +0000605 }
606 }
607 return ClassDescriptorSP();
608}
609
610
Enrico Granata5d84a692014-08-19 21:46:37 +0000611ClangASTType
Sean Callanana3309332014-10-31 18:02:30 +0000612ObjCLanguageRuntime::EncodingToType::RealizeType (const char* name, bool for_expression)
Enrico Granata5d84a692014-08-19 21:46:37 +0000613{
614 if (m_scratch_ast_ctx_ap)
Sean Callanana3309332014-10-31 18:02:30 +0000615 return RealizeType(*m_scratch_ast_ctx_ap, name, for_expression);
Enrico Granata5d84a692014-08-19 21:46:37 +0000616 return ClangASTType();
617}
Greg Clayton77fbc812012-10-09 17:51:53 +0000618
Enrico Granata5d84a692014-08-19 21:46:37 +0000619ClangASTType
Sean Callanana3309332014-10-31 18:02:30 +0000620ObjCLanguageRuntime::EncodingToType::RealizeType (ClangASTContext& ast_ctx, const char* name, bool for_expression)
Enrico Granata5d84a692014-08-19 21:46:37 +0000621{
622 clang::ASTContext *clang_ast = ast_ctx.getASTContext();
623 if (!clang_ast)
624 return ClangASTType();
Sean Callanana3309332014-10-31 18:02:30 +0000625 return RealizeType(*clang_ast, name, for_expression);
Enrico Granata5d84a692014-08-19 21:46:37 +0000626}
627
628ObjCLanguageRuntime::EncodingToType::~EncodingToType() {}
629
630ObjCLanguageRuntime::EncodingToTypeSP
631ObjCLanguageRuntime::GetEncodingToType ()
632{
633 return nullptr;
634}
Enrico Granata3842b9f2015-01-28 00:45:42 +0000635
636bool
637ObjCLanguageRuntime::GetTypeBitSize (const ClangASTType& clang_type,
638 uint64_t &size)
639{
640 void *opaque_ptr = clang_type.GetQualType().getAsOpaquePtr();
641 size = m_type_size_cache.Lookup(opaque_ptr);
642 // an ObjC object will at least have an ISA, so 0 is definitely not OK
643 if (size > 0)
644 return true;
645
646 ClassDescriptorSP class_descriptor_sp = GetClassDescriptorFromClassName(clang_type.GetTypeName());
647 if (!class_descriptor_sp)
648 return false;
649
650 int32_t max_offset = INT32_MIN;
651 uint64_t sizeof_max = 0;
652 bool found = false;
653
654 for (size_t idx = 0;
655 idx < class_descriptor_sp->GetNumIVars();
656 idx++)
657 {
658 const auto& ivar = class_descriptor_sp->GetIVarAtIndex(idx);
659 int32_t cur_offset = ivar.m_offset;
660 if (cur_offset > max_offset)
661 {
662 max_offset = cur_offset;
663 sizeof_max = ivar.m_size;
664 found = true;
665 }
666 }
667
668 size = 8 * (max_offset + sizeof_max);
669 if (found)
670 m_type_size_cache.Insert(opaque_ptr, size);
671
672 return found;
673}