Error
ProcessPOSIX::DoDetach(bool keep_stopped)
{
    Error error;
    if (keep_stopped)
    {
        // FIXME: If you want to implement keep_stopped,
        // this would be the place to do it.
        error.SetErrorString("Detaching with keep_stopped true is not currently supported on this platform.");
        return error;
    }

    Mutex::Locker lock(m_thread_list.GetMutex());

    uint32_t thread_count = m_thread_list.GetSize(false);
    for (uint32_t i = 0; i < thread_count; ++i)
    {
        POSIXThread *thread = static_cast<POSIXThread*>(
            m_thread_list.GetThreadAtIndex(i, false).get());
        error = m_monitor->Detach(thread->GetID());
    }

    if (error.Success())
        SetPrivateState(eStateDetached);

    return error;
}
// ProcessPOSIX override
void
ProcessLinux::StopAllThreads(lldb::tid_t stop_tid)
{
    // If a breakpoint occurs while we're stopping threads, we'll get back
    // here, but we don't want to do it again.  Only the MonitorChildProcess
    // thread calls this function, so we don't need to protect this flag.
    if (m_stopping_threads)
      return;
    m_stopping_threads = true;

    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
    if (log)
        log->Printf ("ProcessLinux::%s() stopping all threads", __FUNCTION__);

    // Walk the thread list and stop the other threads.  The thread that caused
    // the stop should already be marked as stopped before we get here.
    Mutex::Locker thread_list_lock(m_thread_list.GetMutex());

    uint32_t thread_count = m_thread_list.GetSize(false);
    for (uint32_t i = 0; i < thread_count; ++i)
    {
        POSIXThread *thread = static_cast<POSIXThread*>(
            m_thread_list.GetThreadAtIndex(i, false).get());
        assert(thread);
        lldb::tid_t tid = thread->GetID();
        if (!StateIsStoppedState(thread->GetState(), false))
            m_monitor->StopThread(tid);
    }

    m_stopping_threads = false;

    if (log)
        log->Printf ("ProcessLinux::%s() finished", __FUNCTION__);
}
コード例 #3
0
void
ProcessPOSIX::RefreshStateAfterStop()
{
    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
        log->Printf ("ProcessPOSIX::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size());

    Mutex::Locker lock(m_message_mutex);

    // This method used to only handle one message.  Changing it to loop allows
    // it to handle the case where we hit a breakpoint while handling a different
    // breakpoint.
    while (!m_message_queue.empty())
    {
        ProcessMessage &message = m_message_queue.front();

        // Resolve the thread this message corresponds to and pass it along.
        lldb::tid_t tid = message.GetTID();
        if (log)
            log->Printf ("ProcessPOSIX::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid);

        if (message.GetKind() == ProcessMessage::eNewThreadMessage)
        {
            if (log)
                log->Printf ("ProcessPOSIX::%s() adding thread, tid = %" PRIi64, __FUNCTION__, message.GetChildTID());
            lldb::tid_t child_tid = message.GetChildTID();
            ThreadSP thread_sp;
            thread_sp.reset(CreateNewPOSIXThread(*this, child_tid));

            Mutex::Locker lock(m_thread_list.GetMutex());

            m_thread_list.AddThread(thread_sp);
        }

        m_thread_list.RefreshStateAfterStop();

        POSIXThread *thread = static_cast<POSIXThread*>(
            GetThreadList().FindThreadByID(tid, false).get());
        if (thread)
            thread->Notify(message);

        if (message.GetKind() == ProcessMessage::eExitMessage)
        {
            // FIXME: We should tell the user about this, but the limbo message is probably better for that.
            if (log)
                log->Printf ("ProcessPOSIX::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid);

            Mutex::Locker lock(m_thread_list.GetMutex());

            ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
            thread_sp.reset();
            m_seen_initial_stop.erase(tid);
        }

        m_message_queue.pop();
    }
}
コード例 #4
0
Error
ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num)
{
    Error error;
    Mutex::Locker lock(m_thread_list.GetMutex());
    POSIXThread *thread = static_cast<POSIXThread*>(
                          m_thread_list.GetThreadAtIndex(0, false).get());
    if (thread)
        num = thread->NumSupportedHardwareWatchpoints();
    else
        error.SetErrorString("Process does not exist.");
    return error;
}
コード例 #5
0
Error
ProcessPOSIX::DisableWatchpoint(Watchpoint *wp, bool notify)
{
    Error error;
    if (wp)
    {
        user_id_t watchID = wp->GetID();
        addr_t addr = wp->GetLoadAddress();
        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
        if (log)
            log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64 ")",
                        watchID);
        if (!wp->IsEnabled())
        {
            if (log)
                log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64
                            ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.",
                            watchID, (uint64_t)addr);
            // This is needed (for now) to keep watchpoints disabled correctly
            wp->SetEnabled(false, notify);
            return error;
        }

        if (wp->IsHardware())
        {
            bool wp_disabled = true;
            Mutex::Locker lock(m_thread_list.GetMutex());
            uint32_t thread_count = m_thread_list.GetSize(false);
            for (uint32_t i = 0; i < thread_count; ++i)
            {
                POSIXThread *thread = static_cast<POSIXThread*>(
                                      m_thread_list.GetThreadAtIndex(i, false).get());
                if (thread)
                    wp_disabled &= thread->DisableHardwareWatchpoint(wp);
                else
                    wp_disabled = false;
            }
            if (wp_disabled)
            {
                wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
                wp->SetEnabled(false, notify);
                return error;
            }
            else
                error.SetErrorString("Disabling hardware watchpoint failed");
        }
    }
    else
        error.SetErrorString("Watchpoint argument was NULL.");
    return error;
}
コード例 #6
0
bool
ProcessPOSIX::IsAThreadRunning()
{
    bool is_running = false;
    Mutex::Locker lock(m_thread_list.GetMutex());
    uint32_t thread_count = m_thread_list.GetSize(false);
    for (uint32_t i = 0; i < thread_count; ++i)
    {
        POSIXThread *thread = static_cast<POSIXThread*>(
            m_thread_list.GetThreadAtIndex(i, false).get());
        StateType thread_state = thread->GetState();
        if (thread_state == eStateRunning || thread_state == eStateStepping)
        {
            is_running = true;
            break;
        }
    }
    return is_running;
}
コード例 #7
0
Error
ProcessPOSIX::DoResume()
{
    StateType state = GetPrivateState();

    assert(state == eStateStopped);

    SetPrivateState(eStateRunning);

    bool did_resume = false;

    Mutex::Locker lock(m_thread_list.GetMutex());

    uint32_t thread_count = m_thread_list.GetSize(false);
    for (uint32_t i = 0; i < thread_count; ++i)
    {
        POSIXThread *thread = static_cast<POSIXThread*>(
            m_thread_list.GetThreadAtIndex(i, false).get());
        did_resume = thread->Resume() || did_resume;
    }
    assert(did_resume && "Process resume failed!");

    return Error();
}
コード例 #8
0
Error
ProcessPOSIX::EnableWatchpoint(Watchpoint *wp, bool notify)
{
    Error error;
    if (wp)
    {
        user_id_t watchID = wp->GetID();
        addr_t addr = wp->GetLoadAddress();
        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
        if (log)
            log->Printf ("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64 ")",
                         watchID);
        if (wp->IsEnabled())
        {
            if (log)
                log->Printf("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64
                            ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
                            watchID, (uint64_t)addr);
            return error;
        }

        // Try to find a vacant watchpoint slot in the inferiors' main thread
        uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
        Mutex::Locker lock(m_thread_list.GetMutex());
        POSIXThread *thread = static_cast<POSIXThread*>(
                               m_thread_list.GetThreadAtIndex(0, false).get());

        if (thread)
            wp_hw_index = thread->FindVacantWatchpointIndex();

        if (wp_hw_index == LLDB_INVALID_INDEX32)
        {
            error.SetErrorString("Setting hardware watchpoint failed.");
        }
        else
        {
            wp->SetHardwareIndex(wp_hw_index);
            bool wp_enabled = true;
            uint32_t thread_count = m_thread_list.GetSize(false);
            for (uint32_t i = 0; i < thread_count; ++i)
            {
                thread = static_cast<POSIXThread*>(
                         m_thread_list.GetThreadAtIndex(i, false).get());
                if (thread)
                    wp_enabled &= thread->EnableHardwareWatchpoint(wp);
                else
                    wp_enabled = false;
            }
            if (wp_enabled)
            {
                wp->SetEnabled(true, notify);
                return error;
            }
            else
            {
                // Watchpoint enabling failed on at least one
                // of the threads so roll back all of them
                DisableWatchpoint(wp, false);
                error.SetErrorString("Setting hardware watchpoint failed");
            }
        }
    }
    else
        error.SetErrorString("Watchpoint argument was NULL.");
    return error;
}
コード例 #9
0
void
ProcessPOSIX::SendMessage(const ProcessMessage &message)
{
    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));

    Mutex::Locker lock(m_message_mutex);

    Mutex::Locker thread_lock(m_thread_list.GetMutex());

    POSIXThread *thread = static_cast<POSIXThread*>(
        m_thread_list.FindThreadByID(message.GetTID(), false).get());

    switch (message.GetKind())
    {
    case ProcessMessage::eInvalidMessage:
        return;

    case ProcessMessage::eAttachMessage:
        SetPrivateState(eStateStopped);
        return;

    case ProcessMessage::eLimboMessage:
        assert(thread);
        thread->SetState(eStateStopped);
        if (message.GetTID() == GetID())
        {
            m_exit_status = message.GetExitStatus();
            if (m_exit_now)
            {
                SetPrivateState(eStateExited);
                m_monitor->Detach(GetID());
            }
            else
            {
                StopAllThreads(message.GetTID());
                SetPrivateState(eStateStopped);
            }
        }
        else
        {
            StopAllThreads(message.GetTID());
            SetPrivateState(eStateStopped);
        }
        break;

    case ProcessMessage::eExitMessage:
        if (thread != nullptr)
            thread->SetState(eStateExited);
        else
        {
            if (log)
                log->Warning ("ProcessPOSIX::%s eExitMessage for TID %" PRIu64 " failed to find a thread to mark as eStateExited, ignoring", __FUNCTION__, message.GetTID ());
        }

        // FIXME: I'm not sure we need to do this.
        if (message.GetTID() == GetID())
        {
            SetExitStatus(message.GetExitStatus(), NULL);
        }
        else if (!IsAThreadRunning())
            SetPrivateState(eStateStopped);
        break;

    case ProcessMessage::eSignalMessage:
    case ProcessMessage::eSignalDeliveredMessage:
        if (message.GetSignal() == SIGSTOP &&
            AddThreadForInitialStopIfNeeded(message.GetTID()))
            return;
        // Intentional fall-through

    case ProcessMessage::eBreakpointMessage:
    case ProcessMessage::eTraceMessage:
    case ProcessMessage::eWatchpointMessage:
    case ProcessMessage::eCrashMessage:
        assert(thread);
        thread->SetState(eStateStopped);
        StopAllThreads(message.GetTID());
        SetPrivateState(eStateStopped);
        break;

    case ProcessMessage::eNewThreadMessage:
    {
        lldb::tid_t  new_tid = message.GetChildTID();
        if (WaitingForInitialStop(new_tid))
        {
            m_monitor->WaitForInitialTIDStop(new_tid);
        }
        assert(thread);
        thread->SetState(eStateStopped);
        StopAllThreads(message.GetTID());
        SetPrivateState(eStateStopped);
        break;
    }

    case ProcessMessage::eExecMessage:
    {
        assert(thread);
        thread->SetState(eStateStopped);
        StopAllThreads(message.GetTID());
        SetPrivateState(eStateStopped);
        break;
    }
    }


    m_message_queue.push(message);
}
void
ProcessPOSIX::SendMessage(const ProcessMessage &message)
{
    Mutex::Locker lock(m_message_mutex);

    Mutex::Locker thread_lock(m_thread_list.GetMutex());

    POSIXThread *thread = static_cast<POSIXThread*>(
        m_thread_list.FindThreadByID(message.GetTID(), false).get());

    switch (message.GetKind())
    {
    case ProcessMessage::eInvalidMessage:
        return;

    case ProcessMessage::eLimboMessage:
        assert(thread);
        thread->SetState(eStateStopped);
        if (message.GetTID() == GetID())
        {
            m_exit_status = message.GetExitStatus();
            if (m_exit_now)
            {
                SetPrivateState(eStateExited);
                m_monitor->Detach(GetID());
            }
            else
            {
                StopAllThreads(message.GetTID());
                SetPrivateState(eStateStopped);
            }
        }
        else
        {
            StopAllThreads(message.GetTID());
            SetPrivateState(eStateStopped);
        }
        break;

    case ProcessMessage::eExitMessage:
        assert(thread);
        thread->SetState(eStateExited);
        // FIXME: I'm not sure we need to do this.
        if (message.GetTID() == GetID())
        {
            m_exit_status = message.GetExitStatus();
            SetExitStatus(m_exit_status, NULL);
        }
        else if (!IsAThreadRunning())
            SetPrivateState(eStateStopped);
        break;

        assert(thread);
        thread->SetState(eStateStopped);
        StopAllThreads(message.GetTID());
        SetPrivateState(eStateStopped);
        break;

    case ProcessMessage::eSignalMessage:
    case ProcessMessage::eSignalDeliveredMessage:
        if (message.GetSignal() == SIGSTOP &&
            AddThreadForInitialStopIfNeeded(message.GetTID()))
            return;
        // Intentional fall-through

    case ProcessMessage::eBreakpointMessage:
    case ProcessMessage::eTraceMessage:
    case ProcessMessage::eWatchpointMessage:
    case ProcessMessage::eNewThreadMessage:
    case ProcessMessage::eCrashMessage:
        assert(thread);
        thread->SetState(eStateStopped);
        StopAllThreads(message.GetTID());
        SetPrivateState(eStateStopped);
        break;
    }

    m_message_queue.push(message);
}
コード例 #11
0
POSIXThread* POSIXThread__New_1(::uStatic* __this, ::uDelegate* callback)
{
    POSIXThread* inst = (POSIXThread*)::uAllocObject(sizeof(POSIXThread), POSIXThread__typeof());
    inst->_ObjInit_1(callback);
    return inst;
}