diff options
Diffstat (limited to 'source/Plugins/Process/Linux/NativeThreadLinux.cpp')
| -rw-r--r-- | source/Plugins/Process/Linux/NativeThreadLinux.cpp | 143 | 
1 files changed, 106 insertions, 37 deletions
diff --git a/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/source/Plugins/Process/Linux/NativeThreadLinux.cpp index cbf82885e23a6..070b1bcda3b87 100644 --- a/source/Plugins/Process/Linux/NativeThreadLinux.cpp +++ b/source/Plugins/Process/Linux/NativeThreadLinux.cpp @@ -14,10 +14,12 @@  #include "NativeProcessLinux.h"  #include "NativeRegisterContextLinux.h" +#include "SingleStepCheck.h"  #include "lldb/Core/Log.h"  #include "lldb/Core/State.h"  #include "lldb/Host/HostNativeThread.h" +#include "lldb/Host/linux/Ptrace.h"  #include "lldb/Utility/LLDBAssert.h"  #include "lldb/lldb-enumerations.h" @@ -199,8 +201,8 @@ NativeThreadLinux::RemoveWatchpoint (lldb::addr_t addr)      return Error ("Clearing hardware watchpoint failed.");  } -void -NativeThreadLinux::SetRunning () +Error +NativeThreadLinux::Resume(uint32_t signo)  {      const StateType new_state = StateType::eStateRunning;      MaybeLogStateChange (new_state); @@ -213,29 +215,92 @@ NativeThreadLinux::SetRunning ()      // then this is a new thread. So set all existing watchpoints.      if (m_watchpoint_index_map.empty())      { -        const auto process_sp = GetProcess(); -        if (process_sp) +        NativeProcessLinux &process = GetProcess(); + +        const auto &watchpoint_map = process.GetWatchpointMap(); +        GetRegisterContext()->ClearAllHardwareWatchpoints(); +        for (const auto &pair : watchpoint_map)          { -            const auto &watchpoint_map = process_sp->GetWatchpointMap(); -            if (watchpoint_map.empty()) return; -            GetRegisterContext()->ClearAllHardwareWatchpoints(); -            for (const auto &pair : watchpoint_map) -            { -                const auto& wp = pair.second; -                SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware); -            } +            const auto &wp = pair.second; +            SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware);          }      } + +    intptr_t data = 0; + +    if (signo != LLDB_INVALID_SIGNAL_NUMBER) +        data = signo; + +    return NativeProcessLinux::PtraceWrapper(PTRACE_CONT, GetID(), nullptr, reinterpret_cast<void *>(data));  }  void -NativeThreadLinux::SetStepping () +NativeThreadLinux::MaybePrepareSingleStepWorkaround() +{ +    if (!SingleStepWorkaroundNeeded()) +        return; + +    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + +    if (sched_getaffinity(static_cast<::pid_t>(m_tid), sizeof m_original_cpu_set, &m_original_cpu_set) != 0) +    { +        // This should really not fail. But, just in case... +        if (log) +        { +            Error error(errno, eErrorTypePOSIX); +            log->Printf("NativeThreadLinux::%s Unable to get cpu affinity for thread %" PRIx64 ": %s", __FUNCTION__, +                        m_tid, error.AsCString()); +        } +        return; +    } + +    cpu_set_t set; +    CPU_ZERO(&set); +    CPU_SET(0, &set); +    if (sched_setaffinity(static_cast<::pid_t>(m_tid), sizeof set, &set) != 0 && log) +    { +        // This may fail in very locked down systems, if the thread is not allowed to run on +        // cpu 0. If that happens, only thing we can do is it log it and continue... +        Error error(errno, eErrorTypePOSIX); +        log->Printf("NativeThreadLinux::%s Unable to set cpu affinity for thread %" PRIx64 ": %s", __FUNCTION__, m_tid, +                    error.AsCString()); +    } +} + +void +NativeThreadLinux::MaybeCleanupSingleStepWorkaround() +{ +    if (!SingleStepWorkaroundNeeded()) +        return; + +    if (sched_setaffinity(static_cast<::pid_t>(m_tid), sizeof m_original_cpu_set, &m_original_cpu_set) != 0) +    { +        Error error(errno, eErrorTypePOSIX); +        Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); +        log->Printf("NativeThreadLinux::%s Unable to reset cpu affinity for thread %" PRIx64 ": %s", __FUNCTION__, +                    m_tid, error.AsCString()); +    } +} + +Error +NativeThreadLinux::SingleStep(uint32_t signo)  {      const StateType new_state = StateType::eStateStepping;      MaybeLogStateChange (new_state);      m_state = new_state; -      m_stop_info.reason = StopReason::eStopReasonNone; + +    MaybePrepareSingleStepWorkaround(); + +    intptr_t data = 0; +    if (signo != LLDB_INVALID_SIGNAL_NUMBER) +        data = signo; + +    // If hardware single-stepping is not supported, we just do a continue. The breakpoint on the +    // next instruction has been setup in NativeProcessLinux::Resume. +    return NativeProcessLinux::PtraceWrapper(GetProcess().SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP +                                                                                          : PTRACE_CONT, +                                             m_tid, nullptr, reinterpret_cast<void *>(data));  }  void @@ -245,9 +310,7 @@ NativeThreadLinux::SetStoppedBySignal(uint32_t signo, const siginfo_t *info)      if (log)          log->Printf ("NativeThreadLinux::%s called with signal 0x%02" PRIx32, __FUNCTION__, signo); -    const StateType new_state = StateType::eStateStopped; -    MaybeLogStateChange (new_state); -    m_state = new_state; +    SetStopped();      m_stop_info.reason = StopReason::eStopReasonSignal;      m_stop_info.details.signal.signo = signo; @@ -288,6 +351,17 @@ NativeThreadLinux::IsStopped (int *signo)      return true;  } +void +NativeThreadLinux::SetStopped() +{ +    if (m_state == StateType::eStateStepping) +        MaybeCleanupSingleStepWorkaround(); + +    const StateType new_state = StateType::eStateStopped; +    MaybeLogStateChange(new_state); +    m_state = new_state; +    m_stop_description.clear(); +}  void  NativeThreadLinux::SetStoppedByExec () @@ -296,9 +370,7 @@ NativeThreadLinux::SetStoppedByExec ()      if (log)          log->Printf ("NativeThreadLinux::%s()", __FUNCTION__); -    const StateType new_state = StateType::eStateStopped; -    MaybeLogStateChange (new_state); -    m_state = new_state; +    SetStopped();      m_stop_info.reason = StopReason::eStopReasonExec;      m_stop_info.details.signal.signo = SIGSTOP; @@ -307,9 +379,7 @@ NativeThreadLinux::SetStoppedByExec ()  void  NativeThreadLinux::SetStoppedByBreakpoint ()  { -    const StateType new_state = StateType::eStateStopped; -    MaybeLogStateChange (new_state); -    m_state = new_state; +    SetStopped();      m_stop_info.reason = StopReason::eStopReasonBreakpoint;      m_stop_info.details.signal.signo = SIGTRAP; @@ -319,10 +389,7 @@ NativeThreadLinux::SetStoppedByBreakpoint ()  void  NativeThreadLinux::SetStoppedByWatchpoint (uint32_t wp_index)  { -    const StateType new_state = StateType::eStateStopped; -    MaybeLogStateChange (new_state); -    m_state = new_state; -    m_stop_description.clear (); +    SetStopped();      lldbassert(wp_index != LLDB_INVALID_INDEX32 &&                 "wp_index cannot be invalid"); @@ -363,9 +430,7 @@ NativeThreadLinux::IsStoppedAtWatchpoint ()  void  NativeThreadLinux::SetStoppedByTrace ()  { -    const StateType new_state = StateType::eStateStopped; -    MaybeLogStateChange (new_state); -    m_state = new_state; +    SetStopped();      m_stop_info.reason = StopReason::eStopReasonTrace;      m_stop_info.details.signal.signo = SIGTRAP; @@ -374,9 +439,7 @@ NativeThreadLinux::SetStoppedByTrace ()  void  NativeThreadLinux::SetStoppedWithNoReason ()  { -    const StateType new_state = StateType::eStateStopped; -    MaybeLogStateChange (new_state); -    m_state = new_state; +    SetStopped();      m_stop_info.reason = StopReason::eStopReasonNone;      m_stop_info.details.signal.signo = 0; @@ -397,11 +460,9 @@ NativeThreadLinux::RequestStop ()  {      Log* log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); -    const auto process_sp = GetProcess(); -    if (! process_sp) -        return Error("Process is null."); +    NativeProcessLinux &process = GetProcess(); -    lldb::pid_t pid = process_sp->GetID(); +    lldb::pid_t pid = process.GetID();      lldb::tid_t tid = GetID();      if (log) @@ -438,3 +499,11 @@ NativeThreadLinux::MaybeLogStateChange (lldb::StateType new_state)      // Log it.      log->Printf ("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 ") changing from state %s to %s", pid, GetID (), StateAsCString (old_state), StateAsCString (new_state));  } + +NativeProcessLinux & +NativeThreadLinux::GetProcess() +{ +    auto process_sp = std::static_pointer_cast<NativeProcessLinux>(NativeThreadProtocol::GetProcess()); +    assert(process_sp); +    return *process_sp; +}  | 
