11a3d19ddSKamil Rytarowski //===-- NativeThreadNetBSD.cpp -------------------------------- -*- C++ -*-===// 21a3d19ddSKamil Rytarowski // 3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 5*2946cd70SChandler 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" 1936e23ecaSKamil Rytarowski 2036e23ecaSKamil Rytarowski #include <sstream> 21f07a9995SKamil Rytarowski 221a3d19ddSKamil Rytarowski using namespace lldb; 231a3d19ddSKamil Rytarowski using namespace lldb_private; 241a3d19ddSKamil Rytarowski using namespace lldb_private::process_netbsd; 251a3d19ddSKamil Rytarowski 2682abefa4SPavel Labath NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD &process, 271a3d19ddSKamil Rytarowski lldb::tid_t tid) 28f07a9995SKamil Rytarowski : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid), 29d37349f3SPavel Labath m_stop_info(), m_reg_context_up( 30d37349f3SPavel Labath NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(process.GetArchitecture(), *this) 31d37349f3SPavel Labath ), m_stop_description() {} 32f07a9995SKamil Rytarowski 33f07a9995SKamil Rytarowski void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo, 34f07a9995SKamil Rytarowski const siginfo_t *info) { 35f07a9995SKamil Rytarowski Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); 36f07a9995SKamil Rytarowski LLDB_LOG(log, "tid = {0} in called with signal {1}", GetID(), signo); 37f07a9995SKamil Rytarowski 38f07a9995SKamil Rytarowski SetStopped(); 39f07a9995SKamil Rytarowski 40f07a9995SKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonSignal; 41f07a9995SKamil Rytarowski m_stop_info.details.signal.signo = signo; 42f07a9995SKamil Rytarowski 43f07a9995SKamil Rytarowski m_stop_description.clear(); 44f07a9995SKamil Rytarowski if (info) { 45f07a9995SKamil Rytarowski switch (signo) { 46f07a9995SKamil Rytarowski case SIGSEGV: 47f07a9995SKamil Rytarowski case SIGBUS: 48f07a9995SKamil Rytarowski case SIGFPE: 49f07a9995SKamil Rytarowski case SIGILL: 50f07a9995SKamil Rytarowski const auto reason = GetCrashReason(*info); 51f07a9995SKamil Rytarowski m_stop_description = GetCrashReasonString(reason, *info); 52f07a9995SKamil Rytarowski break; 53f07a9995SKamil Rytarowski } 54f07a9995SKamil Rytarowski } 55f07a9995SKamil Rytarowski } 56f07a9995SKamil Rytarowski 57f07a9995SKamil Rytarowski void NativeThreadNetBSD::SetStoppedByBreakpoint() { 58f07a9995SKamil Rytarowski SetStopped(); 59f07a9995SKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonBreakpoint; 60f07a9995SKamil Rytarowski m_stop_info.details.signal.signo = SIGTRAP; 61f07a9995SKamil Rytarowski } 62f07a9995SKamil Rytarowski 633eef2b5eSKamil Rytarowski void NativeThreadNetBSD::SetStoppedByTrace() { 643eef2b5eSKamil Rytarowski SetStopped(); 653eef2b5eSKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonTrace; 663eef2b5eSKamil Rytarowski m_stop_info.details.signal.signo = SIGTRAP; 673eef2b5eSKamil Rytarowski } 683eef2b5eSKamil Rytarowski 693eef2b5eSKamil Rytarowski void NativeThreadNetBSD::SetStoppedByExec() { 703eef2b5eSKamil Rytarowski SetStopped(); 713eef2b5eSKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonExec; 723eef2b5eSKamil Rytarowski m_stop_info.details.signal.signo = SIGTRAP; 733eef2b5eSKamil Rytarowski } 743eef2b5eSKamil Rytarowski 7536e23ecaSKamil Rytarowski void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) { 7636e23ecaSKamil Rytarowski SetStopped(); 7736e23ecaSKamil Rytarowski 7836e23ecaSKamil Rytarowski lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); 7936e23ecaSKamil Rytarowski 8036e23ecaSKamil Rytarowski std::ostringstream ostr; 81d37349f3SPavel Labath ostr << GetRegisterContext().GetWatchpointAddress(wp_index) << " "; 8236e23ecaSKamil Rytarowski ostr << wp_index; 8336e23ecaSKamil Rytarowski 84d37349f3SPavel Labath ostr << " " << GetRegisterContext().GetWatchpointHitAddress(wp_index); 8536e23ecaSKamil Rytarowski 8636e23ecaSKamil Rytarowski m_stop_description = ostr.str(); 8736e23ecaSKamil Rytarowski 8836e23ecaSKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonWatchpoint; 8936e23ecaSKamil Rytarowski m_stop_info.details.signal.signo = SIGTRAP; 9036e23ecaSKamil Rytarowski } 9136e23ecaSKamil Rytarowski 92f07a9995SKamil Rytarowski void NativeThreadNetBSD::SetStopped() { 93f07a9995SKamil Rytarowski const StateType new_state = StateType::eStateStopped; 94f07a9995SKamil Rytarowski m_state = new_state; 95f07a9995SKamil Rytarowski m_stop_description.clear(); 96f07a9995SKamil Rytarowski } 97f07a9995SKamil Rytarowski 98f07a9995SKamil Rytarowski void NativeThreadNetBSD::SetRunning() { 99f07a9995SKamil Rytarowski m_state = StateType::eStateRunning; 100f07a9995SKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonNone; 101f07a9995SKamil Rytarowski } 102f07a9995SKamil Rytarowski 1033eef2b5eSKamil Rytarowski void NativeThreadNetBSD::SetStepping() { 1043eef2b5eSKamil Rytarowski m_state = StateType::eStateStepping; 1053eef2b5eSKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonNone; 1063eef2b5eSKamil Rytarowski } 1073eef2b5eSKamil Rytarowski 108f07a9995SKamil Rytarowski std::string NativeThreadNetBSD::GetName() { return std::string(""); } 109f07a9995SKamil Rytarowski 110f07a9995SKamil Rytarowski lldb::StateType NativeThreadNetBSD::GetState() { return m_state; } 111f07a9995SKamil Rytarowski 112f07a9995SKamil Rytarowski bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info, 113f07a9995SKamil Rytarowski std::string &description) { 114f07a9995SKamil Rytarowski Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); 115f07a9995SKamil Rytarowski 116f07a9995SKamil Rytarowski description.clear(); 117f07a9995SKamil Rytarowski 118f07a9995SKamil Rytarowski switch (m_state) { 119f07a9995SKamil Rytarowski case eStateStopped: 120f07a9995SKamil Rytarowski case eStateCrashed: 121f07a9995SKamil Rytarowski case eStateExited: 122f07a9995SKamil Rytarowski case eStateSuspended: 123f07a9995SKamil Rytarowski case eStateUnloaded: 124f07a9995SKamil Rytarowski stop_info = m_stop_info; 125f07a9995SKamil Rytarowski description = m_stop_description; 126f07a9995SKamil Rytarowski 127f07a9995SKamil Rytarowski return true; 128f07a9995SKamil Rytarowski 129f07a9995SKamil Rytarowski case eStateInvalid: 130f07a9995SKamil Rytarowski case eStateConnected: 131f07a9995SKamil Rytarowski case eStateAttaching: 132f07a9995SKamil Rytarowski case eStateLaunching: 133f07a9995SKamil Rytarowski case eStateRunning: 134f07a9995SKamil Rytarowski case eStateStepping: 135f07a9995SKamil Rytarowski case eStateDetached: 136f07a9995SKamil Rytarowski LLDB_LOG(log, "tid = {0} in state {1} cannot answer stop reason", GetID(), 137f07a9995SKamil Rytarowski StateAsCString(m_state)); 138f07a9995SKamil Rytarowski return false; 139f07a9995SKamil Rytarowski } 140f07a9995SKamil Rytarowski llvm_unreachable("unhandled StateType!"); 141f07a9995SKamil Rytarowski } 142f07a9995SKamil Rytarowski 143d37349f3SPavel Labath NativeRegisterContext& NativeThreadNetBSD::GetRegisterContext() { 144d37349f3SPavel Labath assert(m_reg_context_up); 145d37349f3SPavel Labath return *m_reg_context_up; 146f07a9995SKamil Rytarowski } 147f07a9995SKamil Rytarowski 14897206d57SZachary Turner Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size, 149f07a9995SKamil Rytarowski uint32_t watch_flags, bool hardware) { 15036e23ecaSKamil Rytarowski if (!hardware) 15197206d57SZachary Turner return Status("not implemented"); 15236e23ecaSKamil Rytarowski if (m_state == eStateLaunching) 15397206d57SZachary Turner return Status(); 15497206d57SZachary Turner Status error = RemoveWatchpoint(addr); 15536e23ecaSKamil Rytarowski if (error.Fail()) 15636e23ecaSKamil Rytarowski return error; 157d37349f3SPavel Labath uint32_t wp_index = GetRegisterContext().SetHardwareWatchpoint(addr, size, watch_flags); 15836e23ecaSKamil Rytarowski if (wp_index == LLDB_INVALID_INDEX32) 15997206d57SZachary Turner return Status("Setting hardware watchpoint failed."); 16036e23ecaSKamil Rytarowski m_watchpoint_index_map.insert({addr, wp_index}); 16197206d57SZachary Turner return Status(); 162f07a9995SKamil Rytarowski } 163f07a9995SKamil Rytarowski 16497206d57SZachary Turner Status NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) { 16536e23ecaSKamil Rytarowski auto wp = m_watchpoint_index_map.find(addr); 16636e23ecaSKamil Rytarowski if (wp == m_watchpoint_index_map.end()) 16797206d57SZachary Turner return Status(); 16836e23ecaSKamil Rytarowski uint32_t wp_index = wp->second; 16936e23ecaSKamil Rytarowski m_watchpoint_index_map.erase(wp); 170d37349f3SPavel Labath if (GetRegisterContext().ClearHardwareWatchpoint(wp_index)) 17197206d57SZachary Turner return Status(); 17297206d57SZachary Turner return Status("Clearing hardware watchpoint failed."); 173f07a9995SKamil Rytarowski } 174f07a9995SKamil Rytarowski 17597206d57SZachary Turner Status NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr, 176f07a9995SKamil Rytarowski size_t size) { 17736e23ecaSKamil Rytarowski if (m_state == eStateLaunching) 17897206d57SZachary Turner return Status(); 17936e23ecaSKamil Rytarowski 18097206d57SZachary Turner Status error = RemoveHardwareBreakpoint(addr); 18136e23ecaSKamil Rytarowski if (error.Fail()) 18236e23ecaSKamil Rytarowski return error; 18336e23ecaSKamil Rytarowski 184d37349f3SPavel Labath uint32_t bp_index = GetRegisterContext().SetHardwareBreakpoint(addr, size); 18536e23ecaSKamil Rytarowski 18636e23ecaSKamil Rytarowski if (bp_index == LLDB_INVALID_INDEX32) 18797206d57SZachary Turner return Status("Setting hardware breakpoint failed."); 18836e23ecaSKamil Rytarowski 18936e23ecaSKamil Rytarowski m_hw_break_index_map.insert({addr, bp_index}); 19097206d57SZachary Turner return Status(); 191f07a9995SKamil Rytarowski } 192f07a9995SKamil Rytarowski 19397206d57SZachary Turner Status NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) { 19436e23ecaSKamil Rytarowski auto bp = m_hw_break_index_map.find(addr); 19536e23ecaSKamil Rytarowski if (bp == m_hw_break_index_map.end()) 19697206d57SZachary Turner return Status(); 19736e23ecaSKamil Rytarowski 19836e23ecaSKamil Rytarowski uint32_t bp_index = bp->second; 199d37349f3SPavel Labath if (GetRegisterContext().ClearHardwareBreakpoint(bp_index)) { 20036e23ecaSKamil Rytarowski m_hw_break_index_map.erase(bp); 20197206d57SZachary Turner return Status(); 20236e23ecaSKamil Rytarowski } 20336e23ecaSKamil Rytarowski 20497206d57SZachary Turner return Status("Clearing hardware breakpoint failed."); 205f07a9995SKamil Rytarowski } 206