diff options
Diffstat (limited to 'lldb/source/Plugins/Process/Linux')
8 files changed, 195 insertions, 148 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp index b0a2d6c5c4b..fd3a62eab42 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -39,6 +39,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Process.h" #include "lldb/Target/ProcessLaunchInfo.h" +#include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/PseudoTerminal.h" #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" @@ -2251,93 +2252,31 @@ NativeProcessLinux::MonitorSIGTRAP(const siginfo_t *info, lldb::pid_t pid) } case 0: - case TRAP_TRACE: - // We receive this on single stepping. - if (log) - log->Printf ("NativeProcessLinux::%s() received trace event, pid = %" PRIu64 " (single stepping)", __FUNCTION__, pid); - + case TRAP_TRACE: // We receive this on single stepping. + case TRAP_HWBKPT: // We receive this on watchpoint hit if (thread_sp) { - std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetStoppedByTrace (); - } - - // This thread is currently stopped. - NotifyThreadStop (pid); - - // Here we don't have to request the rest of the threads to stop or request a deferred stop. - // This would have already happened at the time the Resume() with step operation was signaled. - // At this point, we just need to say we stopped, and the deferred notifcation will fire off - // once all running threads have checked in as stopped. - SetCurrentThreadID (pid); - // Tell the process we have a stop (from software breakpoint). - CallAfterRunningThreadsStop (pid, - [=] (lldb::tid_t signaling_tid) - { - SetState (StateType::eStateStopped, true); - }); - break; - - case SI_KERNEL: - case TRAP_BRKPT: - if (log) - log->Printf ("NativeProcessLinux::%s() received breakpoint event, pid = %" PRIu64, __FUNCTION__, pid); - - // This thread is currently stopped. - NotifyThreadStop (pid); - - // Mark the thread as stopped at breakpoint. - if (thread_sp) - { - std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetStoppedByBreakpoint (); - Error error = FixupBreakpointPCAsNeeded (thread_sp); - if (error.Fail ()) + // If a watchpoint was hit, report it + uint32_t wp_index; + Error error = thread_sp->GetRegisterContext()->GetWatchpointHitIndex(wp_index); + if (error.Fail() && log) + log->Printf("NativeProcessLinux::%s() " + "received error while checking for watchpoint hits, " + "pid = %" PRIu64 " error = %s", + __FUNCTION__, pid, error.AsCString()); + if (wp_index != LLDB_INVALID_INDEX32) { - if (log) - log->Printf ("NativeProcessLinux::%s() pid = %" PRIu64 " fixup: %s", __FUNCTION__, pid, error.AsCString ()); + MonitorWatchpoint(pid, thread_sp, wp_index); + break; } } - else - { - if (log) - log->Printf ("NativeProcessLinux::%s() pid = %" PRIu64 ": warning, cannot process software breakpoint since no thread metadata", __FUNCTION__, pid); - } - - - // We need to tell all other running threads before we notify the delegate about this stop. - CallAfterRunningThreadsStop (pid, - [=](lldb::tid_t deferred_notification_tid) - { - SetCurrentThreadID (deferred_notification_tid); - // Tell the process we have a stop (from software breakpoint). - SetState (StateType::eStateStopped, true); - }); + // Otherwise, report step over + MonitorTrace(pid, thread_sp); break; - case TRAP_HWBKPT: - if (log) - log->Printf ("NativeProcessLinux::%s() received watchpoint event, pid = %" PRIu64, __FUNCTION__, pid); - - // This thread is currently stopped. - NotifyThreadStop (pid); - - // Mark the thread as stopped at watchpoint. - // The address is at (lldb::addr_t)info->si_addr if we need it. - if (thread_sp) - std::static_pointer_cast<NativeThreadLinux> (thread_sp)->SetStoppedByWatchpoint (); - else - { - if (log) - log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 " tid %" PRIu64 ": warning, cannot process hardware breakpoint since no thread metadata", __FUNCTION__, GetID (), pid); - } - - // We need to tell all other running threads before we notify the delegate about this stop. - CallAfterRunningThreadsStop (pid, - [=](lldb::tid_t deferred_notification_tid) - { - SetCurrentThreadID (deferred_notification_tid); - // Tell the process we have a stop (from hardware breakpoint). - SetState (StateType::eStateStopped, true); - }); + case SI_KERNEL: + case TRAP_BRKPT: + MonitorBreakpoint(pid, thread_sp); break; case SIGTRAP: @@ -2371,6 +2310,98 @@ NativeProcessLinux::MonitorSIGTRAP(const siginfo_t *info, lldb::pid_t pid) } void +NativeProcessLinux::MonitorTrace(lldb::pid_t pid, NativeThreadProtocolSP thread_sp) +{ + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("NativeProcessLinux::%s() received trace event, pid = %" PRIu64 " (single stepping)", + __FUNCTION__, pid); + + if (thread_sp) + std::static_pointer_cast<NativeThreadLinux>(thread_sp)->SetStoppedByTrace(); + + // This thread is currently stopped. + NotifyThreadStop(pid); + + // Here we don't have to request the rest of the threads to stop or request a deferred stop. + // This would have already happened at the time the Resume() with step operation was signaled. + // At this point, we just need to say we stopped, and the deferred notifcation will fire off + // once all running threads have checked in as stopped. + SetCurrentThreadID(pid); + // Tell the process we have a stop (from software breakpoint). + CallAfterRunningThreadsStop(pid, + [=](lldb::tid_t signaling_tid) + { + SetState(StateType::eStateStopped, true); + }); +} + +void +NativeProcessLinux::MonitorBreakpoint(lldb::pid_t pid, NativeThreadProtocolSP thread_sp) +{ + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf("NativeProcessLinux::%s() received breakpoint event, pid = %" PRIu64, + __FUNCTION__, pid); + + // This thread is currently stopped. + NotifyThreadStop(pid); + + // Mark the thread as stopped at breakpoint. + if (thread_sp) + { + std::static_pointer_cast<NativeThreadLinux>(thread_sp)->SetStoppedByBreakpoint(); + Error error = FixupBreakpointPCAsNeeded(thread_sp); + if (error.Fail()) + if (log) + log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 " fixup: %s", + __FUNCTION__, pid, error.AsCString()); + } + else + if (log) + log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 ": " + "warning, cannot process software breakpoint since no thread metadata", + __FUNCTION__, pid); + + + // We need to tell all other running threads before we notify the delegate about this stop. + CallAfterRunningThreadsStop(pid, + [=](lldb::tid_t deferred_notification_tid) + { + SetCurrentThreadID(deferred_notification_tid); + // Tell the process we have a stop (from software breakpoint). + SetState(StateType::eStateStopped, true); + }); +} + +void +NativeProcessLinux::MonitorWatchpoint(lldb::pid_t pid, NativeThreadProtocolSP thread_sp, uint32_t wp_index) +{ + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_WATCHPOINTS)); + if (log) + log->Printf("NativeProcessLinux::%s() received watchpoint event, " + "pid = %" PRIu64 ", wp_index = %" PRIu32, + __FUNCTION__, pid, wp_index); + + // This thread is currently stopped. + NotifyThreadStop(pid); + + // Mark the thread as stopped at watchpoint. + // The address is at (lldb::addr_t)info->si_addr if we need it. + lldbassert(thread_sp && "thread_sp cannot be NULL"); + std::static_pointer_cast<NativeThreadLinux>(thread_sp)->SetStoppedByWatchpoint(wp_index); + + // We need to tell all other running threads before we notify the delegate about this stop. + CallAfterRunningThreadsStop(pid, + [=](lldb::tid_t deferred_notification_tid) + { + SetCurrentThreadID(deferred_notification_tid); + // Tell the process we have a stop (from watchpoint). + SetState(StateType::eStateStopped, true); + }); +} + +void NativeProcessLinux::MonitorSignal(const siginfo_t *info, lldb::pid_t pid, bool exited) { assert (info && "null info"); diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h index a2ffd6cb68b..07220e97e3a 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -296,6 +296,15 @@ namespace lldb_private MonitorSIGTRAP(const siginfo_t *info, lldb::pid_t pid); void + MonitorTrace(lldb::pid_t pid, NativeThreadProtocolSP thread_sp); + + void + MonitorBreakpoint(lldb::pid_t pid, NativeThreadProtocolSP thread_sp); + + void + MonitorWatchpoint(lldb::pid_t pid, NativeThreadProtocolSP thread_sp, uint32_t wp_index); + + void MonitorSignal(const siginfo_t *info, lldb::pid_t pid, bool exited); #if 0 diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp index 67363ca6bbc..3d798e6e0f9 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp @@ -155,19 +155,17 @@ NativeRegisterContextLinux_mips64::WriteAllRegisterValues (const lldb::DataBuffe } Error -NativeRegisterContextLinux_mips64::IsWatchpointHit (uint8_t wp_index) +NativeRegisterContextLinux_mips64::IsWatchpointHit (uint32_t wp_index, bool &is_hit) { - Error error; - error.SetErrorString ("MIPS TODO: NativeRegisterContextLinux_mips64::IsWatchpointHit not implemented"); - return error; + is_hit = false; + return Error("MIPS TODO: NativeRegisterContextLinux_mips64::IsWatchpointHit not implemented"); } Error -NativeRegisterContextLinux_mips64::IsWatchpointVacant (uint32_t wp_index) +NativeRegisterContextLinux_mips64::IsWatchpointVacant (uint32_t wp_index, bool &is_vacant) { - Error error; - error.SetErrorString ("MIPS TODO: NativeRegisterContextLinux_mips64::IsWatchpointVacant not implemented"); - return error; + is_vacant = false; + return Error("MIPS TODO: NativeRegisterContextLinux_mips64::IsWatchpointVacant not implemented"); } bool diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h index b7833438ae0..35218b7eb58 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h @@ -91,10 +91,10 @@ namespace lldb_private WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override; Error - IsWatchpointHit (uint8_t wp_index) override; + IsWatchpointHit (uint32_t wp_index, bool &is_hit) override; Error - IsWatchpointVacant (uint32_t wp_index) override; + IsWatchpointVacant (uint32_t wp_index, bool &is_vacant) override; bool ClearHardwareWatchpoint (uint32_t wp_index) override; diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp index fa6dfd64b88..06ad5f296ec 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp @@ -9,6 +9,7 @@ #include "NativeRegisterContextLinux_x86_64.h" +#include "lldb/Core/Log.h" #include "lldb/lldb-private-forward.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" @@ -1046,39 +1047,61 @@ NativeRegisterContextLinux_x86_64::WriteGPR() } Error -NativeRegisterContextLinux_x86_64::IsWatchpointHit(uint8_t wp_index) +NativeRegisterContextLinux_x86_64::IsWatchpointHit(uint32_t wp_index, bool &is_hit) { if (wp_index >= NumSupportedHardwareWatchpoints()) - return Error ("Watchpoint index out of range"); + return Error("Watchpoint index out of range"); RegisterValue reg_value; Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value); - if (error.Fail()) return error; + if (error.Fail()) + { + is_hit = false; + return error; + } uint64_t status_bits = reg_value.GetAsUInt64(); - bool is_hit = status_bits & (1 << wp_index); - - error.SetError (!is_hit, lldb::eErrorTypeInvalid); + is_hit = status_bits & (1 << wp_index); return error; } Error -NativeRegisterContextLinux_x86_64::IsWatchpointVacant(uint32_t wp_index) +NativeRegisterContextLinux_x86_64::GetWatchpointHitIndex(uint32_t &wp_index) { + uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); + for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) + { + bool is_hit; + Error error = IsWatchpointHit(wp_index, is_hit); + if (error.Fail()) { + wp_index = LLDB_INVALID_INDEX32; + return error; + } else if (is_hit) { + return error; + } + } + wp_index = LLDB_INVALID_INDEX32; + return Error(); +} + +Error +NativeRegisterContextLinux_x86_64::IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) { if (wp_index >= NumSupportedHardwareWatchpoints()) return Error ("Watchpoint index out of range"); RegisterValue reg_value; Error error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); - if (error.Fail()) return error; + if (error.Fail()) + { + is_vacant = false; + return error; + } uint64_t control_bits = reg_value.GetAsUInt64(); - bool is_vacant = !(control_bits & (1 << (2 * wp_index))); - - error.SetError (!is_vacant, lldb::eErrorTypeInvalid); + is_vacant = !(control_bits & (1 << (2 * wp_index))); return error; } @@ -1096,8 +1119,10 @@ NativeRegisterContextLinux_x86_64::SetHardwareWatchpointWithIndex( if (size != 1 && size != 2 && size != 4 && size != 8) return Error ("Invalid size for watchpoint"); - Error error = IsWatchpointVacant (wp_index); + bool is_vacant; + Error error = IsWatchpointVacant (wp_index, is_vacant); if (error.Fail()) return error; + if (!is_vacant) return Error("Watchpoint index not vacant"); RegisterValue reg_value; error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); @@ -1184,14 +1209,24 @@ uint32_t NativeRegisterContextLinux_x86_64::SetHardwareWatchpoint( lldb::addr_t addr, size_t size, uint32_t watch_flags) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) - if (IsWatchpointVacant(wp_index).Success()) + { + bool is_vacant; + Error error = IsWatchpointVacant(wp_index, is_vacant); + if (is_vacant) { - if (SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index).Fail()) - continue; - return wp_index; + error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index); + if (error.Success()) + return wp_index; } + if (error.Fail() && log) + { + log->Printf("NativeRegisterContextLinux_x86_64::%s Error: %s", + __FUNCTION__, error.AsCString()); + } + } return LLDB_INVALID_INDEX32; } diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h index 0e9d721959b..e183118e8d4 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h @@ -46,10 +46,13 @@ namespace lldb_private WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override; Error - IsWatchpointHit(uint8_t wp_index) override; + IsWatchpointHit(uint32_t wp_index, bool &is_hit) override; Error - IsWatchpointVacant(uint32_t wp_index) override; + GetWatchpointHitIndex(uint32_t &wp_index) override; + + Error + IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override; bool ClearHardwareWatchpoint(uint32_t wp_index) override; diff --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp index 148f55f8033..51597f8dd17 100644 --- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp @@ -22,6 +22,7 @@ #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/HostNativeThread.h" +#include "lldb/Utility/LLDBAssert.h" #include "lldb/lldb-enumerations.h" #include "llvm/ADT/SmallString.h" @@ -379,53 +380,23 @@ NativeThreadLinux::SetStoppedByBreakpoint () } void -NativeThreadLinux::SetStoppedByWatchpoint () +NativeThreadLinux::SetStoppedByWatchpoint (uint32_t wp_index) { - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; - if (log) - { - NativeProcessProtocolSP process_sp = m_process_wp.lock (); - if (process_sp) - pid = process_sp->GetID (); - } - const StateType new_state = StateType::eStateStopped; MaybeLogStateChange (new_state); m_state = new_state; - - NativeRegisterContextSP reg_ctx = GetRegisterContext (); - const uint32_t num_hw_watchpoints = reg_ctx->NumSupportedHardwareWatchpoints (); - m_stop_description.clear (); - for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) - { - if (reg_ctx->IsWatchpointHit (wp_index).Success()) - { - if (log) - log->Printf ("NativeThreadLinux:%s (pid=%" PRIu64 ", tid=%" PRIu64 ") watchpoint found with idx: %u", - __FUNCTION__, pid, GetID (), wp_index); - - std::ostringstream ostr; - ostr << reg_ctx->GetWatchpointAddress (wp_index) << " " << wp_index; - m_stop_description = ostr.str(); - - m_stop_info.reason = StopReason::eStopReasonWatchpoint; - m_stop_info.details.signal.signo = SIGTRAP; - return; - } - } - // The process reported a watchpoint was hit, but we haven't found the - // watchpoint. Assume that a stopped by trace is reported as a hardware - // watchpoint what happens on some linux kernels (e.g.: android-arm64 - // platfrom-21). + lldbassert(wp_index != LLDB_INVALID_INDEX32 && + "wp_index cannot be invalid"); - if (log) - log->Printf ("NativeThreadLinux:%s (pid=%" PRIu64 ", tid=%" PRIu64 ") none of the watchpoint was hit.", - __FUNCTION__, pid, GetID ()); + std::ostringstream ostr; + ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " "; + ostr << wp_index; + m_stop_description = ostr.str(); - SetStoppedByTrace (); + m_stop_info.reason = StopReason::eStopReasonWatchpoint; + m_stop_info.details.signal.signo = SIGTRAP; } bool diff --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h index 2519b5b1da0..c77dcbe093f 100644 --- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h +++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h @@ -76,7 +76,7 @@ namespace lldb_private SetStoppedByBreakpoint (); void - SetStoppedByWatchpoint (); + SetStoppedByWatchpoint (uint32_t wp_index); bool IsStoppedAtBreakpoint (); |