]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
Un-trim part of lldb trunk r256633
[FreeBSD/FreeBSD.git] / source / Plugins / LanguageRuntime / ObjC / AppleObjCRuntime / AppleObjCRuntimeV2.cpp
1 //===-- AppleObjCRuntimeV2.cpp ----------------------------------*- C++ -*-===//
2 //
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 //===----------------------------------------------------------------------===//
9
10 // C Includes
11 #include <stdint.h>
12
13 // C++ Includes
14 #include <string>
15 #include <vector>
16
17 // Other libraries and framework includes
18 #include "clang/AST/ASTContext.h"
19 #include "clang/AST/DeclObjC.h"
20
21 // Project includes
22 #include "lldb/lldb-enumerations.h"
23 #include "lldb/Core/ClangForward.h"
24 #include "lldb/Symbol/CompilerType.h"
25
26 #include "lldb/Core/ClangForward.h"
27 #include "lldb/Core/ConstString.h"
28 #include "lldb/Core/Debugger.h"
29 #include "lldb/Core/Error.h"
30 #include "lldb/Core/Log.h"
31 #include "lldb/Core/Module.h"
32 #include "lldb/Core/PluginManager.h"
33 #include "lldb/Core/Scalar.h"
34 #include "lldb/Core/Section.h"
35 #include "lldb/Core/Stream.h"
36 #include "lldb/Core/StreamString.h"
37 #include "lldb/Core/Timer.h"
38 #include "lldb/Core/ValueObjectVariable.h"
39 #include "lldb/Expression/FunctionCaller.h"
40 #include "lldb/Expression/UtilityFunction.h"
41 #include "lldb/Host/StringConvert.h"
42 #include "lldb/Interpreter/CommandObject.h"
43 #include "lldb/Interpreter/CommandObjectMultiword.h"
44 #include "lldb/Interpreter/CommandReturnObject.h"
45 #include "lldb/Symbol/ClangASTContext.h"
46 #include "lldb/Symbol/ObjectFile.h"
47 #include "lldb/Symbol/Symbol.h"
48 #include "lldb/Symbol/TypeList.h"
49 #include "lldb/Symbol/VariableList.h"
50 #include "lldb/Target/ExecutionContext.h"
51 #include "lldb/Target/Platform.h"
52 #include "lldb/Target/Process.h"
53 #include "lldb/Target/RegisterContext.h"
54 #include "lldb/Target/Target.h"
55 #include "lldb/Target/Thread.h"
56
57 #include "AppleObjCRuntimeV2.h"
58 #include "AppleObjCClassDescriptorV2.h"
59 #include "AppleObjCTypeEncodingParser.h"
60 #include "AppleObjCDeclVendor.h"
61 #include "AppleObjCTrampolineHandler.h"
62
63 #if defined(__APPLE__)
64 #include "Plugins/Platform/MacOSX/PlatformiOSSimulator.h"
65 #endif
66
67 using namespace lldb;
68 using namespace lldb_private;
69
70 // 2 second timeout when running utility functions
71 #define UTILITY_FUNCTION_TIMEOUT_USEC 2*1000*1000
72
73 static const char *g_get_dynamic_class_info_name = "__lldb_apple_objc_v2_get_dynamic_class_info";
74 // Testing using the new C++11 raw string literals. If this breaks GCC then we will
75 // need to revert to the code above...
76 static const char *g_get_dynamic_class_info_body = R"(
77
78 extern "C"
79 {
80     size_t strlen(const char *);
81     char *strncpy (char * s1, const char * s2, size_t n);
82     int printf(const char * format, ...);
83 }
84 //#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
85 #ifdef ENABLE_DEBUG_PRINTF
86 #define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
87 #else
88 #define DEBUG_PRINTF(fmt, ...)
89 #endif
90
91 typedef struct _NXMapTable {
92     void *prototype;
93     unsigned num_classes;
94     unsigned num_buckets_minus_one;
95     void *buckets;
96 } NXMapTable;
97
98 #define NX_MAPNOTAKEY   ((void *)(-1))
99
100 typedef struct BucketInfo
101 {
102     const char *name_ptr;
103     Class isa;
104 } BucketInfo;
105
106 struct ClassInfo
107 {
108     Class isa;
109     uint32_t hash;
110 } __attribute__((__packed__));
111
112 uint32_t
113 __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr,
114                                              void *class_infos_ptr,
115                                              uint32_t class_infos_byte_size)
116 {
117     DEBUG_PRINTF ("gdb_objc_realized_classes_ptr = %p\n", gdb_objc_realized_classes_ptr);
118     DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
119     DEBUG_PRINTF ("class_infos_byte_size = %u\n", class_infos_byte_size);
120     const NXMapTable *grc = (const NXMapTable *)gdb_objc_realized_classes_ptr;
121     if (grc)
122     {
123         const unsigned num_classes = grc->num_classes;
124         if (class_infos_ptr)
125         {
126             const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
127             ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
128             BucketInfo *buckets = (BucketInfo *)grc->buckets;
129             
130             uint32_t idx = 0;
131             for (unsigned i=0; i<=grc->num_buckets_minus_one; ++i)
132             {
133                 if (buckets[i].name_ptr != NX_MAPNOTAKEY)
134                 {
135                     if (idx < max_class_infos)
136                     {
137                         const char *s = buckets[i].name_ptr;
138                         uint32_t h = 5381;
139                         for (unsigned char c = *s; c; c = *++s)
140                             h = ((h << 5) + h) + c;
141                         class_infos[idx].hash = h;
142                         class_infos[idx].isa = buckets[i].isa;
143                     }
144                     ++idx;
145                 }
146             }
147             if (idx < max_class_infos)
148             {
149                 class_infos[idx].isa = NULL;
150                 class_infos[idx].hash = 0;
151             }
152         }
153         return num_classes;
154     }
155     return 0;
156 }
157
158 )";
159
160 static const char *g_get_shared_cache_class_info_name = "__lldb_apple_objc_v2_get_shared_cache_class_info";
161 // Testing using the new C++11 raw string literals. If this breaks GCC then we will
162 // need to revert to the code above...
163 static const char *g_get_shared_cache_class_info_body = R"(
164
165 extern "C"
166 {
167     const char *class_getName(void *objc_class);
168     size_t strlen(const char *);
169     char *strncpy (char * s1, const char * s2, size_t n);
170     int printf(const char * format, ...);
171 }
172
173 // #define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
174 #ifdef ENABLE_DEBUG_PRINTF
175 #define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
176 #else
177 #define DEBUG_PRINTF(fmt, ...)
178 #endif
179
180
181 struct objc_classheader_t {
182     int32_t clsOffset;
183     int32_t hiOffset;
184 };
185
186 struct objc_clsopt_t {
187     uint32_t capacity;
188     uint32_t occupied;
189     uint32_t shift;
190     uint32_t mask;
191     uint32_t zero;
192     uint32_t unused;
193     uint64_t salt;
194     uint32_t scramble[256];
195     uint8_t tab[0]; // tab[mask+1]
196     //  uint8_t checkbytes[capacity];
197     //  int32_t offset[capacity];
198     //  objc_classheader_t clsOffsets[capacity];
199     //  uint32_t duplicateCount;
200     //  objc_classheader_t duplicateOffsets[duplicateCount];
201 };
202
203 struct objc_opt_t {
204     uint32_t version;
205     int32_t selopt_offset;
206     int32_t headeropt_offset;
207     int32_t clsopt_offset;
208 };
209
210 struct objc_opt_v14_t {
211     uint32_t version;
212     uint32_t flags;
213     int32_t selopt_offset;
214     int32_t headeropt_offset;
215     int32_t clsopt_offset;
216 };
217
218 struct ClassInfo
219 {
220     Class isa;
221     uint32_t hash;
222 }  __attribute__((__packed__));
223
224 uint32_t
225 __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
226                                                   void *class_infos_ptr,
227                                                   uint32_t class_infos_byte_size)
228 {
229     uint32_t idx = 0;
230     DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr);
231     DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
232     DEBUG_PRINTF ("class_infos_byte_size = %u (%" PRIu64 " class infos)\n", class_infos_byte_size, (size_t)(class_infos_byte_size/sizeof(ClassInfo)));
233     if (objc_opt_ro_ptr)
234     {
235         const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr;
236         const objc_opt_v14_t* objc_opt_v14 = (objc_opt_v14_t*)objc_opt_ro_ptr;
237         const bool is_v14_format = objc_opt->version >= 14;
238         if (is_v14_format)
239         {
240             DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v14->version);
241             DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v14->flags);
242             DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt_v14->selopt_offset);
243             DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt_v14->headeropt_offset);
244             DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt_v14->clsopt_offset);
245         }
246         else
247         {
248             DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt->version);
249             DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt->selopt_offset);
250             DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset);
251             DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset);
252         }
253         if (objc_opt->version == 12 || objc_opt->version == 13 || objc_opt->version == 14)
254         {
255             const objc_clsopt_t* clsopt = NULL;
256             if (is_v14_format)
257                 clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt_v14 + objc_opt_v14->clsopt_offset);
258             else
259                 clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt + objc_opt->clsopt_offset);
260             const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
261             ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
262             int32_t invalidEntryOffset = 0;
263             // this is safe to do because the version field order is invariant
264             if (objc_opt->version == 12)
265                 invalidEntryOffset = 16;
266             const uint8_t *checkbytes = &clsopt->tab[clsopt->mask+1];
267             const int32_t *offsets = (const int32_t *)(checkbytes + clsopt->capacity);
268             const objc_classheader_t *classOffsets = (const objc_classheader_t *)(offsets + clsopt->capacity);
269             DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity);
270             DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask);
271             DEBUG_PRINTF ("classOffsets = %p\n", classOffsets);
272             for (uint32_t i=0; i<clsopt->capacity; ++i)
273             {
274                 const int32_t clsOffset = classOffsets[i].clsOffset;
275                 if (clsOffset & 1)
276                     continue; // duplicate
277                 else if (clsOffset == invalidEntryOffset)
278                     continue; // invalid offset
279                 
280                 if (class_infos && idx < max_class_infos)
281                 {
282                     class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
283                     const char *name = class_getName (class_infos[idx].isa);
284                     DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
285                     // Hash the class name so we don't have to read it
286                     const char *s = name;
287                     uint32_t h = 5381;
288                     for (unsigned char c = *s; c; c = *++s)
289                         h = ((h << 5) + h) + c;
290                     class_infos[idx].hash = h;
291                 }
292                 ++idx;
293             }
294             
295             const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
296             const uint32_t duplicate_count = *duplicate_count_ptr;
297             const objc_classheader_t *duplicateClassOffsets = (const objc_classheader_t *)(&duplicate_count_ptr[1]);
298             DEBUG_PRINTF ("duplicate_count = %u\n", duplicate_count);
299             DEBUG_PRINTF ("duplicateClassOffsets = %p\n", duplicateClassOffsets);
300             for (uint32_t i=0; i<duplicate_count; ++i)
301             {
302                 const int32_t clsOffset = duplicateClassOffsets[i].clsOffset;
303                 if (clsOffset & 1)
304                     continue; // duplicate
305                 else if (clsOffset == invalidEntryOffset)
306                     continue; // invalid offset
307                 
308                 if (class_infos && idx < max_class_infos)
309                 {
310                     class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
311                     const char *name = class_getName (class_infos[idx].isa);
312                     DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
313                     // Hash the class name so we don't have to read it
314                     const char *s = name;
315                     uint32_t h = 5381;
316                     for (unsigned char c = *s; c; c = *++s)
317                         h = ((h << 5) + h) + c;
318                     class_infos[idx].hash = h;
319                 }
320                 ++idx;
321             }
322         }
323         DEBUG_PRINTF ("%u class_infos\n", idx);
324         DEBUG_PRINTF ("done\n");
325     }
326     return idx;
327 }
328
329
330 )";
331
332 static uint64_t
333 ExtractRuntimeGlobalSymbol (Process* process,
334                             ConstString name,
335                             const ModuleSP &module_sp,
336                             Error& error,
337                             bool read_value = true,
338                             uint8_t byte_size = 0,
339                             uint64_t default_value = LLDB_INVALID_ADDRESS,
340                             SymbolType sym_type = lldb::eSymbolTypeData)
341 {
342     if (!process)
343     {
344         error.SetErrorString("no process");
345         return default_value;
346     }
347     if (!module_sp)
348     {
349         error.SetErrorString("no module");
350         return default_value;
351     }
352     if (!byte_size)
353         byte_size = process->GetAddressByteSize();
354     const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData);
355     if (symbol && symbol->ValueIsAddress())
356     {
357         lldb::addr_t symbol_load_addr = symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());
358         if (symbol_load_addr != LLDB_INVALID_ADDRESS)
359         {
360             if (read_value)
361                 return process->ReadUnsignedIntegerFromMemory(symbol_load_addr, byte_size, default_value, error);
362             else
363                 return symbol_load_addr;
364         }
365         else
366         {
367             error.SetErrorString("symbol address invalid");
368             return default_value;
369         }
370     }
371     else
372     {
373         error.SetErrorString("no symbol");
374         return default_value;
375     }
376 }
377
378 AppleObjCRuntimeV2::AppleObjCRuntimeV2 (Process *process,
379                                         const ModuleSP &objc_module_sp) :
380     AppleObjCRuntime (process),
381     m_get_class_info_code(),
382     m_get_class_info_args (LLDB_INVALID_ADDRESS),
383     m_get_class_info_args_mutex (Mutex::eMutexTypeNormal),
384     m_get_shared_cache_class_info_code(),
385     m_get_shared_cache_class_info_args (LLDB_INVALID_ADDRESS),
386     m_get_shared_cache_class_info_args_mutex (Mutex::eMutexTypeNormal),
387     m_decl_vendor_ap (),
388     m_isa_hash_table_ptr (LLDB_INVALID_ADDRESS),
389     m_hash_signature (),
390     m_has_object_getClass (false),
391     m_loaded_objc_opt (false),
392     m_non_pointer_isa_cache_ap(NonPointerISACache::CreateInstance(*this,objc_module_sp)),
393     m_tagged_pointer_vendor_ap(TaggedPointerVendorV2::CreateInstance(*this,objc_module_sp)),
394     m_encoding_to_type_sp(),
395     m_noclasses_warning_emitted(false)
396 {
397     static const ConstString g_gdb_object_getClass("gdb_object_getClass");
398     m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL);
399 }
400
401 bool
402 AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
403                                               DynamicValueType use_dynamic, 
404                                               TypeAndOrName &class_type_or_name, 
405                                               Address &address,
406                                               Value::ValueType &value_type)
407 {
408     // The Runtime is attached to a particular process, you shouldn't pass in a value from another process.
409     assert (in_value.GetProcessSP().get() == m_process);
410     assert (m_process != NULL);
411     
412     class_type_or_name.Clear();
413     value_type = Value::ValueType::eValueTypeScalar;
414
415     // Make sure we can have a dynamic value before starting...
416     if (CouldHaveDynamicValue (in_value))
417     {
418         // First job, pull out the address at 0 offset from the object  That will be the ISA pointer.
419         ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor (in_value));
420         if (objc_class_sp)
421         {
422             const addr_t object_ptr = in_value.GetPointerValue();
423             address.SetRawAddress(object_ptr);
424
425             ConstString class_name (objc_class_sp->GetClassName());
426             class_type_or_name.SetName(class_name);
427             TypeSP type_sp (objc_class_sp->GetType());
428             if (type_sp)
429                 class_type_or_name.SetTypeSP (type_sp);
430             else
431             {
432                 type_sp = LookupInCompleteClassCache (class_name);
433                 if (type_sp)
434                 {
435                     objc_class_sp->SetType (type_sp);
436                     class_type_or_name.SetTypeSP (type_sp);
437                 }
438                 else
439                 {
440                     // try to go for a CompilerType at least
441                     DeclVendor* vendor = GetDeclVendor();
442                     if (vendor)
443                     {
444                         std::vector<clang::NamedDecl*> decls;
445                         if (vendor->FindDecls(class_name, false, 1, decls) && decls.size())
446                             class_type_or_name.SetCompilerType(ClangASTContext::GetTypeForDecl(decls[0]));
447                     }
448                 }
449             }
450         }
451     }    
452     return class_type_or_name.IsEmpty() == false;
453 }
454
455 //------------------------------------------------------------------
456 // Static Functions
457 //------------------------------------------------------------------
458 LanguageRuntime *
459 AppleObjCRuntimeV2::CreateInstance (Process *process, LanguageType language)
460 {
461     // FIXME: This should be a MacOS or iOS process, and we need to look for the OBJC section to make
462     // sure we aren't using the V1 runtime.
463     if (language == eLanguageTypeObjC)
464     {
465         ModuleSP objc_module_sp;
466         
467         if (AppleObjCRuntime::GetObjCVersion (process, objc_module_sp) == ObjCRuntimeVersions::eAppleObjC_V2)
468             return new AppleObjCRuntimeV2 (process, objc_module_sp);
469         else
470             return NULL;
471     }
472     else
473         return NULL;
474 }
475
476 class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed
477 {
478 public:
479     CommandObjectObjC_ClassTable_Dump (CommandInterpreter &interpreter) :
480     CommandObjectParsed (interpreter,
481                          "dump",
482                          "Dump information on Objective-C classes known to the current process.",
483                          "language objc class-table dump",
484                          eCommandRequiresProcess       |
485                          eCommandProcessMustBeLaunched |
486                          eCommandProcessMustBePaused   )
487     {
488     }
489
490     ~CommandObjectObjC_ClassTable_Dump() override = default;
491
492 protected:
493     bool
494     DoExecute(Args& command, CommandReturnObject &result) override
495     {
496         Process *process = m_exe_ctx.GetProcessPtr();
497         ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime();
498         if (objc_runtime)
499         {
500             auto iterators_pair = objc_runtime->GetDescriptorIteratorPair();
501             auto iterator = iterators_pair.first;
502             for(; iterator != iterators_pair.second; iterator++)
503             {
504                 result.GetOutputStream().Printf("isa = 0x%" PRIx64, iterator->first);
505                 if (iterator->second)
506                 {
507                     result.GetOutputStream().Printf(" name = %s", iterator->second->GetClassName().AsCString("<unknown>"));
508                     result.GetOutputStream().Printf(" instance size = %" PRIu64, iterator->second->GetInstanceSize());
509                     result.GetOutputStream().Printf(" num ivars = %" PRIuPTR, (uintptr_t)iterator->second->GetNumIVars());
510                     if (auto superclass = iterator->second->GetSuperclass())
511                     {
512                         result.GetOutputStream().Printf(" superclass = %s", superclass->GetClassName().AsCString("<unknown>"));
513                     }
514                     result.GetOutputStream().Printf("\n");
515                 }
516                 else
517                 {
518                     result.GetOutputStream().Printf(" has no associated class.\n");
519                 }
520             }
521             result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
522             return true;
523         }
524         else
525         {
526             result.AppendError("current process has no Objective-C runtime loaded");
527             result.SetStatus(lldb::eReturnStatusFailed);
528             return false;
529         }
530     }
531 };
532
533 class CommandObjectMultiwordObjC_TaggedPointer_Info : public CommandObjectParsed
534 {
535 public:
536     CommandObjectMultiwordObjC_TaggedPointer_Info (CommandInterpreter &interpreter) :
537     CommandObjectParsed (interpreter,
538                          "info",
539                          "Dump information on a tagged pointer.",
540                          "language objc tagged-pointer info",
541                          eCommandRequiresProcess       |
542                          eCommandProcessMustBeLaunched |
543                          eCommandProcessMustBePaused   )
544     {
545         CommandArgumentEntry arg;
546         CommandArgumentData index_arg;
547         
548         // Define the first (and only) variant of this arg.
549         index_arg.arg_type = eArgTypeAddress;
550         index_arg.arg_repetition = eArgRepeatPlus;
551         
552         // There is only one variant this argument could be; put it into the argument entry.
553         arg.push_back (index_arg);
554         
555         // Push the data for the first argument into the m_arguments vector.
556         m_arguments.push_back (arg);
557     }
558
559     ~CommandObjectMultiwordObjC_TaggedPointer_Info() override = default;
560
561 protected:
562     bool
563     DoExecute(Args& command, CommandReturnObject &result) override
564     {
565         if (command.GetArgumentCount() == 0)
566         {
567             result.AppendError("this command requires arguments");
568             result.SetStatus(lldb::eReturnStatusFailed);
569             return false;
570         }
571         
572         Process *process = m_exe_ctx.GetProcessPtr();
573         ExecutionContext exe_ctx(process);
574         ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime();
575         if (objc_runtime)
576         {
577             ObjCLanguageRuntime::TaggedPointerVendor *tagged_ptr_vendor = objc_runtime->GetTaggedPointerVendor();
578             if (tagged_ptr_vendor)
579             {
580                 for (size_t i = 0;
581                      i < command.GetArgumentCount();
582                      i++)
583                 {
584                     const char *arg_str = command.GetArgumentAtIndex(i);
585                     if (!arg_str)
586                         continue;
587                     Error error;
588                     lldb::addr_t arg_addr = Args::StringToAddress(&exe_ctx, arg_str, LLDB_INVALID_ADDRESS, &error);
589                     if (arg_addr == 0 || arg_addr == LLDB_INVALID_ADDRESS || error.Fail())
590                         continue;
591                     auto descriptor_sp = tagged_ptr_vendor->GetClassDescriptor(arg_addr);
592                     if (!descriptor_sp)
593                         continue;
594                     uint64_t info_bits = 0;
595                     uint64_t value_bits = 0;
596                     uint64_t payload = 0;
597                     if (descriptor_sp->GetTaggedPointerInfo(&info_bits, &value_bits, &payload))
598                     {
599                         result.GetOutputStream().Printf("0x%" PRIx64 " is tagged.\n\tpayload = 0x%" PRIx64 "\n\tvalue = 0x%" PRIx64 "\n\tinfo bits = 0x%" PRIx64 "\n\tclass = %s\n",
600                                                         (uint64_t)arg_addr,
601                                                         payload,
602                                                         value_bits,
603                                                         info_bits,
604                                                         descriptor_sp->GetClassName().AsCString("<unknown>"));
605                     }
606                     else
607                     {
608                         result.GetOutputStream().Printf("0x%" PRIx64 " is not tagged.\n", (uint64_t)arg_addr);
609                     }
610                 }
611             }
612             else
613             {
614                 result.AppendError("current process has no tagged pointer support");
615                 result.SetStatus(lldb::eReturnStatusFailed);
616                 return false;
617             }
618             result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
619             return true;
620         }
621         else
622         {
623             result.AppendError("current process has no Objective-C runtime loaded");
624             result.SetStatus(lldb::eReturnStatusFailed);
625             return false;
626         }
627     }
628 };
629
630 class CommandObjectMultiwordObjC_ClassTable : public CommandObjectMultiword
631 {
632 public:
633     CommandObjectMultiwordObjC_ClassTable (CommandInterpreter &interpreter) :
634     CommandObjectMultiword (interpreter,
635                             "class-table",
636                             "A set of commands for operating on the Objective-C class table.",
637                             "class-table <subcommand> [<subcommand-options>]")
638     {
639         LoadSubCommand ("dump",   CommandObjectSP (new CommandObjectObjC_ClassTable_Dump (interpreter)));
640     }
641
642     ~CommandObjectMultiwordObjC_ClassTable() override = default;
643 };
644
645 class CommandObjectMultiwordObjC_TaggedPointer : public CommandObjectMultiword
646 {
647 public:
648     
649     CommandObjectMultiwordObjC_TaggedPointer (CommandInterpreter &interpreter) :
650     CommandObjectMultiword (interpreter,
651                             "tagged-pointer",
652                             "A set of commands for operating on Objective-C tagged pointers.",
653                             "class-table <subcommand> [<subcommand-options>]")
654     {
655         LoadSubCommand ("info",   CommandObjectSP (new CommandObjectMultiwordObjC_TaggedPointer_Info (interpreter)));
656     }
657
658     ~CommandObjectMultiwordObjC_TaggedPointer() override = default;
659 };
660
661 class CommandObjectMultiwordObjC : public CommandObjectMultiword
662 {
663 public:
664     CommandObjectMultiwordObjC (CommandInterpreter &interpreter) :
665     CommandObjectMultiword (interpreter,
666                             "objc",
667                             "A set of commands for operating on the Objective-C Language Runtime.",
668                             "objc <subcommand> [<subcommand-options>]")
669     {
670         LoadSubCommand ("class-table",   CommandObjectSP (new CommandObjectMultiwordObjC_ClassTable (interpreter)));
671         LoadSubCommand ("tagged-pointer",   CommandObjectSP (new CommandObjectMultiwordObjC_TaggedPointer (interpreter)));
672     }
673
674     ~CommandObjectMultiwordObjC() override = default;
675 };
676
677 void
678 AppleObjCRuntimeV2::Initialize()
679 {
680     PluginManager::RegisterPlugin (GetPluginNameStatic(),
681                                    "Apple Objective C Language Runtime - Version 2",
682                                    CreateInstance,
683                                    [] (CommandInterpreter& interpreter) -> lldb::CommandObjectSP {
684                                        return CommandObjectSP(new CommandObjectMultiwordObjC(interpreter));
685                                    });
686 }
687
688 void
689 AppleObjCRuntimeV2::Terminate()
690 {
691     PluginManager::UnregisterPlugin (CreateInstance);
692 }
693
694 lldb_private::ConstString
695 AppleObjCRuntimeV2::GetPluginNameStatic()
696 {
697     static ConstString g_name("apple-objc-v2");
698     return g_name;
699 }
700
701 //------------------------------------------------------------------
702 // PluginInterface protocol
703 //------------------------------------------------------------------
704 lldb_private::ConstString
705 AppleObjCRuntimeV2::GetPluginName()
706 {
707     return GetPluginNameStatic();
708 }
709
710 uint32_t
711 AppleObjCRuntimeV2::GetPluginVersion()
712 {
713     return 1;
714 }
715
716 BreakpointResolverSP
717 AppleObjCRuntimeV2::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
718 {
719     BreakpointResolverSP resolver_sp;
720     
721     if (throw_bp)
722         resolver_sp.reset (new BreakpointResolverName (bkpt,
723                                                        "objc_exception_throw",
724                                                        eFunctionNameTypeBase,
725                                                        eLanguageTypeUnknown,
726                                                        Breakpoint::Exact,
727                                                        eLazyBoolNo));
728     // FIXME: We don't do catch breakpoints for ObjC yet.
729     // Should there be some way for the runtime to specify what it can do in this regard?
730     return resolver_sp;
731 }
732
733 UtilityFunction *
734 AppleObjCRuntimeV2::CreateObjectChecker(const char *name)
735 {
736     char check_function_code[2048];
737     
738     int len = 0;
739     if (m_has_object_getClass)
740     {
741         len = ::snprintf (check_function_code, 
742                           sizeof(check_function_code),
743                           "extern \"C\" void *gdb_object_getClass(void *);                                          \n"
744                           "extern \"C\"  int printf(const char *format, ...);                                       \n"
745                           "extern \"C\" void                                                                        \n"
746                           "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector)                                    \n"
747                           "{                                                                                        \n"
748                           "   if ($__lldb_arg_obj == (void *)0)                                                     \n"
749                           "       return; // nil is ok                                                              \n" 
750                           "   if (!gdb_object_getClass($__lldb_arg_obj))                                            \n"
751                           "       *((volatile int *)0) = 'ocgc';                                                    \n"
752                           "   else if ($__lldb_arg_selector != (void *)0)                                           \n"
753                           "   {                                                                                     \n"
754                           "        signed char responds = (signed char) [(id) $__lldb_arg_obj                       \n"
755                           "                                                respondsToSelector:                      \n"
756                           "                                       (struct objc_selector *) $__lldb_arg_selector];   \n"
757                           "       if (responds == (signed char) 0)                                                  \n"
758                           "           *((volatile int *)0) = 'ocgc';                                                \n"
759                           "   }                                                                                     \n"
760                           "}                                                                                        \n",
761                           name);
762     }
763     else
764     {
765         len = ::snprintf (check_function_code, 
766                           sizeof(check_function_code), 
767                           "extern \"C\" void *gdb_class_getClass(void *);                                           \n"
768                           "extern \"C\"  int printf(const char *format, ...);                                       \n"
769                           "extern \"C\"  void                                                                       \n"
770                           "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector)                                    \n"
771                           "{                                                                                        \n"
772                           "   if ($__lldb_arg_obj == (void *)0)                                                     \n"
773                           "       return; // nil is ok                                                              \n" 
774                           "    void **$isa_ptr = (void **)$__lldb_arg_obj;                                          \n"
775                           "    if (*$isa_ptr == (void *)0 || !gdb_class_getClass(*$isa_ptr))                        \n"
776                           "       *((volatile int *)0) = 'ocgc';                                                    \n"
777                           "   else if ($__lldb_arg_selector != (void *)0)                                           \n"
778                           "   {                                                                                     \n"
779                           "        signed char responds = (signed char) [(id) $__lldb_arg_obj                       \n"
780                           "                                                respondsToSelector:                      \n"
781                           "                                        (struct objc_selector *) $__lldb_arg_selector];  \n"
782                           "       if (responds == (signed char) 0)                                                  \n"
783                           "           *((volatile int *)0) = 'ocgc';                                                \n"
784                           "   }                                                                                     \n"
785                           "}                                                                                        \n", 
786                           name);
787     }
788     
789     assert (len < (int)sizeof(check_function_code));
790
791     Error error;
792     return GetTargetRef().GetUtilityFunctionForLanguage(check_function_code, eLanguageTypeObjC, name, error);
793 }
794
795 size_t
796 AppleObjCRuntimeV2::GetByteOffsetForIvar (CompilerType &parent_ast_type, const char *ivar_name)
797 {
798     uint32_t ivar_offset = LLDB_INVALID_IVAR_OFFSET;
799
800     const char *class_name = parent_ast_type.GetConstTypeName().AsCString();
801     if (class_name && class_name[0] && ivar_name && ivar_name[0])
802     {
803         //----------------------------------------------------------------------
804         // Make the objective C V2 mangled name for the ivar offset from the
805         // class name and ivar name
806         //----------------------------------------------------------------------
807         std::string buffer("OBJC_IVAR_$_");
808         buffer.append (class_name);
809         buffer.push_back ('.');
810         buffer.append (ivar_name);
811         ConstString ivar_const_str (buffer.c_str());
812         
813         //----------------------------------------------------------------------
814         // Try to get the ivar offset address from the symbol table first using
815         // the name we created above
816         //----------------------------------------------------------------------
817         SymbolContextList sc_list;
818         Target &target = m_process->GetTarget();
819         target.GetImages().FindSymbolsWithNameAndType(ivar_const_str, eSymbolTypeObjCIVar, sc_list);
820
821         addr_t ivar_offset_address = LLDB_INVALID_ADDRESS;
822
823         Error error;
824         SymbolContext ivar_offset_symbol;
825         if (sc_list.GetSize() == 1 && sc_list.GetContextAtIndex(0, ivar_offset_symbol))
826         {
827             if (ivar_offset_symbol.symbol)
828                 ivar_offset_address = ivar_offset_symbol.symbol->GetLoadAddress (&target);
829         }
830
831         //----------------------------------------------------------------------
832         // If we didn't get the ivar offset address from the symbol table, fall
833         // back to getting it from the runtime
834         //----------------------------------------------------------------------
835         if (ivar_offset_address == LLDB_INVALID_ADDRESS)
836             ivar_offset_address = LookupRuntimeSymbol(ivar_const_str);
837
838         if (ivar_offset_address != LLDB_INVALID_ADDRESS)
839             ivar_offset = m_process->ReadUnsignedIntegerFromMemory (ivar_offset_address,
840                                                                     4,
841                                                                     LLDB_INVALID_IVAR_OFFSET,
842                                                                     error);
843     }
844     return ivar_offset;
845 }
846
847 // tagged pointers are special not-a-real-pointer values that contain both type and value information
848 // this routine attempts to check with as little computational effort as possible whether something
849 // could possibly be a tagged pointer - false positives are possible but false negatives shouldn't
850 bool
851 AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr)
852 {
853     if (!m_tagged_pointer_vendor_ap)
854         return false;
855     return m_tagged_pointer_vendor_ap->IsPossibleTaggedPointer(ptr);
856 }
857
858 class RemoteNXMapTable
859 {
860 public:
861     RemoteNXMapTable () :
862         m_count (0),
863         m_num_buckets_minus_one (0),
864         m_buckets_ptr (LLDB_INVALID_ADDRESS),
865         m_process (NULL),
866         m_end_iterator (*this, -1),
867         m_load_addr (LLDB_INVALID_ADDRESS),
868         m_map_pair_size (0),
869         m_invalid_key (0)
870     {
871     }
872     
873     void
874     Dump ()
875     {
876         printf ("RemoteNXMapTable.m_load_addr = 0x%" PRIx64 "\n", m_load_addr);
877         printf ("RemoteNXMapTable.m_count = %u\n", m_count);
878         printf ("RemoteNXMapTable.m_num_buckets_minus_one = %u\n", m_num_buckets_minus_one);
879         printf ("RemoteNXMapTable.m_buckets_ptr = 0x%" PRIX64 "\n", m_buckets_ptr);
880     }
881     
882     bool
883     ParseHeader (Process* process, lldb::addr_t load_addr)
884     {
885         m_process = process;
886         m_load_addr = load_addr;
887         m_map_pair_size = m_process->GetAddressByteSize() * 2;
888         m_invalid_key = m_process->GetAddressByteSize() == 8 ? UINT64_MAX : UINT32_MAX;
889         Error err;
890         
891         // This currently holds true for all platforms we support, but we might
892         // need to change this to use get the actually byte size of "unsigned"
893         // from the target AST...
894         const uint32_t unsigned_byte_size = sizeof(uint32_t);
895         // Skip the prototype as we don't need it (const struct +NXMapTablePrototype *prototype)
896         
897         bool success = true;
898         if (load_addr == LLDB_INVALID_ADDRESS)
899             success = false;
900         else
901         {
902             lldb::addr_t cursor = load_addr + m_process->GetAddressByteSize();
903                     
904             // unsigned count;
905             m_count = m_process->ReadUnsignedIntegerFromMemory(cursor, unsigned_byte_size, 0, err);
906             if (m_count)
907             {
908                 cursor += unsigned_byte_size;
909             
910                 // unsigned nbBucketsMinusOne;
911                 m_num_buckets_minus_one = m_process->ReadUnsignedIntegerFromMemory(cursor, unsigned_byte_size, 0, err);
912                 cursor += unsigned_byte_size;
913             
914                 // void *buckets;
915                 m_buckets_ptr = m_process->ReadPointerFromMemory(cursor, err);
916                 
917                 success = m_count > 0 && m_buckets_ptr != LLDB_INVALID_ADDRESS;
918             }
919         }
920         
921         if (!success)
922         {
923             m_count = 0;
924             m_num_buckets_minus_one = 0;
925             m_buckets_ptr = LLDB_INVALID_ADDRESS;
926         }
927         return success;
928     }
929     
930     // const_iterator mimics NXMapState and its code comes from NXInitMapState and NXNextMapState.
931     typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA> element;
932
933     friend class const_iterator;
934     class const_iterator
935     {
936     public:
937         const_iterator (RemoteNXMapTable &parent, int index) : m_parent(parent), m_index(index)
938         {
939             AdvanceToValidIndex();
940         }
941         
942         const_iterator (const const_iterator &rhs) : m_parent(rhs.m_parent), m_index(rhs.m_index)
943         {
944             // AdvanceToValidIndex() has been called by rhs already.
945         }
946         
947         const_iterator &operator=(const const_iterator &rhs)
948         {
949             // AdvanceToValidIndex() has been called by rhs already.
950             assert (&m_parent == &rhs.m_parent);
951             m_index = rhs.m_index;
952             return *this;
953         }
954         
955         bool operator==(const const_iterator &rhs) const
956         {
957             if (&m_parent != &rhs.m_parent)
958                 return false;
959             if (m_index != rhs.m_index)
960                 return false;
961             
962             return true;
963         }
964         
965         bool operator!=(const const_iterator &rhs) const
966         {
967             return !(operator==(rhs));
968         }
969         
970         const_iterator &operator++()
971         {
972             AdvanceToValidIndex();
973             return *this;
974         }
975         
976         const element operator*() const
977         {
978             if (m_index == -1)
979             {
980                 // TODO find a way to make this an error, but not an assert
981                 return element();
982             }
983          
984             lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
985             size_t map_pair_size = m_parent.m_map_pair_size;
986             lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
987             
988             Error err;
989             
990             lldb::addr_t key = m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
991             if (!err.Success())
992                 return element();
993             lldb::addr_t value = m_parent.m_process->ReadPointerFromMemory(pair_ptr + m_parent.m_process->GetAddressByteSize(), err);
994             if (!err.Success())
995                 return element();
996             
997             std::string key_string;
998             
999             m_parent.m_process->ReadCStringFromMemory(key, key_string, err);
1000             if (!err.Success())
1001                 return element();
1002             
1003             return element(ConstString(key_string.c_str()), (ObjCLanguageRuntime::ObjCISA)value);
1004         }
1005
1006     private:
1007         void AdvanceToValidIndex ()
1008         {
1009             if (m_index == -1)
1010                 return;
1011             
1012             const lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
1013             const size_t map_pair_size = m_parent.m_map_pair_size;
1014             const lldb::addr_t invalid_key = m_parent.m_invalid_key;
1015             Error err;
1016
1017             while (m_index--)
1018             {
1019                 lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
1020                 lldb::addr_t key = m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
1021                 
1022                 if (!err.Success())
1023                 {
1024                     m_index = -1;
1025                     return;
1026                 }
1027                 
1028                 if (key != invalid_key)
1029                     return;
1030             }
1031         }
1032         RemoteNXMapTable   &m_parent;
1033         int                 m_index;
1034     };
1035     
1036     const_iterator begin ()
1037     {
1038         return const_iterator(*this, m_num_buckets_minus_one + 1);
1039     }
1040     
1041     const_iterator end ()
1042     {
1043         return m_end_iterator;
1044     }
1045     
1046     uint32_t
1047     GetCount () const
1048     {
1049         return m_count;
1050     }
1051     
1052     uint32_t
1053     GetBucketCount () const
1054     {
1055         return m_num_buckets_minus_one;
1056     }
1057     
1058     lldb::addr_t
1059     GetBucketDataPointer () const
1060     {
1061         return m_buckets_ptr;
1062     }
1063     
1064     lldb::addr_t
1065     GetTableLoadAddress() const
1066     {
1067         return m_load_addr;
1068     }
1069
1070 private:
1071     // contents of _NXMapTable struct
1072     uint32_t m_count;
1073     uint32_t m_num_buckets_minus_one;
1074     lldb::addr_t m_buckets_ptr;
1075     lldb_private::Process *m_process;
1076     const_iterator m_end_iterator;
1077     lldb::addr_t m_load_addr;
1078     size_t m_map_pair_size;
1079     lldb::addr_t m_invalid_key;
1080 };
1081
1082 AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() :
1083     m_count (0),
1084     m_num_buckets (0),
1085     m_buckets_ptr (0)
1086 {
1087 }
1088
1089 void
1090 AppleObjCRuntimeV2::HashTableSignature::UpdateSignature (const RemoteNXMapTable &hash_table)
1091 {
1092     m_count = hash_table.GetCount();
1093     m_num_buckets = hash_table.GetBucketCount();
1094     m_buckets_ptr = hash_table.GetBucketDataPointer();
1095 }
1096
1097 bool
1098 AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate (Process *process, AppleObjCRuntimeV2 *runtime, RemoteNXMapTable &hash_table)
1099 {
1100     if (!hash_table.ParseHeader(process, runtime->GetISAHashTablePointer ()))
1101     {
1102         return false; // Failed to parse the header, no need to update anything
1103     }
1104
1105     // Check with out current signature and return true if the count,
1106     // number of buckets or the hash table address changes.
1107     if (m_count == hash_table.GetCount() &&
1108         m_num_buckets == hash_table.GetBucketCount() &&
1109         m_buckets_ptr == hash_table.GetBucketDataPointer())
1110     {
1111         // Hash table hasn't changed
1112         return false;
1113     }
1114     // Hash table data has changed, we need to update
1115     return true;
1116 }
1117
1118 ObjCLanguageRuntime::ClassDescriptorSP
1119 AppleObjCRuntimeV2::GetClassDescriptorFromISA (ObjCISA isa)
1120 {
1121     ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp;
1122     if (m_non_pointer_isa_cache_ap.get())
1123         class_descriptor_sp = m_non_pointer_isa_cache_ap->GetClassDescriptor(isa);
1124     if (!class_descriptor_sp)
1125         class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa);
1126     return class_descriptor_sp;
1127 }
1128
1129 ObjCLanguageRuntime::ClassDescriptorSP
1130 AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& valobj)
1131 {
1132     ClassDescriptorSP objc_class_sp;
1133     if (valobj.IsBaseClass())
1134     {
1135         ValueObject *parent = valobj.GetParent();
1136         // if I am my own parent, bail out of here fast..
1137         if (parent && parent != &valobj)
1138         {
1139             ClassDescriptorSP parent_descriptor_sp = GetClassDescriptor(*parent);
1140             if (parent_descriptor_sp)
1141                 return parent_descriptor_sp->GetSuperclass();
1142         }
1143         return nullptr;
1144     }
1145     // if we get an invalid VO (which might still happen when playing around
1146     // with pointers returned by the expression parser, don't consider this
1147     // a valid ObjC object)
1148     if (valobj.GetCompilerType().IsValid())
1149     {
1150         addr_t isa_pointer = valobj.GetPointerValue();
1151         
1152         // tagged pointer
1153         if (IsTaggedPointer(isa_pointer))
1154         {
1155             return m_tagged_pointer_vendor_ap->GetClassDescriptor(isa_pointer);
1156         }
1157         else
1158         {
1159             ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
1160             
1161             Process *process = exe_ctx.GetProcessPtr();
1162             if (process)
1163             {
1164                 Error error;
1165                 ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
1166                 if (isa != LLDB_INVALID_ADDRESS)
1167                 {
1168                     objc_class_sp = GetClassDescriptorFromISA (isa);
1169                     if (isa && !objc_class_sp)
1170                     {
1171                         Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1172                         if (log)
1173                             log->Printf("0x%" PRIx64 ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was not in class descriptor cache 0x%" PRIx64,
1174                                         isa_pointer,
1175                                         isa);
1176                     }
1177                 }
1178             }
1179         }
1180     }
1181     return objc_class_sp;
1182 }
1183
1184 lldb::addr_t
1185 AppleObjCRuntimeV2::GetISAHashTablePointer ()
1186 {
1187     if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS)
1188     {
1189         Process *process = GetProcess();
1190
1191         ModuleSP objc_module_sp(GetObjCModule());
1192         
1193         if (!objc_module_sp)
1194             return LLDB_INVALID_ADDRESS;
1195
1196         static ConstString g_gdb_objc_realized_classes("gdb_objc_realized_classes");
1197         
1198         const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_objc_realized_classes, lldb::eSymbolTypeAny);
1199         if (symbol)
1200         {
1201             lldb::addr_t gdb_objc_realized_classes_ptr = symbol->GetLoadAddress(&process->GetTarget());
1202             
1203             if (gdb_objc_realized_classes_ptr != LLDB_INVALID_ADDRESS)
1204             {
1205                 Error error;
1206                 m_isa_hash_table_ptr = process->ReadPointerFromMemory(gdb_objc_realized_classes_ptr, error);
1207             }
1208         }
1209     }
1210     return m_isa_hash_table_ptr;
1211 }
1212
1213 bool
1214 AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table)
1215 {
1216     Process *process = GetProcess();
1217     
1218     if (process == NULL)
1219         return false;
1220     
1221     Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1222     
1223     ExecutionContext exe_ctx;
1224     
1225     ThreadSP thread_sp = process->GetThreadList().GetSelectedThread();
1226     
1227     if (!thread_sp)
1228         return false;
1229     
1230     thread_sp->CalculateExecutionContext(exe_ctx);
1231     ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
1232     
1233     if (!ast)
1234         return false;
1235     
1236     Address function_address;
1237     
1238     StreamString errors;
1239     
1240     const uint32_t addr_size = process->GetAddressByteSize();
1241     
1242     Error err;
1243     
1244     // Read the total number of classes from the hash table
1245     const uint32_t num_classes = hash_table.GetCount();
1246     if (num_classes == 0)
1247     {
1248         if (log)
1249             log->Printf ("No dynamic classes found in gdb_objc_realized_classes.");
1250         return false;
1251     }
1252     
1253     // Make some types for our arguments
1254     CompilerType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
1255     CompilerType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
1256     
1257     ValueList arguments;
1258     FunctionCaller *get_class_info_function = nullptr;
1259
1260     if (!m_get_class_info_code.get())
1261     {
1262         Error error;
1263         m_get_class_info_code.reset (GetTargetRef().GetUtilityFunctionForLanguage (g_get_dynamic_class_info_body,
1264                                                                                    eLanguageTypeObjC,
1265                                                                                    g_get_dynamic_class_info_name,
1266                                                                                    error));
1267         if (error.Fail())
1268         {
1269             if (log)
1270                 log->Printf ("Failed to get Utility Function for implementation lookup: %s", error.AsCString());
1271             m_get_class_info_code.reset();
1272         }
1273         else
1274         {
1275             errors.Clear();
1276             
1277             if (!m_get_class_info_code->Install(errors, exe_ctx))
1278             {
1279                 if (log)
1280                     log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
1281                 m_get_class_info_code.reset();
1282             }
1283         }
1284         if (!m_get_class_info_code.get())
1285             return false;
1286         
1287         // Next make the runner function for our implementation utility function.
1288         Value value;
1289         value.SetValueType (Value::eValueTypeScalar);
1290         value.SetCompilerType (clang_void_pointer_type);
1291         arguments.PushValue (value);
1292         arguments.PushValue (value);
1293         
1294         value.SetValueType (Value::eValueTypeScalar);
1295         value.SetCompilerType (clang_uint32_t_type);
1296         arguments.PushValue (value);
1297         
1298         get_class_info_function = m_get_class_info_code->MakeFunctionCaller(clang_uint32_t_type,
1299                                                                             arguments,
1300                                                                             error);
1301         
1302         if (error.Fail())
1303         {
1304             if (log)
1305                 log->Printf("Failed to make function caller for implementation lookup: %s.", error.AsCString());
1306             return false;
1307         }
1308     }
1309     else
1310     {
1311         get_class_info_function = m_get_class_info_code->GetFunctionCaller();
1312         if (!get_class_info_function)
1313         {
1314             if (log)
1315                 log->Printf ("Failed to get implementation lookup function caller: %s.", errors.GetData());
1316             return false;
1317         }
1318         arguments = get_class_info_function->GetArgumentValues();
1319     }
1320
1321     errors.Clear();
1322     
1323     const uint32_t class_info_byte_size = addr_size + 4;
1324     const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
1325     lldb::addr_t class_infos_addr = process->AllocateMemory(class_infos_byte_size,
1326                                                             ePermissionsReadable | ePermissionsWritable,
1327                                                             err);
1328     
1329     if (class_infos_addr == LLDB_INVALID_ADDRESS)
1330         return false;
1331     
1332     Mutex::Locker locker(m_get_class_info_args_mutex);
1333     
1334     // Fill in our function argument values
1335     arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress();
1336     arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
1337     arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
1338     
1339     bool success = false;
1340     
1341     errors.Clear();
1342     
1343     // Write our function arguments into the process so we can run our function
1344     if (get_class_info_function->WriteFunctionArguments (exe_ctx,
1345                                                            m_get_class_info_args,
1346                                                            arguments,
1347                                                            errors))
1348     {
1349         EvaluateExpressionOptions options;
1350         options.SetUnwindOnError(true);
1351         options.SetTryAllThreads(false);
1352         options.SetStopOthers(true);
1353         options.SetIgnoreBreakpoints(true);
1354         options.SetTimeoutUsec(UTILITY_FUNCTION_TIMEOUT_USEC);
1355         
1356         Value return_value;
1357         return_value.SetValueType (Value::eValueTypeScalar);
1358         //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
1359         return_value.SetCompilerType (clang_uint32_t_type);
1360         return_value.GetScalar() = 0;
1361         
1362         errors.Clear();
1363         
1364         // Run the function
1365         ExpressionResults results = get_class_info_function->ExecuteFunction (exe_ctx,
1366                                                                               &m_get_class_info_args,
1367                                                                               options,
1368                                                                               errors,
1369                                                                               return_value);
1370         
1371         if (results == eExpressionCompleted)
1372         {
1373             // The result is the number of ClassInfo structures that were filled in
1374             uint32_t num_class_infos = return_value.GetScalar().ULong();
1375             if (log)
1376                 log->Printf("Discovered %u ObjC classes\n",num_class_infos);
1377             if (num_class_infos > 0)
1378             {
1379                 // Read the ClassInfo structures
1380                 DataBufferHeap buffer (num_class_infos * class_info_byte_size, 0);
1381                 if (process->ReadMemory(class_infos_addr, buffer.GetBytes(), buffer.GetByteSize(), err) == buffer.GetByteSize())
1382                 {
1383                     DataExtractor class_infos_data (buffer.GetBytes(),
1384                                                     buffer.GetByteSize(),
1385                                                     process->GetByteOrder(),
1386                                                     addr_size);
1387                     ParseClassInfoArray (class_infos_data, num_class_infos);
1388                 }
1389             }
1390             success = true;
1391         }
1392         else
1393         {
1394             if (log)
1395                 log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData());
1396         }
1397     }
1398     else
1399     {
1400         if (log)
1401             log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
1402     }
1403     
1404     // Deallocate the memory we allocated for the ClassInfo array
1405     process->DeallocateMemory(class_infos_addr);
1406     
1407     return success;
1408 }
1409
1410 uint32_t
1411 AppleObjCRuntimeV2::ParseClassInfoArray (const DataExtractor &data, uint32_t num_class_infos)
1412 {
1413     // Parses an array of "num_class_infos" packed ClassInfo structures:
1414     //
1415     //    struct ClassInfo
1416     //    {
1417     //        Class isa;
1418     //        uint32_t hash;
1419     //    } __attribute__((__packed__));
1420
1421     Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1422     
1423     uint32_t num_parsed = 0;
1424
1425     // Iterate through all ClassInfo structures
1426     lldb::offset_t offset = 0;
1427     for (uint32_t i=0; i<num_class_infos; ++i)
1428     {
1429         ObjCISA isa = data.GetPointer(&offset);
1430         
1431         if (isa == 0)
1432         {
1433             if (log)
1434                 log->Printf("AppleObjCRuntimeV2 found NULL isa, ignoring this class info");
1435             continue;
1436         }
1437         // Check if we already know about this ISA, if we do, the info will
1438         // never change, so we can just skip it.
1439         if (ISAIsCached(isa))
1440         {
1441             offset += 4;
1442         }
1443         else
1444         {
1445             // Read the 32 bit hash for the class name
1446             const uint32_t name_hash = data.GetU32(&offset);
1447             ClassDescriptorSP descriptor_sp (new ClassDescriptorV2(*this, isa, NULL));
1448             AddClass (isa, descriptor_sp, name_hash);
1449             num_parsed++;
1450             if (log && log->GetVerbose())
1451                 log->Printf("AppleObjCRuntimeV2 added isa=0x%" PRIx64 ", hash=0x%8.8x, name=%s", isa, name_hash,descriptor_sp->GetClassName().AsCString("<unknown>"));
1452         }
1453     }
1454     return num_parsed;
1455 }
1456
1457 AppleObjCRuntimeV2::DescriptorMapUpdateResult
1458 AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
1459 {
1460     Process *process = GetProcess();
1461     
1462     if (process == NULL)
1463         return DescriptorMapUpdateResult::Fail();
1464     
1465     Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1466     
1467     ExecutionContext exe_ctx;
1468     
1469     ThreadSP thread_sp = process->GetThreadList().GetSelectedThread();
1470     
1471     if (!thread_sp)
1472         return DescriptorMapUpdateResult::Fail();
1473     
1474     thread_sp->CalculateExecutionContext(exe_ctx);
1475     ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
1476     
1477     if (!ast)
1478         return DescriptorMapUpdateResult::Fail();
1479     
1480     Address function_address;
1481     
1482     StreamString errors;
1483     
1484     const uint32_t addr_size = process->GetAddressByteSize();
1485     
1486     Error err;
1487     
1488     const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress();
1489     
1490     if (objc_opt_ptr == LLDB_INVALID_ADDRESS)
1491         return DescriptorMapUpdateResult::Fail();
1492     
1493     // Read the total number of classes from the hash table
1494     const uint32_t num_classes = 128*1024;
1495     if (num_classes == 0)
1496     {
1497         if (log)
1498             log->Printf ("No dynamic classes found in gdb_objc_realized_classes_addr.");
1499         return DescriptorMapUpdateResult::Fail();
1500     }
1501     
1502     // Make some types for our arguments
1503     CompilerType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
1504     CompilerType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
1505     
1506     ValueList arguments;
1507     FunctionCaller *get_shared_cache_class_info_function = nullptr;
1508     
1509     if (!m_get_shared_cache_class_info_code.get())
1510     {
1511         Error error;
1512         m_get_shared_cache_class_info_code.reset (GetTargetRef().GetUtilityFunctionForLanguage (g_get_shared_cache_class_info_body,
1513                                                                                                 eLanguageTypeObjC,
1514                                                                                                 g_get_shared_cache_class_info_name,
1515                                                                                                 error));
1516         if (error.Fail())
1517         {
1518             if (log)
1519                 log->Printf ("Failed to get Utility function for implementation lookup: %s.", error.AsCString());
1520             m_get_shared_cache_class_info_code.reset();
1521         }
1522         else
1523         {
1524             errors.Clear();
1525             
1526             if (!m_get_shared_cache_class_info_code->Install(errors, exe_ctx))
1527             {
1528                 if (log)
1529                     log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
1530                 m_get_shared_cache_class_info_code.reset();
1531             }
1532         }
1533         
1534         if (!m_get_shared_cache_class_info_code.get())
1535             return DescriptorMapUpdateResult::Fail();
1536     
1537         // Next make the function caller for our implementation utility function.
1538         Value value;
1539         value.SetValueType (Value::eValueTypeScalar);
1540         //value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type);
1541         value.SetCompilerType (clang_void_pointer_type);
1542         arguments.PushValue (value);
1543         arguments.PushValue (value);
1544         
1545         value.SetValueType (Value::eValueTypeScalar);
1546         //value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
1547         value.SetCompilerType (clang_uint32_t_type);
1548         arguments.PushValue (value);
1549         
1550         get_shared_cache_class_info_function = m_get_shared_cache_class_info_code->MakeFunctionCaller(clang_uint32_t_type,
1551                                                                                                       arguments,
1552                                                                                                       error);
1553         
1554         if (get_shared_cache_class_info_function == nullptr)
1555             return DescriptorMapUpdateResult::Fail();
1556     
1557     }
1558     else
1559     {
1560         get_shared_cache_class_info_function = m_get_shared_cache_class_info_code->GetFunctionCaller();
1561         if (get_shared_cache_class_info_function == nullptr)
1562             return DescriptorMapUpdateResult::Fail();
1563         arguments = get_shared_cache_class_info_function->GetArgumentValues();
1564     }
1565     
1566     errors.Clear();
1567     
1568     const uint32_t class_info_byte_size = addr_size + 4;
1569     const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
1570     lldb::addr_t class_infos_addr = process->AllocateMemory (class_infos_byte_size,
1571                                                              ePermissionsReadable | ePermissionsWritable,
1572                                                              err);
1573     
1574     if (class_infos_addr == LLDB_INVALID_ADDRESS)
1575         return DescriptorMapUpdateResult::Fail();
1576     
1577     Mutex::Locker locker(m_get_shared_cache_class_info_args_mutex);
1578     
1579     // Fill in our function argument values
1580     arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
1581     arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
1582     arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
1583     
1584     bool success = false;
1585     bool any_found = false;
1586     
1587     errors.Clear();
1588     
1589     // Write our function arguments into the process so we can run our function
1590     if (get_shared_cache_class_info_function->WriteFunctionArguments (exe_ctx,
1591                                                                       m_get_shared_cache_class_info_args,
1592                                                                       arguments,
1593                                                                       errors))
1594     {
1595         EvaluateExpressionOptions options;
1596         options.SetUnwindOnError(true);
1597         options.SetTryAllThreads(false);
1598         options.SetStopOthers(true);
1599         options.SetIgnoreBreakpoints(true);
1600         options.SetTimeoutUsec(UTILITY_FUNCTION_TIMEOUT_USEC);
1601         
1602         Value return_value;
1603         return_value.SetValueType (Value::eValueTypeScalar);
1604         //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
1605         return_value.SetCompilerType (clang_uint32_t_type);
1606         return_value.GetScalar() = 0;
1607         
1608         errors.Clear();
1609         
1610         // Run the function
1611         ExpressionResults results = get_shared_cache_class_info_function->ExecuteFunction (exe_ctx,
1612                                                                                            &m_get_shared_cache_class_info_args,
1613                                                                                            options,
1614                                                                                            errors,
1615                                                                                            return_value);
1616         
1617         if (results == eExpressionCompleted)
1618         {
1619             // The result is the number of ClassInfo structures that were filled in
1620             uint32_t num_class_infos = return_value.GetScalar().ULong();
1621             if (log)
1622                 log->Printf("Discovered %u ObjC classes in shared cache\n",num_class_infos);
1623 #ifdef LLDB_CONFIGURATION_DEBUG
1624             assert (num_class_infos <= num_classes);
1625 #endif
1626             if (num_class_infos > 0)
1627             {
1628                 if (num_class_infos > num_classes)
1629                 {
1630                     num_class_infos = num_classes;
1631                     
1632                     success = false;
1633                 }
1634                 else
1635                 {
1636                     success = true;
1637                 }
1638                 
1639                 // Read the ClassInfo structures
1640                 DataBufferHeap buffer (num_class_infos * class_info_byte_size, 0);
1641                 if (process->ReadMemory(class_infos_addr,
1642                                         buffer.GetBytes(),
1643                                         buffer.GetByteSize(),
1644                                         err) == buffer.GetByteSize())
1645                 {
1646                     DataExtractor class_infos_data (buffer.GetBytes(),
1647                                                     buffer.GetByteSize(),
1648                                                     process->GetByteOrder(),
1649                                                     addr_size);
1650
1651                     any_found = (ParseClassInfoArray (class_infos_data, num_class_infos) > 0);
1652                 }
1653             }
1654             else
1655             {
1656                 success = true;
1657             }
1658         }
1659         else
1660         {
1661             if (log)
1662                 log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData());
1663         }
1664     }
1665     else
1666     {
1667         if (log)
1668             log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
1669     }
1670     
1671     // Deallocate the memory we allocated for the ClassInfo array
1672     process->DeallocateMemory(class_infos_addr);
1673     
1674     return DescriptorMapUpdateResult(success, any_found);
1675 }
1676
1677 bool
1678 AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory (RemoteNXMapTable &hash_table)
1679 {
1680     Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1681     
1682     Process *process = GetProcess();
1683
1684     if (process == NULL)
1685         return false;
1686     
1687     uint32_t num_map_table_isas = 0;
1688     
1689     ModuleSP objc_module_sp(GetObjCModule());
1690     
1691     if (objc_module_sp)
1692     {
1693         for (RemoteNXMapTable::element elt : hash_table)
1694         {
1695             ++num_map_table_isas;
1696             
1697             if (ISAIsCached(elt.second))
1698                 continue;
1699             
1700             ClassDescriptorSP descriptor_sp = ClassDescriptorSP(new ClassDescriptorV2(*this, elt.second, elt.first.AsCString()));
1701             
1702             if (log && log->GetVerbose())
1703                 log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64 " (%s) from dynamic table to isa->descriptor cache", elt.second, elt.first.AsCString());
1704             
1705             AddClass (elt.second, descriptor_sp, elt.first.AsCString());
1706         }
1707     }
1708     
1709     return num_map_table_isas > 0;
1710 }
1711
1712 lldb::addr_t
1713 AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress()
1714 {
1715     Process *process = GetProcess();
1716     
1717     if (process)
1718     {
1719         ModuleSP objc_module_sp(GetObjCModule());
1720         
1721         if (objc_module_sp)
1722         {
1723             ObjectFile *objc_object = objc_module_sp->GetObjectFile();
1724             
1725             if (objc_object)
1726             {
1727                 SectionList *section_list = objc_module_sp->GetSectionList();
1728                 
1729                 if (section_list)
1730                 {
1731                     SectionSP text_segment_sp (section_list->FindSectionByName(ConstString("__TEXT")));
1732                     
1733                     if (text_segment_sp)
1734                     {
1735                         SectionSP objc_opt_section_sp (text_segment_sp->GetChildren().FindSectionByName(ConstString("__objc_opt_ro")));
1736                         
1737                         if (objc_opt_section_sp)
1738                         {
1739                             return objc_opt_section_sp->GetLoadBaseAddress(&process->GetTarget());
1740                         }
1741                     }
1742                 }
1743             }
1744         }
1745     }
1746     return LLDB_INVALID_ADDRESS;
1747 }
1748
1749 void
1750 AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded()
1751 {
1752     Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
1753     
1754     // Else we need to check with our process to see when the map was updated.
1755     Process *process = GetProcess();
1756
1757     if (process)
1758     {
1759         RemoteNXMapTable hash_table;
1760         
1761         // Update the process stop ID that indicates the last time we updated the
1762         // map, whether it was successful or not.
1763         m_isa_to_descriptor_stop_id = process->GetStopID();
1764         
1765         if (!m_hash_signature.NeedsUpdate(process, this, hash_table))
1766             return;
1767         
1768         m_hash_signature.UpdateSignature (hash_table);
1769
1770         // Grab the dynamically loaded objc classes from the hash table in memory
1771         UpdateISAToDescriptorMapDynamic(hash_table);
1772
1773         // Now get the objc classes that are baked into the Objective C runtime
1774         // in the shared cache, but only once per process as this data never
1775         // changes
1776         if (!m_loaded_objc_opt)
1777         {
1778             DescriptorMapUpdateResult shared_cache_update_result = UpdateISAToDescriptorMapSharedCache();
1779             if (!shared_cache_update_result.any_found)
1780                 WarnIfNoClassesCached ();
1781             else
1782                 m_loaded_objc_opt = true;
1783         }
1784     }
1785     else
1786     {
1787         m_isa_to_descriptor_stop_id = UINT32_MAX;
1788     }
1789 }
1790
1791 void
1792 AppleObjCRuntimeV2::WarnIfNoClassesCached ()
1793 {
1794     if (m_noclasses_warning_emitted)
1795         return;
1796
1797 #if defined(__APPLE__)
1798     if (m_process &&
1799         m_process->GetTarget().GetPlatform() &&
1800         m_process->GetTarget().GetPlatform()->GetPluginName() == PlatformiOSSimulator::GetPluginNameStatic())
1801     {
1802         // the iOS simulator does not have the objc_opt_ro class table
1803         // so don't actually complain to the user
1804         m_noclasses_warning_emitted = true;
1805         return;
1806     }
1807 #endif
1808
1809     Debugger &debugger(GetProcess()->GetTarget().GetDebugger());
1810     
1811     if (debugger.GetAsyncOutputStream())
1812     {
1813         debugger.GetAsyncOutputStream()->PutCString("warning: could not load any Objective-C class information from the dyld shared cache. This will significantly reduce the quality of type information available.\n");
1814         m_noclasses_warning_emitted = true;
1815     }
1816 }
1817
1818 // TODO: should we have a transparent_kvo parameter here to say if we
1819 // want to replace the KVO swizzled class with the actual user-level type?
1820 ConstString
1821 AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
1822 {
1823     if (isa == g_objc_Tagged_ISA)
1824     {
1825         static const ConstString g_objc_tagged_isa_name ("_lldb_Tagged_ObjC_ISA");
1826         return g_objc_tagged_isa_name;
1827     }
1828     if (isa == g_objc_Tagged_ISA_NSAtom)
1829     {
1830         static const ConstString g_objc_tagged_isa_nsatom_name ("NSAtom");
1831         return g_objc_tagged_isa_nsatom_name;
1832     }
1833     if (isa == g_objc_Tagged_ISA_NSNumber)
1834     {
1835         static const ConstString g_objc_tagged_isa_nsnumber_name ("NSNumber");
1836         return g_objc_tagged_isa_nsnumber_name;
1837     }
1838     if (isa == g_objc_Tagged_ISA_NSDateTS)
1839     {
1840         static const ConstString g_objc_tagged_isa_nsdatets_name ("NSDateTS");
1841         return g_objc_tagged_isa_nsdatets_name;
1842     }
1843     if (isa == g_objc_Tagged_ISA_NSManagedObject)
1844     {
1845         static const ConstString g_objc_tagged_isa_nsmanagedobject_name ("NSManagedObject");
1846         return g_objc_tagged_isa_nsmanagedobject_name;
1847     }
1848     if (isa == g_objc_Tagged_ISA_NSDate)
1849     {
1850         static const ConstString g_objc_tagged_isa_nsdate_name ("NSDate");
1851         return g_objc_tagged_isa_nsdate_name;
1852     }
1853     return ObjCLanguageRuntime::GetActualTypeName(isa);
1854 }
1855
1856 DeclVendor *
1857 AppleObjCRuntimeV2::GetDeclVendor()
1858 {
1859     if (!m_decl_vendor_ap.get())
1860         m_decl_vendor_ap.reset(new AppleObjCDeclVendor(*this));
1861     
1862     return m_decl_vendor_ap.get();
1863 }
1864
1865 lldb::addr_t
1866 AppleObjCRuntimeV2::LookupRuntimeSymbol (const ConstString &name)
1867 {
1868     lldb::addr_t ret = LLDB_INVALID_ADDRESS;
1869
1870     const char *name_cstr = name.AsCString();    
1871     
1872     if (name_cstr)
1873     {
1874         llvm::StringRef name_strref(name_cstr);
1875         
1876         static const llvm::StringRef ivar_prefix("OBJC_IVAR_$_");
1877         static const llvm::StringRef class_prefix("OBJC_CLASS_$_");
1878         
1879         if (name_strref.startswith(ivar_prefix))
1880         {
1881             llvm::StringRef ivar_skipped_prefix = name_strref.substr(ivar_prefix.size());
1882             std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar = ivar_skipped_prefix.split('.');
1883             
1884             if (class_and_ivar.first.size() && class_and_ivar.second.size())
1885             {
1886                 const ConstString class_name_cs(class_and_ivar.first);
1887                 ClassDescriptorSP descriptor = ObjCLanguageRuntime::GetClassDescriptorFromClassName(class_name_cs);
1888                                 
1889                 if (descriptor)
1890                 {
1891                     const ConstString ivar_name_cs(class_and_ivar.second);
1892                     const char *ivar_name_cstr = ivar_name_cs.AsCString();
1893                     
1894                     auto ivar_func = [&ret, ivar_name_cstr](const char *name, const char *type, lldb::addr_t offset_addr, uint64_t size) -> lldb::addr_t
1895                     {
1896                         if (!strcmp(name, ivar_name_cstr))
1897                         {
1898                             ret = offset_addr;
1899                             return true;
1900                         }
1901                         return false;
1902                     };
1903
1904                     descriptor->Describe(std::function<void (ObjCISA)>(nullptr),
1905                                          std::function<bool (const char *, const char *)>(nullptr),
1906                                          std::function<bool (const char *, const char *)>(nullptr),
1907                                          ivar_func);
1908                 }
1909             }
1910         }
1911         else if (name_strref.startswith(class_prefix))
1912         {
1913             llvm::StringRef class_skipped_prefix = name_strref.substr(class_prefix.size());
1914             const ConstString class_name_cs(class_skipped_prefix);
1915             ClassDescriptorSP descriptor = GetClassDescriptorFromClassName(class_name_cs);
1916             
1917             if (descriptor)
1918                 ret = descriptor->GetISA();
1919         }
1920     }
1921     
1922     return ret;
1923 }
1924
1925 AppleObjCRuntimeV2::NonPointerISACache*
1926 AppleObjCRuntimeV2::NonPointerISACache::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
1927 {
1928     Process* process(runtime.GetProcess());
1929     
1930     Error error;
1931     
1932     auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol(process,
1933                                                                 ConstString("objc_debug_isa_magic_mask"),
1934                                                                 objc_module_sp,
1935                                                                 error);
1936     if (error.Fail())
1937         return NULL;
1938
1939     auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol(process,
1940                                                                  ConstString("objc_debug_isa_magic_value"),
1941                                                                  objc_module_sp,
1942                                                                  error);
1943     if (error.Fail())
1944         return NULL;
1945
1946     auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol(process,
1947                                                                 ConstString("objc_debug_isa_class_mask"),
1948                                                                 objc_module_sp,
1949                                                                 error);
1950     if (error.Fail())
1951         return NULL;
1952
1953     // we might want to have some rules to outlaw these other values (e.g if the mask is zero but the value is non-zero, ...)
1954     
1955     return new NonPointerISACache(runtime,
1956                                   objc_debug_isa_class_mask,
1957                                   objc_debug_isa_magic_mask,
1958                                   objc_debug_isa_magic_value);
1959 }
1960
1961 AppleObjCRuntimeV2::TaggedPointerVendorV2*
1962 AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
1963 {
1964     Process* process(runtime.GetProcess());
1965     
1966     Error error;
1967     
1968     auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol(process,
1969                                                                     ConstString("objc_debug_taggedpointer_mask"),
1970                                                                     objc_module_sp,
1971                                                                     error);
1972     if (error.Fail())
1973         return new TaggedPointerVendorLegacy(runtime);
1974     
1975     auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol(process,
1976                                                                           ConstString("objc_debug_taggedpointer_slot_shift"),
1977                                                                           objc_module_sp,
1978                                                                           error,
1979                                                                           true,
1980                                                                           4);
1981     if (error.Fail())
1982         return new TaggedPointerVendorLegacy(runtime);
1983     
1984     auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol(process,
1985                                                                           ConstString("objc_debug_taggedpointer_slot_mask"),
1986                                                                           objc_module_sp,
1987                                                                           error,
1988                                                                           true,
1989                                                                           4);
1990     if (error.Fail())
1991         return new TaggedPointerVendorLegacy(runtime);
1992
1993     auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol(process,
1994                                                                               ConstString("objc_debug_taggedpointer_payload_lshift"),
1995                                                                               objc_module_sp,
1996                                                                               error,
1997                                                                               true,
1998                                                                               4);
1999     if (error.Fail())
2000         return new TaggedPointerVendorLegacy(runtime);
2001     
2002     auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol(process,
2003                                                                               ConstString("objc_debug_taggedpointer_payload_rshift"),
2004                                                                               objc_module_sp,
2005                                                                               error,
2006                                                                               true,
2007                                                                               4);
2008     if (error.Fail())
2009         return new TaggedPointerVendorLegacy(runtime);
2010     
2011     auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol(process,
2012                                                                        ConstString("objc_debug_taggedpointer_classes"),
2013                                                                        objc_module_sp,
2014                                                                        error,
2015                                                                        false);
2016     if (error.Fail())
2017         return new TaggedPointerVendorLegacy(runtime);
2018
2019     
2020     // we might want to have some rules to outlaw these values (e.g if the table's address is zero)
2021     
2022     return new TaggedPointerVendorRuntimeAssisted(runtime,
2023                                                   objc_debug_taggedpointer_mask,
2024                                                   objc_debug_taggedpointer_slot_shift,
2025                                                   objc_debug_taggedpointer_slot_mask,
2026                                                   objc_debug_taggedpointer_payload_lshift,
2027                                                   objc_debug_taggedpointer_payload_rshift,
2028                                                   objc_debug_taggedpointer_classes);
2029 }
2030
2031 bool
2032 AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer (lldb::addr_t ptr)
2033 {
2034     return (ptr & 1);
2035 }
2036
2037 ObjCLanguageRuntime::ClassDescriptorSP
2038 AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor (lldb::addr_t ptr)
2039 {
2040     if (!IsPossibleTaggedPointer(ptr))
2041         return ObjCLanguageRuntime::ClassDescriptorSP();
2042
2043     uint32_t foundation_version = m_runtime.GetFoundationVersion();
2044     
2045     if (foundation_version == LLDB_INVALID_MODULE_VERSION)
2046         return ObjCLanguageRuntime::ClassDescriptorSP();
2047     
2048     uint64_t class_bits = (ptr & 0xE) >> 1;
2049     ConstString name;
2050     
2051     // TODO: make a table
2052     if (foundation_version >= 900)
2053     {
2054         switch (class_bits)
2055         {
2056             case 0:
2057                 name = ConstString("NSAtom");
2058                 break;
2059             case 3:
2060                 name = ConstString("NSNumber");
2061                 break;
2062             case 4:
2063                 name = ConstString("NSDateTS");
2064                 break;
2065             case 5:
2066                 name = ConstString("NSManagedObject");
2067                 break;
2068             case 6:
2069                 name = ConstString("NSDate");
2070                 break;
2071             default:
2072                 return ObjCLanguageRuntime::ClassDescriptorSP();
2073         }
2074     }
2075     else
2076     {
2077         switch (class_bits)
2078         {
2079             case 1:
2080                 name = ConstString("NSNumber");
2081                 break;
2082             case 5:
2083                 name = ConstString("NSManagedObject");
2084                 break;
2085             case 6:
2086                 name = ConstString("NSDate");
2087                 break;
2088             case 7:
2089                 name = ConstString("NSDateTS");
2090                 break;
2091             default:
2092                 return ObjCLanguageRuntime::ClassDescriptorSP();
2093         }
2094     }
2095     return ClassDescriptorSP(new ClassDescriptorV2Tagged(name,ptr));
2096 }
2097
2098 AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::TaggedPointerVendorRuntimeAssisted (AppleObjCRuntimeV2& runtime,
2099                                                                                             uint64_t objc_debug_taggedpointer_mask,
2100                                                                                             uint32_t objc_debug_taggedpointer_slot_shift,
2101                                                                                             uint32_t objc_debug_taggedpointer_slot_mask,
2102                                                                                             uint32_t objc_debug_taggedpointer_payload_lshift,
2103                                                                                             uint32_t objc_debug_taggedpointer_payload_rshift,
2104                                                                                             lldb::addr_t objc_debug_taggedpointer_classes) :
2105 TaggedPointerVendorV2(runtime),
2106 m_cache(),
2107 m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask),
2108 m_objc_debug_taggedpointer_slot_shift(objc_debug_taggedpointer_slot_shift),
2109 m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask),
2110 m_objc_debug_taggedpointer_payload_lshift(objc_debug_taggedpointer_payload_lshift),
2111 m_objc_debug_taggedpointer_payload_rshift(objc_debug_taggedpointer_payload_rshift),
2112 m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes)
2113 {
2114 }
2115
2116 bool
2117 AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::IsPossibleTaggedPointer (lldb::addr_t ptr)
2118 {
2119     return (ptr & m_objc_debug_taggedpointer_mask) != 0;
2120 }
2121
2122 ObjCLanguageRuntime::ClassDescriptorSP
2123 AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor (lldb::addr_t ptr)
2124 {
2125     ClassDescriptorSP actual_class_descriptor_sp;
2126     uint64_t data_payload;
2127
2128     if (!IsPossibleTaggedPointer(ptr))
2129         return ObjCLanguageRuntime::ClassDescriptorSP();
2130     
2131     uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) & m_objc_debug_taggedpointer_slot_mask;
2132     
2133     CacheIterator iterator = m_cache.find(slot),
2134     end = m_cache.end();
2135     if (iterator != end)
2136     {
2137         actual_class_descriptor_sp = iterator->second;
2138     }
2139     else
2140     {
2141         Process* process(m_runtime.GetProcess());
2142         uintptr_t slot_ptr = slot*process->GetAddressByteSize()+m_objc_debug_taggedpointer_classes;
2143         Error error;
2144         uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
2145         if (error.Fail() || slot_data == 0 || slot_data == uintptr_t(LLDB_INVALID_ADDRESS))
2146             return nullptr;
2147         actual_class_descriptor_sp = m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data);
2148         if (!actual_class_descriptor_sp)
2149             return ObjCLanguageRuntime::ClassDescriptorSP();
2150         m_cache[slot] = actual_class_descriptor_sp;
2151     }
2152     
2153     data_payload = (((uint64_t)ptr << m_objc_debug_taggedpointer_payload_lshift) >> m_objc_debug_taggedpointer_payload_rshift);
2154     
2155     return ClassDescriptorSP(new ClassDescriptorV2Tagged(actual_class_descriptor_sp,data_payload));
2156 }
2157
2158 AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache (AppleObjCRuntimeV2& runtime,
2159                                                             uint64_t objc_debug_isa_class_mask,
2160                                                             uint64_t objc_debug_isa_magic_mask,
2161                                                             uint64_t objc_debug_isa_magic_value) :
2162 m_runtime(runtime),
2163 m_cache(),
2164 m_objc_debug_isa_class_mask(objc_debug_isa_class_mask),
2165 m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask),
2166 m_objc_debug_isa_magic_value(objc_debug_isa_magic_value)
2167 {
2168 }
2169
2170 ObjCLanguageRuntime::ClassDescriptorSP
2171 AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor (ObjCISA isa)
2172 {
2173     ObjCISA real_isa = 0;
2174     if (EvaluateNonPointerISA(isa, real_isa) == false)
2175         return ObjCLanguageRuntime::ClassDescriptorSP();
2176     auto cache_iter = m_cache.find(real_isa);
2177     if (cache_iter != m_cache.end())
2178         return cache_iter->second;
2179     auto descriptor_sp = m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa);
2180     if (descriptor_sp) // cache only positive matches since the table might grow
2181         m_cache[real_isa] = descriptor_sp;
2182     return descriptor_sp;
2183 }
2184
2185 bool
2186 AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA (ObjCISA isa, ObjCISA& ret_isa)
2187 {
2188     if ( (isa & ~m_objc_debug_isa_class_mask) == 0)
2189         return false;
2190     if ( (isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value)
2191     {
2192         ret_isa = isa & m_objc_debug_isa_class_mask;
2193         return (ret_isa != 0); // this is a pointer so 0 is not a valid value
2194     }
2195     return false;
2196 }
2197
2198 ObjCLanguageRuntime::EncodingToTypeSP
2199 AppleObjCRuntimeV2::GetEncodingToType ()
2200 {
2201     if (!m_encoding_to_type_sp)
2202         m_encoding_to_type_sp.reset(new AppleObjCTypeEncodingParser(*this));
2203     return m_encoding_to_type_sp;
2204 }
2205
2206 lldb_private::AppleObjCRuntime::ObjCISA
2207 AppleObjCRuntimeV2::GetPointerISA (ObjCISA isa)
2208 {
2209     ObjCISA ret = isa;
2210     
2211     if (m_non_pointer_isa_cache_ap)
2212         m_non_pointer_isa_cache_ap->EvaluateNonPointerISA(isa, ret);
2213     
2214     return ret;
2215 }