1 //===-- NativeThreadNetBSD.cpp -------------------------------- -*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "NativeThreadNetBSD.h" 10 #include "NativeRegisterContextNetBSD.h" 11 12 #include "NativeProcessNetBSD.h" 13 14 #include "Plugins/Process/POSIX/CrashReason.h" 15 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" 16 #include "lldb/Utility/LLDBAssert.h" 17 #include "lldb/Utility/RegisterValue.h" 18 #include "lldb/Utility/State.h" 19 20 #include <sstream> 21 22 using namespace lldb; 23 using namespace lldb_private; 24 using namespace lldb_private::process_netbsd; 25 26 NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD &process, 27 lldb::tid_t tid) 28 : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid), 29 m_stop_info(), m_reg_context_up( 30 NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(process.GetArchitecture(), *this) 31 ), m_stop_description() {} 32 33 void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo, 34 const siginfo_t *info) { 35 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); 36 LLDB_LOG(log, "tid = {0} in called with signal {1}", GetID(), signo); 37 38 SetStopped(); 39 40 m_stop_info.reason = StopReason::eStopReasonSignal; 41 m_stop_info.details.signal.signo = signo; 42 43 m_stop_description.clear(); 44 if (info) { 45 switch (signo) { 46 case SIGSEGV: 47 case SIGBUS: 48 case SIGFPE: 49 case SIGILL: 50 const auto reason = GetCrashReason(*info); 51 m_stop_description = GetCrashReasonString(reason, *info); 52 break; 53 } 54 } 55 } 56 57 void NativeThreadNetBSD::SetStoppedByBreakpoint() { 58 SetStopped(); 59 m_stop_info.reason = StopReason::eStopReasonBreakpoint; 60 m_stop_info.details.signal.signo = SIGTRAP; 61 } 62 63 void NativeThreadNetBSD::SetStoppedByTrace() { 64 SetStopped(); 65 m_stop_info.reason = StopReason::eStopReasonTrace; 66 m_stop_info.details.signal.signo = SIGTRAP; 67 } 68 69 void NativeThreadNetBSD::SetStoppedByExec() { 70 SetStopped(); 71 m_stop_info.reason = StopReason::eStopReasonExec; 72 m_stop_info.details.signal.signo = SIGTRAP; 73 } 74 75 void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) { 76 SetStopped(); 77 78 lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); 79 80 std::ostringstream ostr; 81 ostr << GetRegisterContext().GetWatchpointAddress(wp_index) << " "; 82 ostr << wp_index; 83 84 ostr << " " << GetRegisterContext().GetWatchpointHitAddress(wp_index); 85 86 m_stop_description = ostr.str(); 87 88 m_stop_info.reason = StopReason::eStopReasonWatchpoint; 89 m_stop_info.details.signal.signo = SIGTRAP; 90 } 91 92 void NativeThreadNetBSD::SetStopped() { 93 const StateType new_state = StateType::eStateStopped; 94 m_state = new_state; 95 m_stop_description.clear(); 96 } 97 98 void NativeThreadNetBSD::SetRunning() { 99 m_state = StateType::eStateRunning; 100 m_stop_info.reason = StopReason::eStopReasonNone; 101 } 102 103 void NativeThreadNetBSD::SetStepping() { 104 m_state = StateType::eStateStepping; 105 m_stop_info.reason = StopReason::eStopReasonNone; 106 } 107 108 std::string NativeThreadNetBSD::GetName() { return std::string(""); } 109 110 lldb::StateType NativeThreadNetBSD::GetState() { return m_state; } 111 112 bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info, 113 std::string &description) { 114 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); 115 116 description.clear(); 117 118 switch (m_state) { 119 case eStateStopped: 120 case eStateCrashed: 121 case eStateExited: 122 case eStateSuspended: 123 case eStateUnloaded: 124 stop_info = m_stop_info; 125 description = m_stop_description; 126 127 return true; 128 129 case eStateInvalid: 130 case eStateConnected: 131 case eStateAttaching: 132 case eStateLaunching: 133 case eStateRunning: 134 case eStateStepping: 135 case eStateDetached: 136 LLDB_LOG(log, "tid = {0} in state {1} cannot answer stop reason", GetID(), 137 StateAsCString(m_state)); 138 return false; 139 } 140 llvm_unreachable("unhandled StateType!"); 141 } 142 143 NativeRegisterContext& NativeThreadNetBSD::GetRegisterContext() { 144 assert(m_reg_context_up); 145 return *m_reg_context_up; 146 } 147 148 Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size, 149 uint32_t watch_flags, bool hardware) { 150 if (!hardware) 151 return Status("not implemented"); 152 if (m_state == eStateLaunching) 153 return Status(); 154 Status error = RemoveWatchpoint(addr); 155 if (error.Fail()) 156 return error; 157 uint32_t wp_index = GetRegisterContext().SetHardwareWatchpoint(addr, size, watch_flags); 158 if (wp_index == LLDB_INVALID_INDEX32) 159 return Status("Setting hardware watchpoint failed."); 160 m_watchpoint_index_map.insert({addr, wp_index}); 161 return Status(); 162 } 163 164 Status NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) { 165 auto wp = m_watchpoint_index_map.find(addr); 166 if (wp == m_watchpoint_index_map.end()) 167 return Status(); 168 uint32_t wp_index = wp->second; 169 m_watchpoint_index_map.erase(wp); 170 if (GetRegisterContext().ClearHardwareWatchpoint(wp_index)) 171 return Status(); 172 return Status("Clearing hardware watchpoint failed."); 173 } 174 175 Status NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr, 176 size_t size) { 177 if (m_state == eStateLaunching) 178 return Status(); 179 180 Status error = RemoveHardwareBreakpoint(addr); 181 if (error.Fail()) 182 return error; 183 184 uint32_t bp_index = GetRegisterContext().SetHardwareBreakpoint(addr, size); 185 186 if (bp_index == LLDB_INVALID_INDEX32) 187 return Status("Setting hardware breakpoint failed."); 188 189 m_hw_break_index_map.insert({addr, bp_index}); 190 return Status(); 191 } 192 193 Status NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) { 194 auto bp = m_hw_break_index_map.find(addr); 195 if (bp == m_hw_break_index_map.end()) 196 return Status(); 197 198 uint32_t bp_index = bp->second; 199 if (GetRegisterContext().ClearHardwareBreakpoint(bp_index)) { 200 m_hw_break_index_map.erase(bp); 201 return Status(); 202 } 203 204 return Status("Clearing hardware breakpoint failed."); 205 } 206