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