1*be691f3bSpatrick //===-- NativeThreadFreeBSD.cpp -------------------------------------------===// 2*be691f3bSpatrick // 3*be691f3bSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*be691f3bSpatrick // See https://llvm.org/LICENSE.txt for license information. 5*be691f3bSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*be691f3bSpatrick // 7*be691f3bSpatrick //===----------------------------------------------------------------------===// 8*be691f3bSpatrick 9*be691f3bSpatrick #include "NativeThreadFreeBSD.h" 10*be691f3bSpatrick #include "NativeRegisterContextFreeBSD.h" 11*be691f3bSpatrick 12*be691f3bSpatrick #include "NativeProcessFreeBSD.h" 13*be691f3bSpatrick 14*be691f3bSpatrick #include "Plugins/Process/POSIX/CrashReason.h" 15*be691f3bSpatrick #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" 16*be691f3bSpatrick #include "lldb/Utility/LLDBAssert.h" 17*be691f3bSpatrick #include "lldb/Utility/RegisterValue.h" 18*be691f3bSpatrick #include "lldb/Utility/State.h" 19*be691f3bSpatrick #include "llvm/Support/Errno.h" 20*be691f3bSpatrick 21*be691f3bSpatrick // clang-format off 22*be691f3bSpatrick #include <sys/types.h> 23*be691f3bSpatrick #include <sys/ptrace.h> 24*be691f3bSpatrick #include <sys/sysctl.h> 25*be691f3bSpatrick #include <sys/user.h> 26*be691f3bSpatrick // clang-format on 27*be691f3bSpatrick 28*be691f3bSpatrick #include <sstream> 29*be691f3bSpatrick #include <vector> 30*be691f3bSpatrick 31*be691f3bSpatrick using namespace lldb; 32*be691f3bSpatrick using namespace lldb_private; 33*be691f3bSpatrick using namespace lldb_private::process_freebsd; 34*be691f3bSpatrick 35*be691f3bSpatrick NativeThreadFreeBSD::NativeThreadFreeBSD(NativeProcessFreeBSD &process, 36*be691f3bSpatrick lldb::tid_t tid) 37*be691f3bSpatrick : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid), 38*be691f3bSpatrick m_stop_info(), 39*be691f3bSpatrick m_reg_context_up( 40*be691f3bSpatrick NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD( 41*be691f3bSpatrick process.GetArchitecture(), *this)), 42*be691f3bSpatrick m_stop_description() {} 43*be691f3bSpatrick 44*be691f3bSpatrick Status NativeThreadFreeBSD::Resume() { 45*be691f3bSpatrick Status ret = NativeProcessFreeBSD::PtraceWrapper(PT_RESUME, GetID()); 46*be691f3bSpatrick if (!ret.Success()) 47*be691f3bSpatrick return ret; 48*be691f3bSpatrick ret = NativeProcessFreeBSD::PtraceWrapper(PT_CLEARSTEP, GetID()); 49*be691f3bSpatrick // we can get EINVAL if the architecture in question does not support 50*be691f3bSpatrick // hardware single-stepping -- that's fine, we have nothing to clear 51*be691f3bSpatrick // then 52*be691f3bSpatrick if (ret.GetError() == EINVAL) 53*be691f3bSpatrick ret.Clear(); 54*be691f3bSpatrick if (ret.Success()) 55*be691f3bSpatrick SetRunning(); 56*be691f3bSpatrick return ret; 57*be691f3bSpatrick } 58*be691f3bSpatrick 59*be691f3bSpatrick Status NativeThreadFreeBSD::SingleStep() { 60*be691f3bSpatrick Status ret = NativeProcessFreeBSD::PtraceWrapper(PT_RESUME, GetID()); 61*be691f3bSpatrick if (!ret.Success()) 62*be691f3bSpatrick return ret; 63*be691f3bSpatrick ret = NativeProcessFreeBSD::PtraceWrapper(PT_SETSTEP, GetID()); 64*be691f3bSpatrick if (ret.Success()) 65*be691f3bSpatrick SetStepping(); 66*be691f3bSpatrick return ret; 67*be691f3bSpatrick } 68*be691f3bSpatrick 69*be691f3bSpatrick Status NativeThreadFreeBSD::Suspend() { 70*be691f3bSpatrick Status ret = NativeProcessFreeBSD::PtraceWrapper(PT_SUSPEND, GetID()); 71*be691f3bSpatrick if (ret.Success()) 72*be691f3bSpatrick SetStopped(); 73*be691f3bSpatrick return ret; 74*be691f3bSpatrick } 75*be691f3bSpatrick 76*be691f3bSpatrick void NativeThreadFreeBSD::SetStoppedBySignal(uint32_t signo, 77*be691f3bSpatrick const siginfo_t *info) { 78*be691f3bSpatrick Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); 79*be691f3bSpatrick LLDB_LOG(log, "tid = {0} in called with signal {1}", GetID(), signo); 80*be691f3bSpatrick 81*be691f3bSpatrick SetStopped(); 82*be691f3bSpatrick 83*be691f3bSpatrick m_stop_info.reason = StopReason::eStopReasonSignal; 84*be691f3bSpatrick m_stop_info.details.signal.signo = signo; 85*be691f3bSpatrick 86*be691f3bSpatrick m_stop_description.clear(); 87*be691f3bSpatrick if (info) { 88*be691f3bSpatrick switch (signo) { 89*be691f3bSpatrick case SIGSEGV: 90*be691f3bSpatrick case SIGBUS: 91*be691f3bSpatrick case SIGFPE: 92*be691f3bSpatrick case SIGILL: 93*be691f3bSpatrick const auto reason = GetCrashReason(*info); 94*be691f3bSpatrick m_stop_description = GetCrashReasonString(reason, *info); 95*be691f3bSpatrick break; 96*be691f3bSpatrick } 97*be691f3bSpatrick } 98*be691f3bSpatrick } 99*be691f3bSpatrick 100*be691f3bSpatrick void NativeThreadFreeBSD::SetStoppedByBreakpoint() { 101*be691f3bSpatrick SetStopped(); 102*be691f3bSpatrick m_stop_info.reason = StopReason::eStopReasonBreakpoint; 103*be691f3bSpatrick m_stop_info.details.signal.signo = SIGTRAP; 104*be691f3bSpatrick } 105*be691f3bSpatrick 106*be691f3bSpatrick void NativeThreadFreeBSD::SetStoppedByTrace() { 107*be691f3bSpatrick SetStopped(); 108*be691f3bSpatrick m_stop_info.reason = StopReason::eStopReasonTrace; 109*be691f3bSpatrick m_stop_info.details.signal.signo = SIGTRAP; 110*be691f3bSpatrick } 111*be691f3bSpatrick 112*be691f3bSpatrick void NativeThreadFreeBSD::SetStoppedByExec() { 113*be691f3bSpatrick SetStopped(); 114*be691f3bSpatrick m_stop_info.reason = StopReason::eStopReasonExec; 115*be691f3bSpatrick m_stop_info.details.signal.signo = SIGTRAP; 116*be691f3bSpatrick } 117*be691f3bSpatrick 118*be691f3bSpatrick void NativeThreadFreeBSD::SetStoppedByWatchpoint(uint32_t wp_index) { 119*be691f3bSpatrick lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); 120*be691f3bSpatrick 121*be691f3bSpatrick std::ostringstream ostr; 122*be691f3bSpatrick ostr << GetRegisterContext().GetWatchpointAddress(wp_index) << " "; 123*be691f3bSpatrick ostr << wp_index; 124*be691f3bSpatrick 125*be691f3bSpatrick ostr << " " << GetRegisterContext().GetWatchpointHitAddress(wp_index); 126*be691f3bSpatrick 127*be691f3bSpatrick SetStopped(); 128*be691f3bSpatrick m_stop_description = ostr.str(); 129*be691f3bSpatrick m_stop_info.reason = StopReason::eStopReasonWatchpoint; 130*be691f3bSpatrick m_stop_info.details.signal.signo = SIGTRAP; 131*be691f3bSpatrick } 132*be691f3bSpatrick 133*be691f3bSpatrick void NativeThreadFreeBSD::SetStoppedByFork(lldb::pid_t child_pid, 134*be691f3bSpatrick lldb::tid_t child_tid) { 135*be691f3bSpatrick SetStopped(); 136*be691f3bSpatrick 137*be691f3bSpatrick m_stop_info.reason = StopReason::eStopReasonFork; 138*be691f3bSpatrick m_stop_info.details.fork.child_pid = child_pid; 139*be691f3bSpatrick m_stop_info.details.fork.child_tid = child_tid; 140*be691f3bSpatrick } 141*be691f3bSpatrick 142*be691f3bSpatrick void NativeThreadFreeBSD::SetStoppedByVFork(lldb::pid_t child_pid, 143*be691f3bSpatrick lldb::tid_t child_tid) { 144*be691f3bSpatrick SetStopped(); 145*be691f3bSpatrick 146*be691f3bSpatrick m_stop_info.reason = StopReason::eStopReasonVFork; 147*be691f3bSpatrick m_stop_info.details.fork.child_pid = child_pid; 148*be691f3bSpatrick m_stop_info.details.fork.child_tid = child_tid; 149*be691f3bSpatrick } 150*be691f3bSpatrick 151*be691f3bSpatrick void NativeThreadFreeBSD::SetStoppedByVForkDone() { 152*be691f3bSpatrick SetStopped(); 153*be691f3bSpatrick 154*be691f3bSpatrick m_stop_info.reason = StopReason::eStopReasonVForkDone; 155*be691f3bSpatrick } 156*be691f3bSpatrick 157*be691f3bSpatrick void NativeThreadFreeBSD::SetStoppedWithNoReason() { 158*be691f3bSpatrick SetStopped(); 159*be691f3bSpatrick 160*be691f3bSpatrick m_stop_info.reason = StopReason::eStopReasonNone; 161*be691f3bSpatrick m_stop_info.details.signal.signo = 0; 162*be691f3bSpatrick } 163*be691f3bSpatrick 164*be691f3bSpatrick void NativeThreadFreeBSD::SetStopped() { 165*be691f3bSpatrick const StateType new_state = StateType::eStateStopped; 166*be691f3bSpatrick m_state = new_state; 167*be691f3bSpatrick m_stop_description.clear(); 168*be691f3bSpatrick } 169*be691f3bSpatrick 170*be691f3bSpatrick void NativeThreadFreeBSD::SetRunning() { 171*be691f3bSpatrick m_state = StateType::eStateRunning; 172*be691f3bSpatrick m_stop_info.reason = StopReason::eStopReasonNone; 173*be691f3bSpatrick } 174*be691f3bSpatrick 175*be691f3bSpatrick void NativeThreadFreeBSD::SetStepping() { 176*be691f3bSpatrick m_state = StateType::eStateStepping; 177*be691f3bSpatrick m_stop_info.reason = StopReason::eStopReasonNone; 178*be691f3bSpatrick } 179*be691f3bSpatrick 180*be691f3bSpatrick std::string NativeThreadFreeBSD::GetName() { 181*be691f3bSpatrick Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); 182*be691f3bSpatrick 183*be691f3bSpatrick std::vector<struct kinfo_proc> kp; 184*be691f3bSpatrick int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD, 185*be691f3bSpatrick static_cast<int>(GetProcess().GetID())}; 186*be691f3bSpatrick 187*be691f3bSpatrick while (1) { 188*be691f3bSpatrick size_t len = kp.size() * sizeof(struct kinfo_proc); 189*be691f3bSpatrick void *ptr = len == 0 ? nullptr : kp.data(); 190*be691f3bSpatrick int error = ::sysctl(mib, 4, ptr, &len, nullptr, 0); 191*be691f3bSpatrick if (ptr == nullptr || (error != 0 && errno == ENOMEM)) { 192*be691f3bSpatrick kp.resize(len / sizeof(struct kinfo_proc)); 193*be691f3bSpatrick continue; 194*be691f3bSpatrick } 195*be691f3bSpatrick if (error != 0) { 196*be691f3bSpatrick len = 0; 197*be691f3bSpatrick LLDB_LOG(log, "tid = {0} in state {1} failed to get thread name: {2}", 198*be691f3bSpatrick GetID(), m_state, strerror(errno)); 199*be691f3bSpatrick } 200*be691f3bSpatrick kp.resize(len / sizeof(struct kinfo_proc)); 201*be691f3bSpatrick break; 202*be691f3bSpatrick } 203*be691f3bSpatrick 204*be691f3bSpatrick for (auto &procinfo : kp) { 205*be691f3bSpatrick if (procinfo.ki_tid == static_cast<lwpid_t>(GetID())) 206*be691f3bSpatrick return procinfo.ki_tdname; 207*be691f3bSpatrick } 208*be691f3bSpatrick 209*be691f3bSpatrick return ""; 210*be691f3bSpatrick } 211*be691f3bSpatrick 212*be691f3bSpatrick lldb::StateType NativeThreadFreeBSD::GetState() { return m_state; } 213*be691f3bSpatrick 214*be691f3bSpatrick bool NativeThreadFreeBSD::GetStopReason(ThreadStopInfo &stop_info, 215*be691f3bSpatrick std::string &description) { 216*be691f3bSpatrick Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); 217*be691f3bSpatrick description.clear(); 218*be691f3bSpatrick 219*be691f3bSpatrick switch (m_state) { 220*be691f3bSpatrick case eStateStopped: 221*be691f3bSpatrick case eStateCrashed: 222*be691f3bSpatrick case eStateExited: 223*be691f3bSpatrick case eStateSuspended: 224*be691f3bSpatrick case eStateUnloaded: 225*be691f3bSpatrick stop_info = m_stop_info; 226*be691f3bSpatrick description = m_stop_description; 227*be691f3bSpatrick 228*be691f3bSpatrick return true; 229*be691f3bSpatrick 230*be691f3bSpatrick case eStateInvalid: 231*be691f3bSpatrick case eStateConnected: 232*be691f3bSpatrick case eStateAttaching: 233*be691f3bSpatrick case eStateLaunching: 234*be691f3bSpatrick case eStateRunning: 235*be691f3bSpatrick case eStateStepping: 236*be691f3bSpatrick case eStateDetached: 237*be691f3bSpatrick LLDB_LOG(log, "tid = {0} in state {1} cannot answer stop reason", GetID(), 238*be691f3bSpatrick StateAsCString(m_state)); 239*be691f3bSpatrick return false; 240*be691f3bSpatrick } 241*be691f3bSpatrick llvm_unreachable("unhandled StateType!"); 242*be691f3bSpatrick } 243*be691f3bSpatrick 244*be691f3bSpatrick NativeRegisterContextFreeBSD &NativeThreadFreeBSD::GetRegisterContext() { 245*be691f3bSpatrick assert(m_reg_context_up); 246*be691f3bSpatrick return *m_reg_context_up; 247*be691f3bSpatrick } 248*be691f3bSpatrick 249*be691f3bSpatrick Status NativeThreadFreeBSD::SetWatchpoint(lldb::addr_t addr, size_t size, 250*be691f3bSpatrick uint32_t watch_flags, bool hardware) { 251*be691f3bSpatrick assert(m_state == eStateStopped); 252*be691f3bSpatrick if (!hardware) 253*be691f3bSpatrick return Status("not implemented"); 254*be691f3bSpatrick Status error = RemoveWatchpoint(addr); 255*be691f3bSpatrick if (error.Fail()) 256*be691f3bSpatrick return error; 257*be691f3bSpatrick uint32_t wp_index = 258*be691f3bSpatrick GetRegisterContext().SetHardwareWatchpoint(addr, size, watch_flags); 259*be691f3bSpatrick if (wp_index == LLDB_INVALID_INDEX32) 260*be691f3bSpatrick return Status("Setting hardware watchpoint failed."); 261*be691f3bSpatrick m_watchpoint_index_map.insert({addr, wp_index}); 262*be691f3bSpatrick return Status(); 263*be691f3bSpatrick } 264*be691f3bSpatrick 265*be691f3bSpatrick Status NativeThreadFreeBSD::RemoveWatchpoint(lldb::addr_t addr) { 266*be691f3bSpatrick auto wp = m_watchpoint_index_map.find(addr); 267*be691f3bSpatrick if (wp == m_watchpoint_index_map.end()) 268*be691f3bSpatrick return Status(); 269*be691f3bSpatrick uint32_t wp_index = wp->second; 270*be691f3bSpatrick m_watchpoint_index_map.erase(wp); 271*be691f3bSpatrick if (GetRegisterContext().ClearHardwareWatchpoint(wp_index)) 272*be691f3bSpatrick return Status(); 273*be691f3bSpatrick return Status("Clearing hardware watchpoint failed."); 274*be691f3bSpatrick } 275*be691f3bSpatrick 276*be691f3bSpatrick Status NativeThreadFreeBSD::SetHardwareBreakpoint(lldb::addr_t addr, 277*be691f3bSpatrick size_t size) { 278*be691f3bSpatrick assert(m_state == eStateStopped); 279*be691f3bSpatrick Status error = RemoveHardwareBreakpoint(addr); 280*be691f3bSpatrick if (error.Fail()) 281*be691f3bSpatrick return error; 282*be691f3bSpatrick 283*be691f3bSpatrick uint32_t bp_index = GetRegisterContext().SetHardwareBreakpoint(addr, size); 284*be691f3bSpatrick 285*be691f3bSpatrick if (bp_index == LLDB_INVALID_INDEX32) 286*be691f3bSpatrick return Status("Setting hardware breakpoint failed."); 287*be691f3bSpatrick 288*be691f3bSpatrick m_hw_break_index_map.insert({addr, bp_index}); 289*be691f3bSpatrick return Status(); 290*be691f3bSpatrick } 291*be691f3bSpatrick 292*be691f3bSpatrick Status NativeThreadFreeBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) { 293*be691f3bSpatrick auto bp = m_hw_break_index_map.find(addr); 294*be691f3bSpatrick if (bp == m_hw_break_index_map.end()) 295*be691f3bSpatrick return Status(); 296*be691f3bSpatrick 297*be691f3bSpatrick uint32_t bp_index = bp->second; 298*be691f3bSpatrick if (GetRegisterContext().ClearHardwareBreakpoint(bp_index)) { 299*be691f3bSpatrick m_hw_break_index_map.erase(bp); 300*be691f3bSpatrick return Status(); 301*be691f3bSpatrick } 302*be691f3bSpatrick 303*be691f3bSpatrick return Status("Clearing hardware breakpoint failed."); 304*be691f3bSpatrick } 305*be691f3bSpatrick 306*be691f3bSpatrick llvm::Error 307*be691f3bSpatrick NativeThreadFreeBSD::CopyWatchpointsFrom(NativeThreadFreeBSD &source) { 308*be691f3bSpatrick llvm::Error s = GetRegisterContext().CopyHardwareWatchpointsFrom( 309*be691f3bSpatrick source.GetRegisterContext()); 310*be691f3bSpatrick if (!s) { 311*be691f3bSpatrick m_watchpoint_index_map = source.m_watchpoint_index_map; 312*be691f3bSpatrick m_hw_break_index_map = source.m_hw_break_index_map; 313*be691f3bSpatrick } 314*be691f3bSpatrick return s; 315*be691f3bSpatrick } 316