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