bool ProcessFreeBSD::IsSoftwareStepBreakpoint(lldb::tid_t tid) {
  ThreadSP thread = GetThreadList().FindThreadByID(tid);
  if (!thread)
    return false;

  assert(thread->GetRegisterContext());
  lldb::addr_t stop_pc = thread->GetRegisterContext()->GetPC();

  const auto &iter = m_threads_stepping_with_breakpoint.find(tid);
  if (iter == m_threads_stepping_with_breakpoint.end())
    return false;

  lldb::break_id_t bp_id = iter->second;
  BreakpointSP bp = GetTarget().GetBreakpointByID(bp_id);
  if (!bp)
    return false;

  BreakpointLocationSP bp_loc = bp->FindLocationByAddress(stop_pc);
  if (!bp_loc)
    return false;

  GetTarget().RemoveBreakpointByID(bp_id);
  m_threads_stepping_with_breakpoint.erase(tid);
  return true;
}
ThreadSP
SystemRuntimeMacOSX::GetExtendedBacktraceThread (ThreadSP real_thread, ConstString type)
{
    ThreadSP originating_thread_sp;
    if (BacktraceRecordingHeadersInitialized() && type == ConstString ("libdispatch"))
    {
        Error 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().GetSelectedThread());
            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);
                    bool stop_id_is_valid = true;
                    if (item.stop_id == 0)
                        stop_id_is_valid = false;
                    originating_thread_sp.reset (new HistoryThread (*m_process,
                                                 item.enqueuing_thread_id,
                                                 item.enqueuing_callstack,
                                                 item.stop_id,
                                                 stop_id_is_valid));
                    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;
}
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;
}
Beispiel #4
0
addr_t
SystemRuntimeMacOSX::GetThreadCreatorItem (ThreadSP thread_sp)
{
    addr_t enqueued_item_ptr = thread_sp->GetExtendedBacktraceToken();
    if (enqueued_item_ptr == LLDB_INVALID_ADDRESS)
    {
        if (thread_sp->GetQueueID() == LLDB_INVALID_QUEUE_ID || thread_sp->GetQueueID() == 0)
            return LLDB_INVALID_ADDRESS;
    
        Error error;
        uint64_t this_thread_queue_id = thread_sp->GetQueueID();
    
        addr_t queues_head = GetQueuesHead();
        if (queues_head == LLDB_INVALID_ADDRESS)
            return LLDB_INVALID_ADDRESS;
    
        // Step through the queues_head linked list looking for a queue matching this thread, if any
        uint64_t queue_obj_ptr = queues_head;
        enqueued_item_ptr = LLDB_INVALID_ADDRESS;
    
        while (queue_obj_ptr != 0)
        {
            uint64_t queue_id = m_process->ReadUnsignedIntegerFromMemory (queue_obj_ptr + m_ldi_header.queue_offsets.queue_id, 8, LLDB_INVALID_ADDRESS, error);
            if (error.Success() && queue_id != LLDB_INVALID_ADDRESS)
            {
                if (queue_id == this_thread_queue_id)
                {
                    enqueued_item_ptr = m_process->ReadPointerFromMemory (queue_obj_ptr + m_ldi_header.queue_offsets.current_item_ptr, error);
                    break;
                }
            }
            queue_obj_ptr = m_process->ReadPointerFromMemory (queue_obj_ptr + m_ldi_header.queue_offsets.next, error);
            if (error.Success() == false || queue_obj_ptr == LLDB_INVALID_ADDRESS)
            {
                break;
            }
        }
    }
    
    return enqueued_item_ptr;
}
Beispiel #5
0
void
SystemRuntimeMacOSX::SetNewThreadExtendedBacktraceToken (ThreadSP original_thread_sp, ThreadSP new_extended_thread_sp)
{
    addr_t enqueued_item_ptr = GetThreadCreatorItem (original_thread_sp);
    if (enqueued_item_ptr != LLDB_INVALID_ADDRESS)
    {
        Error error;
        uint64_t further_extended_backtrace = m_process->ReadPointerFromMemory (enqueued_item_ptr + m_ldi_header.item_offsets.enqueueing_thread_dispatch_block_ptr, error);
        if (error.Success() && further_extended_backtrace != 0 && further_extended_backtrace != LLDB_INVALID_ADDRESS)
        {
            new_extended_thread_sp->SetExtendedBacktraceToken (further_extended_backtrace);
        }
    }
}
Beispiel #6
0
void
ThreadCollection::AddThreadSortedByIndexID (const ThreadSP &thread_sp)
{
    std::lock_guard<std::recursive_mutex> guard(GetMutex());
    // Make sure we always keep the threads sorted by thread index ID
    const uint32_t thread_index_id = thread_sp->GetIndexID();
    if (m_threads.empty() || m_threads.back()->GetIndexID() < thread_index_id)
        m_threads.push_back (thread_sp);
    else
    {
        m_threads.insert(std::upper_bound(m_threads.begin(), m_threads.end(), thread_sp,
                                          [] (const ThreadSP &lhs, const ThreadSP &rhs) -> bool
                                          {
                                              return lhs->GetIndexID() < rhs->GetIndexID();
                                          }), thread_sp);
    }
}
Beispiel #7
0
void
SystemRuntimeMacOSX::SetNewThreadQueueID (ThreadSP original_thread_sp, ThreadSP new_extended_thread_sp)
{
    queue_id_t queue_id = LLDB_INVALID_QUEUE_ID;
    addr_t enqueued_item_ptr = GetThreadCreatorItem (original_thread_sp);
    if (enqueued_item_ptr != LLDB_INVALID_ADDRESS && m_ldi_header.item_offsets.queue_id_from_thread_info != 0xffff)
    {
        Error error;
        queue_id = m_process->ReadUnsignedIntegerFromMemory (enqueued_item_ptr + m_ldi_header.item_offsets.queue_id_from_thread_info, 8, LLDB_INVALID_QUEUE_ID, error);
        if (!error.Success())
            queue_id = LLDB_INVALID_QUEUE_ID;
    }

    if (queue_id != LLDB_INVALID_QUEUE_ID)
    {
        new_extended_thread_sp->SetQueueID (queue_id);
    }
}
Beispiel #8
0
void
SystemRuntimeMacOSX::SetNewThreadThreadName (ThreadSP original_thread_sp, ThreadSP new_extended_thread_sp)
{
    addr_t enqueued_item_ptr = GetThreadCreatorItem (original_thread_sp);

    if (enqueued_item_ptr != LLDB_INVALID_ADDRESS)
    {
        Error error;
        addr_t thread_name_ptr = m_process->ReadPointerFromMemory (enqueued_item_ptr + m_ldi_header.item_offsets.thread_name_ptr, error);
        if (thread_name_ptr != LLDB_INVALID_ADDRESS && error.Success())
        {
            char namebuf[512];
            if (m_process->ReadCStringFromMemory (thread_name_ptr, namebuf, sizeof (namebuf), error) > 0 && error.Success())
            {
                new_extended_thread_sp->SetName (namebuf);
            }
        }
    }
}
Beispiel #9
0
bool
OperatingSystemGo::UpdateThreadList(ThreadList &old_thread_list, ThreadList &real_thread_list,
                                    ThreadList &new_thread_list)
{
    new_thread_list = real_thread_list;
    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));

    if (!(m_allg_sp || Init(real_thread_list)) || (m_allg_sp && !m_allglen_sp) ||
        !GetGlobalPluginProperties()->GetEnableGoroutines())
    {
        return new_thread_list.GetSize(false) > 0;
    }

    if (log)
        log->Printf("OperatingSystemGo::UpdateThreadList(%d, %d, %d) fetching thread data from Go for pid %" PRIu64,
                    old_thread_list.GetSize(false), real_thread_list.GetSize(false), new_thread_list.GetSize(0),
                    m_process->GetID());
    uint64_t allglen = m_allglen_sp->GetValueAsUnsigned(0);
    if (allglen == 0)
    {
        return new_thread_list.GetSize(false) > 0;
    }
    std::vector<Goroutine> goroutines;
    // The threads that are in "new_thread_list" upon entry are the threads from the
    // lldb_private::Process subclass, no memory threads will be in this list.

    Error err;
    for (uint64_t i = 0; i < allglen; ++i)
    {
        goroutines.push_back(CreateGoroutineAtIndex(i, err));
        if (err.Fail())
        {
            err.PutToLog(log, "OperatingSystemGo::UpdateThreadList");
            return new_thread_list.GetSize(false) > 0;
        }
    }
    // Make a map so we can match goroutines with backing threads.
    std::map<uint64_t, ThreadSP> stack_map;
    for (uint32_t i = 0; i < real_thread_list.GetSize(false); ++i)
    {
        ThreadSP thread = real_thread_list.GetThreadAtIndex(i, false);
        stack_map[thread->GetRegisterContext()->GetSP()] = thread;
    }
    for (const Goroutine &goroutine : goroutines)
    {
        if (0 /* Gidle */ == goroutine.m_status || 6 /* Gdead */ == goroutine.m_status)
        {
            continue;
        }
        ThreadSP memory_thread = old_thread_list.FindThreadByID(goroutine.m_goid, false);
        if (memory_thread && IsOperatingSystemPluginThread(memory_thread) && memory_thread->IsValid())
        {
            memory_thread->ClearBackingThread();
        }
        else
        {
            memory_thread.reset(new ThreadMemory(*m_process, goroutine.m_goid, nullptr, nullptr, goroutine.m_gobuf));
        }
        // Search for the backing thread if the goroutine is running.
        if (2 == (goroutine.m_status & 0xfff))
        {
            auto backing_it = stack_map.lower_bound(goroutine.m_lostack);
            if (backing_it != stack_map.end())
            {
                if (goroutine.m_histack >= backing_it->first)
                {
                    if (log)
                        log->Printf("OperatingSystemGo::UpdateThreadList found backing thread %" PRIx64 " (%" PRIx64
                                    ") for thread %" PRIx64 "",
                                    backing_it->second->GetID(), backing_it->second->GetProtocolID(),
                                    memory_thread->GetID());
                    memory_thread->SetBackingThread(backing_it->second);
                    new_thread_list.RemoveThreadByID(backing_it->second->GetID(), false);
                }
            }
        }
        new_thread_list.AddThread(memory_thread);
    }

    return new_thread_list.GetSize(false) > 0;
}