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