brintos

brintos / llvm-project-archived public Read only

0
0
Text · 40.5 KiB · 04a25e4 Raw
1027 lines · cpp
1//===-- SystemRuntimeMacOSX.cpp -------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "Plugins/Process/Utility/HistoryThread.h"10#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"11#include "lldb/Breakpoint/StoppointCallbackContext.h"12#include "lldb/Core/Module.h"13#include "lldb/Core/ModuleSpec.h"14#include "lldb/Core/PluginManager.h"15#include "lldb/Core/Section.h"16#include "lldb/Symbol/ObjectFile.h"17#include "lldb/Symbol/SymbolContext.h"18#include "lldb/Target/Process.h"19#include "lldb/Target/ProcessStructReader.h"20#include "lldb/Target/Queue.h"21#include "lldb/Target/QueueList.h"22#include "lldb/Target/Target.h"23#include "lldb/Target/Thread.h"24#include "lldb/Utility/DataBufferHeap.h"25#include "lldb/Utility/DataExtractor.h"26#include "lldb/Utility/FileSpec.h"27#include "lldb/Utility/LLDBLog.h"28#include "lldb/Utility/Log.h"29#include "lldb/Utility/StreamString.h"30 31#include "AbortWithPayloadFrameRecognizer.h"32#include "SystemRuntimeMacOSX.h"33 34#include <memory>35 36using namespace lldb;37using namespace lldb_private;38 39LLDB_PLUGIN_DEFINE(SystemRuntimeMacOSX)40 41// Create an instance of this class. This function is filled into the plugin42// info class that gets handed out by the plugin factory and allows the lldb to43// instantiate an instance of this class.44SystemRuntime *SystemRuntimeMacOSX::CreateInstance(Process *process) {45  bool create = false;46  if (!create) {47    create = true;48    Module *exe_module = process->GetTarget().GetExecutableModulePointer();49    if (exe_module) {50      ObjectFile *object_file = exe_module->GetObjectFile();51      if (object_file) {52        create = (object_file->GetStrata() == ObjectFile::eStrataUser);53      }54    }55 56    if (create) {57      const llvm::Triple &triple_ref =58          process->GetTarget().GetArchitecture().GetTriple();59      switch (triple_ref.getOS()) {60      case llvm::Triple::Darwin:61      case llvm::Triple::MacOSX:62      case llvm::Triple::IOS:63      case llvm::Triple::TvOS:64      case llvm::Triple::WatchOS:65      case llvm::Triple::BridgeOS:66      case llvm::Triple::DriverKit:67      case llvm::Triple::XROS:68        create = triple_ref.getVendor() == llvm::Triple::Apple;69        break;70      default:71        create = false;72        break;73      }74    }75  }76 77  if (create)78    return new SystemRuntimeMacOSX(process);79  return nullptr;80}81 82// Constructor83SystemRuntimeMacOSX::SystemRuntimeMacOSX(Process *process)84    : SystemRuntime(process), m_break_id(LLDB_INVALID_BREAK_ID), m_mutex(),85      m_get_queues_handler(process), m_get_pending_items_handler(process),86      m_get_item_info_handler(process), m_get_thread_item_info_handler(process),87      m_page_to_free(LLDB_INVALID_ADDRESS), m_page_to_free_size(0),88      m_lib_backtrace_recording_info(),89      m_dispatch_queue_offsets_addr(LLDB_INVALID_ADDRESS),90      m_libdispatch_offsets(),91      m_libpthread_layout_offsets_addr(LLDB_INVALID_ADDRESS),92      m_libpthread_offsets(), m_dispatch_tsd_indexes_addr(LLDB_INVALID_ADDRESS),93      m_libdispatch_tsd_indexes(),94      m_dispatch_voucher_offsets_addr(LLDB_INVALID_ADDRESS),95      m_libdispatch_voucher_offsets() {96 97  RegisterAbortWithPayloadFrameRecognizer(process);98}99 100// Destructor101SystemRuntimeMacOSX::~SystemRuntimeMacOSX() { Clear(true); }102 103void SystemRuntimeMacOSX::Detach() {104  m_get_queues_handler.Detach();105  m_get_pending_items_handler.Detach();106  m_get_item_info_handler.Detach();107  m_get_thread_item_info_handler.Detach();108}109 110// Clear out the state of this class.111void SystemRuntimeMacOSX::Clear(bool clear_process) {112  std::lock_guard<std::recursive_mutex> guard(m_mutex);113 114  if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))115    m_process->ClearBreakpointSiteByID(m_break_id);116 117  if (clear_process)118    m_process = nullptr;119  m_break_id = LLDB_INVALID_BREAK_ID;120}121 122std::string123SystemRuntimeMacOSX::GetQueueNameFromThreadQAddress(addr_t dispatch_qaddr) {124  std::string dispatch_queue_name;125  if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0)126    return "";127 128  ReadLibdispatchOffsets();129  if (m_libdispatch_offsets.IsValid()) {130    // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a131    // thread - deref it to get the address of the dispatch_queue_t structure132    // for this thread's queue.133    Status error;134    addr_t dispatch_queue_addr =135        m_process->ReadPointerFromMemory(dispatch_qaddr, error);136    if (error.Success()) {137      if (m_libdispatch_offsets.dqo_version >= 4) {138        // libdispatch versions 4+, pointer to dispatch name is in the queue139        // structure.140        addr_t pointer_to_label_address =141            dispatch_queue_addr + m_libdispatch_offsets.dqo_label;142        addr_t label_addr =143            m_process->ReadPointerFromMemory(pointer_to_label_address, error);144        if (error.Success()) {145          m_process->ReadCStringFromMemory(label_addr, dispatch_queue_name,146                                           error);147        }148      } else {149        // libdispatch versions 1-3, dispatch name is a fixed width char array150        // in the queue structure.151        addr_t label_addr =152            dispatch_queue_addr + m_libdispatch_offsets.dqo_label;153        dispatch_queue_name.resize(m_libdispatch_offsets.dqo_label_size, '\0');154        size_t bytes_read =155            m_process->ReadMemory(label_addr, &dispatch_queue_name[0],156                                  m_libdispatch_offsets.dqo_label_size, error);157        if (bytes_read < m_libdispatch_offsets.dqo_label_size)158          dispatch_queue_name.erase(bytes_read);159      }160    }161  }162  return dispatch_queue_name;163}164 165lldb::addr_t SystemRuntimeMacOSX::GetLibdispatchQueueAddressFromThreadQAddress(166    addr_t dispatch_qaddr) {167  addr_t libdispatch_queue_t_address = LLDB_INVALID_ADDRESS;168  Status error;169  libdispatch_queue_t_address =170      m_process->ReadPointerFromMemory(dispatch_qaddr, error);171  if (!error.Success()) {172    libdispatch_queue_t_address = LLDB_INVALID_ADDRESS;173  }174  return libdispatch_queue_t_address;175}176 177lldb::QueueKind SystemRuntimeMacOSX::GetQueueKind(addr_t dispatch_queue_addr) {178  if (dispatch_queue_addr == LLDB_INVALID_ADDRESS || dispatch_queue_addr == 0)179    return eQueueKindUnknown;180 181  QueueKind kind = eQueueKindUnknown;182  ReadLibdispatchOffsets();183  if (m_libdispatch_offsets.IsValid() &&184      m_libdispatch_offsets.dqo_version >= 4) {185    Status error;186    uint64_t width = m_process->ReadUnsignedIntegerFromMemory(187        dispatch_queue_addr + m_libdispatch_offsets.dqo_width,188        m_libdispatch_offsets.dqo_width_size, 0, error);189    if (error.Success()) {190      if (width == 1) {191        kind = eQueueKindSerial;192      }193      if (width > 1) {194        kind = eQueueKindConcurrent;195      }196    }197  }198  return kind;199}200 201void SystemRuntimeMacOSX::AddThreadExtendedInfoPacketHints(202    lldb_private::StructuredData::ObjectSP dict_sp) {203  StructuredData::Dictionary *dict = dict_sp->GetAsDictionary();204  if (dict) {205    ReadLibpthreadOffsets();206    if (m_libpthread_offsets.IsValid()) {207      dict->AddIntegerItem("plo_pthread_tsd_base_offset",208                           m_libpthread_offsets.plo_pthread_tsd_base_offset);209      dict->AddIntegerItem(210          "plo_pthread_tsd_base_address_offset",211          m_libpthread_offsets.plo_pthread_tsd_base_address_offset);212      dict->AddIntegerItem("plo_pthread_tsd_entry_size",213                           m_libpthread_offsets.plo_pthread_tsd_entry_size);214    }215 216    ReadLibdispatchTSDIndexes();217    if (m_libdispatch_tsd_indexes.IsValid()) {218      dict->AddIntegerItem("dti_queue_index",219                           m_libdispatch_tsd_indexes.dti_queue_index);220      dict->AddIntegerItem("dti_voucher_index",221                           m_libdispatch_tsd_indexes.dti_voucher_index);222      dict->AddIntegerItem("dti_qos_class_index",223                           m_libdispatch_tsd_indexes.dti_qos_class_index);224    }225  }226}227 228bool SystemRuntimeMacOSX::SafeToCallFunctionsOnThisThread(ThreadSP thread_sp) {229  if (thread_sp && thread_sp->GetFrameWithConcreteFrameIndex(0)) {230    const SymbolContext sym_ctx(231        thread_sp->GetFrameWithConcreteFrameIndex(0)->GetSymbolContext(232            eSymbolContextSymbol));233    static ConstString g_select_symbol("__select");234    if (sym_ctx.GetFunctionName() == g_select_symbol) {235      return false;236    }237  }238  return true;239}240 241lldb::queue_id_t242SystemRuntimeMacOSX::GetQueueIDFromThreadQAddress(lldb::addr_t dispatch_qaddr) {243  queue_id_t queue_id = LLDB_INVALID_QUEUE_ID;244 245  if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0)246    return queue_id;247 248  ReadLibdispatchOffsets();249  if (m_libdispatch_offsets.IsValid()) {250    // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a251    // thread - deref it to get the address of the dispatch_queue_t structure252    // for this thread's queue.253    Status error;254    uint64_t dispatch_queue_addr =255        m_process->ReadPointerFromMemory(dispatch_qaddr, error);256    if (error.Success()) {257      addr_t serialnum_address =258          dispatch_queue_addr + m_libdispatch_offsets.dqo_serialnum;259      queue_id_t serialnum = m_process->ReadUnsignedIntegerFromMemory(260          serialnum_address, m_libdispatch_offsets.dqo_serialnum_size,261          LLDB_INVALID_QUEUE_ID, error);262      if (error.Success()) {263        queue_id = serialnum;264      }265    }266  }267 268  return queue_id;269}270 271void SystemRuntimeMacOSX::ReadLibdispatchOffsetsAddress() {272  if (m_dispatch_queue_offsets_addr != LLDB_INVALID_ADDRESS)273    return;274 275  static ConstString g_dispatch_queue_offsets_symbol_name(276      "dispatch_queue_offsets");277  const Symbol *dispatch_queue_offsets_symbol = nullptr;278 279  // libdispatch symbols were in libSystem.B.dylib up through Mac OS X 10.6280  // ("Snow Leopard")281  ModuleSpec libSystem_module_spec(FileSpec("libSystem.B.dylib"));282  ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule(283      libSystem_module_spec));284  if (module_sp)285    dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType(286        g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);287 288  // libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion")289  // and later290  if (dispatch_queue_offsets_symbol == nullptr) {291    ModuleSpec libdispatch_module_spec(FileSpec("libdispatch.dylib"));292    module_sp = m_process->GetTarget().GetImages().FindFirstModule(293        libdispatch_module_spec);294    if (module_sp)295      dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType(296          g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);297  }298  if (dispatch_queue_offsets_symbol)299    m_dispatch_queue_offsets_addr =300        dispatch_queue_offsets_symbol->GetLoadAddress(&m_process->GetTarget());301}302 303void SystemRuntimeMacOSX::ReadLibdispatchOffsets() {304  if (m_libdispatch_offsets.IsValid())305    return;306 307  ReadLibdispatchOffsetsAddress();308 309  uint8_t memory_buffer[sizeof(struct LibdispatchOffsets)];310  DataExtractor data(memory_buffer, sizeof(memory_buffer),311                     m_process->GetByteOrder(),312                     m_process->GetAddressByteSize());313 314  Status error;315  if (m_process->ReadMemory(m_dispatch_queue_offsets_addr, memory_buffer,316                            sizeof(memory_buffer),317                            error) == sizeof(memory_buffer)) {318    lldb::offset_t data_offset = 0;319 320    // The struct LibdispatchOffsets is a series of uint16_t's - extract them321    // all in one big go.322    data.GetU16(&data_offset, &m_libdispatch_offsets.dqo_version,323                sizeof(struct LibdispatchOffsets) / sizeof(uint16_t));324  }325}326 327void SystemRuntimeMacOSX::ReadLibpthreadOffsetsAddress() {328  if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS)329    return;330 331  static ConstString g_libpthread_layout_offsets_symbol_name(332      "pthread_layout_offsets");333  const Symbol *libpthread_layout_offsets_symbol = nullptr;334 335  ModuleSpec libpthread_module_spec(FileSpec("libsystem_pthread.dylib"));336  ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule(337      libpthread_module_spec));338  if (module_sp) {339    libpthread_layout_offsets_symbol =340        module_sp->FindFirstSymbolWithNameAndType(341            g_libpthread_layout_offsets_symbol_name, eSymbolTypeData);342    if (libpthread_layout_offsets_symbol) {343      m_libpthread_layout_offsets_addr =344          libpthread_layout_offsets_symbol->GetLoadAddress(345              &m_process->GetTarget());346    }347  }348}349 350void SystemRuntimeMacOSX::ReadLibpthreadOffsets() {351  if (m_libpthread_offsets.IsValid())352    return;353 354  ReadLibpthreadOffsetsAddress();355 356  if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS) {357    uint8_t memory_buffer[sizeof(struct LibpthreadOffsets)];358    DataExtractor data(memory_buffer, sizeof(memory_buffer),359                       m_process->GetByteOrder(),360                       m_process->GetAddressByteSize());361    Status error;362    if (m_process->ReadMemory(m_libpthread_layout_offsets_addr, memory_buffer,363                              sizeof(memory_buffer),364                              error) == sizeof(memory_buffer)) {365      lldb::offset_t data_offset = 0;366 367      // The struct LibpthreadOffsets is a series of uint16_t's - extract them368      // all in one big go.369      data.GetU16(&data_offset, &m_libpthread_offsets.plo_version,370                  sizeof(struct LibpthreadOffsets) / sizeof(uint16_t));371    }372  }373}374 375void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexesAddress() {376  if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS)377    return;378 379  static ConstString g_libdispatch_tsd_indexes_symbol_name(380      "dispatch_tsd_indexes");381  const Symbol *libdispatch_tsd_indexes_symbol = nullptr;382 383  ModuleSpec libpthread_module_spec(FileSpec("libdispatch.dylib"));384  ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule(385      libpthread_module_spec));386  if (module_sp) {387    libdispatch_tsd_indexes_symbol = module_sp->FindFirstSymbolWithNameAndType(388        g_libdispatch_tsd_indexes_symbol_name, eSymbolTypeData);389    if (libdispatch_tsd_indexes_symbol) {390      m_dispatch_tsd_indexes_addr =391          libdispatch_tsd_indexes_symbol->GetLoadAddress(392              &m_process->GetTarget());393    }394  }395}396 397void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexes() {398  if (m_libdispatch_tsd_indexes.IsValid())399    return;400 401  ReadLibdispatchTSDIndexesAddress();402 403  if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) {404 405// We don't need to check the version number right now, it will be at least 2,406// but keep this code around to fetch just the version # for the future where407// we need to fetch alternate versions of the struct.408#if 0409        uint16_t dti_version = 2;410        Address dti_struct_addr;411        if (m_process->GetTarget().ResolveLoadAddress (m_dispatch_tsd_indexes_addr, dti_struct_addr))412        {413            Status error;414            uint16_t version = m_process->GetTarget().ReadUnsignedIntegerFromMemory (dti_struct_addr, false, 2, UINT16_MAX, error);415            if (error.Success() && dti_version != UINT16_MAX)416            {417                dti_version = version;418            }419        }420#endif421 422    TypeSystemClangSP scratch_ts_sp =423        ScratchTypeSystemClang::GetForTarget(m_process->GetTarget());424    if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) {425      CompilerType uint16 =426          scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 16);427      CompilerType dispatch_tsd_indexes_s = scratch_ts_sp->CreateRecordType(428          nullptr, OptionalClangModuleID(), lldb::eAccessPublic,429          "__lldb_dispatch_tsd_indexes_s",430          llvm::to_underlying(clang::TagTypeKind::Struct),431          lldb::eLanguageTypeC);432 433      TypeSystemClang::StartTagDeclarationDefinition(dispatch_tsd_indexes_s);434      TypeSystemClang::AddFieldToRecordType(dispatch_tsd_indexes_s,435                                            "dti_version", uint16,436                                            lldb::eAccessPublic, 0);437      TypeSystemClang::AddFieldToRecordType(dispatch_tsd_indexes_s,438                                            "dti_queue_index", uint16,439                                            lldb::eAccessPublic, 0);440      TypeSystemClang::AddFieldToRecordType(dispatch_tsd_indexes_s,441                                            "dti_voucher_index", uint16,442                                            lldb::eAccessPublic, 0);443      TypeSystemClang::AddFieldToRecordType(dispatch_tsd_indexes_s,444                                            "dti_qos_class_index", uint16,445                                            lldb::eAccessPublic, 0);446      TypeSystemClang::CompleteTagDeclarationDefinition(dispatch_tsd_indexes_s);447 448      ProcessStructReader struct_reader(m_process, m_dispatch_tsd_indexes_addr,449                                        dispatch_tsd_indexes_s);450 451      m_libdispatch_tsd_indexes.dti_version =452          struct_reader.GetField<uint16_t>("dti_version");453      m_libdispatch_tsd_indexes.dti_queue_index =454          struct_reader.GetField<uint16_t>("dti_queue_index");455      m_libdispatch_tsd_indexes.dti_voucher_index =456          struct_reader.GetField<uint16_t>("dti_voucher_index");457      m_libdispatch_tsd_indexes.dti_qos_class_index =458          struct_reader.GetField<uint16_t>("dti_qos_class_index");459    }460  }461}462 463ThreadSP SystemRuntimeMacOSX::GetExtendedBacktraceThread(ThreadSP real_thread,464                                                         ConstString type) {465  ThreadSP originating_thread_sp;466  if (BacktraceRecordingHeadersInitialized() && type == "libdispatch") {467    Status error;468 469    // real_thread is either an actual, live thread (in which case we need to470    // call into libBacktraceRecording to find its originator) or it is an471    // extended backtrace itself, in which case we get the token from it and472    // call into libBacktraceRecording to find the originator of that token.473 474    if (real_thread->GetExtendedBacktraceToken() != LLDB_INVALID_ADDRESS) {475      originating_thread_sp = GetExtendedBacktraceFromItemRef(476          real_thread->GetExtendedBacktraceToken());477    } else {478      ThreadSP cur_thread_sp(479          m_process->GetThreadList().GetExpressionExecutionThread());480      AppleGetThreadItemInfoHandler::GetThreadItemInfoReturnInfo ret =481          m_get_thread_item_info_handler.GetThreadItemInfo(482              *cur_thread_sp.get(), real_thread->GetID(), m_page_to_free,483              m_page_to_free_size, error);484      m_page_to_free = LLDB_INVALID_ADDRESS;485      m_page_to_free_size = 0;486      if (ret.item_buffer_ptr != 0 &&487          ret.item_buffer_ptr != LLDB_INVALID_ADDRESS &&488          ret.item_buffer_size > 0) {489        DataBufferHeap data(ret.item_buffer_size, 0);490        if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(),491                                  ret.item_buffer_size, error) &&492            error.Success()) {493          DataExtractor extractor(data.GetBytes(), data.GetByteSize(),494                                  m_process->GetByteOrder(),495                                  m_process->GetAddressByteSize());496          ItemInfo item = ExtractItemInfoFromBuffer(extractor);497          originating_thread_sp = std::make_shared<HistoryThread>(498              *m_process, item.enqueuing_thread_id, item.enqueuing_callstack);499          originating_thread_sp->SetExtendedBacktraceToken(500              item.item_that_enqueued_this);501          originating_thread_sp->SetQueueName(502              item.enqueuing_queue_label.c_str());503          originating_thread_sp->SetQueueID(item.enqueuing_queue_serialnum);504          //                    originating_thread_sp->SetThreadName505          //                    (item.enqueuing_thread_label.c_str());506        }507        m_page_to_free = ret.item_buffer_ptr;508        m_page_to_free_size = ret.item_buffer_size;509      }510    }511  } else if (type == "Application Specific Backtrace") {512    StructuredData::ObjectSP thread_extended_sp =513        real_thread->GetExtendedInfo();514 515    if (!thread_extended_sp)516      return {};517 518    StructuredData::Array *thread_extended_info =519        thread_extended_sp->GetAsArray();520 521    if (!thread_extended_info || !thread_extended_info->GetSize())522      return {};523 524    std::vector<addr_t> app_specific_backtrace_pcs;525 526    auto extract_frame_pc =527        [&app_specific_backtrace_pcs](StructuredData::Object *obj) -> bool {528      if (!obj)529        return false;530 531      StructuredData::Dictionary *dict = obj->GetAsDictionary();532      if (!dict)533        return false;534 535      lldb::addr_t pc = LLDB_INVALID_ADDRESS;536      if (!dict->GetValueForKeyAsInteger("pc", pc))537        return false;538 539      app_specific_backtrace_pcs.push_back(pc);540 541      return pc != LLDB_INVALID_ADDRESS;542    };543 544    if (!thread_extended_info->ForEach(extract_frame_pc))545      return {};546 547    originating_thread_sp = std::make_shared<HistoryThread>(548        *m_process, real_thread->GetIndexID(), app_specific_backtrace_pcs,549        HistoryPCType::Calls);550    originating_thread_sp->SetQueueName(type.AsCString());551  }552  return originating_thread_sp;553}554 555ThreadSP556SystemRuntimeMacOSX::GetExtendedBacktraceFromItemRef(lldb::addr_t item_ref) {557  ThreadSP return_thread_sp;558 559  AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;560  ThreadSP cur_thread_sp(561      m_process->GetThreadList().GetExpressionExecutionThread());562  Status error;563  ret = m_get_item_info_handler.GetItemInfo(*cur_thread_sp.get(), item_ref,564                                            m_page_to_free, m_page_to_free_size,565                                            error);566  m_page_to_free = LLDB_INVALID_ADDRESS;567  m_page_to_free_size = 0;568  if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS &&569      ret.item_buffer_size > 0) {570    DataBufferHeap data(ret.item_buffer_size, 0);571    if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(),572                              ret.item_buffer_size, error) &&573        error.Success()) {574      DataExtractor extractor(data.GetBytes(), data.GetByteSize(),575                              m_process->GetByteOrder(),576                              m_process->GetAddressByteSize());577      ItemInfo item = ExtractItemInfoFromBuffer(extractor);578      return_thread_sp = std::make_shared<HistoryThread>(579          *m_process, item.enqueuing_thread_id, item.enqueuing_callstack);580      return_thread_sp->SetExtendedBacktraceToken(item.item_that_enqueued_this);581      return_thread_sp->SetQueueName(item.enqueuing_queue_label.c_str());582      return_thread_sp->SetQueueID(item.enqueuing_queue_serialnum);583      //            return_thread_sp->SetThreadName584      //            (item.enqueuing_thread_label.c_str());585 586      m_page_to_free = ret.item_buffer_ptr;587      m_page_to_free_size = ret.item_buffer_size;588    }589  }590  return return_thread_sp;591}592 593ThreadSP594SystemRuntimeMacOSX::GetExtendedBacktraceForQueueItem(QueueItemSP queue_item_sp,595                                                      ConstString type) {596  ThreadSP extended_thread_sp;597  if (type != "libdispatch")598    return extended_thread_sp;599 600  extended_thread_sp = std::make_shared<HistoryThread>(601      *m_process, queue_item_sp->GetEnqueueingThreadID(),602      queue_item_sp->GetEnqueueingBacktrace());603  extended_thread_sp->SetExtendedBacktraceToken(604      queue_item_sp->GetItemThatEnqueuedThis());605  extended_thread_sp->SetQueueName(queue_item_sp->GetQueueLabel().c_str());606  extended_thread_sp->SetQueueID(queue_item_sp->GetEnqueueingQueueID());607  //    extended_thread_sp->SetThreadName608  //    (queue_item_sp->GetThreadLabel().c_str());609 610  return extended_thread_sp;611}612 613/* Returns true if we were able to get the version / offset information614 * out of libBacktraceRecording.  false means we were unable to retrieve615 * this; the queue_info_version field will be 0.616 */617 618bool SystemRuntimeMacOSX::BacktraceRecordingHeadersInitialized() {619  if (m_lib_backtrace_recording_info.queue_info_version != 0)620    return true;621 622  addr_t queue_info_version_address = LLDB_INVALID_ADDRESS;623  addr_t queue_info_data_offset_address = LLDB_INVALID_ADDRESS;624  addr_t item_info_version_address = LLDB_INVALID_ADDRESS;625  addr_t item_info_data_offset_address = LLDB_INVALID_ADDRESS;626  Target &target = m_process->GetTarget();627 628  static ConstString introspection_dispatch_queue_info_version(629      "__introspection_dispatch_queue_info_version");630  SymbolContextList sc_list;631  m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(632      introspection_dispatch_queue_info_version, eSymbolTypeData, sc_list);633  if (!sc_list.IsEmpty()) {634    SymbolContext sc;635    sc_list.GetContextAtIndex(0, sc);636    Address addr = sc.GetFunctionOrSymbolAddress();637    queue_info_version_address = addr.GetLoadAddress(&target);638  }639  sc_list.Clear();640 641  static ConstString introspection_dispatch_queue_info_data_offset(642      "__introspection_dispatch_queue_info_data_offset");643  m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(644      introspection_dispatch_queue_info_data_offset, eSymbolTypeData, sc_list);645  if (!sc_list.IsEmpty()) {646    SymbolContext sc;647    sc_list.GetContextAtIndex(0, sc);648    Address addr = sc.GetFunctionOrSymbolAddress();649    queue_info_data_offset_address = addr.GetLoadAddress(&target);650  }651  sc_list.Clear();652 653  static ConstString introspection_dispatch_item_info_version(654      "__introspection_dispatch_item_info_version");655  m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(656      introspection_dispatch_item_info_version, eSymbolTypeData, sc_list);657  if (!sc_list.IsEmpty()) {658    SymbolContext sc;659    sc_list.GetContextAtIndex(0, sc);660    Address addr = sc.GetFunctionOrSymbolAddress();661    item_info_version_address = addr.GetLoadAddress(&target);662  }663  sc_list.Clear();664 665  static ConstString introspection_dispatch_item_info_data_offset(666      "__introspection_dispatch_item_info_data_offset");667  m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(668      introspection_dispatch_item_info_data_offset, eSymbolTypeData, sc_list);669  if (!sc_list.IsEmpty()) {670    SymbolContext sc;671    sc_list.GetContextAtIndex(0, sc);672    Address addr = sc.GetFunctionOrSymbolAddress();673    item_info_data_offset_address = addr.GetLoadAddress(&target);674  }675 676  if (queue_info_version_address != LLDB_INVALID_ADDRESS &&677      queue_info_data_offset_address != LLDB_INVALID_ADDRESS &&678      item_info_version_address != LLDB_INVALID_ADDRESS &&679      item_info_data_offset_address != LLDB_INVALID_ADDRESS) {680    Status error;681    m_lib_backtrace_recording_info.queue_info_version =682        m_process->ReadUnsignedIntegerFromMemory(queue_info_version_address, 2,683                                                 0, error);684    if (error.Success()) {685      m_lib_backtrace_recording_info.queue_info_data_offset =686          m_process->ReadUnsignedIntegerFromMemory(687              queue_info_data_offset_address, 2, 0, error);688      if (error.Success()) {689        m_lib_backtrace_recording_info.item_info_version =690            m_process->ReadUnsignedIntegerFromMemory(item_info_version_address,691                                                     2, 0, error);692        if (error.Success()) {693          m_lib_backtrace_recording_info.item_info_data_offset =694              m_process->ReadUnsignedIntegerFromMemory(695                  item_info_data_offset_address, 2, 0, error);696          if (!error.Success()) {697            m_lib_backtrace_recording_info.queue_info_version = 0;698          }699        } else {700          m_lib_backtrace_recording_info.queue_info_version = 0;701        }702      } else {703        m_lib_backtrace_recording_info.queue_info_version = 0;704      }705    }706  }707 708  return m_lib_backtrace_recording_info.queue_info_version != 0;709}710 711const std::vector<ConstString> &712SystemRuntimeMacOSX::GetExtendedBacktraceTypes() {713  if (m_types.size() == 0) {714    m_types.push_back(ConstString("libdispatch"));715    m_types.push_back(ConstString("Application Specific Backtrace"));716    // We could have pthread as another type in the future if we have a way of717    // gathering that information & it's useful to distinguish between them.718  }719  return m_types;720}721 722void SystemRuntimeMacOSX::PopulateQueueList(723    lldb_private::QueueList &queue_list) {724  if (BacktraceRecordingHeadersInitialized()) {725    AppleGetQueuesHandler::GetQueuesReturnInfo queue_info_pointer;726    ThreadSP cur_thread_sp(727        m_process->GetThreadList().GetExpressionExecutionThread());728    if (cur_thread_sp) {729      Status error;730      queue_info_pointer = m_get_queues_handler.GetCurrentQueues(731          *cur_thread_sp.get(), m_page_to_free, m_page_to_free_size, error);732      m_page_to_free = LLDB_INVALID_ADDRESS;733      m_page_to_free_size = 0;734      if (error.Success()) {735 736        if (queue_info_pointer.count > 0 &&737            queue_info_pointer.queues_buffer_size > 0 &&738            queue_info_pointer.queues_buffer_ptr != 0 &&739            queue_info_pointer.queues_buffer_ptr != LLDB_INVALID_ADDRESS) {740          PopulateQueuesUsingLibBTR(queue_info_pointer.queues_buffer_ptr,741                                    queue_info_pointer.queues_buffer_size,742                                    queue_info_pointer.count, queue_list);743        }744      }745    }746  }747 748  // We either didn't have libBacktraceRecording (and need to create the queues749  // list based on threads) or we did get the queues list from750  // libBacktraceRecording but some special queues may not be included in its751  // information.  This is needed because libBacktraceRecording will only list752  // queues with pending or running items by default - but the magic com.apple753  // .main-thread queue on thread 1 is always around.754 755  for (ThreadSP thread_sp : m_process->Threads()) {756    if (thread_sp->GetAssociatedWithLibdispatchQueue() != eLazyBoolNo) {757      if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID) {758        if (queue_list.FindQueueByID(thread_sp->GetQueueID()).get() ==759            nullptr) {760          QueueSP queue_sp(new Queue(m_process->shared_from_this(),761                                     thread_sp->GetQueueID(),762                                     thread_sp->GetQueueName()));763          if (thread_sp->ThreadHasQueueInformation()) {764            queue_sp->SetKind(thread_sp->GetQueueKind());765            queue_sp->SetLibdispatchQueueAddress(766                thread_sp->GetQueueLibdispatchQueueAddress());767            queue_list.AddQueue(queue_sp);768          } else {769            queue_sp->SetKind(770                GetQueueKind(thread_sp->GetQueueLibdispatchQueueAddress()));771            queue_sp->SetLibdispatchQueueAddress(772                thread_sp->GetQueueLibdispatchQueueAddress());773            queue_list.AddQueue(queue_sp);774          }775        }776      }777    }778  }779}780 781// Returns either an array of introspection_dispatch_item_info_ref's for the782// pending items on a queue or an array introspection_dispatch_item_info_ref's783// and code addresses for the pending items on a queue.  The information about784// each of these pending items then needs to be fetched individually by passing785// the ref to libBacktraceRecording.786 787SystemRuntimeMacOSX::PendingItemsForQueue788SystemRuntimeMacOSX::GetPendingItemRefsForQueue(lldb::addr_t queue) {789  PendingItemsForQueue pending_item_refs = {};790  AppleGetPendingItemsHandler::GetPendingItemsReturnInfo pending_items_pointer;791  ThreadSP cur_thread_sp(792      m_process->GetThreadList().GetExpressionExecutionThread());793  if (cur_thread_sp) {794    Status error;795    pending_items_pointer = m_get_pending_items_handler.GetPendingItems(796        *cur_thread_sp.get(), queue, m_page_to_free, m_page_to_free_size,797        error);798    m_page_to_free = LLDB_INVALID_ADDRESS;799    m_page_to_free_size = 0;800    if (error.Success()) {801      if (pending_items_pointer.count > 0 &&802          pending_items_pointer.items_buffer_size > 0 &&803          pending_items_pointer.items_buffer_ptr != 0 &&804          pending_items_pointer.items_buffer_ptr != LLDB_INVALID_ADDRESS) {805        DataBufferHeap data(pending_items_pointer.items_buffer_size, 0);806        if (m_process->ReadMemory(807                pending_items_pointer.items_buffer_ptr, data.GetBytes(),808                pending_items_pointer.items_buffer_size, error)) {809          DataExtractor extractor(data.GetBytes(), data.GetByteSize(),810                                  m_process->GetByteOrder(),811                                  m_process->GetAddressByteSize());812 813          // We either have an array of814          //    void* item_ref815          // (old style) or we have a structure returned which looks like816          //817          // struct introspection_dispatch_pending_item_info_s {818          //   void *item_ref;819          //   void *function_or_block;820          // };821          //822          // struct introspection_dispatch_pending_items_array_s {823          //   uint32_t version;824          //   uint32_t size_of_item_info;825          //   introspection_dispatch_pending_item_info_s items[];826          //   }827 828          offset_t offset = 0;829          uint64_t i = 0;830          uint32_t version = extractor.GetU32(&offset);831          if (version == 1) {832            pending_item_refs.new_style = true;833            uint32_t item_size = extractor.GetU32(&offset);834            uint32_t start_of_array_offset = offset;835            while (offset < pending_items_pointer.items_buffer_size &&836                   i < pending_items_pointer.count) {837              offset = start_of_array_offset + (i * item_size);838              ItemRefAndCodeAddress item;839              item.item_ref = extractor.GetAddress(&offset);840              item.code_address = extractor.GetAddress(&offset);841              pending_item_refs.item_refs_and_code_addresses.push_back(item);842              i++;843            }844          } else {845            offset = 0;846            pending_item_refs.new_style = false;847            while (offset < pending_items_pointer.items_buffer_size &&848                   i < pending_items_pointer.count) {849              ItemRefAndCodeAddress item;850              item.item_ref = extractor.GetAddress(&offset);851              item.code_address = LLDB_INVALID_ADDRESS;852              pending_item_refs.item_refs_and_code_addresses.push_back(item);853              i++;854            }855          }856        }857        m_page_to_free = pending_items_pointer.items_buffer_ptr;858        m_page_to_free_size = pending_items_pointer.items_buffer_size;859      }860    }861  }862  return pending_item_refs;863}864 865void SystemRuntimeMacOSX::PopulatePendingItemsForQueue(Queue *queue) {866  if (BacktraceRecordingHeadersInitialized()) {867    PendingItemsForQueue pending_item_refs =868        GetPendingItemRefsForQueue(queue->GetLibdispatchQueueAddress());869    for (ItemRefAndCodeAddress pending_item :870         pending_item_refs.item_refs_and_code_addresses) {871      Address addr;872      m_process->GetTarget().ResolveLoadAddress(pending_item.code_address,873                                                addr);874      QueueItemSP queue_item_sp(new QueueItem(queue->shared_from_this(),875                                              m_process->shared_from_this(),876                                              pending_item.item_ref, addr));877      queue->PushPendingQueueItem(queue_item_sp);878    }879  }880}881 882void SystemRuntimeMacOSX::CompleteQueueItem(QueueItem *queue_item,883                                            addr_t item_ref) {884  AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;885 886  ThreadSP cur_thread_sp(887      m_process->GetThreadList().GetExpressionExecutionThread());888  Status error;889  ret = m_get_item_info_handler.GetItemInfo(*cur_thread_sp.get(), item_ref,890                                            m_page_to_free, m_page_to_free_size,891                                            error);892  m_page_to_free = LLDB_INVALID_ADDRESS;893  m_page_to_free_size = 0;894  if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS &&895      ret.item_buffer_size > 0) {896    DataBufferHeap data(ret.item_buffer_size, 0);897    if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(),898                              ret.item_buffer_size, error) &&899        error.Success()) {900      DataExtractor extractor(data.GetBytes(), data.GetByteSize(),901                              m_process->GetByteOrder(),902                              m_process->GetAddressByteSize());903      ItemInfo item = ExtractItemInfoFromBuffer(extractor);904      queue_item->SetItemThatEnqueuedThis(item.item_that_enqueued_this);905      queue_item->SetEnqueueingThreadID(item.enqueuing_thread_id);906      queue_item->SetEnqueueingQueueID(item.enqueuing_queue_serialnum);907      queue_item->SetStopID(item.stop_id);908      queue_item->SetEnqueueingBacktrace(item.enqueuing_callstack);909      queue_item->SetThreadLabel(item.enqueuing_thread_label);910      queue_item->SetQueueLabel(item.enqueuing_queue_label);911      queue_item->SetTargetQueueLabel(item.target_queue_label);912    }913    m_page_to_free = ret.item_buffer_ptr;914    m_page_to_free_size = ret.item_buffer_size;915  }916}917 918void SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR(919    lldb::addr_t queues_buffer, uint64_t queues_buffer_size, uint64_t count,920    lldb_private::QueueList &queue_list) {921  Status error;922  DataBufferHeap data(queues_buffer_size, 0);923  Log *log = GetLog(LLDBLog::SystemRuntime);924  if (m_process->ReadMemory(queues_buffer, data.GetBytes(), queues_buffer_size,925                            error) == queues_buffer_size &&926      error.Success()) {927    // We've read the information out of inferior memory; free it on the next928    // call we make929    m_page_to_free = queues_buffer;930    m_page_to_free_size = queues_buffer_size;931 932    DataExtractor extractor(data.GetBytes(), data.GetByteSize(),933                            m_process->GetByteOrder(),934                            m_process->GetAddressByteSize());935    offset_t offset = 0;936    uint64_t queues_read = 0;937 938    // The information about the queues is stored in this format (v1): typedef939    // struct introspection_dispatch_queue_info_s {940    //     uint32_t offset_to_next;941    //     dispatch_queue_t queue;942    //     uint64_t serialnum;     // queue's serialnum in the process, as943    //     provided by libdispatch944    //     uint32_t running_work_items_count;945    //     uint32_t pending_work_items_count;946    //947    //     char data[];     // Starting here, we have variable-length data:948    //     // char queue_label[];949    // } introspection_dispatch_queue_info_s;950 951    while (queues_read < count && offset < queues_buffer_size) {952      offset_t start_of_this_item = offset;953 954      uint32_t offset_to_next = extractor.GetU32(&offset);955 956      offset += 4; // Skip over the 4 bytes of reserved space957      addr_t queue = extractor.GetAddress(&offset);958      uint64_t serialnum = extractor.GetU64(&offset);959      uint32_t running_work_items_count = extractor.GetU32(&offset);960      uint32_t pending_work_items_count = extractor.GetU32(&offset);961 962      // Read the first field of the variable length data963      offset = start_of_this_item +964               m_lib_backtrace_recording_info.queue_info_data_offset;965      const char *queue_label = extractor.GetCStr(&offset);966      if (queue_label == nullptr)967        queue_label = "";968 969      offset_t start_of_next_item = start_of_this_item + offset_to_next;970      offset = start_of_next_item;971 972      LLDB_LOGF(log,973                "SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR added "974                "queue with dispatch_queue_t 0x%" PRIx64975                ", serial number 0x%" PRIx64976                ", running items %d, pending items %d, name '%s'",977                queue, serialnum, running_work_items_count,978                pending_work_items_count, queue_label);979 980      QueueSP queue_sp(981          new Queue(m_process->shared_from_this(), serialnum, queue_label));982      queue_sp->SetNumRunningWorkItems(running_work_items_count);983      queue_sp->SetNumPendingWorkItems(pending_work_items_count);984      queue_sp->SetLibdispatchQueueAddress(queue);985      queue_sp->SetKind(GetQueueKind(queue));986      queue_list.AddQueue(queue_sp);987      queues_read++;988    }989  }990}991 992SystemRuntimeMacOSX::ItemInfo SystemRuntimeMacOSX::ExtractItemInfoFromBuffer(993    lldb_private::DataExtractor &extractor) {994  ItemInfo item;995 996  offset_t offset = 0;997 998  item.item_that_enqueued_this = extractor.GetAddress(&offset);999  item.function_or_block = extractor.GetAddress(&offset);1000  item.enqueuing_thread_id = extractor.GetU64(&offset);1001  item.enqueuing_queue_serialnum = extractor.GetU64(&offset);1002  item.target_queue_serialnum = extractor.GetU64(&offset);1003  item.enqueuing_callstack_frame_count = extractor.GetU32(&offset);1004  item.stop_id = extractor.GetU32(&offset);1005 1006  offset = m_lib_backtrace_recording_info.item_info_data_offset;1007 1008  for (uint32_t i = 0; i < item.enqueuing_callstack_frame_count; i++) {1009    item.enqueuing_callstack.push_back(extractor.GetAddress(&offset));1010  }1011  item.enqueuing_thread_label = extractor.GetCStr(&offset);1012  item.enqueuing_queue_label = extractor.GetCStr(&offset);1013  item.target_queue_label = extractor.GetCStr(&offset);1014 1015  return item;1016}1017 1018void SystemRuntimeMacOSX::Initialize() {1019  PluginManager::RegisterPlugin(1020      GetPluginNameStatic(),1021      "System runtime plugin for Mac OS X native libraries.", CreateInstance);1022}1023 1024void SystemRuntimeMacOSX::Terminate() {1025  PluginManager::UnregisterPlugin(CreateInstance);1026}1027