11a3d19ddSKamil Rytarowski //===-- NativeThreadNetBSD.cpp -------------------------------- -*- C++ -*-===// 21a3d19ddSKamil Rytarowski // 31a3d19ddSKamil Rytarowski // The LLVM Compiler Infrastructure 41a3d19ddSKamil Rytarowski // 51a3d19ddSKamil Rytarowski // This file is distributed under the University of Illinois Open Source 61a3d19ddSKamil Rytarowski // License. See LICENSE.TXT for details. 71a3d19ddSKamil Rytarowski // 81a3d19ddSKamil Rytarowski //===----------------------------------------------------------------------===// 91a3d19ddSKamil Rytarowski 101a3d19ddSKamil Rytarowski #include "NativeThreadNetBSD.h" 111a3d19ddSKamil Rytarowski #include "NativeRegisterContextNetBSD.h" 121a3d19ddSKamil Rytarowski 131a3d19ddSKamil Rytarowski #include "NativeProcessNetBSD.h" 141a3d19ddSKamil Rytarowski 15f07a9995SKamil Rytarowski #include "Plugins/Process/POSIX/CrashReason.h" 16f07a9995SKamil Rytarowski #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" 17f07a9995SKamil Rytarowski #include "lldb/Core/RegisterValue.h" 18f07a9995SKamil Rytarowski #include "lldb/Core/State.h" 1936e23ecaSKamil Rytarowski #include "lldb/Utility/LLDBAssert.h" 2036e23ecaSKamil Rytarowski 2136e23ecaSKamil Rytarowski #include <sstream> 22f07a9995SKamil Rytarowski 231a3d19ddSKamil Rytarowski using namespace lldb; 241a3d19ddSKamil Rytarowski using namespace lldb_private; 251a3d19ddSKamil Rytarowski using namespace lldb_private::process_netbsd; 261a3d19ddSKamil Rytarowski 27*82abefa4SPavel Labath NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD &process, 281a3d19ddSKamil Rytarowski lldb::tid_t tid) 29f07a9995SKamil Rytarowski : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid), 30f07a9995SKamil Rytarowski m_stop_info(), m_reg_context_sp(), m_stop_description() {} 31f07a9995SKamil Rytarowski 32f07a9995SKamil Rytarowski void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo, 33f07a9995SKamil Rytarowski const siginfo_t *info) { 34f07a9995SKamil Rytarowski Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); 35f07a9995SKamil Rytarowski LLDB_LOG(log, "tid = {0} in called with signal {1}", GetID(), signo); 36f07a9995SKamil Rytarowski 37f07a9995SKamil Rytarowski SetStopped(); 38f07a9995SKamil Rytarowski 39f07a9995SKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonSignal; 40f07a9995SKamil Rytarowski m_stop_info.details.signal.signo = signo; 41f07a9995SKamil Rytarowski 42f07a9995SKamil Rytarowski m_stop_description.clear(); 43f07a9995SKamil Rytarowski if (info) { 44f07a9995SKamil Rytarowski switch (signo) { 45f07a9995SKamil Rytarowski case SIGSEGV: 46f07a9995SKamil Rytarowski case SIGBUS: 47f07a9995SKamil Rytarowski case SIGFPE: 48f07a9995SKamil Rytarowski case SIGILL: 49f07a9995SKamil Rytarowski const auto reason = GetCrashReason(*info); 50f07a9995SKamil Rytarowski m_stop_description = GetCrashReasonString(reason, *info); 51f07a9995SKamil Rytarowski break; 52f07a9995SKamil Rytarowski } 53f07a9995SKamil Rytarowski } 54f07a9995SKamil Rytarowski } 55f07a9995SKamil Rytarowski 56f07a9995SKamil Rytarowski void NativeThreadNetBSD::SetStoppedByBreakpoint() { 57f07a9995SKamil Rytarowski SetStopped(); 58f07a9995SKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonBreakpoint; 59f07a9995SKamil Rytarowski m_stop_info.details.signal.signo = SIGTRAP; 60f07a9995SKamil Rytarowski } 61f07a9995SKamil Rytarowski 623eef2b5eSKamil Rytarowski void NativeThreadNetBSD::SetStoppedByTrace() { 633eef2b5eSKamil Rytarowski SetStopped(); 643eef2b5eSKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonTrace; 653eef2b5eSKamil Rytarowski m_stop_info.details.signal.signo = SIGTRAP; 663eef2b5eSKamil Rytarowski } 673eef2b5eSKamil Rytarowski 683eef2b5eSKamil Rytarowski void NativeThreadNetBSD::SetStoppedByExec() { 693eef2b5eSKamil Rytarowski SetStopped(); 703eef2b5eSKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonExec; 713eef2b5eSKamil Rytarowski m_stop_info.details.signal.signo = SIGTRAP; 723eef2b5eSKamil Rytarowski } 733eef2b5eSKamil Rytarowski 7436e23ecaSKamil Rytarowski void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) { 7536e23ecaSKamil Rytarowski SetStopped(); 7636e23ecaSKamil Rytarowski 7736e23ecaSKamil Rytarowski lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); 7836e23ecaSKamil Rytarowski 7936e23ecaSKamil Rytarowski std::ostringstream ostr; 8036e23ecaSKamil Rytarowski ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " "; 8136e23ecaSKamil Rytarowski ostr << wp_index; 8236e23ecaSKamil Rytarowski 8336e23ecaSKamil Rytarowski ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index); 8436e23ecaSKamil Rytarowski 8536e23ecaSKamil Rytarowski m_stop_description = ostr.str(); 8636e23ecaSKamil Rytarowski 8736e23ecaSKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonWatchpoint; 8836e23ecaSKamil Rytarowski m_stop_info.details.signal.signo = SIGTRAP; 8936e23ecaSKamil Rytarowski } 9036e23ecaSKamil Rytarowski 91f07a9995SKamil Rytarowski void NativeThreadNetBSD::SetStopped() { 92f07a9995SKamil Rytarowski const StateType new_state = StateType::eStateStopped; 93f07a9995SKamil Rytarowski m_state = new_state; 94f07a9995SKamil Rytarowski m_stop_description.clear(); 95f07a9995SKamil Rytarowski } 96f07a9995SKamil Rytarowski 97f07a9995SKamil Rytarowski void NativeThreadNetBSD::SetRunning() { 98f07a9995SKamil Rytarowski m_state = StateType::eStateRunning; 99f07a9995SKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonNone; 100f07a9995SKamil Rytarowski } 101f07a9995SKamil Rytarowski 1023eef2b5eSKamil Rytarowski void NativeThreadNetBSD::SetStepping() { 1033eef2b5eSKamil Rytarowski m_state = StateType::eStateStepping; 1043eef2b5eSKamil Rytarowski m_stop_info.reason = StopReason::eStopReasonNone; 1053eef2b5eSKamil Rytarowski } 1063eef2b5eSKamil Rytarowski 107f07a9995SKamil Rytarowski std::string NativeThreadNetBSD::GetName() { return std::string(""); } 108f07a9995SKamil Rytarowski 109f07a9995SKamil Rytarowski lldb::StateType NativeThreadNetBSD::GetState() { return m_state; } 110f07a9995SKamil Rytarowski 111f07a9995SKamil Rytarowski bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info, 112f07a9995SKamil Rytarowski std::string &description) { 113f07a9995SKamil Rytarowski Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); 114f07a9995SKamil Rytarowski 115f07a9995SKamil Rytarowski description.clear(); 116f07a9995SKamil Rytarowski 117f07a9995SKamil Rytarowski switch (m_state) { 118f07a9995SKamil Rytarowski case eStateStopped: 119f07a9995SKamil Rytarowski case eStateCrashed: 120f07a9995SKamil Rytarowski case eStateExited: 121f07a9995SKamil Rytarowski case eStateSuspended: 122f07a9995SKamil Rytarowski case eStateUnloaded: 123f07a9995SKamil Rytarowski stop_info = m_stop_info; 124f07a9995SKamil Rytarowski description = m_stop_description; 125f07a9995SKamil Rytarowski 126f07a9995SKamil Rytarowski return true; 127f07a9995SKamil Rytarowski 128f07a9995SKamil Rytarowski case eStateInvalid: 129f07a9995SKamil Rytarowski case eStateConnected: 130f07a9995SKamil Rytarowski case eStateAttaching: 131f07a9995SKamil Rytarowski case eStateLaunching: 132f07a9995SKamil Rytarowski case eStateRunning: 133f07a9995SKamil Rytarowski case eStateStepping: 134f07a9995SKamil Rytarowski case eStateDetached: 135f07a9995SKamil Rytarowski LLDB_LOG(log, "tid = {0} in state {1} cannot answer stop reason", GetID(), 136f07a9995SKamil Rytarowski StateAsCString(m_state)); 137f07a9995SKamil Rytarowski return false; 138f07a9995SKamil Rytarowski } 139f07a9995SKamil Rytarowski llvm_unreachable("unhandled StateType!"); 140f07a9995SKamil Rytarowski } 141f07a9995SKamil Rytarowski 142f07a9995SKamil Rytarowski NativeRegisterContextSP NativeThreadNetBSD::GetRegisterContext() { 143f07a9995SKamil Rytarowski // Return the register context if we already created it. 144f07a9995SKamil Rytarowski if (m_reg_context_sp) 145f07a9995SKamil Rytarowski return m_reg_context_sp; 146f07a9995SKamil Rytarowski 147f07a9995SKamil Rytarowski ArchSpec target_arch; 148*82abefa4SPavel Labath if (!m_process.GetArchitecture(target_arch)) 149f07a9995SKamil Rytarowski return NativeRegisterContextSP(); 150f07a9995SKamil Rytarowski 151f07a9995SKamil Rytarowski const uint32_t concrete_frame_idx = 0; 152f07a9995SKamil Rytarowski m_reg_context_sp.reset( 153f07a9995SKamil Rytarowski NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD( 154f07a9995SKamil Rytarowski target_arch, *this, concrete_frame_idx)); 155f07a9995SKamil Rytarowski 156f07a9995SKamil Rytarowski return m_reg_context_sp; 157f07a9995SKamil Rytarowski } 158f07a9995SKamil Rytarowski 15997206d57SZachary Turner Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size, 160f07a9995SKamil Rytarowski uint32_t watch_flags, bool hardware) { 16136e23ecaSKamil Rytarowski if (!hardware) 16297206d57SZachary Turner return Status("not implemented"); 16336e23ecaSKamil Rytarowski if (m_state == eStateLaunching) 16497206d57SZachary Turner return Status(); 16597206d57SZachary Turner Status error = RemoveWatchpoint(addr); 16636e23ecaSKamil Rytarowski if (error.Fail()) 16736e23ecaSKamil Rytarowski return error; 16836e23ecaSKamil Rytarowski NativeRegisterContextSP reg_ctx = GetRegisterContext(); 16936e23ecaSKamil Rytarowski uint32_t wp_index = reg_ctx->SetHardwareWatchpoint(addr, size, watch_flags); 17036e23ecaSKamil Rytarowski if (wp_index == LLDB_INVALID_INDEX32) 17197206d57SZachary Turner return Status("Setting hardware watchpoint failed."); 17236e23ecaSKamil Rytarowski m_watchpoint_index_map.insert({addr, wp_index}); 17397206d57SZachary Turner return Status(); 174f07a9995SKamil Rytarowski } 175f07a9995SKamil Rytarowski 17697206d57SZachary Turner Status NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) { 17736e23ecaSKamil Rytarowski auto wp = m_watchpoint_index_map.find(addr); 17836e23ecaSKamil Rytarowski if (wp == m_watchpoint_index_map.end()) 17997206d57SZachary Turner return Status(); 18036e23ecaSKamil Rytarowski uint32_t wp_index = wp->second; 18136e23ecaSKamil Rytarowski m_watchpoint_index_map.erase(wp); 18236e23ecaSKamil Rytarowski if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index)) 18397206d57SZachary Turner return Status(); 18497206d57SZachary Turner return Status("Clearing hardware watchpoint failed."); 185f07a9995SKamil Rytarowski } 186f07a9995SKamil Rytarowski 18797206d57SZachary Turner Status NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr, 188f07a9995SKamil Rytarowski size_t size) { 18936e23ecaSKamil Rytarowski if (m_state == eStateLaunching) 19097206d57SZachary Turner return Status(); 19136e23ecaSKamil Rytarowski 19297206d57SZachary Turner Status error = RemoveHardwareBreakpoint(addr); 19336e23ecaSKamil Rytarowski if (error.Fail()) 19436e23ecaSKamil Rytarowski return error; 19536e23ecaSKamil Rytarowski 19636e23ecaSKamil Rytarowski NativeRegisterContextSP reg_ctx = GetRegisterContext(); 19736e23ecaSKamil Rytarowski uint32_t bp_index = reg_ctx->SetHardwareBreakpoint(addr, size); 19836e23ecaSKamil Rytarowski 19936e23ecaSKamil Rytarowski if (bp_index == LLDB_INVALID_INDEX32) 20097206d57SZachary Turner return Status("Setting hardware breakpoint failed."); 20136e23ecaSKamil Rytarowski 20236e23ecaSKamil Rytarowski m_hw_break_index_map.insert({addr, bp_index}); 20397206d57SZachary Turner return Status(); 204f07a9995SKamil Rytarowski } 205f07a9995SKamil Rytarowski 20697206d57SZachary Turner Status NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) { 20736e23ecaSKamil Rytarowski auto bp = m_hw_break_index_map.find(addr); 20836e23ecaSKamil Rytarowski if (bp == m_hw_break_index_map.end()) 20997206d57SZachary Turner return Status(); 21036e23ecaSKamil Rytarowski 21136e23ecaSKamil Rytarowski uint32_t bp_index = bp->second; 21236e23ecaSKamil Rytarowski if (GetRegisterContext()->ClearHardwareBreakpoint(bp_index)) { 21336e23ecaSKamil Rytarowski m_hw_break_index_map.erase(bp); 21497206d57SZachary Turner return Status(); 21536e23ecaSKamil Rytarowski } 21636e23ecaSKamil Rytarowski 21797206d57SZachary Turner return Status("Clearing hardware breakpoint failed."); 218f07a9995SKamil Rytarowski } 219