blob: df986f6de56bf252f964d1b44da69124e80c3127 [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{
Jim Ingham5a369122010-09-28 01:25:32 +000047}
48
Greg Claytona66c4d92013-02-13 22:56:14 +000049bool
50ObjCLanguageRuntime::AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, const char *class_name)
51{
52 if (isa != 0)
53 {
54 m_isa_to_descriptor[isa] = descriptor_sp;
55 // class_name is assumed to be valid
56 m_hash_to_isa_map.insert(std::make_pair(MappedHash::HashStringUsingDJB(class_name), isa));
57 return true;
58 }
59 return false;
60}
61
Jim Ingham5a369122010-09-28 01:25:32 +000062void
63ObjCLanguageRuntime::AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t selector, lldb::addr_t impl_addr)
64{
Greg Clayton5160ce52013-03-27 23:08:40 +000065 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Ingham5a369122010-09-28 01:25:32 +000066 if (log)
67 {
Daniel Malead01b2952012-11-29 21:49:15 +000068 log->Printf ("Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 " implementation 0x%" PRIx64 ".", class_addr, selector, impl_addr);
Jim Ingham5a369122010-09-28 01:25:32 +000069 }
70 m_impl_cache.insert (std::pair<ClassAndSel,lldb::addr_t> (ClassAndSel(class_addr, selector), impl_addr));
71}
72
73lldb::addr_t
74ObjCLanguageRuntime::LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t selector)
75{
76 MsgImplMap::iterator pos, end = m_impl_cache.end();
77 pos = m_impl_cache.find (ClassAndSel(class_addr, selector));
78 if (pos != end)
79 return (*pos).second;
80 return LLDB_INVALID_ADDRESS;
81}
Jim Ingham61be0902011-05-02 18:13:59 +000082
Jim Inghamd555bac2011-06-24 22:03:24 +000083
Sean Callanan72772842012-02-22 23:57:45 +000084lldb::TypeSP
85ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name)
86{
87 CompleteClassMap::iterator complete_class_iter = m_complete_class_cache.find(name);
88
89 if (complete_class_iter != m_complete_class_cache.end())
90 {
Greg Claytond64dd122012-10-23 22:41:19 +000091 // Check the weak pointer to make sure the type hasn't been unloaded
92 TypeSP complete_type_sp (complete_class_iter->second.lock());
Sean Callanan72772842012-02-22 23:57:45 +000093
Greg Claytond64dd122012-10-23 22:41:19 +000094 if (complete_type_sp)
95 return complete_type_sp;
Sean Callanan72772842012-02-22 23:57:45 +000096 else
Greg Claytond64dd122012-10-23 22:41:19 +000097 m_complete_class_cache.erase(name);
Sean Callanan72772842012-02-22 23:57:45 +000098 }
99
Enrico Granataf15ee4e2013-04-05 18:49:06 +0000100 if (m_negative_complete_class_cache.count(name) > 0)
101 return TypeSP();
102
Enrico Granata17598482012-11-08 02:22:02 +0000103 const ModuleList &modules = m_process->GetTarget().GetImages();
Greg Claytond64dd122012-10-23 22:41:19 +0000104
Sean Callanan72772842012-02-22 23:57:45 +0000105 SymbolContextList sc_list;
Greg Claytond64dd122012-10-23 22:41:19 +0000106 const size_t matching_symbols = modules.FindSymbolsWithNameAndType (name,
107 eSymbolTypeObjCClass,
108 sc_list);
Sean Callanan72772842012-02-22 23:57:45 +0000109
Greg Claytond64dd122012-10-23 22:41:19 +0000110 if (matching_symbols)
Sean Callanan72772842012-02-22 23:57:45 +0000111 {
Greg Claytond64dd122012-10-23 22:41:19 +0000112 SymbolContext sc;
Sean Callanan72772842012-02-22 23:57:45 +0000113
Greg Claytond64dd122012-10-23 22:41:19 +0000114 sc_list.GetContextAtIndex(0, sc);
115
116 ModuleSP module_sp(sc.module_sp);
117
118 if (!module_sp)
Sean Callanan72772842012-02-22 23:57:45 +0000119 return TypeSP();
Sean Callanan72772842012-02-22 23:57:45 +0000120
Greg Claytond64dd122012-10-23 22:41:19 +0000121 const SymbolContext null_sc;
122 const bool exact_match = true;
123 const uint32_t max_matches = UINT32_MAX;
124 TypeList types;
125
126 const uint32_t num_types = module_sp->FindTypes (null_sc,
127 name,
128 exact_match,
129 max_matches,
130 types);
131
132 if (num_types)
Sean Callanan7be70e82012-12-19 23:05:01 +0000133 {
Greg Claytond64dd122012-10-23 22:41:19 +0000134 uint32_t i;
135 for (i = 0; i < num_types; ++i)
136 {
137 TypeSP type_sp (types.GetTypeAtIndex(i));
138
Greg Claytond8d4a572015-08-11 21:38:15 +0000139 if (ClangASTContext::IsObjCObjectOrInterfaceType(type_sp->GetClangForwardType()))
Greg Claytond64dd122012-10-23 22:41:19 +0000140 {
141 if (type_sp->IsCompleteObjCClass())
142 {
143 m_complete_class_cache[name] = type_sp;
144 return type_sp;
145 }
Greg Claytond64dd122012-10-23 22:41:19 +0000146 }
147 }
Sean Callanan72772842012-02-22 23:57:45 +0000148 }
149 }
Enrico Granataf15ee4e2013-04-05 18:49:06 +0000150 m_negative_complete_class_cache.insert(name);
Sean Callanan72772842012-02-22 23:57:45 +0000151 return TypeSP();
152}
153
Jim Inghamd555bac2011-06-24 22:03:24 +0000154size_t
Greg Claytona1e5dc82015-08-11 22:53:00 +0000155ObjCLanguageRuntime::GetByteOffsetForIvar (CompilerType &parent_qual_type, const char *ivar_name)
Jim Inghamd555bac2011-06-24 22:03:24 +0000156{
157 return LLDB_INVALID_IVAR_OFFSET;
158}
159
Greg Clayton1b3815c2013-01-30 00:18:29 +0000160void
161ObjCLanguageRuntime::MethodName::Clear()
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000162{
Greg Clayton1b3815c2013-01-30 00:18:29 +0000163 m_full.Clear();
164 m_class.Clear();
165 m_category.Clear();
166 m_selector.Clear();
167 m_type = eTypeUnspecified;
168 m_category_is_valid = false;
169}
Greg Claytone42ae842012-01-19 03:24:53 +0000170
Greg Clayton1b3815c2013-01-30 00:18:29 +0000171//bool
172//ObjCLanguageRuntime::MethodName::SetName (const char *name, bool strict)
173//{
174// Clear();
175// if (name && name[0])
176// {
177// // If "strict" is true. then the method must be specified with a
178// // '+' or '-' at the beginning. If "strict" is false, then the '+'
179// // or '-' can be omitted
180// bool valid_prefix = false;
181//
182// if (name[0] == '+' || name[0] == '-')
183// {
184// valid_prefix = name[1] == '[';
185// }
186// else if (!strict)
187// {
188// // "strict" is false, the name just needs to start with '['
189// valid_prefix = name[0] == '[';
190// }
191//
192// if (valid_prefix)
193// {
194// 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:]*)\\]$");
195// llvm::StringRef matches[4];
196// // Since we are using a global regular expression, we must use the threadsafe version of execute
197// if (g_regex.ExecuteThreadSafe(name, matches, 4))
198// {
199// m_full.SetCString(name);
200// if (matches[0].empty())
201// m_type = eTypeUnspecified;
202// else if (matches[0][0] == '+')
203// m_type = eTypeClassMethod;
204// else
205// m_type = eTypeInstanceMethod;
206// m_class.SetString(matches[1]);
207// m_selector.SetString(matches[3]);
208// if (!matches[2].empty())
209// m_category.SetString(matches[2]);
210// }
211// }
212// }
213// return IsValid(strict);
214//}
215
216bool
217ObjCLanguageRuntime::MethodName::SetName (const char *name, bool strict)
218{
219 Clear();
220 if (name && name[0])
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000221 {
Greg Clayton1b3815c2013-01-30 00:18:29 +0000222 // If "strict" is true. then the method must be specified with a
223 // '+' or '-' at the beginning. If "strict" is false, then the '+'
224 // or '-' can be omitted
225 bool valid_prefix = false;
226
227 if (name[0] == '+' || name[0] == '-')
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000228 {
Greg Clayton1b3815c2013-01-30 00:18:29 +0000229 valid_prefix = name[1] == '[';
230 if (name[0] == '+')
231 m_type = eTypeClassMethod;
232 else
233 m_type = eTypeInstanceMethod;
234 }
235 else if (!strict)
236 {
237 // "strict" is false, the name just needs to start with '['
238 valid_prefix = name[0] == '[';
239 }
240
241 if (valid_prefix)
242 {
243 int name_len = strlen (name);
244 // Objective C methods must have at least:
245 // "-[" or "+[" prefix
246 // One character for a class name
247 // One character for the space between the class name
248 // One character for the method name
249 // "]" suffix
250 if (name_len >= (5 + (strict ? 1 : 0)) && name[name_len - 1] == ']')
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000251 {
Greg Clayton1b3815c2013-01-30 00:18:29 +0000252 m_full.SetCStringWithLength(name, name_len);
253 }
254 }
255 }
256 return IsValid(strict);
257}
258
259const ConstString &
260ObjCLanguageRuntime::MethodName::GetClassName ()
261{
262 if (!m_class)
263 {
264 if (IsValid(false))
265 {
266 const char *full = m_full.GetCString();
267 const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
268 const char *paren_pos = strchr (class_start, '(');
269 if (paren_pos)
270 {
271 m_class.SetCStringWithLength (class_start, paren_pos - class_start);
272 }
273 else
274 {
275 // No '(' was found in the full name, we can definitively say
276 // that our category was valid (and empty).
277 m_category_is_valid = true;
278 const char *space_pos = strchr (full, ' ');
279 if (space_pos)
Greg Claytone42ae842012-01-19 03:24:53 +0000280 {
Greg Clayton1b3815c2013-01-30 00:18:29 +0000281 m_class.SetCStringWithLength (class_start, space_pos - class_start);
282 if (!m_class_category)
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000283 {
Greg Clayton1b3815c2013-01-30 00:18:29 +0000284 // No category in name, so we can also fill in the m_class_category
285 m_class_category = m_class;
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000286 }
287 }
288 }
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000289 }
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000290 }
Greg Clayton1b3815c2013-01-30 00:18:29 +0000291 return m_class;
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000292}
Enrico Granata3467d802012-09-04 18:47:54 +0000293
Greg Clayton1b3815c2013-01-30 00:18:29 +0000294const ConstString &
295ObjCLanguageRuntime::MethodName::GetClassNameWithCategory ()
296{
297 if (!m_class_category)
298 {
299 if (IsValid(false))
300 {
301 const char *full = m_full.GetCString();
302 const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
303 const char *space_pos = strchr (full, ' ');
304 if (space_pos)
305 {
306 m_class_category.SetCStringWithLength (class_start, space_pos - class_start);
307 // If m_class hasn't been filled in and the class with category doesn't
308 // contain a '(', then we can also fill in the m_class
309 if (!m_class && strchr (m_class_category.GetCString(), '(') == NULL)
310 {
311 m_class = m_class_category;
312 // No '(' was found in the full name, we can definitively say
313 // that our category was valid (and empty).
314 m_category_is_valid = true;
315
316 }
317 }
318 }
319 }
320 return m_class_category;
321}
322
323const ConstString &
324ObjCLanguageRuntime::MethodName::GetSelector ()
325{
326 if (!m_selector)
327 {
328 if (IsValid(false))
329 {
330 const char *full = m_full.GetCString();
331 const char *space_pos = strchr (full, ' ');
332 if (space_pos)
333 {
334 ++space_pos; // skip the space
335 m_selector.SetCStringWithLength (space_pos, m_full.GetLength() - (space_pos - full) - 1);
336 }
337 }
338 }
339 return m_selector;
340}
341
342const ConstString &
343ObjCLanguageRuntime::MethodName::GetCategory ()
344{
345 if (!m_category_is_valid && !m_category)
346 {
347 if (IsValid(false))
348 {
349 m_category_is_valid = true;
350 const char *full = m_full.GetCString();
351 const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
352 const char *open_paren_pos = strchr (class_start, '(');
353 if (open_paren_pos)
354 {
355 ++open_paren_pos; // Skip the open paren
356 const char *close_paren_pos = strchr (open_paren_pos, ')');
357 if (close_paren_pos)
358 m_category.SetCStringWithLength (open_paren_pos, close_paren_pos - open_paren_pos);
359 }
360 }
361 }
362 return m_category;
363}
364
365ConstString
366ObjCLanguageRuntime::MethodName::GetFullNameWithoutCategory (bool empty_if_no_category)
367{
368 if (IsValid(false))
369 {
370 if (HasCategory())
371 {
372 StreamString strm;
373 if (m_type == eTypeClassMethod)
374 strm.PutChar('+');
375 else if (m_type == eTypeInstanceMethod)
376 strm.PutChar('-');
377 strm.Printf("[%s %s]", GetClassName().GetCString(), GetSelector().GetCString());
378 return ConstString(strm.GetString().c_str());
379 }
380
381 if (!empty_if_no_category)
382 {
383 // Just return the full name since it doesn't have a category
384 return GetFullName();
385 }
386 }
387 return ConstString();
388}
389
390size_t
391ObjCLanguageRuntime::MethodName::GetFullNames (std::vector<ConstString> &names, bool append)
392{
393 if (!append)
394 names.clear();
395 if (IsValid(false))
396 {
397 StreamString strm;
398 const bool is_class_method = m_type == eTypeClassMethod;
399 const bool is_instance_method = m_type == eTypeInstanceMethod;
400 const ConstString &category = GetCategory();
401 if (is_class_method || is_instance_method)
402 {
403 names.push_back (m_full);
404 if (category)
405 {
406 strm.Printf("%c[%s %s]",
407 is_class_method ? '+' : '-',
408 GetClassName().GetCString(),
409 GetSelector().GetCString());
410 names.push_back(ConstString(strm.GetString().c_str()));
411 }
412 }
413 else
414 {
415 const ConstString &class_name = GetClassName();
416 const ConstString &selector = GetSelector();
417 strm.Printf("+[%s %s]", class_name.GetCString(), selector.GetCString());
418 names.push_back(ConstString(strm.GetString().c_str()));
419 strm.Clear();
420 strm.Printf("-[%s %s]", class_name.GetCString(), selector.GetCString());
421 names.push_back(ConstString(strm.GetString().c_str()));
422 strm.Clear();
423 if (category)
424 {
425 strm.Printf("+[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
426 names.push_back(ConstString(strm.GetString().c_str()));
427 strm.Clear();
428 strm.Printf("-[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
429 names.push_back(ConstString(strm.GetString().c_str()));
430 }
431 }
432 }
433 return names.size();
434}
435
436
Enrico Granata3467d802012-09-04 18:47:54 +0000437bool
438ObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value,
439 uint32_t ptr_size,
440 bool allow_NULLs,
441 bool allow_tagged,
Greg Clayton77fbc812012-10-09 17:51:53 +0000442 bool check_version_specific) const
Enrico Granata3467d802012-09-04 18:47:54 +0000443{
444 if (!value)
445 return allow_NULLs;
446 if ( (value % 2) == 1 && allow_tagged)
447 return true;
448 if ((value % ptr_size) == 0)
449 return (check_version_specific ? CheckPointer(value,ptr_size) : true);
450 else
451 return false;
452}
453
454ObjCLanguageRuntime::ObjCISA
Sean Callananbc47dfc2012-09-11 21:44:01 +0000455ObjCLanguageRuntime::GetISA(const ConstString &name)
456{
Greg Claytona66c4d92013-02-13 22:56:14 +0000457 ISAToDescriptorIterator pos = GetDescriptorIterator (name);
458 if (pos != m_isa_to_descriptor.end())
459 return pos->first;
Sean Callananbc47dfc2012-09-11 21:44:01 +0000460 return 0;
461}
462
Greg Claytona66c4d92013-02-13 22:56:14 +0000463ObjCLanguageRuntime::ISAToDescriptorIterator
464ObjCLanguageRuntime::GetDescriptorIterator (const ConstString &name)
465{
466 ISAToDescriptorIterator end = m_isa_to_descriptor.end();
467
468 if (name)
469 {
470 UpdateISAToDescriptorMap();
471 if (m_hash_to_isa_map.empty())
472 {
473 // No name hashes were provided, we need to just linearly power through the
474 // names and find a match
475 for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin(); pos != end; ++pos)
476 {
477 if (pos->second->GetClassName() == name)
478 return pos;
479 }
480 }
481 else
482 {
483 // Name hashes were provided, so use them to efficiently lookup name to isa/descriptor
484 const uint32_t name_hash = MappedHash::HashStringUsingDJB (name.GetCString());
485 std::pair <HashToISAIterator, HashToISAIterator> range = m_hash_to_isa_map.equal_range(name_hash);
486 for (HashToISAIterator range_pos = range.first; range_pos != range.second; ++range_pos)
487 {
488 ISAToDescriptorIterator pos = m_isa_to_descriptor.find (range_pos->second);
489 if (pos != m_isa_to_descriptor.end())
490 {
491 if (pos->second->GetClassName() == name)
492 return pos;
493 }
494 }
495 }
496 }
497 return end;
498}
499
Enrico Granataba4b8b02015-05-06 21:01:07 +0000500std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,ObjCLanguageRuntime::ISAToDescriptorIterator>
501ObjCLanguageRuntime::GetDescriptorIteratorPair (bool update_if_needed)
502{
503 if (update_if_needed)
504 UpdateISAToDescriptorMapIfNeeded();
Colin Riley5de42512015-05-08 12:17:27 +0000505
506 return std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,
507 ObjCLanguageRuntime::ISAToDescriptorIterator>(
508 m_isa_to_descriptor.begin(),
509 m_isa_to_descriptor.end());
Enrico Granataba4b8b02015-05-06 21:01:07 +0000510}
511
Greg Claytona66c4d92013-02-13 22:56:14 +0000512
Sean Callananbc47dfc2012-09-11 21:44:01 +0000513ObjCLanguageRuntime::ObjCISA
Enrico Granata3467d802012-09-04 18:47:54 +0000514ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
515{
Greg Clayton03da4cc2013-04-19 21:31:16 +0000516 ClassDescriptorSP objc_class_sp (GetClassDescriptorFromISA(isa));
Greg Clayton77fbc812012-10-09 17:51:53 +0000517 if (objc_class_sp)
Enrico Granata3467d802012-09-04 18:47:54 +0000518 {
Greg Clayton77fbc812012-10-09 17:51:53 +0000519 ClassDescriptorSP objc_super_class_sp (objc_class_sp->GetSuperclass());
520 if (objc_super_class_sp)
521 return objc_super_class_sp->GetISA();
Enrico Granata3467d802012-09-04 18:47:54 +0000522 }
Greg Clayton77fbc812012-10-09 17:51:53 +0000523 return 0;
Enrico Granata3467d802012-09-04 18:47:54 +0000524}
525
Enrico Granata3467d802012-09-04 18:47:54 +0000526ConstString
527ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
528{
Greg Clayton77fbc812012-10-09 17:51:53 +0000529 ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor(isa));
530 if (objc_class_sp)
531 return objc_class_sp->GetClassName();
532 return ConstString();
Enrico Granata3467d802012-09-04 18:47:54 +0000533}
Greg Clayton77fbc812012-10-09 17:51:53 +0000534
535ObjCLanguageRuntime::ClassDescriptorSP
Greg Clayton03da4cc2013-04-19 21:31:16 +0000536ObjCLanguageRuntime::GetClassDescriptorFromClassName (const ConstString &class_name)
Greg Clayton77fbc812012-10-09 17:51:53 +0000537{
Greg Claytona66c4d92013-02-13 22:56:14 +0000538 ISAToDescriptorIterator pos = GetDescriptorIterator (class_name);
539 if (pos != m_isa_to_descriptor.end())
540 return pos->second;
Greg Claytonf0246d12012-10-11 18:07:21 +0000541 return ClassDescriptorSP();
542
543}
544
545ObjCLanguageRuntime::ClassDescriptorSP
546ObjCLanguageRuntime::GetClassDescriptor (ValueObject& valobj)
547{
548 ClassDescriptorSP objc_class_sp;
549 // if we get an invalid VO (which might still happen when playing around
550 // with pointers returned by the expression parser, don't consider this
551 // a valid ObjC object)
Greg Clayton57ee3062013-07-11 22:46:58 +0000552 if (valobj.GetClangType().IsValid())
Greg Claytonf0246d12012-10-11 18:07:21 +0000553 {
554 addr_t isa_pointer = valobj.GetPointerValue();
555 if (isa_pointer != LLDB_INVALID_ADDRESS)
556 {
557 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
558
559 Process *process = exe_ctx.GetProcessPtr();
560 if (process)
561 {
562 Error error;
563 ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
564 if (isa != LLDB_INVALID_ADDRESS)
Greg Clayton03da4cc2013-04-19 21:31:16 +0000565 objc_class_sp = GetClassDescriptorFromISA (isa);
Greg Claytonf0246d12012-10-11 18:07:21 +0000566 }
567 }
568 }
569 return objc_class_sp;
570}
571
572ObjCLanguageRuntime::ClassDescriptorSP
573ObjCLanguageRuntime::GetNonKVOClassDescriptor (ValueObject& valobj)
574{
575 ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (GetClassDescriptor (valobj));
576 if (objc_class_sp)
577 {
578 if (!objc_class_sp->IsKVO())
579 return objc_class_sp;
580
581 ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
582 if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
583 return non_kvo_objc_class_sp;
584 }
Greg Clayton77fbc812012-10-09 17:51:53 +0000585 return ClassDescriptorSP();
586}
587
Greg Claytonf0246d12012-10-11 18:07:21 +0000588
Greg Clayton77fbc812012-10-09 17:51:53 +0000589ObjCLanguageRuntime::ClassDescriptorSP
Greg Clayton03da4cc2013-04-19 21:31:16 +0000590ObjCLanguageRuntime::GetClassDescriptorFromISA (ObjCISA isa)
Greg Clayton77fbc812012-10-09 17:51:53 +0000591{
Greg Clayton77fbc812012-10-09 17:51:53 +0000592 if (isa)
593 {
Greg Claytonf0246d12012-10-11 18:07:21 +0000594 UpdateISAToDescriptorMap();
Greg Claytona66c4d92013-02-13 22:56:14 +0000595 ObjCLanguageRuntime::ISAToDescriptorIterator pos = m_isa_to_descriptor.find(isa);
596 if (pos != m_isa_to_descriptor.end())
Greg Claytonf0246d12012-10-11 18:07:21 +0000597 return pos->second;
Greg Clayton77fbc812012-10-09 17:51:53 +0000598 }
Greg Claytonf0246d12012-10-11 18:07:21 +0000599 return ClassDescriptorSP();
Greg Clayton77fbc812012-10-09 17:51:53 +0000600}
601
602ObjCLanguageRuntime::ClassDescriptorSP
603ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa)
604{
605 if (isa)
606 {
Greg Clayton03da4cc2013-04-19 21:31:16 +0000607 ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA (isa);
Greg Clayton77fbc812012-10-09 17:51:53 +0000608 if (objc_class_sp && objc_class_sp->IsValid())
609 {
Greg Claytonf0246d12012-10-11 18:07:21 +0000610 if (!objc_class_sp->IsKVO())
Greg Clayton77fbc812012-10-09 17:51:53 +0000611 return objc_class_sp;
Greg Claytonf0246d12012-10-11 18:07:21 +0000612
613 ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
614 if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
615 return non_kvo_objc_class_sp;
Greg Clayton77fbc812012-10-09 17:51:53 +0000616 }
617 }
618 return ClassDescriptorSP();
619}
620
621
Greg Claytona1e5dc82015-08-11 22:53:00 +0000622CompilerType
Sean Callanana3309332014-10-31 18:02:30 +0000623ObjCLanguageRuntime::EncodingToType::RealizeType (const char* name, bool for_expression)
Enrico Granata5d84a692014-08-19 21:46:37 +0000624{
625 if (m_scratch_ast_ctx_ap)
Sean Callanana3309332014-10-31 18:02:30 +0000626 return RealizeType(*m_scratch_ast_ctx_ap, name, for_expression);
Greg Claytona1e5dc82015-08-11 22:53:00 +0000627 return CompilerType();
Enrico Granata5d84a692014-08-19 21:46:37 +0000628}
Greg Clayton77fbc812012-10-09 17:51:53 +0000629
Greg Claytona1e5dc82015-08-11 22:53:00 +0000630CompilerType
Sean Callanana3309332014-10-31 18:02:30 +0000631ObjCLanguageRuntime::EncodingToType::RealizeType (ClangASTContext& ast_ctx, const char* name, bool for_expression)
Enrico Granata5d84a692014-08-19 21:46:37 +0000632{
633 clang::ASTContext *clang_ast = ast_ctx.getASTContext();
634 if (!clang_ast)
Greg Claytona1e5dc82015-08-11 22:53:00 +0000635 return CompilerType();
Sean Callanana3309332014-10-31 18:02:30 +0000636 return RealizeType(*clang_ast, name, for_expression);
Enrico Granata5d84a692014-08-19 21:46:37 +0000637}
638
639ObjCLanguageRuntime::EncodingToType::~EncodingToType() {}
640
641ObjCLanguageRuntime::EncodingToTypeSP
642ObjCLanguageRuntime::GetEncodingToType ()
643{
644 return nullptr;
645}
Enrico Granata3842b9f2015-01-28 00:45:42 +0000646
647bool
Greg Claytona1e5dc82015-08-11 22:53:00 +0000648ObjCLanguageRuntime::GetTypeBitSize (const CompilerType& clang_type,
Enrico Granata3842b9f2015-01-28 00:45:42 +0000649 uint64_t &size)
650{
Greg Claytond8d4a572015-08-11 21:38:15 +0000651 void *opaque_ptr = clang_type.GetOpaqueQualType();
Enrico Granata3842b9f2015-01-28 00:45:42 +0000652 size = m_type_size_cache.Lookup(opaque_ptr);
653 // an ObjC object will at least have an ISA, so 0 is definitely not OK
654 if (size > 0)
655 return true;
656
657 ClassDescriptorSP class_descriptor_sp = GetClassDescriptorFromClassName(clang_type.GetTypeName());
658 if (!class_descriptor_sp)
659 return false;
660
661 int32_t max_offset = INT32_MIN;
662 uint64_t sizeof_max = 0;
663 bool found = false;
664
665 for (size_t idx = 0;
666 idx < class_descriptor_sp->GetNumIVars();
667 idx++)
668 {
669 const auto& ivar = class_descriptor_sp->GetIVarAtIndex(idx);
670 int32_t cur_offset = ivar.m_offset;
671 if (cur_offset > max_offset)
672 {
673 max_offset = cur_offset;
674 sizeof_max = ivar.m_size;
675 found = true;
676 }
677 }
678
679 size = 8 * (max_offset + sizeof_max);
680 if (found)
681 m_type_size_cache.Insert(opaque_ptr, size);
682
683 return found;
684}
Jim Inghama72b31c2015-04-22 19:42:18 +0000685
686//------------------------------------------------------------------
687// Exception breakpoint Precondition class for ObjC:
688//------------------------------------------------------------------
689void
690ObjCLanguageRuntime::ObjCExceptionPrecondition::AddClassName(const char *class_name)
691{
692 m_class_names.insert(class_name);
693}
694
695ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition()
696{
697}
698
699bool
700ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition(StoppointCallbackContext &context)
701{
702 return true;
703}
704
705void
706ObjCLanguageRuntime::ObjCExceptionPrecondition::DescribePrecondition(Stream &stream, lldb::DescriptionLevel level)
707{
708}
709
710Error
711ObjCLanguageRuntime::ObjCExceptionPrecondition::ConfigurePrecondition(Args &args)
712{
713 Error error;
714 if (args.GetArgumentCount() > 0)
715 error.SetErrorString("The ObjC Exception breakpoint doesn't support extra options.");
716 return error;
717}