//===-- AppleObjCRuntimeV2.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <stdint.h>

#include <memory>
#include <string>
#include <vector>

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"

#include "lldb/Host/OptionParser.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/lldb-enumerations.h"

#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionValueBoolean.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"

#include "AppleObjCClassDescriptorV2.h"
#include "AppleObjCDeclVendor.h"
#include "AppleObjCRuntimeV2.h"
#include "AppleObjCTrampolineHandler.h"
#include "AppleObjCTypeEncodingParser.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/TargetInfo.h"

#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"

#include <vector>

using namespace lldb;
using namespace lldb_private;

char AppleObjCRuntimeV2::ID = 0;

static const char *g_get_dynamic_class_info_name =
    "__lldb_apple_objc_v2_get_dynamic_class_info";

static const char *g_get_dynamic_class_info_body = R"(

extern "C"
{
    size_t strlen(const char *);
    char *strncpy (char * s1, const char * s2, size_t n);
    int printf(const char * format, ...);
}
#define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__)

typedef struct _NXMapTable {
    void *prototype;
    unsigned num_classes;
    unsigned num_buckets_minus_one;
    void *buckets;
} NXMapTable;

#define NX_MAPNOTAKEY   ((void *)(-1))

typedef struct BucketInfo
{
    const char *name_ptr;
    Class isa;
} BucketInfo;

struct ClassInfo
{
    Class isa;
    uint32_t hash;
} __attribute__((__packed__));

uint32_t
__lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr,
                                             void *class_infos_ptr,
                                             uint32_t class_infos_byte_size,
                                             uint32_t should_log)
{
    DEBUG_PRINTF ("gdb_objc_realized_classes_ptr = %p\n", gdb_objc_realized_classes_ptr);
    DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
    DEBUG_PRINTF ("class_infos_byte_size = %u\n", class_infos_byte_size);
    const NXMapTable *grc = (const NXMapTable *)gdb_objc_realized_classes_ptr;
    if (grc)
    {
        const unsigned num_classes = grc->num_classes;
        DEBUG_PRINTF ("num_classes = %u\n", grc->num_classes);
        if (class_infos_ptr)
        {
            const unsigned num_buckets_minus_one = grc->num_buckets_minus_one;
            DEBUG_PRINTF ("num_buckets_minus_one = %u\n", num_buckets_minus_one);

            const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
            DEBUG_PRINTF ("max_class_infos = %u\n", max_class_infos);

            ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
            BucketInfo *buckets = (BucketInfo *)grc->buckets;

            uint32_t idx = 0;
            for (unsigned i=0; i<=num_buckets_minus_one; ++i)
            {
                if (buckets[i].name_ptr != NX_MAPNOTAKEY)
                {
                    if (idx < max_class_infos)
                    {
                        const char *s = buckets[i].name_ptr;
                        uint32_t h = 5381;
                        for (unsigned char c = *s; c; c = *++s)
                            h = ((h << 5) + h) + c;
                        class_infos[idx].hash = h;
                        class_infos[idx].isa = buckets[i].isa;
                        DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, buckets[i].name_ptr);
                    }
                    ++idx;
                }
            }
            if (idx < max_class_infos)
            {
                class_infos[idx].isa = NULL;
                class_infos[idx].hash = 0;
            }
        }
        return num_classes;
    }
    return 0;
}

)";

// We'll substitute in class_getName or class_getNameRaw depending
// on which is present.
static const char *g_shared_cache_class_name_funcptr = R"(
extern "C"
{
    const char *%s(void *objc_class);
    const char *(*class_name_lookup_func)(void *) = %s;
}
)";

static const char *g_get_shared_cache_class_info_name =
    "__lldb_apple_objc_v2_get_shared_cache_class_info";

static const char *g_get_shared_cache_class_info_body = R"(

extern "C"
{
    size_t strlen(const char *);
    char *strncpy (char * s1, const char * s2, size_t n);
    int printf(const char * format, ...);
}

#define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__)


struct objc_classheader_t {
    int32_t clsOffset;
    int32_t hiOffset;
};

struct objc_clsopt_t {
    uint32_t capacity;
    uint32_t occupied;
    uint32_t shift;
    uint32_t mask;
    uint32_t zero;
    uint32_t unused;
    uint64_t salt;
    uint32_t scramble[256];
    uint8_t tab[0]; // tab[mask+1]
    //  uint8_t checkbytes[capacity];
    //  int32_t offset[capacity];
    //  objc_classheader_t clsOffsets[capacity];
    //  uint32_t duplicateCount;
    //  objc_classheader_t duplicateOffsets[duplicateCount];
};

struct objc_opt_t {
    uint32_t version;
    int32_t selopt_offset;
    int32_t headeropt_offset;
    int32_t clsopt_offset;
};

struct objc_opt_v14_t {
    uint32_t version;
    uint32_t flags;
    int32_t selopt_offset;
    int32_t headeropt_offset;
    int32_t clsopt_offset;
};

struct ClassInfo
{
    Class isa;
    uint32_t hash;
}  __attribute__((__packed__));

uint32_t
__lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
                                                  void *class_infos_ptr,
                                                  uint32_t class_infos_byte_size,
                                                  uint32_t should_log)
{
    uint32_t idx = 0;
    DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr);
    DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
    DEBUG_PRINTF ("class_infos_byte_size = %u (%llu class infos)\n", class_infos_byte_size, (uint64_t)(class_infos_byte_size/sizeof(ClassInfo)));
    if (objc_opt_ro_ptr)
    {
        const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr;
        const objc_opt_v14_t* objc_opt_v14 = (objc_opt_v14_t*)objc_opt_ro_ptr;
        if (objc_opt->version >= 14)
        {
            DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v14->version);
            DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v14->flags);
            DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt_v14->selopt_offset);
            DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt_v14->headeropt_offset);
            DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt_v14->clsopt_offset);
        }
        else
        {
            DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt->version);
            DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt->selopt_offset);
            DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset);
            DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset);
        }
        if (objc_opt->version == 12 || objc_opt->version == 13 || objc_opt->version == 14 || objc_opt->version == 15)
        {
            const objc_clsopt_t* clsopt = NULL;
            if (objc_opt->version >= 14)
                clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt_v14 + objc_opt_v14->clsopt_offset);
            else
                clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt + objc_opt->clsopt_offset);
            const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
            DEBUG_PRINTF("max_class_infos = %llu\n", (uint64_t)max_class_infos);
            ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
            int32_t invalidEntryOffset = 0;
            // this is safe to do because the version field order is invariant
            if (objc_opt->version == 12)
                invalidEntryOffset = 16;
            const uint8_t *checkbytes = &clsopt->tab[clsopt->mask+1];
            const int32_t *offsets = (const int32_t *)(checkbytes + clsopt->capacity);
            const objc_classheader_t *classOffsets = (const objc_classheader_t *)(offsets + clsopt->capacity);
            DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity);
            DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask);
            DEBUG_PRINTF ("classOffsets = %p\n", classOffsets);
            DEBUG_PRINTF("invalidEntryOffset = %d\n", invalidEntryOffset);
            for (uint32_t i=0; i<clsopt->capacity; ++i)
            {
                const int32_t clsOffset = classOffsets[i].clsOffset;
                DEBUG_PRINTF("clsOffset[%u] = %u\n", i, clsOffset);
                if (clsOffset & 1)
                {
                    DEBUG_PRINTF("clsOffset & 1\n");
                    continue; // duplicate
                }
                else if (clsOffset == invalidEntryOffset)
                {
                    DEBUG_PRINTF("clsOffset == invalidEntryOffset\n");
                    continue; // invalid offset
                }

                if (class_infos && idx < max_class_infos)
                {
                    class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
                    const char *name = class_name_lookup_func (class_infos[idx].isa);
                    DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
                    // Hash the class name so we don't have to read it
                    const char *s = name;
                    uint32_t h = 5381;
                    for (unsigned char c = *s; c; c = *++s)
                    {
                        // class_getName demangles swift names and the hash must
                        // be calculated on the mangled name.  hash==0 means lldb
                        // will fetch the mangled name and compute the hash in
                        // ParseClassInfoArray.
                        if (c == '.')
                        {
                            h = 0;
                            break;
                        }
                        h = ((h << 5) + h) + c;
                    }
                    class_infos[idx].hash = h;
                }
                else
                {
                    DEBUG_PRINTF("not(class_infos && idx < max_class_infos)\n");
                }
                ++idx;
            }

            const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
            const uint32_t duplicate_count = *duplicate_count_ptr;
            const objc_classheader_t *duplicateClassOffsets = (const objc_classheader_t *)(&duplicate_count_ptr[1]);
            DEBUG_PRINTF ("duplicate_count = %u\n", duplicate_count);
            DEBUG_PRINTF ("duplicateClassOffsets = %p\n", duplicateClassOffsets);
            for (uint32_t i=0; i<duplicate_count; ++i)
            {
                const int32_t clsOffset = duplicateClassOffsets[i].clsOffset;
                if (clsOffset & 1)
                    continue; // duplicate
                else if (clsOffset == invalidEntryOffset)
                    continue; // invalid offset

                if (class_infos && idx < max_class_infos)
                {
                    class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
                    const char *name = class_name_lookup_func (class_infos[idx].isa);
                    DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
                    // Hash the class name so we don't have to read it
                    const char *s = name;
                    uint32_t h = 5381;
                    for (unsigned char c = *s; c; c = *++s)
                    {
                        // class_getName demangles swift names and the hash must
                        // be calculated on the mangled name.  hash==0 means lldb
                        // will fetch the mangled name and compute the hash in
                        // ParseClassInfoArray.
                        if (c == '.')
                        {
                            h = 0;
                            break;
                        }
                        h = ((h << 5) + h) + c;
                    }
                    class_infos[idx].hash = h;
                }
                ++idx;
            }
        }
        DEBUG_PRINTF ("%u class_infos\n", idx);
        DEBUG_PRINTF ("done\n");
    }
    return idx;
}


)";

static uint64_t
ExtractRuntimeGlobalSymbol(Process *process, ConstString name,
                           const ModuleSP &module_sp, Status &error,
                           bool read_value = true, uint8_t byte_size = 0,
                           uint64_t default_value = LLDB_INVALID_ADDRESS,
                           SymbolType sym_type = lldb::eSymbolTypeData) {
  if (!process) {
    error.SetErrorString("no process");
    return default_value;
  }
  if (!module_sp) {
    error.SetErrorString("no module");
    return default_value;
  }
  if (!byte_size)
    byte_size = process->GetAddressByteSize();
  const Symbol *symbol =
      module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData);
  if (symbol && symbol->ValueIsAddress()) {
    lldb::addr_t symbol_load_addr =
        symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());
    if (symbol_load_addr != LLDB_INVALID_ADDRESS) {
      if (read_value)
        return process->ReadUnsignedIntegerFromMemory(
            symbol_load_addr, byte_size, default_value, error);
      return symbol_load_addr;
    } else {
      error.SetErrorString("symbol address invalid");
      return default_value;
    }
  } else {
    error.SetErrorString("no symbol");
    return default_value;
  }
}

static void RegisterObjCExceptionRecognizer(Process *process);

AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process,
                                       const ModuleSP &objc_module_sp)
    : AppleObjCRuntime(process), m_get_class_info_code(),
      m_get_class_info_args(LLDB_INVALID_ADDRESS),
      m_get_class_info_args_mutex(), m_get_shared_cache_class_info_code(),
      m_get_shared_cache_class_info_args(LLDB_INVALID_ADDRESS),
      m_get_shared_cache_class_info_args_mutex(), m_decl_vendor_up(),
      m_tagged_pointer_obfuscator(LLDB_INVALID_ADDRESS),
      m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS), m_hash_signature(),
      m_has_object_getClass(false), m_loaded_objc_opt(false),
      m_non_pointer_isa_cache_up(
          NonPointerISACache::CreateInstance(*this, objc_module_sp)),
      m_tagged_pointer_vendor_up(
          TaggedPointerVendorV2::CreateInstance(*this, objc_module_sp)),
      m_encoding_to_type_sp(), m_noclasses_warning_emitted(false),
      m_CFBoolean_values() {
  static const ConstString g_gdb_object_getClass("gdb_object_getClass");
  m_has_object_getClass =
      (objc_module_sp->FindFirstSymbolWithNameAndType(
           g_gdb_object_getClass, eSymbolTypeCode) != nullptr);
  RegisterObjCExceptionRecognizer(process);
}

bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress(
    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
    TypeAndOrName &class_type_or_name, Address &address,
    Value::ValueType &value_type) {
  // We should never get here with a null process...
  assert(m_process != nullptr);

  // The Runtime is attached to a particular process, you shouldn't pass in a
  // value from another process. Note, however, the process might be NULL (e.g.
  // if the value was made with SBTarget::EvaluateExpression...) in which case
  // it is sufficient if the target's match:

  Process *process = in_value.GetProcessSP().get();
  if (process)
    assert(process == m_process);
  else
    assert(in_value.GetTargetSP().get() == m_process->CalculateTarget().get());

  class_type_or_name.Clear();
  value_type = Value::ValueType::Scalar;

  // Make sure we can have a dynamic value before starting...
  if (CouldHaveDynamicValue(in_value)) {
    // First job, pull out the address at 0 offset from the object  That will
    // be the ISA pointer.
    ClassDescriptorSP objc_class_sp(GetNonKVOClassDescriptor(in_value));
    if (objc_class_sp) {
      const addr_t object_ptr = in_value.GetPointerValue();
      address.SetRawAddress(object_ptr);

      ConstString class_name(objc_class_sp->GetClassName());
      class_type_or_name.SetName(class_name);
      TypeSP type_sp(objc_class_sp->GetType());
      if (type_sp)
        class_type_or_name.SetTypeSP(type_sp);
      else {
        type_sp = LookupInCompleteClassCache(class_name);
        if (type_sp) {
          objc_class_sp->SetType(type_sp);
          class_type_or_name.SetTypeSP(type_sp);
        } else {
          // try to go for a CompilerType at least
          if (auto *vendor = GetDeclVendor()) {
            auto types = vendor->FindTypes(class_name, /*max_matches*/ 1);
            if (!types.empty())
              class_type_or_name.SetCompilerType(types.front());
          }
        }
      }
    }
  }
  return !class_type_or_name.IsEmpty();
}

// Static Functions
LanguageRuntime *AppleObjCRuntimeV2::CreateInstance(Process *process,
                                                    LanguageType language) {
  // FIXME: This should be a MacOS or iOS process, and we need to look for the
  // OBJC section to make
  // sure we aren't using the V1 runtime.
  if (language == eLanguageTypeObjC) {
    ModuleSP objc_module_sp;

    if (AppleObjCRuntime::GetObjCVersion(process, objc_module_sp) ==
        ObjCRuntimeVersions::eAppleObjC_V2)
      return new AppleObjCRuntimeV2(process, objc_module_sp);
    return nullptr;
  } else
    return nullptr;
}

static constexpr OptionDefinition g_objc_classtable_dump_options[] = {
    {LLDB_OPT_SET_ALL,
     false,
     "verbose",
     'v',
     OptionParser::eNoArgument,
     nullptr,
     {},
     0,
     eArgTypeNone,
     "Print ivar and method information in detail"}};

class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() : Options(), m_verbose(false, false) {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;
      switch (short_option) {
      case 'v':
        m_verbose.SetCurrentValue(true);
        m_verbose.SetOptionWasSet();
        break;

      default:
        error.SetErrorStringWithFormat("unrecognized short option '%c'",
                                       short_option);
        break;
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_verbose.Clear();
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_objc_classtable_dump_options);
    }

    OptionValueBoolean m_verbose;
  };

  CommandObjectObjC_ClassTable_Dump(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "dump",
                            "Dump information on Objective-C classes "
                            "known to the current process.",
                            "language objc class-table dump",
                            eCommandRequiresProcess |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused),
        m_options() {
    CommandArgumentEntry arg;
    CommandArgumentData index_arg;

    // Define the first (and only) variant of this arg.
    index_arg.arg_type = eArgTypeRegularExpression;
    index_arg.arg_repetition = eArgRepeatOptional;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg.push_back(index_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg);
  }

  ~CommandObjectObjC_ClassTable_Dump() override = default;

  Options *GetOptions() override { return &m_options; }

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    std::unique_ptr<RegularExpression> regex_up;
    switch (command.GetArgumentCount()) {
    case 0:
      break;
    case 1: {
      regex_up = std::make_unique<RegularExpression>(
          llvm::StringRef::withNullAsEmpty(command.GetArgumentAtIndex(0)));
      if (!regex_up->IsValid()) {
        result.AppendError(
            "invalid argument - please provide a valid regular expression");
        result.SetStatus(lldb::eReturnStatusFailed);
        return false;
      }
      break;
    }
    default: {
      result.AppendError("please provide 0 or 1 arguments");
      result.SetStatus(lldb::eReturnStatusFailed);
      return false;
    }
    }

    Process *process = m_exe_ctx.GetProcessPtr();
    ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process);
    if (objc_runtime) {
      auto iterators_pair = objc_runtime->GetDescriptorIteratorPair();
      auto iterator = iterators_pair.first;
      auto &std_out = result.GetOutputStream();
      for (; iterator != iterators_pair.second; iterator++) {
        if (iterator->second) {
          const char *class_name =
              iterator->second->GetClassName().AsCString("<unknown>");
          if (regex_up && class_name &&
              !regex_up->Execute(llvm::StringRef(class_name)))
            continue;
          std_out.Printf("isa = 0x%" PRIx64, iterator->first);
          std_out.Printf(" name = %s", class_name);
          std_out.Printf(" instance size = %" PRIu64,
                         iterator->second->GetInstanceSize());
          std_out.Printf(" num ivars = %" PRIuPTR,
                         (uintptr_t)iterator->second->GetNumIVars());
          if (auto superclass = iterator->second->GetSuperclass()) {
            std_out.Printf(" superclass = %s",
                           superclass->GetClassName().AsCString("<unknown>"));
          }
          std_out.Printf("\n");
          if (m_options.m_verbose) {
            for (size_t i = 0; i < iterator->second->GetNumIVars(); i++) {
              auto ivar = iterator->second->GetIVarAtIndex(i);
              std_out.Printf(
                  "  ivar name = %s type = %s size = %" PRIu64
                  " offset = %" PRId32 "\n",
                  ivar.m_name.AsCString("<unknown>"),
                  ivar.m_type.GetDisplayTypeName().AsCString("<unknown>"),
                  ivar.m_size, ivar.m_offset);
            }
            iterator->second->Describe(
                nullptr,
                [&std_out](const char *name, const char *type) -> bool {
                  std_out.Printf("  instance method name = %s type = %s\n",
                                 name, type);
                  return false;
                },
                [&std_out](const char *name, const char *type) -> bool {
                  std_out.Printf("  class method name = %s type = %s\n", name,
                                 type);
                  return false;
                },
                nullptr);
          }
        } else {
          if (regex_up && !regex_up->Execute(llvm::StringRef()))
            continue;
          std_out.Printf("isa = 0x%" PRIx64 " has no associated class.\n",
                         iterator->first);
        }
      }
      result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
      return true;
    }
    result.AppendError("current process has no Objective-C runtime loaded");
    result.SetStatus(lldb::eReturnStatusFailed);
    return false;
  }

  CommandOptions m_options;
};

class CommandObjectMultiwordObjC_TaggedPointer_Info
    : public CommandObjectParsed {
public:
  CommandObjectMultiwordObjC_TaggedPointer_Info(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "info", "Dump information on a tagged pointer.",
            "language objc tagged-pointer info",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched |
                eCommandProcessMustBePaused) {
    CommandArgumentEntry arg;
    CommandArgumentData index_arg;

    // Define the first (and only) variant of this arg.
    index_arg.arg_type = eArgTypeAddress;
    index_arg.arg_repetition = eArgRepeatPlus;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg.push_back(index_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg);
  }

  ~CommandObjectMultiwordObjC_TaggedPointer_Info() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    if (command.GetArgumentCount() == 0) {
      result.AppendError("this command requires arguments");
      result.SetStatus(lldb::eReturnStatusFailed);
      return false;
    }

    Process *process = m_exe_ctx.GetProcessPtr();
    ExecutionContext exe_ctx(process);
    ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process);
    if (objc_runtime) {
      ObjCLanguageRuntime::TaggedPointerVendor *tagged_ptr_vendor =
          objc_runtime->GetTaggedPointerVendor();
      if (tagged_ptr_vendor) {
        for (size_t i = 0; i < command.GetArgumentCount(); i++) {
          const char *arg_str = command.GetArgumentAtIndex(i);
          if (!arg_str)
            continue;
          Status error;
          lldb::addr_t arg_addr = OptionArgParser::ToAddress(
              &exe_ctx, arg_str, LLDB_INVALID_ADDRESS, &error);
          if (arg_addr == 0 || arg_addr == LLDB_INVALID_ADDRESS || error.Fail())
            continue;
          auto descriptor_sp = tagged_ptr_vendor->GetClassDescriptor(arg_addr);
          if (!descriptor_sp)
            continue;
          uint64_t info_bits = 0;
          uint64_t value_bits = 0;
          uint64_t payload = 0;
          if (descriptor_sp->GetTaggedPointerInfo(&info_bits, &value_bits,
                                                  &payload)) {
            result.GetOutputStream().Printf(
                "0x%" PRIx64 " is tagged.\n\tpayload = 0x%" PRIx64
                "\n\tvalue = 0x%" PRIx64 "\n\tinfo bits = 0x%" PRIx64
                "\n\tclass = %s\n",
                (uint64_t)arg_addr, payload, value_bits, info_bits,
                descriptor_sp->GetClassName().AsCString("<unknown>"));
          } else {
            result.GetOutputStream().Printf("0x%" PRIx64 " is not tagged.\n",
                                            (uint64_t)arg_addr);
          }
        }
      } else {
        result.AppendError("current process has no tagged pointer support");
        result.SetStatus(lldb::eReturnStatusFailed);
        return false;
      }
      result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
      return true;
    }
    result.AppendError("current process has no Objective-C runtime loaded");
    result.SetStatus(lldb::eReturnStatusFailed);
    return false;
  }
};

class CommandObjectMultiwordObjC_ClassTable : public CommandObjectMultiword {
public:
  CommandObjectMultiwordObjC_ClassTable(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "class-table",
            "Commands for operating on the Objective-C class table.",
            "class-table <subcommand> [<subcommand-options>]") {
    LoadSubCommand(
        "dump",
        CommandObjectSP(new CommandObjectObjC_ClassTable_Dump(interpreter)));
  }

  ~CommandObjectMultiwordObjC_ClassTable() override = default;
};

class CommandObjectMultiwordObjC_TaggedPointer : public CommandObjectMultiword {
public:
  CommandObjectMultiwordObjC_TaggedPointer(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "tagged-pointer",
            "Commands for operating on Objective-C tagged pointers.",
            "class-table <subcommand> [<subcommand-options>]") {
    LoadSubCommand(
        "info",
        CommandObjectSP(
            new CommandObjectMultiwordObjC_TaggedPointer_Info(interpreter)));
  }

  ~CommandObjectMultiwordObjC_TaggedPointer() override = default;
};

class CommandObjectMultiwordObjC : public CommandObjectMultiword {
public:
  CommandObjectMultiwordObjC(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "objc",
            "Commands for operating on the Objective-C language runtime.",
            "objc <subcommand> [<subcommand-options>]") {
    LoadSubCommand("class-table",
                   CommandObjectSP(
                       new CommandObjectMultiwordObjC_ClassTable(interpreter)));
    LoadSubCommand("tagged-pointer",
                   CommandObjectSP(new CommandObjectMultiwordObjC_TaggedPointer(
                       interpreter)));
  }

  ~CommandObjectMultiwordObjC() override = default;
};

void AppleObjCRuntimeV2::Initialize() {
  PluginManager::RegisterPlugin(
      GetPluginNameStatic(), "Apple Objective-C Language Runtime - Version 2",
      CreateInstance,
      [](CommandInterpreter &interpreter) -> lldb::CommandObjectSP {
        return CommandObjectSP(new CommandObjectMultiwordObjC(interpreter));
      },
      GetBreakpointExceptionPrecondition);
}

void AppleObjCRuntimeV2::Terminate() {
  PluginManager::UnregisterPlugin(CreateInstance);
}

lldb_private::ConstString AppleObjCRuntimeV2::GetPluginNameStatic() {
  static ConstString g_name("apple-objc-v2");
  return g_name;
}

// PluginInterface protocol
lldb_private::ConstString AppleObjCRuntimeV2::GetPluginName() {
  return GetPluginNameStatic();
}

uint32_t AppleObjCRuntimeV2::GetPluginVersion() { return 1; }

BreakpointResolverSP
AppleObjCRuntimeV2::CreateExceptionResolver(const BreakpointSP &bkpt,
                                            bool catch_bp, bool throw_bp) {
  BreakpointResolverSP resolver_sp;

  if (throw_bp)
    resolver_sp = std::make_shared<BreakpointResolverName>(
        bkpt, std::get<1>(GetExceptionThrowLocation()).AsCString(),
        eFunctionNameTypeBase, eLanguageTypeUnknown, Breakpoint::Exact, 0,
        eLazyBoolNo);
  // FIXME: We don't do catch breakpoints for ObjC yet.
  // Should there be some way for the runtime to specify what it can do in this
  // regard?
  return resolver_sp;
}

llvm::Expected<std::unique_ptr<UtilityFunction>>
AppleObjCRuntimeV2::CreateObjectChecker(std::string name,
                                        ExecutionContext &exe_ctx) {
  char check_function_code[2048];

  int len = 0;
  if (m_has_object_getClass) {
    len = ::snprintf(check_function_code, sizeof(check_function_code), R"(
                     extern "C" void *gdb_object_getClass(void *);
                     extern "C" int printf(const char *format, ...);
                     extern "C" void
                     %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) {
                       if ($__lldb_arg_obj == (void *)0)
                         return; // nil is ok
                       if (!gdb_object_getClass($__lldb_arg_obj)) {
                         *((volatile int *)0) = 'ocgc';
                       } else if ($__lldb_arg_selector != (void *)0) {
                         signed char $responds = (signed char)
                             [(id)$__lldb_arg_obj respondsToSelector:
                                 (void *) $__lldb_arg_selector];
                         if ($responds == (signed char) 0)
                           *((volatile int *)0) = 'ocgc';
                       }
                     })",
                     name.c_str());
  } else {
    len = ::snprintf(check_function_code, sizeof(check_function_code), R"(
                     extern "C" void *gdb_class_getClass(void *);
                     extern "C" int printf(const char *format, ...);
                     extern "C" void
                     %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) {
                       if ($__lldb_arg_obj == (void *)0)
                         return; // nil is ok
                       void **$isa_ptr = (void **)$__lldb_arg_obj;
                       if (*$isa_ptr == (void *)0 ||
                           !gdb_class_getClass(*$isa_ptr))
                         *((volatile int *)0) = 'ocgc';
                       else if ($__lldb_arg_selector != (void *)0) {
                         signed char $responds = (signed char)
                             [(id)$__lldb_arg_obj respondsToSelector:
                                 (void *) $__lldb_arg_selector];
                         if ($responds == (signed char) 0)
                           *((volatile int *)0) = 'ocgc';
                       }
                     })",
                     name.c_str());
  }

  assert(len < (int)sizeof(check_function_code));
  UNUSED_IF_ASSERT_DISABLED(len);

  return GetTargetRef().CreateUtilityFunction(check_function_code, name,
                                              eLanguageTypeC, exe_ctx);
}

size_t AppleObjCRuntimeV2::GetByteOffsetForIvar(CompilerType &parent_ast_type,
                                                const char *ivar_name) {
  uint32_t ivar_offset = LLDB_INVALID_IVAR_OFFSET;

  ConstString class_name = parent_ast_type.GetTypeName();
  if (!class_name.IsEmpty() && ivar_name && ivar_name[0]) {
    // Make the objective C V2 mangled name for the ivar offset from the class
    // name and ivar name
    std::string buffer("OBJC_IVAR_$_");
    buffer.append(class_name.AsCString());
    buffer.push_back('.');
    buffer.append(ivar_name);
    ConstString ivar_const_str(buffer.c_str());

    // Try to get the ivar offset address from the symbol table first using the
    // name we created above
    SymbolContextList sc_list;
    Target &target = m_process->GetTarget();
    target.GetImages().FindSymbolsWithNameAndType(ivar_const_str,
                                                  eSymbolTypeObjCIVar, sc_list);

    addr_t ivar_offset_address = LLDB_INVALID_ADDRESS;

    Status error;
    SymbolContext ivar_offset_symbol;
    if (sc_list.GetSize() == 1 &&
        sc_list.GetContextAtIndex(0, ivar_offset_symbol)) {
      if (ivar_offset_symbol.symbol)
        ivar_offset_address =
            ivar_offset_symbol.symbol->GetLoadAddress(&target);
    }

    // If we didn't get the ivar offset address from the symbol table, fall
    // back to getting it from the runtime
    if (ivar_offset_address == LLDB_INVALID_ADDRESS)
      ivar_offset_address = LookupRuntimeSymbol(ivar_const_str);

    if (ivar_offset_address != LLDB_INVALID_ADDRESS)
      ivar_offset = m_process->ReadUnsignedIntegerFromMemory(
          ivar_offset_address, 4, LLDB_INVALID_IVAR_OFFSET, error);
  }
  return ivar_offset;
}

// tagged pointers are special not-a-real-pointer values that contain both type
// and value information this routine attempts to check with as little
// computational effort as possible whether something could possibly be a
// tagged pointer - false positives are possible but false negatives shouldn't
bool AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr) {
  if (!m_tagged_pointer_vendor_up)
    return false;
  return m_tagged_pointer_vendor_up->IsPossibleTaggedPointer(ptr);
}

class RemoteNXMapTable {
public:
  RemoteNXMapTable()
      : m_count(0), m_num_buckets_minus_one(0),
        m_buckets_ptr(LLDB_INVALID_ADDRESS), m_process(nullptr),
        m_end_iterator(*this, -1), m_load_addr(LLDB_INVALID_ADDRESS),
        m_map_pair_size(0), m_invalid_key(0) {}

  void Dump() {
    printf("RemoteNXMapTable.m_load_addr = 0x%" PRIx64 "\n", m_load_addr);
    printf("RemoteNXMapTable.m_count = %u\n", m_count);
    printf("RemoteNXMapTable.m_num_buckets_minus_one = %u\n",
           m_num_buckets_minus_one);
    printf("RemoteNXMapTable.m_buckets_ptr = 0x%" PRIX64 "\n", m_buckets_ptr);
  }

  bool ParseHeader(Process *process, lldb::addr_t load_addr) {
    m_process = process;
    m_load_addr = load_addr;
    m_map_pair_size = m_process->GetAddressByteSize() * 2;
    m_invalid_key =
        m_process->GetAddressByteSize() == 8 ? UINT64_MAX : UINT32_MAX;
    Status err;

    // This currently holds true for all platforms we support, but we might
    // need to change this to use get the actually byte size of "unsigned" from
    // the target AST...
    const uint32_t unsigned_byte_size = sizeof(uint32_t);
    // Skip the prototype as we don't need it (const struct
    // +NXMapTablePrototype *prototype)

    bool success = true;
    if (load_addr == LLDB_INVALID_ADDRESS)
      success = false;
    else {
      lldb::addr_t cursor = load_addr + m_process->GetAddressByteSize();

      // unsigned count;
      m_count = m_process->ReadUnsignedIntegerFromMemory(
          cursor, unsigned_byte_size, 0, err);
      if (m_count) {
        cursor += unsigned_byte_size;

        // unsigned nbBucketsMinusOne;
        m_num_buckets_minus_one = m_process->ReadUnsignedIntegerFromMemory(
            cursor, unsigned_byte_size, 0, err);
        cursor += unsigned_byte_size;

        // void *buckets;
        m_buckets_ptr = m_process->ReadPointerFromMemory(cursor, err);

        success = m_count > 0 && m_buckets_ptr != LLDB_INVALID_ADDRESS;
      }
    }

    if (!success) {
      m_count = 0;
      m_num_buckets_minus_one = 0;
      m_buckets_ptr = LLDB_INVALID_ADDRESS;
    }
    return success;
  }

  // const_iterator mimics NXMapState and its code comes from NXInitMapState
  // and NXNextMapState.
  typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA> element;

  friend class const_iterator;
  class const_iterator {
  public:
    const_iterator(RemoteNXMapTable &parent, int index)
        : m_parent(parent), m_index(index) {
      AdvanceToValidIndex();
    }

    const_iterator(const const_iterator &rhs)
        : m_parent(rhs.m_parent), m_index(rhs.m_index) {
      // AdvanceToValidIndex() has been called by rhs already.
    }

    const_iterator &operator=(const const_iterator &rhs) {
      // AdvanceToValidIndex() has been called by rhs already.
      assert(&m_parent == &rhs.m_parent);
      m_index = rhs.m_index;
      return *this;
    }

    bool operator==(const const_iterator &rhs) const {
      if (&m_parent != &rhs.m_parent)
        return false;
      if (m_index != rhs.m_index)
        return false;

      return true;
    }

    bool operator!=(const const_iterator &rhs) const {
      return !(operator==(rhs));
    }

    const_iterator &operator++() {
      AdvanceToValidIndex();
      return *this;
    }

    const element operator*() const {
      if (m_index == -1) {
        // TODO find a way to make this an error, but not an assert
        return element();
      }

      lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
      size_t map_pair_size = m_parent.m_map_pair_size;
      lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);

      Status err;

      lldb::addr_t key =
          m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
      if (!err.Success())
        return element();
      lldb::addr_t value = m_parent.m_process->ReadPointerFromMemory(
          pair_ptr + m_parent.m_process->GetAddressByteSize(), err);
      if (!err.Success())
        return element();

      std::string key_string;

      m_parent.m_process->ReadCStringFromMemory(key, key_string, err);
      if (!err.Success())
        return element();

      return element(ConstString(key_string.c_str()),
                     (ObjCLanguageRuntime::ObjCISA)value);
    }

  private:
    void AdvanceToValidIndex() {
      if (m_index == -1)
        return;

      const lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
      const size_t map_pair_size = m_parent.m_map_pair_size;
      const lldb::addr_t invalid_key = m_parent.m_invalid_key;
      Status err;

      while (m_index--) {
        lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
        lldb::addr_t key =
            m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);

        if (!err.Success()) {
          m_index = -1;
          return;
        }

        if (key != invalid_key)
          return;
      }
    }
    RemoteNXMapTable &m_parent;
    int m_index;
  };

  const_iterator begin() {
    return const_iterator(*this, m_num_buckets_minus_one + 1);
  }

  const_iterator end() { return m_end_iterator; }

  uint32_t GetCount() const { return m_count; }

  uint32_t GetBucketCount() const { return m_num_buckets_minus_one; }

  lldb::addr_t GetBucketDataPointer() const { return m_buckets_ptr; }

  lldb::addr_t GetTableLoadAddress() const { return m_load_addr; }

private:
  // contents of _NXMapTable struct
  uint32_t m_count;
  uint32_t m_num_buckets_minus_one;
  lldb::addr_t m_buckets_ptr;
  lldb_private::Process *m_process;
  const_iterator m_end_iterator;
  lldb::addr_t m_load_addr;
  size_t m_map_pair_size;
  lldb::addr_t m_invalid_key;
};

AppleObjCRuntimeV2::HashTableSignature::HashTableSignature()
    : m_count(0), m_num_buckets(0), m_buckets_ptr(0) {}

void AppleObjCRuntimeV2::HashTableSignature::UpdateSignature(
    const RemoteNXMapTable &hash_table) {
  m_count = hash_table.GetCount();
  m_num_buckets = hash_table.GetBucketCount();
  m_buckets_ptr = hash_table.GetBucketDataPointer();
}

bool AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate(
    Process *process, AppleObjCRuntimeV2 *runtime,
    RemoteNXMapTable &hash_table) {
  if (!hash_table.ParseHeader(process, runtime->GetISAHashTablePointer())) {
    return false; // Failed to parse the header, no need to update anything
  }

  // Check with out current signature and return true if the count, number of
  // buckets or the hash table address changes.
  if (m_count == hash_table.GetCount() &&
      m_num_buckets == hash_table.GetBucketCount() &&
      m_buckets_ptr == hash_table.GetBucketDataPointer()) {
    // Hash table hasn't changed
    return false;
  }
  // Hash table data has changed, we need to update
  return true;
}

ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV2::GetClassDescriptorFromISA(ObjCISA isa) {
  ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp;
  if (m_non_pointer_isa_cache_up)
    class_descriptor_sp = m_non_pointer_isa_cache_up->GetClassDescriptor(isa);
  if (!class_descriptor_sp)
    class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa);
  return class_descriptor_sp;
}

ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV2::GetClassDescriptor(ValueObject &valobj) {
  ClassDescriptorSP objc_class_sp;
  if (valobj.IsBaseClass()) {
    ValueObject *parent = valobj.GetParent();
    // if I am my own parent, bail out of here fast..
    if (parent && parent != &valobj) {
      ClassDescriptorSP parent_descriptor_sp = GetClassDescriptor(*parent);
      if (parent_descriptor_sp)
        return parent_descriptor_sp->GetSuperclass();
    }
    return nullptr;
  }
  // if we get an invalid VO (which might still happen when playing around with
  // pointers returned by the expression parser, don't consider this a valid
  // ObjC object)
  if (!valobj.GetCompilerType().IsValid())
    return objc_class_sp;
  addr_t isa_pointer = valobj.GetPointerValue();

  // tagged pointer
  if (IsTaggedPointer(isa_pointer))
    return m_tagged_pointer_vendor_up->GetClassDescriptor(isa_pointer);
  ExecutionContext exe_ctx(valobj.GetExecutionContextRef());

  Process *process = exe_ctx.GetProcessPtr();
  if (!process)
    return objc_class_sp;

  Status error;
  ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
  if (isa == LLDB_INVALID_ADDRESS)
    return objc_class_sp;

  objc_class_sp = GetClassDescriptorFromISA(isa);
  if (isa && !objc_class_sp) {
    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
    LLDB_LOGF(log,
              "0x%" PRIx64 ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was "
              "not in class descriptor cache 0x%" PRIx64,
              isa_pointer, isa);
  }
  return objc_class_sp;
}

lldb::addr_t AppleObjCRuntimeV2::GetTaggedPointerObfuscator() {
  if (m_tagged_pointer_obfuscator != LLDB_INVALID_ADDRESS)
    return m_tagged_pointer_obfuscator;

  Process *process = GetProcess();
  ModuleSP objc_module_sp(GetObjCModule());

  if (!objc_module_sp)
    return LLDB_INVALID_ADDRESS;

  static ConstString g_gdb_objc_obfuscator(
      "objc_debug_taggedpointer_obfuscator");

  const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
      g_gdb_objc_obfuscator, lldb::eSymbolTypeAny);
  if (symbol) {
    lldb::addr_t g_gdb_obj_obfuscator_ptr =
        symbol->GetLoadAddress(&process->GetTarget());

    if (g_gdb_obj_obfuscator_ptr != LLDB_INVALID_ADDRESS) {
      Status error;
      m_tagged_pointer_obfuscator =
          process->ReadPointerFromMemory(g_gdb_obj_obfuscator_ptr, error);
    }
  }
  // If we don't have a correct value at this point, there must be no
  // obfuscation.
  if (m_tagged_pointer_obfuscator == LLDB_INVALID_ADDRESS)
    m_tagged_pointer_obfuscator = 0;

  return m_tagged_pointer_obfuscator;
}

lldb::addr_t AppleObjCRuntimeV2::GetISAHashTablePointer() {
  if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS) {
    Process *process = GetProcess();

    ModuleSP objc_module_sp(GetObjCModule());

    if (!objc_module_sp)
      return LLDB_INVALID_ADDRESS;

    static ConstString g_gdb_objc_realized_classes("gdb_objc_realized_classes");

    const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
        g_gdb_objc_realized_classes, lldb::eSymbolTypeAny);
    if (symbol) {
      lldb::addr_t gdb_objc_realized_classes_ptr =
          symbol->GetLoadAddress(&process->GetTarget());

      if (gdb_objc_realized_classes_ptr != LLDB_INVALID_ADDRESS) {
        Status error;
        m_isa_hash_table_ptr = process->ReadPointerFromMemory(
            gdb_objc_realized_classes_ptr, error);
      }
    }
  }
  return m_isa_hash_table_ptr;
}

AppleObjCRuntimeV2::DescriptorMapUpdateResult
AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
    RemoteNXMapTable &hash_table) {
  Process *process = GetProcess();

  if (process == nullptr)
    return DescriptorMapUpdateResult::Fail();

  uint32_t num_class_infos = 0;

  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));

  ExecutionContext exe_ctx;

  ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();

  if (!thread_sp)
    return DescriptorMapUpdateResult::Fail();

  thread_sp->CalculateExecutionContext(exe_ctx);
  TypeSystemClang *ast =
      ScratchTypeSystemClang::GetForTarget(process->GetTarget());

  if (!ast)
    return DescriptorMapUpdateResult::Fail();

  Address function_address;

  const uint32_t addr_size = process->GetAddressByteSize();

  Status err;

  // Read the total number of classes from the hash table
  const uint32_t num_classes = hash_table.GetCount();
  if (num_classes == 0) {
    LLDB_LOGF(log, "No dynamic classes found in gdb_objc_realized_classes.");
    return DescriptorMapUpdateResult::Success(0);
  }

  // Make some types for our arguments
  CompilerType clang_uint32_t_type =
      ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
  CompilerType clang_void_pointer_type =
      ast->GetBasicType(eBasicTypeVoid).GetPointerType();

  ValueList arguments;
  FunctionCaller *get_class_info_function = nullptr;

  if (!m_get_class_info_code) {
    auto utility_fn_or_error = GetTargetRef().CreateUtilityFunction(
        g_get_dynamic_class_info_body, g_get_dynamic_class_info_name,
        eLanguageTypeC, exe_ctx);
    if (!utility_fn_or_error) {
      LLDB_LOG_ERROR(
          log, utility_fn_or_error.takeError(),
          "Failed to get utility function for implementation lookup: {0}");
      return DescriptorMapUpdateResult::Fail();
    }
    m_get_class_info_code = std::move(*utility_fn_or_error);

    // Next make the runner function for our implementation utility function.
    Value value;
    value.SetValueType(Value::ValueType::Scalar);
    value.SetCompilerType(clang_void_pointer_type);
    arguments.PushValue(value);
    arguments.PushValue(value);

    value.SetValueType(Value::ValueType::Scalar);
    value.SetCompilerType(clang_uint32_t_type);
    arguments.PushValue(value);
    arguments.PushValue(value);

    Status error;
    get_class_info_function = m_get_class_info_code->MakeFunctionCaller(
        clang_uint32_t_type, arguments, thread_sp, error);

    if (error.Fail()) {
      LLDB_LOGF(log,
                "Failed to make function caller for implementation lookup: %s.",
                error.AsCString());
      return DescriptorMapUpdateResult::Fail();
    }
  } else {
    get_class_info_function = m_get_class_info_code->GetFunctionCaller();
    if (!get_class_info_function) {
      LLDB_LOGF(log, "Failed to get implementation lookup function caller.");
      return DescriptorMapUpdateResult::Fail();
    }
    arguments = get_class_info_function->GetArgumentValues();
  }

  DiagnosticManager diagnostics;

  const uint32_t class_info_byte_size = addr_size + 4;
  const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
  lldb::addr_t class_infos_addr = process->AllocateMemory(
      class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err);

  if (class_infos_addr == LLDB_INVALID_ADDRESS) {
    LLDB_LOGF(log,
              "unable to allocate %" PRIu32
              " bytes in process for shared cache read",
              class_infos_byte_size);
    return DescriptorMapUpdateResult::Fail();
  }

  std::lock_guard<std::mutex> guard(m_get_class_info_args_mutex);

  // Fill in our function argument values
  arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress();
  arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
  arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;

  // Only dump the runtime classes from the expression evaluation if the log is
  // verbose:
  Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES);
  bool dump_log = type_log && type_log->GetVerbose();

  arguments.GetValueAtIndex(3)->GetScalar() = dump_log ? 1 : 0;

  bool success = false;

  diagnostics.Clear();

  // Write our function arguments into the process so we can run our function
  if (get_class_info_function->WriteFunctionArguments(
          exe_ctx, m_get_class_info_args, arguments, diagnostics)) {
    EvaluateExpressionOptions options;
    options.SetUnwindOnError(true);
    options.SetTryAllThreads(false);
    options.SetStopOthers(true);
    options.SetIgnoreBreakpoints(true);
    options.SetTimeout(process->GetUtilityExpressionTimeout());
    options.SetIsForUtilityExpr(true);

    Value return_value;
    return_value.SetValueType(Value::ValueType::Scalar);
    return_value.SetCompilerType(clang_uint32_t_type);
    return_value.GetScalar() = 0;

    diagnostics.Clear();

    // Run the function
    ExpressionResults results = get_class_info_function->ExecuteFunction(
        exe_ctx, &m_get_class_info_args, options, diagnostics, return_value);

    if (results == eExpressionCompleted) {
      // The result is the number of ClassInfo structures that were filled in
      num_class_infos = return_value.GetScalar().ULong();
      LLDB_LOGF(log, "Discovered %u ObjC classes\n", num_class_infos);
      if (num_class_infos > 0) {
        // Read the ClassInfo structures
        DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0);
        if (process->ReadMemory(class_infos_addr, buffer.GetBytes(),
                                buffer.GetByteSize(),
                                err) == buffer.GetByteSize()) {
          DataExtractor class_infos_data(buffer.GetBytes(),
                                         buffer.GetByteSize(),
                                         process->GetByteOrder(), addr_size);
          ParseClassInfoArray(class_infos_data, num_class_infos);
        }
      }
      success = true;
    } else {
      if (log) {
        LLDB_LOGF(log, "Error evaluating our find class name function.");
        diagnostics.Dump(log);
      }
    }
  } else {
    if (log) {
      LLDB_LOGF(log, "Error writing function arguments.");
      diagnostics.Dump(log);
    }
  }

  // Deallocate the memory we allocated for the ClassInfo array
  process->DeallocateMemory(class_infos_addr);

  return DescriptorMapUpdateResult(success, num_class_infos);
}

uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data,
                                                 uint32_t num_class_infos) {
  // Parses an array of "num_class_infos" packed ClassInfo structures:
  //
  //    struct ClassInfo
  //    {
  //        Class isa;
  //        uint32_t hash;
  //    } __attribute__((__packed__));

  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
  bool should_log = log && log->GetVerbose();

  uint32_t num_parsed = 0;

  // Iterate through all ClassInfo structures
  lldb::offset_t offset = 0;
  for (uint32_t i = 0; i < num_class_infos; ++i) {
    ObjCISA isa = data.GetAddress(&offset);

    if (isa == 0) {
      if (should_log)
        LLDB_LOGF(
            log, "AppleObjCRuntimeV2 found NULL isa, ignoring this class info");
      continue;
    }
    // Check if we already know about this ISA, if we do, the info will never
    // change, so we can just skip it.
    if (ISAIsCached(isa)) {
      if (should_log)
        LLDB_LOGF(log,
                  "AppleObjCRuntimeV2 found cached isa=0x%" PRIx64
                  ", ignoring this class info",
                  isa);
      offset += 4;
    } else {
      // Read the 32 bit hash for the class name
      const uint32_t name_hash = data.GetU32(&offset);
      ClassDescriptorSP descriptor_sp(
          new ClassDescriptorV2(*this, isa, nullptr));

      // The code in g_get_shared_cache_class_info_body sets the value of the
      // hash to 0 to signal a demangled symbol. We use class_getName() in that
      // code to find the class name, but this returns a demangled name for
      // Swift symbols. For those symbols, recompute the hash here by reading
      // their name from the runtime.
      if (name_hash)
        AddClass(isa, descriptor_sp, name_hash);
      else
        AddClass(isa, descriptor_sp,
                 descriptor_sp->GetClassName().AsCString(nullptr));
      num_parsed++;
      if (should_log)
        LLDB_LOGF(log,
                  "AppleObjCRuntimeV2 added isa=0x%" PRIx64
                  ", hash=0x%8.8x, name=%s",
                  isa, name_hash,
                  descriptor_sp->GetClassName().AsCString("<unknown>"));
    }
  }
  if (should_log)
    LLDB_LOGF(log, "AppleObjCRuntimeV2 parsed %" PRIu32 " class infos",
              num_parsed);
  return num_parsed;
}

AppleObjCRuntimeV2::DescriptorMapUpdateResult
AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
  Process *process = GetProcess();

  if (process == nullptr)
    return DescriptorMapUpdateResult::Fail();

  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));

  ExecutionContext exe_ctx;

  ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();

  if (!thread_sp)
    return DescriptorMapUpdateResult::Fail();

  thread_sp->CalculateExecutionContext(exe_ctx);
  TypeSystemClang *ast =
      ScratchTypeSystemClang::GetForTarget(process->GetTarget());

  if (!ast)
    return DescriptorMapUpdateResult::Fail();

  Address function_address;

  const uint32_t addr_size = process->GetAddressByteSize();

  Status err;

  uint32_t num_class_infos = 0;

  const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress();

  if (objc_opt_ptr == LLDB_INVALID_ADDRESS)
    return DescriptorMapUpdateResult::Fail();

  const uint32_t num_classes = 128 * 1024;

  // Make some types for our arguments
  CompilerType clang_uint32_t_type =
      ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
  CompilerType clang_void_pointer_type =
      ast->GetBasicType(eBasicTypeVoid).GetPointerType();

  ValueList arguments;
  FunctionCaller *get_shared_cache_class_info_function = nullptr;

  if (!m_get_shared_cache_class_info_code) {
    Status error;

    // If the inferior objc.dylib has the class_getNameRaw function,
    // use that in our jitted expression.  Else fall back to the old
    // class_getName.
    static ConstString g_class_getName_symbol_name("class_getName");
    static ConstString g_class_getNameRaw_symbol_name(
        "objc_debug_class_getNameRaw");
    ConstString class_name_getter_function_name = g_class_getName_symbol_name;

    ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process);
    if (objc_runtime) {
      for (lldb::ModuleSP mod_sp : process->GetTarget().GetImages().Modules()) {
        if (objc_runtime->IsModuleObjCLibrary(mod_sp)) {
          const Symbol *symbol = mod_sp->FindFirstSymbolWithNameAndType(
              g_class_getNameRaw_symbol_name, lldb::eSymbolTypeCode);
          if (symbol &&
              (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())) {
            class_name_getter_function_name = g_class_getNameRaw_symbol_name;
          }
        }
      }
    }

    // Substitute in the correct class_getName / class_getNameRaw function name,
    // concatenate the two parts of our expression text.  The format string
    // has two %s's, so provide the name twice.
    std::string shared_class_expression;
    llvm::raw_string_ostream(shared_class_expression)
        << llvm::format(g_shared_cache_class_name_funcptr,
                        class_name_getter_function_name.AsCString(),
                        class_name_getter_function_name.AsCString());

    shared_class_expression += g_get_shared_cache_class_info_body;

    auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
        std::move(shared_class_expression), g_get_shared_cache_class_info_name,
        eLanguageTypeC, exe_ctx);
    if (!utility_fn_or_error) {
      LLDB_LOG_ERROR(
          log, utility_fn_or_error.takeError(),
          "Failed to get utility function for implementation lookup: {0}");
      return DescriptorMapUpdateResult::Fail();
    }

    m_get_shared_cache_class_info_code = std::move(*utility_fn_or_error);

    // Next make the function caller for our implementation utility function.
    Value value;
    value.SetValueType(Value::ValueType::Scalar);
    value.SetCompilerType(clang_void_pointer_type);
    arguments.PushValue(value);
    arguments.PushValue(value);

    value.SetValueType(Value::ValueType::Scalar);
    value.SetCompilerType(clang_uint32_t_type);
    arguments.PushValue(value);
    arguments.PushValue(value);

    get_shared_cache_class_info_function =
        m_get_shared_cache_class_info_code->MakeFunctionCaller(
            clang_uint32_t_type, arguments, thread_sp, error);

    if (get_shared_cache_class_info_function == nullptr)
      return DescriptorMapUpdateResult::Fail();

  } else {
    get_shared_cache_class_info_function =
        m_get_shared_cache_class_info_code->GetFunctionCaller();
    if (get_shared_cache_class_info_function == nullptr)
      return DescriptorMapUpdateResult::Fail();
    arguments = get_shared_cache_class_info_function->GetArgumentValues();
  }

  DiagnosticManager diagnostics;

  const uint32_t class_info_byte_size = addr_size + 4;
  const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
  lldb::addr_t class_infos_addr = process->AllocateMemory(
      class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err);

  if (class_infos_addr == LLDB_INVALID_ADDRESS) {
    LLDB_LOGF(log,
              "unable to allocate %" PRIu32
              " bytes in process for shared cache read",
              class_infos_byte_size);
    return DescriptorMapUpdateResult::Fail();
  }

  std::lock_guard<std::mutex> guard(m_get_shared_cache_class_info_args_mutex);

  // Fill in our function argument values
  arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
  arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
  arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
  // Only dump the runtime classes from the expression evaluation if the log is
  // verbose:
  Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES);
  bool dump_log = type_log && type_log->GetVerbose();

  arguments.GetValueAtIndex(3)->GetScalar() = dump_log ? 1 : 0;

  bool success = false;

  diagnostics.Clear();

  // Write our function arguments into the process so we can run our function
  if (get_shared_cache_class_info_function->WriteFunctionArguments(
          exe_ctx, m_get_shared_cache_class_info_args, arguments,
          diagnostics)) {
    EvaluateExpressionOptions options;
    options.SetUnwindOnError(true);
    options.SetTryAllThreads(false);
    options.SetStopOthers(true);
    options.SetIgnoreBreakpoints(true);
    options.SetTimeout(process->GetUtilityExpressionTimeout());
    options.SetIsForUtilityExpr(true);

    Value return_value;
    return_value.SetValueType(Value::ValueType::Scalar);
    return_value.SetCompilerType(clang_uint32_t_type);
    return_value.GetScalar() = 0;

    diagnostics.Clear();

    // Run the function
    ExpressionResults results =
        get_shared_cache_class_info_function->ExecuteFunction(
            exe_ctx, &m_get_shared_cache_class_info_args, options, diagnostics,
            return_value);

    if (results == eExpressionCompleted) {
      // The result is the number of ClassInfo structures that were filled in
      num_class_infos = return_value.GetScalar().ULong();
      LLDB_LOGF(log, "Discovered %u ObjC classes in shared cache\n",
                num_class_infos);
      assert(num_class_infos <= num_classes);
      if (num_class_infos > 0) {
        if (num_class_infos > num_classes) {
          num_class_infos = num_classes;

          success = false;
        } else {
          success = true;
        }

        // Read the ClassInfo structures
        DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0);
        if (process->ReadMemory(class_infos_addr, buffer.GetBytes(),
                                buffer.GetByteSize(),
                                err) == buffer.GetByteSize()) {
          DataExtractor class_infos_data(buffer.GetBytes(),
                                         buffer.GetByteSize(),
                                         process->GetByteOrder(), addr_size);

          ParseClassInfoArray(class_infos_data, num_class_infos);
        }
      } else {
        success = true;
      }
    } else {
      if (log) {
        LLDB_LOGF(log, "Error evaluating our find class name function.");
        diagnostics.Dump(log);
      }
    }
  } else {
    if (log) {
      LLDB_LOGF(log, "Error writing function arguments.");
      diagnostics.Dump(log);
    }
  }

  // Deallocate the memory we allocated for the ClassInfo array
  process->DeallocateMemory(class_infos_addr);

  return DescriptorMapUpdateResult(success, num_class_infos);
}

bool AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory(
    RemoteNXMapTable &hash_table) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));

  Process *process = GetProcess();

  if (process == nullptr)
    return false;

  uint32_t num_map_table_isas = 0;

  ModuleSP objc_module_sp(GetObjCModule());

  if (objc_module_sp) {
    for (RemoteNXMapTable::element elt : hash_table) {
      ++num_map_table_isas;

      if (ISAIsCached(elt.second))
        continue;

      ClassDescriptorSP descriptor_sp = ClassDescriptorSP(
          new ClassDescriptorV2(*this, elt.second, elt.first.AsCString()));

      if (log && log->GetVerbose())
        LLDB_LOGF(log,
                  "AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64
                  " (%s) from dynamic table to isa->descriptor cache",
                  elt.second, elt.first.AsCString());

      AddClass(elt.second, descriptor_sp, elt.first.AsCString());
    }
  }

  return num_map_table_isas > 0;
}

lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress() {
  Process *process = GetProcess();

  if (process) {
    ModuleSP objc_module_sp(GetObjCModule());

    if (objc_module_sp) {
      ObjectFile *objc_object = objc_module_sp->GetObjectFile();

      if (objc_object) {
        SectionList *section_list = objc_module_sp->GetSectionList();

        if (section_list) {
          SectionSP text_segment_sp(
              section_list->FindSectionByName(ConstString("__TEXT")));

          if (text_segment_sp) {
            SectionSP objc_opt_section_sp(
                text_segment_sp->GetChildren().FindSectionByName(
                    ConstString("__objc_opt_ro")));

            if (objc_opt_section_sp) {
              return objc_opt_section_sp->GetLoadBaseAddress(
                  &process->GetTarget());
            }
          }
        }
      }
    }
  }
  return LLDB_INVALID_ADDRESS;
}

void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
  LLDB_SCOPED_TIMER();

  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));

  // Else we need to check with our process to see when the map was updated.
  Process *process = GetProcess();

  if (process) {
    RemoteNXMapTable hash_table;

    // Update the process stop ID that indicates the last time we updated the
    // map, whether it was successful or not.
    m_isa_to_descriptor_stop_id = process->GetStopID();

    if (!m_hash_signature.NeedsUpdate(process, this, hash_table))
      return;

    m_hash_signature.UpdateSignature(hash_table);

    // Grab the dynamically loaded objc classes from the hash table in memory
    DescriptorMapUpdateResult dynamic_update_result =
        UpdateISAToDescriptorMapDynamic(hash_table);

    // Now get the objc classes that are baked into the Objective-C runtime in
    // the shared cache, but only once per process as this data never changes
    if (!m_loaded_objc_opt) {
      // it is legitimately possible for the shared cache to be empty - in that
      // case, the dynamic hash table will contain all the class information we
      // need; the situation we're trying to detect is one where we aren't
      // seeing class information from the runtime - in order to detect that
      // vs. just the shared cache being empty or sparsely populated, we set an
      // arbitrary (very low) threshold for the number of classes that we want
      // to see in a "good" scenario - anything below that is suspicious
      // (Foundation alone has thousands of classes)
      const uint32_t num_classes_to_warn_at = 500;

      DescriptorMapUpdateResult shared_cache_update_result =
          UpdateISAToDescriptorMapSharedCache();

      LLDB_LOGF(log,
                "attempted to read objc class data - results: "
                "[dynamic_update]: ran: %s, count: %" PRIu32
                " [shared_cache_update]: ran: %s, count: %" PRIu32,
                dynamic_update_result.m_update_ran ? "yes" : "no",
                dynamic_update_result.m_num_found,
                shared_cache_update_result.m_update_ran ? "yes" : "no",
                shared_cache_update_result.m_num_found);

      // warn if:
      // - we could not run either expression
      // - we found fewer than num_classes_to_warn_at classes total
      if ((!shared_cache_update_result.m_update_ran) ||
          (!dynamic_update_result.m_update_ran))
        WarnIfNoClassesCached(
            SharedCacheWarningReason::eExpressionExecutionFailure);
      else if (dynamic_update_result.m_num_found +
                   shared_cache_update_result.m_num_found <
               num_classes_to_warn_at)
        WarnIfNoClassesCached(SharedCacheWarningReason::eNotEnoughClassesRead);
      else
        m_loaded_objc_opt = true;
    }
  } else {
    m_isa_to_descriptor_stop_id = UINT32_MAX;
  }
}

static bool DoesProcessHaveSharedCache(Process &process) {
  PlatformSP platform_sp = process.GetTarget().GetPlatform();
  if (!platform_sp)
    return true; // this should not happen

  ConstString platform_plugin_name = platform_sp->GetPluginName();
  if (platform_plugin_name) {
    llvm::StringRef platform_plugin_name_sr =
        platform_plugin_name.GetStringRef();
    if (platform_plugin_name_sr.endswith("-simulator"))
      return false;
  }

  return true;
}

void AppleObjCRuntimeV2::WarnIfNoClassesCached(
    SharedCacheWarningReason reason) {
  if (m_noclasses_warning_emitted)
    return;

  if (GetProcess() && !DoesProcessHaveSharedCache(*GetProcess())) {
    // Simulators do not have the objc_opt_ro class table so don't actually
    // complain to the user
    m_noclasses_warning_emitted = true;
    return;
  }

  Debugger &debugger(GetProcess()->GetTarget().GetDebugger());
  if (auto stream = debugger.GetAsyncOutputStream()) {
    switch (reason) {
    case SharedCacheWarningReason::eNotEnoughClassesRead:
      stream->PutCString("warning: could not find Objective-C class data in "
                         "the process. This may reduce the quality of type "
                         "information available.\n");
      m_noclasses_warning_emitted = true;
      break;
    case SharedCacheWarningReason::eExpressionExecutionFailure:
      stream->PutCString("warning: could not execute support code to read "
                         "Objective-C class data in the process. This may "
                         "reduce the quality of type information available.\n");
      m_noclasses_warning_emitted = true;
      break;
    }
  }
}

DeclVendor *AppleObjCRuntimeV2::GetDeclVendor() {
  if (!m_decl_vendor_up)
    m_decl_vendor_up = std::make_unique<AppleObjCDeclVendor>(*this);

  return m_decl_vendor_up.get();
}

lldb::addr_t AppleObjCRuntimeV2::LookupRuntimeSymbol(ConstString name) {
  lldb::addr_t ret = LLDB_INVALID_ADDRESS;

  const char *name_cstr = name.AsCString();

  if (name_cstr) {
    llvm::StringRef name_strref(name_cstr);

    llvm::StringRef ivar_prefix("OBJC_IVAR_$_");
    llvm::StringRef class_prefix("OBJC_CLASS_$_");

    if (name_strref.startswith(ivar_prefix)) {
      llvm::StringRef ivar_skipped_prefix =
          name_strref.substr(ivar_prefix.size());
      std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar =
          ivar_skipped_prefix.split('.');

      if (class_and_ivar.first.size() && class_and_ivar.second.size()) {
        const ConstString class_name_cs(class_and_ivar.first);
        ClassDescriptorSP descriptor =
            ObjCLanguageRuntime::GetClassDescriptorFromClassName(class_name_cs);

        if (descriptor) {
          const ConstString ivar_name_cs(class_and_ivar.second);
          const char *ivar_name_cstr = ivar_name_cs.AsCString();

          auto ivar_func = [&ret,
                            ivar_name_cstr](const char *name, const char *type,
                                            lldb::addr_t offset_addr,
                                            uint64_t size) -> lldb::addr_t {
            if (!strcmp(name, ivar_name_cstr)) {
              ret = offset_addr;
              return true;
            }
            return false;
          };

          descriptor->Describe(
              std::function<void(ObjCISA)>(nullptr),
              std::function<bool(const char *, const char *)>(nullptr),
              std::function<bool(const char *, const char *)>(nullptr),
              ivar_func);
        }
      }
    } else if (name_strref.startswith(class_prefix)) {
      llvm::StringRef class_skipped_prefix =
          name_strref.substr(class_prefix.size());
      const ConstString class_name_cs(class_skipped_prefix);
      ClassDescriptorSP descriptor =
          GetClassDescriptorFromClassName(class_name_cs);

      if (descriptor)
        ret = descriptor->GetISA();
    }
  }

  return ret;
}

AppleObjCRuntimeV2::NonPointerISACache *
AppleObjCRuntimeV2::NonPointerISACache::CreateInstance(
    AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp) {
  Process *process(runtime.GetProcess());

  Status error;

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));

  auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol(
      process, ConstString("objc_debug_isa_magic_mask"), objc_module_sp, error);
  if (error.Fail())
    return nullptr;

  auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol(
      process, ConstString("objc_debug_isa_magic_value"), objc_module_sp,
      error);
  if (error.Fail())
    return nullptr;

  auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol(
      process, ConstString("objc_debug_isa_class_mask"), objc_module_sp, error);
  if (error.Fail())
    return nullptr;

  if (log)
    log->PutCString("AOCRT::NPI: Found all the non-indexed ISA masks");

  bool foundError = false;
  auto objc_debug_indexed_isa_magic_mask = ExtractRuntimeGlobalSymbol(
      process, ConstString("objc_debug_indexed_isa_magic_mask"), objc_module_sp,
      error);
  foundError |= error.Fail();

  auto objc_debug_indexed_isa_magic_value = ExtractRuntimeGlobalSymbol(
      process, ConstString("objc_debug_indexed_isa_magic_value"),
      objc_module_sp, error);
  foundError |= error.Fail();

  auto objc_debug_indexed_isa_index_mask = ExtractRuntimeGlobalSymbol(
      process, ConstString("objc_debug_indexed_isa_index_mask"), objc_module_sp,
      error);
  foundError |= error.Fail();

  auto objc_debug_indexed_isa_index_shift = ExtractRuntimeGlobalSymbol(
      process, ConstString("objc_debug_indexed_isa_index_shift"),
      objc_module_sp, error);
  foundError |= error.Fail();

  auto objc_indexed_classes =
      ExtractRuntimeGlobalSymbol(process, ConstString("objc_indexed_classes"),
                                 objc_module_sp, error, false);
  foundError |= error.Fail();

  if (log)
    log->PutCString("AOCRT::NPI: Found all the indexed ISA masks");

  // we might want to have some rules to outlaw these other values (e.g if the
  // mask is zero but the value is non-zero, ...)

  return new NonPointerISACache(
      runtime, objc_module_sp, objc_debug_isa_class_mask,
      objc_debug_isa_magic_mask, objc_debug_isa_magic_value,
      objc_debug_indexed_isa_magic_mask, objc_debug_indexed_isa_magic_value,
      objc_debug_indexed_isa_index_mask, objc_debug_indexed_isa_index_shift,
      foundError ? 0 : objc_indexed_classes);
}

AppleObjCRuntimeV2::TaggedPointerVendorV2 *
AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance(
    AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp) {
  Process *process(runtime.GetProcess());

  Status error;

  auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol(
      process, ConstString("objc_debug_taggedpointer_mask"), objc_module_sp,
      error);
  if (error.Fail())
    return new TaggedPointerVendorLegacy(runtime);

  auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol(
      process, ConstString("objc_debug_taggedpointer_slot_shift"),
      objc_module_sp, error, true, 4);
  if (error.Fail())
    return new TaggedPointerVendorLegacy(runtime);

  auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol(
      process, ConstString("objc_debug_taggedpointer_slot_mask"),
      objc_module_sp, error, true, 4);
  if (error.Fail())
    return new TaggedPointerVendorLegacy(runtime);

  auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol(
      process, ConstString("objc_debug_taggedpointer_payload_lshift"),
      objc_module_sp, error, true, 4);
  if (error.Fail())
    return new TaggedPointerVendorLegacy(runtime);

  auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol(
      process, ConstString("objc_debug_taggedpointer_payload_rshift"),
      objc_module_sp, error, true, 4);
  if (error.Fail())
    return new TaggedPointerVendorLegacy(runtime);

  auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol(
      process, ConstString("objc_debug_taggedpointer_classes"), objc_module_sp,
      error, false);
  if (error.Fail())
    return new TaggedPointerVendorLegacy(runtime);

  // try to detect the "extended tagged pointer" variables - if any are
  // missing, use the non-extended vendor
  do {
    auto objc_debug_taggedpointer_ext_mask = ExtractRuntimeGlobalSymbol(
        process, ConstString("objc_debug_taggedpointer_ext_mask"),
        objc_module_sp, error);
    if (error.Fail())
      break;

    auto objc_debug_taggedpointer_ext_slot_shift = ExtractRuntimeGlobalSymbol(
        process, ConstString("objc_debug_taggedpointer_ext_slot_shift"),
        objc_module_sp, error, true, 4);
    if (error.Fail())
      break;

    auto objc_debug_taggedpointer_ext_slot_mask = ExtractRuntimeGlobalSymbol(
        process, ConstString("objc_debug_taggedpointer_ext_slot_mask"),
        objc_module_sp, error, true, 4);
    if (error.Fail())
      break;

    auto objc_debug_taggedpointer_ext_classes = ExtractRuntimeGlobalSymbol(
        process, ConstString("objc_debug_taggedpointer_ext_classes"),
        objc_module_sp, error, false);
    if (error.Fail())
      break;

    auto objc_debug_taggedpointer_ext_payload_lshift =
        ExtractRuntimeGlobalSymbol(
            process, ConstString("objc_debug_taggedpointer_ext_payload_lshift"),
            objc_module_sp, error, true, 4);
    if (error.Fail())
      break;

    auto objc_debug_taggedpointer_ext_payload_rshift =
        ExtractRuntimeGlobalSymbol(
            process, ConstString("objc_debug_taggedpointer_ext_payload_rshift"),
            objc_module_sp, error, true, 4);
    if (error.Fail())
      break;

    return new TaggedPointerVendorExtended(
        runtime, objc_debug_taggedpointer_mask,
        objc_debug_taggedpointer_ext_mask, objc_debug_taggedpointer_slot_shift,
        objc_debug_taggedpointer_ext_slot_shift,
        objc_debug_taggedpointer_slot_mask,
        objc_debug_taggedpointer_ext_slot_mask,
        objc_debug_taggedpointer_payload_lshift,
        objc_debug_taggedpointer_payload_rshift,
        objc_debug_taggedpointer_ext_payload_lshift,
        objc_debug_taggedpointer_ext_payload_rshift,
        objc_debug_taggedpointer_classes, objc_debug_taggedpointer_ext_classes);
  } while (false);

  // we might want to have some rules to outlaw these values (e.g if the
  // table's address is zero)

  return new TaggedPointerVendorRuntimeAssisted(
      runtime, objc_debug_taggedpointer_mask,
      objc_debug_taggedpointer_slot_shift, objc_debug_taggedpointer_slot_mask,
      objc_debug_taggedpointer_payload_lshift,
      objc_debug_taggedpointer_payload_rshift,
      objc_debug_taggedpointer_classes);
}

bool AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer(
    lldb::addr_t ptr) {
  return (ptr & 1);
}

ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor(
    lldb::addr_t ptr) {
  if (!IsPossibleTaggedPointer(ptr))
    return ObjCLanguageRuntime::ClassDescriptorSP();

  uint32_t foundation_version = m_runtime.GetFoundationVersion();

  if (foundation_version == LLDB_INVALID_MODULE_VERSION)
    return ObjCLanguageRuntime::ClassDescriptorSP();

  uint64_t class_bits = (ptr & 0xE) >> 1;
  ConstString name;

  static ConstString g_NSAtom("NSAtom");
  static ConstString g_NSNumber("NSNumber");
  static ConstString g_NSDateTS("NSDateTS");
  static ConstString g_NSManagedObject("NSManagedObject");
  static ConstString g_NSDate("NSDate");

  if (foundation_version >= 900) {
    switch (class_bits) {
    case 0:
      name = g_NSAtom;
      break;
    case 3:
      name = g_NSNumber;
      break;
    case 4:
      name = g_NSDateTS;
      break;
    case 5:
      name = g_NSManagedObject;
      break;
    case 6:
      name = g_NSDate;
      break;
    default:
      return ObjCLanguageRuntime::ClassDescriptorSP();
    }
  } else {
    switch (class_bits) {
    case 1:
      name = g_NSNumber;
      break;
    case 5:
      name = g_NSManagedObject;
      break;
    case 6:
      name = g_NSDate;
      break;
    case 7:
      name = g_NSDateTS;
      break;
    default:
      return ObjCLanguageRuntime::ClassDescriptorSP();
    }
  }

  lldb::addr_t unobfuscated = ptr ^ m_runtime.GetTaggedPointerObfuscator();
  return ClassDescriptorSP(new ClassDescriptorV2Tagged(name, unobfuscated));
}

AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::
    TaggedPointerVendorRuntimeAssisted(
        AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,
        uint32_t objc_debug_taggedpointer_slot_shift,
        uint32_t objc_debug_taggedpointer_slot_mask,
        uint32_t objc_debug_taggedpointer_payload_lshift,
        uint32_t objc_debug_taggedpointer_payload_rshift,
        lldb::addr_t objc_debug_taggedpointer_classes)
    : TaggedPointerVendorV2(runtime), m_cache(),
      m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask),
      m_objc_debug_taggedpointer_slot_shift(
          objc_debug_taggedpointer_slot_shift),
      m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask),
      m_objc_debug_taggedpointer_payload_lshift(
          objc_debug_taggedpointer_payload_lshift),
      m_objc_debug_taggedpointer_payload_rshift(
          objc_debug_taggedpointer_payload_rshift),
      m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes) {}

bool AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::
    IsPossibleTaggedPointer(lldb::addr_t ptr) {
  return (ptr & m_objc_debug_taggedpointer_mask) != 0;
}

ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(
    lldb::addr_t ptr) {
  ClassDescriptorSP actual_class_descriptor_sp;
  uint64_t data_payload;
  uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();

  if (!IsPossibleTaggedPointer(unobfuscated))
    return ObjCLanguageRuntime::ClassDescriptorSP();

  uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) &
                   m_objc_debug_taggedpointer_slot_mask;

  CacheIterator iterator = m_cache.find(slot), end = m_cache.end();
  if (iterator != end) {
    actual_class_descriptor_sp = iterator->second;
  } else {
    Process *process(m_runtime.GetProcess());
    uintptr_t slot_ptr = slot * process->GetAddressByteSize() +
                         m_objc_debug_taggedpointer_classes;
    Status error;
    uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
    if (error.Fail() || slot_data == 0 ||
        slot_data == uintptr_t(LLDB_INVALID_ADDRESS))
      return nullptr;
    actual_class_descriptor_sp =
        m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data);
    if (!actual_class_descriptor_sp)
      return ObjCLanguageRuntime::ClassDescriptorSP();
    m_cache[slot] = actual_class_descriptor_sp;
  }

  data_payload =
      (((uint64_t)unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >>
       m_objc_debug_taggedpointer_payload_rshift);

  return ClassDescriptorSP(
      new ClassDescriptorV2Tagged(actual_class_descriptor_sp, data_payload));
}

AppleObjCRuntimeV2::TaggedPointerVendorExtended::TaggedPointerVendorExtended(
    AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,
    uint64_t objc_debug_taggedpointer_ext_mask,
    uint32_t objc_debug_taggedpointer_slot_shift,
    uint32_t objc_debug_taggedpointer_ext_slot_shift,
    uint32_t objc_debug_taggedpointer_slot_mask,
    uint32_t objc_debug_taggedpointer_ext_slot_mask,
    uint32_t objc_debug_taggedpointer_payload_lshift,
    uint32_t objc_debug_taggedpointer_payload_rshift,
    uint32_t objc_debug_taggedpointer_ext_payload_lshift,
    uint32_t objc_debug_taggedpointer_ext_payload_rshift,
    lldb::addr_t objc_debug_taggedpointer_classes,
    lldb::addr_t objc_debug_taggedpointer_ext_classes)
    : TaggedPointerVendorRuntimeAssisted(
          runtime, objc_debug_taggedpointer_mask,
          objc_debug_taggedpointer_slot_shift,
          objc_debug_taggedpointer_slot_mask,
          objc_debug_taggedpointer_payload_lshift,
          objc_debug_taggedpointer_payload_rshift,
          objc_debug_taggedpointer_classes),
      m_ext_cache(),
      m_objc_debug_taggedpointer_ext_mask(objc_debug_taggedpointer_ext_mask),
      m_objc_debug_taggedpointer_ext_slot_shift(
          objc_debug_taggedpointer_ext_slot_shift),
      m_objc_debug_taggedpointer_ext_slot_mask(
          objc_debug_taggedpointer_ext_slot_mask),
      m_objc_debug_taggedpointer_ext_payload_lshift(
          objc_debug_taggedpointer_ext_payload_lshift),
      m_objc_debug_taggedpointer_ext_payload_rshift(
          objc_debug_taggedpointer_ext_payload_rshift),
      m_objc_debug_taggedpointer_ext_classes(
          objc_debug_taggedpointer_ext_classes) {}

bool AppleObjCRuntimeV2::TaggedPointerVendorExtended::
    IsPossibleExtendedTaggedPointer(lldb::addr_t ptr) {
  if (!IsPossibleTaggedPointer(ptr))
    return false;

  if (m_objc_debug_taggedpointer_ext_mask == 0)
    return false;

  return ((ptr & m_objc_debug_taggedpointer_ext_mask) ==
          m_objc_debug_taggedpointer_ext_mask);
}

ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor(
    lldb::addr_t ptr) {
  ClassDescriptorSP actual_class_descriptor_sp;
  uint64_t data_payload;
  uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();

  if (!IsPossibleTaggedPointer(unobfuscated))
    return ObjCLanguageRuntime::ClassDescriptorSP();

  if (!IsPossibleExtendedTaggedPointer(unobfuscated))
    return this->TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(ptr);

  uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_ext_slot_shift) &
                   m_objc_debug_taggedpointer_ext_slot_mask;

  CacheIterator iterator = m_ext_cache.find(slot), end = m_ext_cache.end();
  if (iterator != end) {
    actual_class_descriptor_sp = iterator->second;
  } else {
    Process *process(m_runtime.GetProcess());
    uintptr_t slot_ptr = slot * process->GetAddressByteSize() +
                         m_objc_debug_taggedpointer_ext_classes;
    Status error;
    uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
    if (error.Fail() || slot_data == 0 ||
        slot_data == uintptr_t(LLDB_INVALID_ADDRESS))
      return nullptr;
    actual_class_descriptor_sp =
        m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data);
    if (!actual_class_descriptor_sp)
      return ObjCLanguageRuntime::ClassDescriptorSP();
    m_ext_cache[slot] = actual_class_descriptor_sp;
  }

  data_payload = (((uint64_t)unobfuscated
                   << m_objc_debug_taggedpointer_ext_payload_lshift) >>
                  m_objc_debug_taggedpointer_ext_payload_rshift);

  return ClassDescriptorSP(
      new ClassDescriptorV2Tagged(actual_class_descriptor_sp, data_payload));
}

AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache(
    AppleObjCRuntimeV2 &runtime, const ModuleSP &objc_module_sp,
    uint64_t objc_debug_isa_class_mask, uint64_t objc_debug_isa_magic_mask,
    uint64_t objc_debug_isa_magic_value,
    uint64_t objc_debug_indexed_isa_magic_mask,
    uint64_t objc_debug_indexed_isa_magic_value,
    uint64_t objc_debug_indexed_isa_index_mask,
    uint64_t objc_debug_indexed_isa_index_shift,
    lldb::addr_t objc_indexed_classes)
    : m_runtime(runtime), m_cache(), m_objc_module_wp(objc_module_sp),
      m_objc_debug_isa_class_mask(objc_debug_isa_class_mask),
      m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask),
      m_objc_debug_isa_magic_value(objc_debug_isa_magic_value),
      m_objc_debug_indexed_isa_magic_mask(objc_debug_indexed_isa_magic_mask),
      m_objc_debug_indexed_isa_magic_value(objc_debug_indexed_isa_magic_value),
      m_objc_debug_indexed_isa_index_mask(objc_debug_indexed_isa_index_mask),
      m_objc_debug_indexed_isa_index_shift(objc_debug_indexed_isa_index_shift),
      m_objc_indexed_classes(objc_indexed_classes), m_indexed_isa_cache() {}

ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor(ObjCISA isa) {
  ObjCISA real_isa = 0;
  if (!EvaluateNonPointerISA(isa, real_isa))
    return ObjCLanguageRuntime::ClassDescriptorSP();
  auto cache_iter = m_cache.find(real_isa);
  if (cache_iter != m_cache.end())
    return cache_iter->second;
  auto descriptor_sp =
      m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa);
  if (descriptor_sp) // cache only positive matches since the table might grow
    m_cache[real_isa] = descriptor_sp;
  return descriptor_sp;
}

bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA(
    ObjCISA isa, ObjCISA &ret_isa) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));

  LLDB_LOGF(log, "AOCRT::NPI Evaluate(isa = 0x%" PRIx64 ")", (uint64_t)isa);

  if ((isa & ~m_objc_debug_isa_class_mask) == 0)
    return false;

  // If all of the indexed ISA variables are set, then its possible that this
  // ISA is indexed, and we should first try to get its value using the index.
  // Note, we check these variables first as the ObjC runtime will set at least
  // one of their values to 0 if they aren't needed.
  if (m_objc_debug_indexed_isa_magic_mask &&
      m_objc_debug_indexed_isa_magic_value &&
      m_objc_debug_indexed_isa_index_mask &&
      m_objc_debug_indexed_isa_index_shift && m_objc_indexed_classes) {
    if ((isa & ~m_objc_debug_indexed_isa_index_mask) == 0)
      return false;

    if ((isa & m_objc_debug_indexed_isa_magic_mask) ==
        m_objc_debug_indexed_isa_magic_value) {
      // Magic bits are correct, so try extract the index.
      uintptr_t index = (isa & m_objc_debug_indexed_isa_index_mask) >>
                        m_objc_debug_indexed_isa_index_shift;
      // If the index is out of bounds of the length of the array then check if
      // the array has been updated.  If that is the case then we should try
      // read the count again, and update the cache if the count has been
      // updated.
      if (index > m_indexed_isa_cache.size()) {
        LLDB_LOGF(log,
                  "AOCRT::NPI (index = %" PRIu64
                  ") exceeds cache (size = %" PRIu64 ")",
                  (uint64_t)index, (uint64_t)m_indexed_isa_cache.size());

        Process *process(m_runtime.GetProcess());

        ModuleSP objc_module_sp(m_objc_module_wp.lock());
        if (!objc_module_sp)
          return false;

        Status error;
        auto objc_indexed_classes_count = ExtractRuntimeGlobalSymbol(
            process, ConstString("objc_indexed_classes_count"), objc_module_sp,
            error);
        if (error.Fail())
          return false;

        LLDB_LOGF(log, "AOCRT::NPI (new class count = %" PRIu64 ")",
                  (uint64_t)objc_indexed_classes_count);

        if (objc_indexed_classes_count > m_indexed_isa_cache.size()) {
          // Read the class entries we don't have.  We should just read all of
          // them instead of just the one we need as then we can cache those we
          // may need later.
          auto num_new_classes =
              objc_indexed_classes_count - m_indexed_isa_cache.size();
          const uint32_t addr_size = process->GetAddressByteSize();
          DataBufferHeap buffer(num_new_classes * addr_size, 0);

          lldb::addr_t last_read_class =
              m_objc_indexed_classes + (m_indexed_isa_cache.size() * addr_size);
          size_t bytes_read = process->ReadMemory(
              last_read_class, buffer.GetBytes(), buffer.GetByteSize(), error);
          if (error.Fail() || bytes_read != buffer.GetByteSize())
            return false;

          LLDB_LOGF(log, "AOCRT::NPI (read new classes count = %" PRIu64 ")",
                    (uint64_t)num_new_classes);

          // Append the new entries to the existing cache.
          DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(),
                             process->GetByteOrder(),
                             process->GetAddressByteSize());

          lldb::offset_t offset = 0;
          for (unsigned i = 0; i != num_new_classes; ++i)
            m_indexed_isa_cache.push_back(data.GetAddress(&offset));
        }
      }

      // If the index is still out of range then this isn't a pointer.
      if (index > m_indexed_isa_cache.size())
        return false;

      LLDB_LOGF(log, "AOCRT::NPI Evaluate(ret_isa = 0x%" PRIx64 ")",
                (uint64_t)m_indexed_isa_cache[index]);

      ret_isa = m_indexed_isa_cache[index];
      return (ret_isa != 0); // this is a pointer so 0 is not a valid value
    }

    return false;
  }

  // Definitely not an indexed ISA, so try to use a mask to extract the pointer
  // from the ISA.
  if ((isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value) {
    ret_isa = isa & m_objc_debug_isa_class_mask;
    return (ret_isa != 0); // this is a pointer so 0 is not a valid value
  }
  return false;
}

ObjCLanguageRuntime::EncodingToTypeSP AppleObjCRuntimeV2::GetEncodingToType() {
  if (!m_encoding_to_type_sp)
    m_encoding_to_type_sp =
        std::make_shared<AppleObjCTypeEncodingParser>(*this);
  return m_encoding_to_type_sp;
}

lldb_private::AppleObjCRuntime::ObjCISA
AppleObjCRuntimeV2::GetPointerISA(ObjCISA isa) {
  ObjCISA ret = isa;

  if (m_non_pointer_isa_cache_up)
    m_non_pointer_isa_cache_up->EvaluateNonPointerISA(isa, ret);

  return ret;
}

bool AppleObjCRuntimeV2::GetCFBooleanValuesIfNeeded() {
  if (m_CFBoolean_values)
    return true;

  static ConstString g_kCFBooleanFalse("__kCFBooleanFalse");
  static ConstString g_kCFBooleanTrue("__kCFBooleanTrue");

  std::function<lldb::addr_t(ConstString)> get_symbol =
      [this](ConstString sym) -> lldb::addr_t {
    SymbolContextList sc_list;
    GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType(
        sym, lldb::eSymbolTypeData, sc_list);
    if (sc_list.GetSize() == 1) {
      SymbolContext sc;
      sc_list.GetContextAtIndex(0, sc);
      if (sc.symbol)
        return sc.symbol->GetLoadAddress(&GetProcess()->GetTarget());
    }

    return LLDB_INVALID_ADDRESS;
  };

  lldb::addr_t false_addr = get_symbol(g_kCFBooleanFalse);
  lldb::addr_t true_addr = get_symbol(g_kCFBooleanTrue);

  return (m_CFBoolean_values = {false_addr, true_addr}).operator bool();
}

void AppleObjCRuntimeV2::GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
                                                      lldb::addr_t &cf_false) {
  if (GetCFBooleanValuesIfNeeded()) {
    cf_true = m_CFBoolean_values->second;
    cf_false = m_CFBoolean_values->first;
  } else
    this->AppleObjCRuntime::GetValuesForGlobalCFBooleans(cf_true, cf_false);
}

#pragma mark Frame recognizers

class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame {
public:
  ObjCExceptionRecognizedStackFrame(StackFrameSP frame_sp) {
    ThreadSP thread_sp = frame_sp->GetThread();
    ProcessSP process_sp = thread_sp->GetProcess();

    const lldb::ABISP &abi = process_sp->GetABI();
    if (!abi)
      return;

    TypeSystemClang *clang_ast_context =
        ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget());
    if (!clang_ast_context)
      return;
    CompilerType voidstar =
        clang_ast_context->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();

    ValueList args;
    Value input_value;
    input_value.SetCompilerType(voidstar);
    args.PushValue(input_value);

    if (!abi->GetArgumentValues(*thread_sp, args))
      return;

    addr_t exception_addr = args.GetValueAtIndex(0)->GetScalar().ULongLong();

    Value value(exception_addr);
    value.SetCompilerType(voidstar);
    exception = ValueObjectConstResult::Create(frame_sp.get(), value,
                                               ConstString("exception"));
    exception = ValueObjectRecognizerSynthesizedValue::Create(
        *exception, eValueTypeVariableArgument);
    exception = exception->GetDynamicValue(eDynamicDontRunTarget);

    m_arguments = ValueObjectListSP(new ValueObjectList());
    m_arguments->Append(exception);

    m_stop_desc = "hit Objective-C exception";
  }

  ValueObjectSP exception;

  lldb::ValueObjectSP GetExceptionObject() override { return exception; }
};

class ObjCExceptionThrowFrameRecognizer : public StackFrameRecognizer {
  lldb::RecognizedStackFrameSP
  RecognizeFrame(lldb::StackFrameSP frame) override {
    return lldb::RecognizedStackFrameSP(
        new ObjCExceptionRecognizedStackFrame(frame));
  };
  std::string GetName() override {
    return "ObjC Exception Throw StackFrame Recognizer";
  }
};

static void RegisterObjCExceptionRecognizer(Process *process) {
  FileSpec module;
  ConstString function;
  std::tie(module, function) = AppleObjCRuntime::GetExceptionThrowLocation();
  std::vector<ConstString> symbols = {function};

  process->GetTarget().GetFrameRecognizerManager().AddRecognizer(
      StackFrameRecognizerSP(new ObjCExceptionThrowFrameRecognizer()),
      module.GetFilename(), symbols,
      /*first_instruction_only*/ true);
}
