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