11a3d19ddSKamil Rytarowski //===-- NativeThreadNetBSD.cpp -------------------------------- -*- C++ -*-===// 21a3d19ddSKamil Rytarowski // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61a3d19ddSKamil Rytarowski // 71a3d19ddSKamil Rytarowski //===----------------------------------------------------------------------===// 81a3d19ddSKamil Rytarowski 91a3d19ddSKamil Rytarowski #include "NativeThreadNetBSD.h" 101a3d19ddSKamil Rytarowski #include "NativeRegisterContextNetBSD.h" 111a3d19ddSKamil Rytarowski 121a3d19ddSKamil Rytarowski #include "NativeProcessNetBSD.h" 131a3d19ddSKamil Rytarowski 14f07a9995SKamil Rytarowski #include "Plugins/Process/POSIX/CrashReason.h" 15f07a9995SKamil Rytarowski #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" 1636e23ecaSKamil Rytarowski #include "lldb/Utility/LLDBAssert.h" 17d821c997SPavel Labath #include "lldb/Utility/RegisterValue.h" 18d821c997SPavel Labath #include "lldb/Utility/State.h" 19*23a766dcSMichał Górny #include "llvm/Support/Errno.h" 2036e23ecaSKamil Rytarowski 2136e23ecaSKamil Rytarowski #include <sstream> 22f07a9995SKamil Rytarowski 23*23a766dcSMichał Górny // clang-format off 24*23a766dcSMichał Górny #include <sys/types.h> 25*23a766dcSMichał Górny #include <sys/sysctl.h> 26*23a766dcSMichał Górny // clang-format on 27*23a766dcSMichał Górny 281a3d19ddSKamil Rytarowski using namespace lldb; 291a3d19ddSKamil Rytarowski using namespace lldb_private; 301a3d19ddSKamil Rytarowski using namespace lldb_private::process_netbsd; 311a3d19ddSKamil Rytarowski 3282abefa4SPavel Labath NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD &process, 331a3d19ddSKamil Rytarowski lldb::tid_t tid) 34f07a9995SKamil Rytarowski : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid), 35d37349f3SPavel Labath m_stop_info(), m_reg_context_up( 36d37349f3SPavel Labath NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(process.GetArchitecture(), *this) 37d37349f3SPavel Labath ), m_stop_description() {} 38f07a9995SKamil Rytarowski 39f07a9995SKamil Rytarowski void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo, 40f07a9995SKamil Rytarowski const siginfo_t *info) { 41f07a9995SKamil Rytarowski Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); 42f07a9995SKamil Rytarowski LLDB_LOG(log, "tid = {0} in called with signal {1}", GetID(), signo); 43f07a9995SKamil Rytarowski 44f07a9995SKamil Rytarowski SetStopped(); 45f07a9995SKamil Rytarowski 46f07a9995SKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonSignal; 47f07a9995SKamil Rytarowski m_stop_info.details.signal.signo = signo; 48f07a9995SKamil Rytarowski 49f07a9995SKamil Rytarowski m_stop_description.clear(); 50f07a9995SKamil Rytarowski if (info) { 51f07a9995SKamil Rytarowski switch (signo) { 52f07a9995SKamil Rytarowski case SIGSEGV: 53f07a9995SKamil Rytarowski case SIGBUS: 54f07a9995SKamil Rytarowski case SIGFPE: 55f07a9995SKamil Rytarowski case SIGILL: 56f07a9995SKamil Rytarowski const auto reason = GetCrashReason(*info); 57f07a9995SKamil Rytarowski m_stop_description = GetCrashReasonString(reason, *info); 58f07a9995SKamil Rytarowski break; 59f07a9995SKamil Rytarowski } 60f07a9995SKamil Rytarowski } 61f07a9995SKamil Rytarowski } 62f07a9995SKamil Rytarowski 63f07a9995SKamil Rytarowski void NativeThreadNetBSD::SetStoppedByBreakpoint() { 64f07a9995SKamil Rytarowski SetStopped(); 65f07a9995SKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonBreakpoint; 66f07a9995SKamil Rytarowski m_stop_info.details.signal.signo = SIGTRAP; 67f07a9995SKamil Rytarowski } 68f07a9995SKamil Rytarowski 693eef2b5eSKamil Rytarowski void NativeThreadNetBSD::SetStoppedByTrace() { 703eef2b5eSKamil Rytarowski SetStopped(); 713eef2b5eSKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonTrace; 723eef2b5eSKamil Rytarowski m_stop_info.details.signal.signo = SIGTRAP; 733eef2b5eSKamil Rytarowski } 743eef2b5eSKamil Rytarowski 753eef2b5eSKamil Rytarowski void NativeThreadNetBSD::SetStoppedByExec() { 763eef2b5eSKamil Rytarowski SetStopped(); 773eef2b5eSKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonExec; 783eef2b5eSKamil Rytarowski m_stop_info.details.signal.signo = SIGTRAP; 793eef2b5eSKamil Rytarowski } 803eef2b5eSKamil Rytarowski 8136e23ecaSKamil Rytarowski void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) { 8236e23ecaSKamil Rytarowski SetStopped(); 8336e23ecaSKamil Rytarowski 8436e23ecaSKamil Rytarowski lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); 8536e23ecaSKamil Rytarowski 8636e23ecaSKamil Rytarowski std::ostringstream ostr; 87d37349f3SPavel Labath ostr << GetRegisterContext().GetWatchpointAddress(wp_index) << " "; 8836e23ecaSKamil Rytarowski ostr << wp_index; 8936e23ecaSKamil Rytarowski 90d37349f3SPavel Labath ostr << " " << GetRegisterContext().GetWatchpointHitAddress(wp_index); 9136e23ecaSKamil Rytarowski 9236e23ecaSKamil Rytarowski m_stop_description = ostr.str(); 9336e23ecaSKamil Rytarowski 9436e23ecaSKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonWatchpoint; 9536e23ecaSKamil Rytarowski m_stop_info.details.signal.signo = SIGTRAP; 9636e23ecaSKamil Rytarowski } 9736e23ecaSKamil Rytarowski 98f07a9995SKamil Rytarowski void NativeThreadNetBSD::SetStopped() { 99f07a9995SKamil Rytarowski const StateType new_state = StateType::eStateStopped; 100f07a9995SKamil Rytarowski m_state = new_state; 101f07a9995SKamil Rytarowski m_stop_description.clear(); 102f07a9995SKamil Rytarowski } 103f07a9995SKamil Rytarowski 104f07a9995SKamil Rytarowski void NativeThreadNetBSD::SetRunning() { 105f07a9995SKamil Rytarowski m_state = StateType::eStateRunning; 106f07a9995SKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonNone; 107f07a9995SKamil Rytarowski } 108f07a9995SKamil Rytarowski 1093eef2b5eSKamil Rytarowski void NativeThreadNetBSD::SetStepping() { 1103eef2b5eSKamil Rytarowski m_state = StateType::eStateStepping; 1113eef2b5eSKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonNone; 1123eef2b5eSKamil Rytarowski } 1133eef2b5eSKamil Rytarowski 114*23a766dcSMichał Górny std::string NativeThreadNetBSD::GetName() { 115*23a766dcSMichał Górny Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); 116*23a766dcSMichał Górny 117*23a766dcSMichał Górny std::vector<struct kinfo_lwp> infos; 118*23a766dcSMichał Górny int mib[5] = {CTL_KERN, KERN_LWP, static_cast<int>(m_process.GetID()), 119*23a766dcSMichał Górny sizeof(struct kinfo_lwp), 0}; 120*23a766dcSMichał Górny size_t size; 121*23a766dcSMichał Górny 122*23a766dcSMichał Górny if (::sysctl(mib, 5, nullptr, &size, nullptr, 0) == -1 || size == 0) { 123*23a766dcSMichał Górny LLDB_LOG(log, "sysctl() for LWP info size failed: {0}", 124*23a766dcSMichał Górny llvm::sys::StrError()); 125*23a766dcSMichał Górny return ""; 126*23a766dcSMichał Górny } 127*23a766dcSMichał Górny 128*23a766dcSMichał Górny mib[4] = size / sizeof(size_t); 129*23a766dcSMichał Górny infos.resize(size / sizeof(struct kinfo_lwp)); 130*23a766dcSMichał Górny 131*23a766dcSMichał Górny if (sysctl(mib, 5, infos.data(), &size, NULL, 0) == -1 || size == 0) { 132*23a766dcSMichał Górny LLDB_LOG(log, "sysctl() for LWP info failed: {0}", llvm::sys::StrError()); 133*23a766dcSMichał Górny return ""; 134*23a766dcSMichał Górny } 135*23a766dcSMichał Górny 136*23a766dcSMichał Górny size_t nlwps = size / sizeof(struct kinfo_lwp); 137*23a766dcSMichał Górny for (size_t i = 0; i < nlwps; i++) { 138*23a766dcSMichał Górny if (static_cast<lldb::tid_t>(infos[i].l_lid) == m_tid) { 139*23a766dcSMichał Górny return infos[i].l_name; 140*23a766dcSMichał Górny } 141*23a766dcSMichał Górny } 142*23a766dcSMichał Górny 143*23a766dcSMichał Górny LLDB_LOG(log, "unable to find lwp {0} in LWP infos", m_tid); 144*23a766dcSMichał Górny return ""; 145*23a766dcSMichał Górny } 146f07a9995SKamil Rytarowski 147f07a9995SKamil Rytarowski lldb::StateType NativeThreadNetBSD::GetState() { return m_state; } 148f07a9995SKamil Rytarowski 149f07a9995SKamil Rytarowski bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info, 150f07a9995SKamil Rytarowski std::string &description) { 151f07a9995SKamil Rytarowski Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); 152f07a9995SKamil Rytarowski 153f07a9995SKamil Rytarowski description.clear(); 154f07a9995SKamil Rytarowski 155f07a9995SKamil Rytarowski switch (m_state) { 156f07a9995SKamil Rytarowski case eStateStopped: 157f07a9995SKamil Rytarowski case eStateCrashed: 158f07a9995SKamil Rytarowski case eStateExited: 159f07a9995SKamil Rytarowski case eStateSuspended: 160f07a9995SKamil Rytarowski case eStateUnloaded: 161f07a9995SKamil Rytarowski stop_info = m_stop_info; 162f07a9995SKamil Rytarowski description = m_stop_description; 163f07a9995SKamil Rytarowski 164f07a9995SKamil Rytarowski return true; 165f07a9995SKamil Rytarowski 166f07a9995SKamil Rytarowski case eStateInvalid: 167f07a9995SKamil Rytarowski case eStateConnected: 168f07a9995SKamil Rytarowski case eStateAttaching: 169f07a9995SKamil Rytarowski case eStateLaunching: 170f07a9995SKamil Rytarowski case eStateRunning: 171f07a9995SKamil Rytarowski case eStateStepping: 172f07a9995SKamil Rytarowski case eStateDetached: 173f07a9995SKamil Rytarowski LLDB_LOG(log, "tid = {0} in state {1} cannot answer stop reason", GetID(), 174f07a9995SKamil Rytarowski StateAsCString(m_state)); 175f07a9995SKamil Rytarowski return false; 176f07a9995SKamil Rytarowski } 177f07a9995SKamil Rytarowski llvm_unreachable("unhandled StateType!"); 178f07a9995SKamil Rytarowski } 179f07a9995SKamil Rytarowski 180d37349f3SPavel Labath NativeRegisterContext& NativeThreadNetBSD::GetRegisterContext() { 181d37349f3SPavel Labath assert(m_reg_context_up); 182d37349f3SPavel Labath return *m_reg_context_up; 183f07a9995SKamil Rytarowski } 184f07a9995SKamil Rytarowski 18597206d57SZachary Turner Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size, 186f07a9995SKamil Rytarowski uint32_t watch_flags, bool hardware) { 18736e23ecaSKamil Rytarowski if (!hardware) 18897206d57SZachary Turner return Status("not implemented"); 18936e23ecaSKamil Rytarowski if (m_state == eStateLaunching) 19097206d57SZachary Turner return Status(); 19197206d57SZachary Turner Status error = RemoveWatchpoint(addr); 19236e23ecaSKamil Rytarowski if (error.Fail()) 19336e23ecaSKamil Rytarowski return error; 194d37349f3SPavel Labath uint32_t wp_index = GetRegisterContext().SetHardwareWatchpoint(addr, size, watch_flags); 19536e23ecaSKamil Rytarowski if (wp_index == LLDB_INVALID_INDEX32) 19697206d57SZachary Turner return Status("Setting hardware watchpoint failed."); 19736e23ecaSKamil Rytarowski m_watchpoint_index_map.insert({addr, wp_index}); 19897206d57SZachary Turner return Status(); 199f07a9995SKamil Rytarowski } 200f07a9995SKamil Rytarowski 20197206d57SZachary Turner Status NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) { 20236e23ecaSKamil Rytarowski auto wp = m_watchpoint_index_map.find(addr); 20336e23ecaSKamil Rytarowski if (wp == m_watchpoint_index_map.end()) 20497206d57SZachary Turner return Status(); 20536e23ecaSKamil Rytarowski uint32_t wp_index = wp->second; 20636e23ecaSKamil Rytarowski m_watchpoint_index_map.erase(wp); 207d37349f3SPavel Labath if (GetRegisterContext().ClearHardwareWatchpoint(wp_index)) 20897206d57SZachary Turner return Status(); 20997206d57SZachary Turner return Status("Clearing hardware watchpoint failed."); 210f07a9995SKamil Rytarowski } 211f07a9995SKamil Rytarowski 21297206d57SZachary Turner Status NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr, 213f07a9995SKamil Rytarowski size_t size) { 21436e23ecaSKamil Rytarowski if (m_state == eStateLaunching) 21597206d57SZachary Turner return Status(); 21636e23ecaSKamil Rytarowski 21797206d57SZachary Turner Status error = RemoveHardwareBreakpoint(addr); 21836e23ecaSKamil Rytarowski if (error.Fail()) 21936e23ecaSKamil Rytarowski return error; 22036e23ecaSKamil Rytarowski 221d37349f3SPavel Labath uint32_t bp_index = GetRegisterContext().SetHardwareBreakpoint(addr, size); 22236e23ecaSKamil Rytarowski 22336e23ecaSKamil Rytarowski if (bp_index == LLDB_INVALID_INDEX32) 22497206d57SZachary Turner return Status("Setting hardware breakpoint failed."); 22536e23ecaSKamil Rytarowski 22636e23ecaSKamil Rytarowski m_hw_break_index_map.insert({addr, bp_index}); 22797206d57SZachary Turner return Status(); 228f07a9995SKamil Rytarowski } 229f07a9995SKamil Rytarowski 23097206d57SZachary Turner Status NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) { 23136e23ecaSKamil Rytarowski auto bp = m_hw_break_index_map.find(addr); 23236e23ecaSKamil Rytarowski if (bp == m_hw_break_index_map.end()) 23397206d57SZachary Turner return Status(); 23436e23ecaSKamil Rytarowski 23536e23ecaSKamil Rytarowski uint32_t bp_index = bp->second; 236d37349f3SPavel Labath if (GetRegisterContext().ClearHardwareBreakpoint(bp_index)) { 23736e23ecaSKamil Rytarowski m_hw_break_index_map.erase(bp); 23897206d57SZachary Turner return Status(); 23936e23ecaSKamil Rytarowski } 24036e23ecaSKamil Rytarowski 24197206d57SZachary Turner return Status("Clearing hardware breakpoint failed."); 242f07a9995SKamil Rytarowski } 243