//===-- SystemRuntimeMacOSX.cpp ---------------------------------*- C++ -*-===//
//
// 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 "Plugins/Process/Utility/HistoryThread.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/ProcessStructReader.h"
#include "lldb/Target/Queue.h"
#include "lldb/Target/QueueList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"

#include "SystemRuntimeMacOSX.h"

#include <memory>

using namespace lldb;
using namespace lldb_private;

// Create an instance of this class. This function is filled into the plugin
// info class that gets handed out by the plugin factory and allows the lldb to
// instantiate an instance of this class.
SystemRuntime *SystemRuntimeMacOSX::CreateInstance(Process *process) {
  bool create = false;
  if (!create) {
    create = true;
    Module *exe_module = process->GetTarget().GetExecutableModulePointer();
    if (exe_module) {
      ObjectFile *object_file = exe_module->GetObjectFile();
      if (object_file) {
        create = (object_file->GetStrata() == ObjectFile::eStrataUser);
      }
    }

    if (create) {
      const llvm::Triple &triple_ref =
          process->GetTarget().GetArchitecture().GetTriple();
      switch (triple_ref.getOS()) {
      case llvm::Triple::Darwin:
      case llvm::Triple::MacOSX:
      case llvm::Triple::IOS:
      case llvm::Triple::TvOS:
      case llvm::Triple::WatchOS:
      // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
        create = triple_ref.getVendor() == llvm::Triple::Apple;
        break;
      default:
        create = false;
        break;
      }
    }
  }

  if (create)
    return new SystemRuntimeMacOSX(process);
  return nullptr;
}

// Constructor
SystemRuntimeMacOSX::SystemRuntimeMacOSX(Process *process)
    : SystemRuntime(process), m_break_id(LLDB_INVALID_BREAK_ID), m_mutex(),
      m_get_queues_handler(process), m_get_pending_items_handler(process),
      m_get_item_info_handler(process), m_get_thread_item_info_handler(process),
      m_page_to_free(LLDB_INVALID_ADDRESS), m_page_to_free_size(0),
      m_lib_backtrace_recording_info(),
      m_dispatch_queue_offsets_addr(LLDB_INVALID_ADDRESS),
      m_libdispatch_offsets(),
      m_libpthread_layout_offsets_addr(LLDB_INVALID_ADDRESS),
      m_libpthread_offsets(), m_dispatch_tsd_indexes_addr(LLDB_INVALID_ADDRESS),
      m_libdispatch_tsd_indexes(),
      m_dispatch_voucher_offsets_addr(LLDB_INVALID_ADDRESS),
      m_libdispatch_voucher_offsets() {}

// Destructor
SystemRuntimeMacOSX::~SystemRuntimeMacOSX() { Clear(true); }

void SystemRuntimeMacOSX::Detach() {
  m_get_queues_handler.Detach();
  m_get_pending_items_handler.Detach();
  m_get_item_info_handler.Detach();
  m_get_thread_item_info_handler.Detach();
}

// Clear out the state of this class.
void SystemRuntimeMacOSX::Clear(bool clear_process) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);

  if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
    m_process->ClearBreakpointSiteByID(m_break_id);

  if (clear_process)
    m_process = nullptr;
  m_break_id = LLDB_INVALID_BREAK_ID;
}

std::string
SystemRuntimeMacOSX::GetQueueNameFromThreadQAddress(addr_t dispatch_qaddr) {
  std::string dispatch_queue_name;
  if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0)
    return "";

  ReadLibdispatchOffsets();
  if (m_libdispatch_offsets.IsValid()) {
    // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a
    // thread - deref it to get the address of the dispatch_queue_t structure
    // for this thread's queue.
    Status error;
    addr_t dispatch_queue_addr =
        m_process->ReadPointerFromMemory(dispatch_qaddr, error);
    if (error.Success()) {
      if (m_libdispatch_offsets.dqo_version >= 4) {
        // libdispatch versions 4+, pointer to dispatch name is in the queue
        // structure.
        addr_t pointer_to_label_address =
            dispatch_queue_addr + m_libdispatch_offsets.dqo_label;
        addr_t label_addr =
            m_process->ReadPointerFromMemory(pointer_to_label_address, error);
        if (error.Success()) {
          m_process->ReadCStringFromMemory(label_addr, dispatch_queue_name,
                                           error);
        }
      } else {
        // libdispatch versions 1-3, dispatch name is a fixed width char array
        // in the queue structure.
        addr_t label_addr =
            dispatch_queue_addr + m_libdispatch_offsets.dqo_label;
        dispatch_queue_name.resize(m_libdispatch_offsets.dqo_label_size, '\0');
        size_t bytes_read =
            m_process->ReadMemory(label_addr, &dispatch_queue_name[0],
                                  m_libdispatch_offsets.dqo_label_size, error);
        if (bytes_read < m_libdispatch_offsets.dqo_label_size)
          dispatch_queue_name.erase(bytes_read);
      }
    }
  }
  return dispatch_queue_name;
}

lldb::addr_t SystemRuntimeMacOSX::GetLibdispatchQueueAddressFromThreadQAddress(
    addr_t dispatch_qaddr) {
  addr_t libdispatch_queue_t_address = LLDB_INVALID_ADDRESS;
  Status error;
  libdispatch_queue_t_address =
      m_process->ReadPointerFromMemory(dispatch_qaddr, error);
  if (!error.Success()) {
    libdispatch_queue_t_address = LLDB_INVALID_ADDRESS;
  }
  return libdispatch_queue_t_address;
}

lldb::QueueKind SystemRuntimeMacOSX::GetQueueKind(addr_t dispatch_queue_addr) {
  if (dispatch_queue_addr == LLDB_INVALID_ADDRESS || dispatch_queue_addr == 0)
    return eQueueKindUnknown;

  QueueKind kind = eQueueKindUnknown;
  ReadLibdispatchOffsets();
  if (m_libdispatch_offsets.IsValid() &&
      m_libdispatch_offsets.dqo_version >= 4) {
    Status error;
    uint64_t width = m_process->ReadUnsignedIntegerFromMemory(
        dispatch_queue_addr + m_libdispatch_offsets.dqo_width,
        m_libdispatch_offsets.dqo_width_size, 0, error);
    if (error.Success()) {
      if (width == 1) {
        kind = eQueueKindSerial;
      }
      if (width > 1) {
        kind = eQueueKindConcurrent;
      }
    }
  }
  return kind;
}

void SystemRuntimeMacOSX::AddThreadExtendedInfoPacketHints(
    lldb_private::StructuredData::ObjectSP dict_sp) {
  StructuredData::Dictionary *dict = dict_sp->GetAsDictionary();
  if (dict) {
    ReadLibpthreadOffsets();
    if (m_libpthread_offsets.IsValid()) {
      dict->AddIntegerItem("plo_pthread_tsd_base_offset",
                           m_libpthread_offsets.plo_pthread_tsd_base_offset);
      dict->AddIntegerItem(
          "plo_pthread_tsd_base_address_offset",
          m_libpthread_offsets.plo_pthread_tsd_base_address_offset);
      dict->AddIntegerItem("plo_pthread_tsd_entry_size",
                           m_libpthread_offsets.plo_pthread_tsd_entry_size);
    }

    ReadLibdispatchTSDIndexes();
    if (m_libdispatch_tsd_indexes.IsValid()) {
      dict->AddIntegerItem("dti_queue_index",
                           m_libdispatch_tsd_indexes.dti_queue_index);
      dict->AddIntegerItem("dti_voucher_index",
                           m_libdispatch_tsd_indexes.dti_voucher_index);
      dict->AddIntegerItem("dti_qos_class_index",
                           m_libdispatch_tsd_indexes.dti_qos_class_index);
    }
  }
}

bool SystemRuntimeMacOSX::SafeToCallFunctionsOnThisThread(ThreadSP thread_sp) {
  if (thread_sp && thread_sp->GetStackFrameCount() > 0 &&
      thread_sp->GetFrameWithConcreteFrameIndex(0)) {
    const SymbolContext sym_ctx(
        thread_sp->GetFrameWithConcreteFrameIndex(0)->GetSymbolContext(
            eSymbolContextSymbol));
    static ConstString g_select_symbol("__select");
    if (sym_ctx.GetFunctionName() == g_select_symbol) {
      return false;
    }
  }
  return true;
}

lldb::queue_id_t
SystemRuntimeMacOSX::GetQueueIDFromThreadQAddress(lldb::addr_t dispatch_qaddr) {
  queue_id_t queue_id = LLDB_INVALID_QUEUE_ID;

  if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0)
    return queue_id;

  ReadLibdispatchOffsets();
  if (m_libdispatch_offsets.IsValid()) {
    // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a
    // thread - deref it to get the address of the dispatch_queue_t structure
    // for this thread's queue.
    Status error;
    uint64_t dispatch_queue_addr =
        m_process->ReadPointerFromMemory(dispatch_qaddr, error);
    if (error.Success()) {
      addr_t serialnum_address =
          dispatch_queue_addr + m_libdispatch_offsets.dqo_serialnum;
      queue_id_t serialnum = m_process->ReadUnsignedIntegerFromMemory(
          serialnum_address, m_libdispatch_offsets.dqo_serialnum_size,
          LLDB_INVALID_QUEUE_ID, error);
      if (error.Success()) {
        queue_id = serialnum;
      }
    }
  }

  return queue_id;
}

void SystemRuntimeMacOSX::ReadLibdispatchOffsetsAddress() {
  if (m_dispatch_queue_offsets_addr != LLDB_INVALID_ADDRESS)
    return;

  static ConstString g_dispatch_queue_offsets_symbol_name(
      "dispatch_queue_offsets");
  const Symbol *dispatch_queue_offsets_symbol = nullptr;

  // libdispatch symbols were in libSystem.B.dylib up through Mac OS X 10.6
  // ("Snow Leopard")
  ModuleSpec libSystem_module_spec(FileSpec("libSystem.B.dylib"));
  ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule(
      libSystem_module_spec));
  if (module_sp)
    dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType(
        g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);

  // libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion")
  // and later
  if (dispatch_queue_offsets_symbol == nullptr) {
    ModuleSpec libdispatch_module_spec(FileSpec("libdispatch.dylib"));
    module_sp = m_process->GetTarget().GetImages().FindFirstModule(
        libdispatch_module_spec);
    if (module_sp)
      dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType(
          g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
  }
  if (dispatch_queue_offsets_symbol)
    m_dispatch_queue_offsets_addr =
        dispatch_queue_offsets_symbol->GetLoadAddress(&m_process->GetTarget());
}

void SystemRuntimeMacOSX::ReadLibdispatchOffsets() {
  if (m_libdispatch_offsets.IsValid())
    return;

  ReadLibdispatchOffsetsAddress();

  uint8_t memory_buffer[sizeof(struct LibdispatchOffsets)];
  DataExtractor data(memory_buffer, sizeof(memory_buffer),
                     m_process->GetByteOrder(),
                     m_process->GetAddressByteSize());

  Status error;
  if (m_process->ReadMemory(m_dispatch_queue_offsets_addr, memory_buffer,
                            sizeof(memory_buffer),
                            error) == sizeof(memory_buffer)) {
    lldb::offset_t data_offset = 0;

    // The struct LibdispatchOffsets is a series of uint16_t's - extract them
    // all in one big go.
    data.GetU16(&data_offset, &m_libdispatch_offsets.dqo_version,
                sizeof(struct LibdispatchOffsets) / sizeof(uint16_t));
  }
}

void SystemRuntimeMacOSX::ReadLibpthreadOffsetsAddress() {
  if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS)
    return;

  static ConstString g_libpthread_layout_offsets_symbol_name(
      "pthread_layout_offsets");
  const Symbol *libpthread_layout_offsets_symbol = nullptr;

  ModuleSpec libpthread_module_spec(FileSpec("libsystem_pthread.dylib"));
  ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule(
      libpthread_module_spec));
  if (module_sp) {
    libpthread_layout_offsets_symbol =
        module_sp->FindFirstSymbolWithNameAndType(
            g_libpthread_layout_offsets_symbol_name, eSymbolTypeData);
    if (libpthread_layout_offsets_symbol) {
      m_libpthread_layout_offsets_addr =
          libpthread_layout_offsets_symbol->GetLoadAddress(
              &m_process->GetTarget());
    }
  }
}

void SystemRuntimeMacOSX::ReadLibpthreadOffsets() {
  if (m_libpthread_offsets.IsValid())
    return;

  ReadLibpthreadOffsetsAddress();

  if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS) {
    uint8_t memory_buffer[sizeof(struct LibpthreadOffsets)];
    DataExtractor data(memory_buffer, sizeof(memory_buffer),
                       m_process->GetByteOrder(),
                       m_process->GetAddressByteSize());
    Status error;
    if (m_process->ReadMemory(m_libpthread_layout_offsets_addr, memory_buffer,
                              sizeof(memory_buffer),
                              error) == sizeof(memory_buffer)) {
      lldb::offset_t data_offset = 0;

      // The struct LibpthreadOffsets is a series of uint16_t's - extract them
      // all in one big go.
      data.GetU16(&data_offset, &m_libpthread_offsets.plo_version,
                  sizeof(struct LibpthreadOffsets) / sizeof(uint16_t));
    }
  }
}

void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexesAddress() {
  if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS)
    return;

  static ConstString g_libdispatch_tsd_indexes_symbol_name(
      "dispatch_tsd_indexes");
  const Symbol *libdispatch_tsd_indexes_symbol = nullptr;

  ModuleSpec libpthread_module_spec(FileSpec("libdispatch.dylib"));
  ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule(
      libpthread_module_spec));
  if (module_sp) {
    libdispatch_tsd_indexes_symbol = module_sp->FindFirstSymbolWithNameAndType(
        g_libdispatch_tsd_indexes_symbol_name, eSymbolTypeData);
    if (libdispatch_tsd_indexes_symbol) {
      m_dispatch_tsd_indexes_addr =
          libdispatch_tsd_indexes_symbol->GetLoadAddress(
              &m_process->GetTarget());
    }
  }
}

void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexes() {
  if (m_libdispatch_tsd_indexes.IsValid())
    return;

  ReadLibdispatchTSDIndexesAddress();

  if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) {

// We don't need to check the version number right now, it will be at least 2,
// but keep this code around to fetch just the version # for the future where
// we need to fetch alternate versions of the struct.
#if 0
        uint16_t dti_version = 2;
        Address dti_struct_addr;
        if (m_process->GetTarget().ResolveLoadAddress (m_dispatch_tsd_indexes_addr, dti_struct_addr))
        {
            Status error;
            uint16_t version = m_process->GetTarget().ReadUnsignedIntegerFromMemory (dti_struct_addr, false, 2, UINT16_MAX, error);
            if (error.Success() && dti_version != UINT16_MAX)
            {
                dti_version = version;
            }
        }
#endif

    ClangASTContext *ast_ctx =
        ClangASTContext::GetScratch(m_process->GetTarget());
    if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) {
      CompilerType uint16 =
          ast_ctx->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 16);
      CompilerType dispatch_tsd_indexes_s = ast_ctx->CreateRecordType(
          nullptr, lldb::eAccessPublic, "__lldb_dispatch_tsd_indexes_s",
          clang::TTK_Struct, lldb::eLanguageTypeC);

      ClangASTContext::StartTagDeclarationDefinition(dispatch_tsd_indexes_s);
      ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s,
                                            "dti_version", uint16,
                                            lldb::eAccessPublic, 0);
      ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s,
                                            "dti_queue_index", uint16,
                                            lldb::eAccessPublic, 0);
      ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s,
                                            "dti_voucher_index", uint16,
                                            lldb::eAccessPublic, 0);
      ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s,
                                            "dti_qos_class_index", uint16,
                                            lldb::eAccessPublic, 0);
      ClangASTContext::CompleteTagDeclarationDefinition(dispatch_tsd_indexes_s);

      ProcessStructReader struct_reader(m_process, m_dispatch_tsd_indexes_addr,
                                        dispatch_tsd_indexes_s);

      m_libdispatch_tsd_indexes.dti_version =
          struct_reader.GetField<uint16_t>(ConstString("dti_version"));
      m_libdispatch_tsd_indexes.dti_queue_index =
          struct_reader.GetField<uint16_t>(ConstString("dti_queue_index"));
      m_libdispatch_tsd_indexes.dti_voucher_index =
          struct_reader.GetField<uint16_t>(ConstString("dti_voucher_index"));
      m_libdispatch_tsd_indexes.dti_qos_class_index =
          struct_reader.GetField<uint16_t>(ConstString("dti_qos_class_index"));
    }
  }
}

ThreadSP SystemRuntimeMacOSX::GetExtendedBacktraceThread(ThreadSP real_thread,
                                                         ConstString type) {
  ThreadSP originating_thread_sp;
  if (BacktraceRecordingHeadersInitialized() && type == "libdispatch") {
    Status error;

    // real_thread is either an actual, live thread (in which case we need to
    // call into libBacktraceRecording to find its originator) or it is an
    // extended backtrace itself, in which case we get the token from it and
    // call into libBacktraceRecording to find the originator of that token.

    if (real_thread->GetExtendedBacktraceToken() != LLDB_INVALID_ADDRESS) {
      originating_thread_sp = GetExtendedBacktraceFromItemRef(
          real_thread->GetExtendedBacktraceToken());
    } else {
      ThreadSP cur_thread_sp(
          m_process->GetThreadList().GetExpressionExecutionThread());
      AppleGetThreadItemInfoHandler::GetThreadItemInfoReturnInfo ret =
          m_get_thread_item_info_handler.GetThreadItemInfo(
              *cur_thread_sp.get(), real_thread->GetID(), m_page_to_free,
              m_page_to_free_size, error);
      m_page_to_free = LLDB_INVALID_ADDRESS;
      m_page_to_free_size = 0;
      if (ret.item_buffer_ptr != 0 &&
          ret.item_buffer_ptr != LLDB_INVALID_ADDRESS &&
          ret.item_buffer_size > 0) {
        DataBufferHeap data(ret.item_buffer_size, 0);
        if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(),
                                  ret.item_buffer_size, error) &&
            error.Success()) {
          DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
                                  m_process->GetByteOrder(),
                                  m_process->GetAddressByteSize());
          ItemInfo item = ExtractItemInfoFromBuffer(extractor);
          originating_thread_sp = std::make_shared<HistoryThread>(
              *m_process, item.enqueuing_thread_id, item.enqueuing_callstack);
          originating_thread_sp->SetExtendedBacktraceToken(
              item.item_that_enqueued_this);
          originating_thread_sp->SetQueueName(
              item.enqueuing_queue_label.c_str());
          originating_thread_sp->SetQueueID(item.enqueuing_queue_serialnum);
          //                    originating_thread_sp->SetThreadName
          //                    (item.enqueuing_thread_label.c_str());
        }
        m_page_to_free = ret.item_buffer_ptr;
        m_page_to_free_size = ret.item_buffer_size;
      }
    }
  }
  return originating_thread_sp;
}

ThreadSP
SystemRuntimeMacOSX::GetExtendedBacktraceFromItemRef(lldb::addr_t item_ref) {
  ThreadSP return_thread_sp;

  AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;
  ThreadSP cur_thread_sp(
      m_process->GetThreadList().GetExpressionExecutionThread());
  Status error;
  ret = m_get_item_info_handler.GetItemInfo(*cur_thread_sp.get(), item_ref,
                                            m_page_to_free, m_page_to_free_size,
                                            error);
  m_page_to_free = LLDB_INVALID_ADDRESS;
  m_page_to_free_size = 0;
  if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS &&
      ret.item_buffer_size > 0) {
    DataBufferHeap data(ret.item_buffer_size, 0);
    if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(),
                              ret.item_buffer_size, error) &&
        error.Success()) {
      DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
                              m_process->GetByteOrder(),
                              m_process->GetAddressByteSize());
      ItemInfo item = ExtractItemInfoFromBuffer(extractor);
      return_thread_sp = std::make_shared<HistoryThread>(
          *m_process, item.enqueuing_thread_id, item.enqueuing_callstack);
      return_thread_sp->SetExtendedBacktraceToken(item.item_that_enqueued_this);
      return_thread_sp->SetQueueName(item.enqueuing_queue_label.c_str());
      return_thread_sp->SetQueueID(item.enqueuing_queue_serialnum);
      //            return_thread_sp->SetThreadName
      //            (item.enqueuing_thread_label.c_str());

      m_page_to_free = ret.item_buffer_ptr;
      m_page_to_free_size = ret.item_buffer_size;
    }
  }
  return return_thread_sp;
}

ThreadSP
SystemRuntimeMacOSX::GetExtendedBacktraceForQueueItem(QueueItemSP queue_item_sp,
                                                      ConstString type) {
  ThreadSP extended_thread_sp;
  if (type != "libdispatch")
    return extended_thread_sp;

  extended_thread_sp = std::make_shared<HistoryThread>(
      *m_process, queue_item_sp->GetEnqueueingThreadID(),
      queue_item_sp->GetEnqueueingBacktrace());
  extended_thread_sp->SetExtendedBacktraceToken(
      queue_item_sp->GetItemThatEnqueuedThis());
  extended_thread_sp->SetQueueName(queue_item_sp->GetQueueLabel().c_str());
  extended_thread_sp->SetQueueID(queue_item_sp->GetEnqueueingQueueID());
  //    extended_thread_sp->SetThreadName
  //    (queue_item_sp->GetThreadLabel().c_str());

  return extended_thread_sp;
}

/* Returns true if we were able to get the version / offset information
 * out of libBacktraceRecording.  false means we were unable to retrieve
 * this; the queue_info_version field will be 0.
 */

bool SystemRuntimeMacOSX::BacktraceRecordingHeadersInitialized() {
  if (m_lib_backtrace_recording_info.queue_info_version != 0)
    return true;

  addr_t queue_info_version_address = LLDB_INVALID_ADDRESS;
  addr_t queue_info_data_offset_address = LLDB_INVALID_ADDRESS;
  addr_t item_info_version_address = LLDB_INVALID_ADDRESS;
  addr_t item_info_data_offset_address = LLDB_INVALID_ADDRESS;
  Target &target = m_process->GetTarget();

  static ConstString introspection_dispatch_queue_info_version(
      "__introspection_dispatch_queue_info_version");
  SymbolContextList sc_list;
  m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(
      introspection_dispatch_queue_info_version, eSymbolTypeData, sc_list);
  if (!sc_list.IsEmpty()) {
    SymbolContext sc;
    sc_list.GetContextAtIndex(0, sc);
    AddressRange addr_range;
    sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range);
    queue_info_version_address =
        addr_range.GetBaseAddress().GetLoadAddress(&target);
  }
  sc_list.Clear();

  static ConstString introspection_dispatch_queue_info_data_offset(
      "__introspection_dispatch_queue_info_data_offset");
  m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(
      introspection_dispatch_queue_info_data_offset, eSymbolTypeData, sc_list);
  if (!sc_list.IsEmpty()) {
    SymbolContext sc;
    sc_list.GetContextAtIndex(0, sc);
    AddressRange addr_range;
    sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range);
    queue_info_data_offset_address =
        addr_range.GetBaseAddress().GetLoadAddress(&target);
  }
  sc_list.Clear();

  static ConstString introspection_dispatch_item_info_version(
      "__introspection_dispatch_item_info_version");
  m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(
      introspection_dispatch_item_info_version, eSymbolTypeData, sc_list);
  if (!sc_list.IsEmpty()) {
    SymbolContext sc;
    sc_list.GetContextAtIndex(0, sc);
    AddressRange addr_range;
    sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range);
    item_info_version_address =
        addr_range.GetBaseAddress().GetLoadAddress(&target);
  }
  sc_list.Clear();

  static ConstString introspection_dispatch_item_info_data_offset(
      "__introspection_dispatch_item_info_data_offset");
  m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(
      introspection_dispatch_item_info_data_offset, eSymbolTypeData, sc_list);
  if (!sc_list.IsEmpty()) {
    SymbolContext sc;
    sc_list.GetContextAtIndex(0, sc);
    AddressRange addr_range;
    sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range);
    item_info_data_offset_address =
        addr_range.GetBaseAddress().GetLoadAddress(&target);
  }

  if (queue_info_version_address != LLDB_INVALID_ADDRESS &&
      queue_info_data_offset_address != LLDB_INVALID_ADDRESS &&
      item_info_version_address != LLDB_INVALID_ADDRESS &&
      item_info_data_offset_address != LLDB_INVALID_ADDRESS) {
    Status error;
    m_lib_backtrace_recording_info.queue_info_version =
        m_process->ReadUnsignedIntegerFromMemory(queue_info_version_address, 2,
                                                 0, error);
    if (error.Success()) {
      m_lib_backtrace_recording_info.queue_info_data_offset =
          m_process->ReadUnsignedIntegerFromMemory(
              queue_info_data_offset_address, 2, 0, error);
      if (error.Success()) {
        m_lib_backtrace_recording_info.item_info_version =
            m_process->ReadUnsignedIntegerFromMemory(item_info_version_address,
                                                     2, 0, error);
        if (error.Success()) {
          m_lib_backtrace_recording_info.item_info_data_offset =
              m_process->ReadUnsignedIntegerFromMemory(
                  item_info_data_offset_address, 2, 0, error);
          if (!error.Success()) {
            m_lib_backtrace_recording_info.queue_info_version = 0;
          }
        } else {
          m_lib_backtrace_recording_info.queue_info_version = 0;
        }
      } else {
        m_lib_backtrace_recording_info.queue_info_version = 0;
      }
    }
  }

  return m_lib_backtrace_recording_info.queue_info_version != 0;
}

const std::vector<ConstString> &
SystemRuntimeMacOSX::GetExtendedBacktraceTypes() {
  if (m_types.size() == 0) {
    m_types.push_back(ConstString("libdispatch"));
    // We could have pthread as another type in the future if we have a way of
    // gathering that information & it's useful to distinguish between them.
  }
  return m_types;
}

void SystemRuntimeMacOSX::PopulateQueueList(
    lldb_private::QueueList &queue_list) {
  if (BacktraceRecordingHeadersInitialized()) {
    AppleGetQueuesHandler::GetQueuesReturnInfo queue_info_pointer;
    ThreadSP cur_thread_sp(
        m_process->GetThreadList().GetExpressionExecutionThread());
    if (cur_thread_sp) {
      Status error;
      queue_info_pointer = m_get_queues_handler.GetCurrentQueues(
          *cur_thread_sp.get(), m_page_to_free, m_page_to_free_size, error);
      m_page_to_free = LLDB_INVALID_ADDRESS;
      m_page_to_free_size = 0;
      if (error.Success()) {

        if (queue_info_pointer.count > 0 &&
            queue_info_pointer.queues_buffer_size > 0 &&
            queue_info_pointer.queues_buffer_ptr != 0 &&
            queue_info_pointer.queues_buffer_ptr != LLDB_INVALID_ADDRESS) {
          PopulateQueuesUsingLibBTR(queue_info_pointer.queues_buffer_ptr,
                                    queue_info_pointer.queues_buffer_size,
                                    queue_info_pointer.count, queue_list);
        }
      }
    }
  }

  // We either didn't have libBacktraceRecording (and need to create the queues
  // list based on threads) or we did get the queues list from
  // libBacktraceRecording but some special queues may not be included in its
  // information.  This is needed because libBacktraceRecording will only list
  // queues with pending or running items by default - but the magic com.apple
  // .main-thread queue on thread 1 is always around.

  for (ThreadSP thread_sp : m_process->Threads()) {
    if (thread_sp->GetAssociatedWithLibdispatchQueue() != eLazyBoolNo) {
      if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID) {
        if (queue_list.FindQueueByID(thread_sp->GetQueueID()).get() ==
            nullptr) {
          QueueSP queue_sp(new Queue(m_process->shared_from_this(),
                                     thread_sp->GetQueueID(),
                                     thread_sp->GetQueueName()));
          if (thread_sp->ThreadHasQueueInformation()) {
            queue_sp->SetKind(thread_sp->GetQueueKind());
            queue_sp->SetLibdispatchQueueAddress(
                thread_sp->GetQueueLibdispatchQueueAddress());
            queue_list.AddQueue(queue_sp);
          } else {
            queue_sp->SetKind(
                GetQueueKind(thread_sp->GetQueueLibdispatchQueueAddress()));
            queue_sp->SetLibdispatchQueueAddress(
                thread_sp->GetQueueLibdispatchQueueAddress());
            queue_list.AddQueue(queue_sp);
          }
        }
      }
    }
  }
}

// Returns either an array of introspection_dispatch_item_info_ref's for the
// pending items on a queue or an array introspection_dispatch_item_info_ref's
// and code addresses for the pending items on a queue.  The information about
// each of these pending items then needs to be fetched individually by passing
// the ref to libBacktraceRecording.

SystemRuntimeMacOSX::PendingItemsForQueue
SystemRuntimeMacOSX::GetPendingItemRefsForQueue(lldb::addr_t queue) {
  PendingItemsForQueue pending_item_refs;
  AppleGetPendingItemsHandler::GetPendingItemsReturnInfo pending_items_pointer;
  ThreadSP cur_thread_sp(
      m_process->GetThreadList().GetExpressionExecutionThread());
  if (cur_thread_sp) {
    Status error;
    pending_items_pointer = m_get_pending_items_handler.GetPendingItems(
        *cur_thread_sp.get(), queue, m_page_to_free, m_page_to_free_size,
        error);
    m_page_to_free = LLDB_INVALID_ADDRESS;
    m_page_to_free_size = 0;
    if (error.Success()) {
      if (pending_items_pointer.count > 0 &&
          pending_items_pointer.items_buffer_size > 0 &&
          pending_items_pointer.items_buffer_ptr != 0 &&
          pending_items_pointer.items_buffer_ptr != LLDB_INVALID_ADDRESS) {
        DataBufferHeap data(pending_items_pointer.items_buffer_size, 0);
        if (m_process->ReadMemory(
                pending_items_pointer.items_buffer_ptr, data.GetBytes(),
                pending_items_pointer.items_buffer_size, error)) {
          DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
                                  m_process->GetByteOrder(),
                                  m_process->GetAddressByteSize());

          // We either have an array of
          //    void* item_ref
          // (old style) or we have a structure returned which looks like
          //
          // struct introspection_dispatch_pending_item_info_s {
          //   void *item_ref;
          //   void *function_or_block;
          // };
          //
          // struct introspection_dispatch_pending_items_array_s {
          //   uint32_t version;
          //   uint32_t size_of_item_info;
          //   introspection_dispatch_pending_item_info_s items[];
          //   }

          offset_t offset = 0;
          int i = 0;
          uint32_t version = extractor.GetU32(&offset);
          if (version == 1) {
            pending_item_refs.new_style = true;
            uint32_t item_size = extractor.GetU32(&offset);
            uint32_t start_of_array_offset = offset;
            while (offset < pending_items_pointer.items_buffer_size &&
                   static_cast<size_t>(i) < pending_items_pointer.count) {
              offset = start_of_array_offset + (i * item_size);
              ItemRefAndCodeAddress item;
              item.item_ref = extractor.GetPointer(&offset);
              item.code_address = extractor.GetPointer(&offset);
              pending_item_refs.item_refs_and_code_addresses.push_back(item);
              i++;
            }
          } else {
            offset = 0;
            pending_item_refs.new_style = false;
            while (offset < pending_items_pointer.items_buffer_size &&
                   static_cast<size_t>(i) < pending_items_pointer.count) {
              ItemRefAndCodeAddress item;
              item.item_ref = extractor.GetPointer(&offset);
              item.code_address = LLDB_INVALID_ADDRESS;
              pending_item_refs.item_refs_and_code_addresses.push_back(item);
              i++;
            }
          }
        }
        m_page_to_free = pending_items_pointer.items_buffer_ptr;
        m_page_to_free_size = pending_items_pointer.items_buffer_size;
      }
    }
  }
  return pending_item_refs;
}

void SystemRuntimeMacOSX::PopulatePendingItemsForQueue(Queue *queue) {
  if (BacktraceRecordingHeadersInitialized()) {
    PendingItemsForQueue pending_item_refs =
        GetPendingItemRefsForQueue(queue->GetLibdispatchQueueAddress());
    for (ItemRefAndCodeAddress pending_item :
         pending_item_refs.item_refs_and_code_addresses) {
      Address addr;
      m_process->GetTarget().ResolveLoadAddress(pending_item.code_address,
                                                addr);
      QueueItemSP queue_item_sp(new QueueItem(queue->shared_from_this(),
                                              m_process->shared_from_this(),
                                              pending_item.item_ref, addr));
      queue->PushPendingQueueItem(queue_item_sp);
    }
  }
}

void SystemRuntimeMacOSX::CompleteQueueItem(QueueItem *queue_item,
                                            addr_t item_ref) {
  AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;

  ThreadSP cur_thread_sp(
      m_process->GetThreadList().GetExpressionExecutionThread());
  Status error;
  ret = m_get_item_info_handler.GetItemInfo(*cur_thread_sp.get(), item_ref,
                                            m_page_to_free, m_page_to_free_size,
                                            error);
  m_page_to_free = LLDB_INVALID_ADDRESS;
  m_page_to_free_size = 0;
  if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS &&
      ret.item_buffer_size > 0) {
    DataBufferHeap data(ret.item_buffer_size, 0);
    if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(),
                              ret.item_buffer_size, error) &&
        error.Success()) {
      DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
                              m_process->GetByteOrder(),
                              m_process->GetAddressByteSize());
      ItemInfo item = ExtractItemInfoFromBuffer(extractor);
      queue_item->SetItemThatEnqueuedThis(item.item_that_enqueued_this);
      queue_item->SetEnqueueingThreadID(item.enqueuing_thread_id);
      queue_item->SetEnqueueingQueueID(item.enqueuing_queue_serialnum);
      queue_item->SetStopID(item.stop_id);
      queue_item->SetEnqueueingBacktrace(item.enqueuing_callstack);
      queue_item->SetThreadLabel(item.enqueuing_thread_label);
      queue_item->SetQueueLabel(item.enqueuing_queue_label);
      queue_item->SetTargetQueueLabel(item.target_queue_label);
    }
    m_page_to_free = ret.item_buffer_ptr;
    m_page_to_free_size = ret.item_buffer_size;
  }
}

void SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR(
    lldb::addr_t queues_buffer, uint64_t queues_buffer_size, uint64_t count,
    lldb_private::QueueList &queue_list) {
  Status error;
  DataBufferHeap data(queues_buffer_size, 0);
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME));
  if (m_process->ReadMemory(queues_buffer, data.GetBytes(), queues_buffer_size,
                            error) == queues_buffer_size &&
      error.Success()) {
    // We've read the information out of inferior memory; free it on the next
    // call we make
    m_page_to_free = queues_buffer;
    m_page_to_free_size = queues_buffer_size;

    DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
                            m_process->GetByteOrder(),
                            m_process->GetAddressByteSize());
    offset_t offset = 0;
    uint64_t queues_read = 0;

    // The information about the queues is stored in this format (v1): typedef
    // struct introspection_dispatch_queue_info_s {
    //     uint32_t offset_to_next;
    //     dispatch_queue_t queue;
    //     uint64_t serialnum;     // queue's serialnum in the process, as
    //     provided by libdispatch
    //     uint32_t running_work_items_count;
    //     uint32_t pending_work_items_count;
    //
    //     char data[];     // Starting here, we have variable-length data:
    //     // char queue_label[];
    // } introspection_dispatch_queue_info_s;

    while (queues_read < count && offset < queues_buffer_size) {
      offset_t start_of_this_item = offset;

      uint32_t offset_to_next = extractor.GetU32(&offset);

      offset += 4; // Skip over the 4 bytes of reserved space
      addr_t queue = extractor.GetPointer(&offset);
      uint64_t serialnum = extractor.GetU64(&offset);
      uint32_t running_work_items_count = extractor.GetU32(&offset);
      uint32_t pending_work_items_count = extractor.GetU32(&offset);

      // Read the first field of the variable length data
      offset = start_of_this_item +
               m_lib_backtrace_recording_info.queue_info_data_offset;
      const char *queue_label = extractor.GetCStr(&offset);
      if (queue_label == nullptr)
        queue_label = "";

      offset_t start_of_next_item = start_of_this_item + offset_to_next;
      offset = start_of_next_item;

      LLDB_LOGF(log,
                "SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR added "
                "queue with dispatch_queue_t 0x%" PRIx64
                ", serial number 0x%" PRIx64
                ", running items %d, pending items %d, name '%s'",
                queue, serialnum, running_work_items_count,
                pending_work_items_count, queue_label);

      QueueSP queue_sp(
          new Queue(m_process->shared_from_this(), serialnum, queue_label));
      queue_sp->SetNumRunningWorkItems(running_work_items_count);
      queue_sp->SetNumPendingWorkItems(pending_work_items_count);
      queue_sp->SetLibdispatchQueueAddress(queue);
      queue_sp->SetKind(GetQueueKind(queue));
      queue_list.AddQueue(queue_sp);
      queues_read++;
    }
  }
}

SystemRuntimeMacOSX::ItemInfo SystemRuntimeMacOSX::ExtractItemInfoFromBuffer(
    lldb_private::DataExtractor &extractor) {
  ItemInfo item;

  offset_t offset = 0;

  item.item_that_enqueued_this = extractor.GetPointer(&offset);
  item.function_or_block = extractor.GetPointer(&offset);
  item.enqueuing_thread_id = extractor.GetU64(&offset);
  item.enqueuing_queue_serialnum = extractor.GetU64(&offset);
  item.target_queue_serialnum = extractor.GetU64(&offset);
  item.enqueuing_callstack_frame_count = extractor.GetU32(&offset);
  item.stop_id = extractor.GetU32(&offset);

  offset = m_lib_backtrace_recording_info.item_info_data_offset;

  for (uint32_t i = 0; i < item.enqueuing_callstack_frame_count; i++) {
    item.enqueuing_callstack.push_back(extractor.GetPointer(&offset));
  }
  item.enqueuing_thread_label = extractor.GetCStr(&offset);
  item.enqueuing_queue_label = extractor.GetCStr(&offset);
  item.target_queue_label = extractor.GetCStr(&offset);

  return item;
}

void SystemRuntimeMacOSX::Initialize() {
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                GetPluginDescriptionStatic(), CreateInstance);
}

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

lldb_private::ConstString SystemRuntimeMacOSX::GetPluginNameStatic() {
  static ConstString g_name("systemruntime-macosx");
  return g_name;
}

const char *SystemRuntimeMacOSX::GetPluginDescriptionStatic() {
  return "System runtime plugin for Mac OS X native libraries.";
}

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

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