15ffd83dbSDimitry Andric //===-- NativeThreadNetBSD.cpp --------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "NativeThreadNetBSD.h"
100b57cec5SDimitry Andric #include "NativeRegisterContextNetBSD.h"
110b57cec5SDimitry Andric
120b57cec5SDimitry Andric #include "NativeProcessNetBSD.h"
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "Plugins/Process/POSIX/CrashReason.h"
150b57cec5SDimitry Andric #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
160b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
170b57cec5SDimitry Andric #include "lldb/Utility/RegisterValue.h"
180b57cec5SDimitry Andric #include "lldb/Utility/State.h"
19480093f4SDimitry Andric #include "llvm/Support/Errno.h"
20480093f4SDimitry Andric
21480093f4SDimitry Andric // clang-format off
22480093f4SDimitry Andric #include <sys/types.h>
23480093f4SDimitry Andric #include <sys/ptrace.h>
24480093f4SDimitry Andric // clang-format on
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric #include <sstream>
270b57cec5SDimitry Andric
28480093f4SDimitry Andric // clang-format off
29480093f4SDimitry Andric #include <sys/types.h>
30480093f4SDimitry Andric #include <sys/sysctl.h>
31480093f4SDimitry Andric // clang-format on
32480093f4SDimitry Andric
330b57cec5SDimitry Andric using namespace lldb;
340b57cec5SDimitry Andric using namespace lldb_private;
350b57cec5SDimitry Andric using namespace lldb_private::process_netbsd;
360b57cec5SDimitry Andric
NativeThreadNetBSD(NativeProcessNetBSD & process,lldb::tid_t tid)370b57cec5SDimitry Andric NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD &process,
380b57cec5SDimitry Andric lldb::tid_t tid)
390b57cec5SDimitry Andric : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid),
400b57cec5SDimitry Andric m_stop_info(), m_reg_context_up(
410b57cec5SDimitry Andric NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(process.GetArchitecture(), *this)
420b57cec5SDimitry Andric ), m_stop_description() {}
430b57cec5SDimitry Andric
Resume()44480093f4SDimitry Andric Status NativeThreadNetBSD::Resume() {
45480093f4SDimitry Andric Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(),
46480093f4SDimitry Andric nullptr, GetID());
47480093f4SDimitry Andric if (!ret.Success())
48480093f4SDimitry Andric return ret;
49480093f4SDimitry Andric ret = NativeProcessNetBSD::PtraceWrapper(PT_CLEARSTEP, m_process.GetID(),
50480093f4SDimitry Andric nullptr, GetID());
51480093f4SDimitry Andric if (ret.Success())
52480093f4SDimitry Andric SetRunning();
53480093f4SDimitry Andric return ret;
54480093f4SDimitry Andric }
55480093f4SDimitry Andric
SingleStep()56480093f4SDimitry Andric Status NativeThreadNetBSD::SingleStep() {
57480093f4SDimitry Andric Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(),
58480093f4SDimitry Andric nullptr, GetID());
59480093f4SDimitry Andric if (!ret.Success())
60480093f4SDimitry Andric return ret;
61480093f4SDimitry Andric ret = NativeProcessNetBSD::PtraceWrapper(PT_SETSTEP, m_process.GetID(),
62480093f4SDimitry Andric nullptr, GetID());
63480093f4SDimitry Andric if (ret.Success())
64480093f4SDimitry Andric SetStepping();
65480093f4SDimitry Andric return ret;
66480093f4SDimitry Andric }
67480093f4SDimitry Andric
Suspend()68480093f4SDimitry Andric Status NativeThreadNetBSD::Suspend() {
69480093f4SDimitry Andric Status ret = NativeProcessNetBSD::PtraceWrapper(PT_SUSPEND, m_process.GetID(),
70480093f4SDimitry Andric nullptr, GetID());
71480093f4SDimitry Andric if (ret.Success())
72480093f4SDimitry Andric SetStopped();
73480093f4SDimitry Andric return ret;
74480093f4SDimitry Andric }
75480093f4SDimitry Andric
SetStoppedBySignal(uint32_t signo,const siginfo_t * info)760b57cec5SDimitry Andric void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo,
770b57cec5SDimitry Andric const siginfo_t *info) {
780b57cec5SDimitry Andric Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
790b57cec5SDimitry Andric LLDB_LOG(log, "tid = {0} in called with signal {1}", GetID(), signo);
800b57cec5SDimitry Andric
810b57cec5SDimitry Andric SetStopped();
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric m_stop_info.reason = StopReason::eStopReasonSignal;
840b57cec5SDimitry Andric m_stop_info.details.signal.signo = signo;
850b57cec5SDimitry Andric
860b57cec5SDimitry Andric m_stop_description.clear();
870b57cec5SDimitry Andric if (info) {
880b57cec5SDimitry Andric switch (signo) {
890b57cec5SDimitry Andric case SIGSEGV:
900b57cec5SDimitry Andric case SIGBUS:
910b57cec5SDimitry Andric case SIGFPE:
920b57cec5SDimitry Andric case SIGILL:
930b57cec5SDimitry Andric const auto reason = GetCrashReason(*info);
940b57cec5SDimitry Andric m_stop_description = GetCrashReasonString(reason, *info);
950b57cec5SDimitry Andric break;
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric
SetStoppedByBreakpoint()1000b57cec5SDimitry Andric void NativeThreadNetBSD::SetStoppedByBreakpoint() {
1010b57cec5SDimitry Andric SetStopped();
1020b57cec5SDimitry Andric m_stop_info.reason = StopReason::eStopReasonBreakpoint;
1030b57cec5SDimitry Andric m_stop_info.details.signal.signo = SIGTRAP;
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric
SetStoppedByTrace()1060b57cec5SDimitry Andric void NativeThreadNetBSD::SetStoppedByTrace() {
1070b57cec5SDimitry Andric SetStopped();
1080b57cec5SDimitry Andric m_stop_info.reason = StopReason::eStopReasonTrace;
1090b57cec5SDimitry Andric m_stop_info.details.signal.signo = SIGTRAP;
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric
SetStoppedByExec()1120b57cec5SDimitry Andric void NativeThreadNetBSD::SetStoppedByExec() {
1130b57cec5SDimitry Andric SetStopped();
1140b57cec5SDimitry Andric m_stop_info.reason = StopReason::eStopReasonExec;
1150b57cec5SDimitry Andric m_stop_info.details.signal.signo = SIGTRAP;
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric
SetStoppedByWatchpoint(uint32_t wp_index)1180b57cec5SDimitry Andric void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) {
1190b57cec5SDimitry Andric lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid");
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric std::ostringstream ostr;
1220b57cec5SDimitry Andric ostr << GetRegisterContext().GetWatchpointAddress(wp_index) << " ";
1230b57cec5SDimitry Andric ostr << wp_index;
1240b57cec5SDimitry Andric
1250b57cec5SDimitry Andric ostr << " " << GetRegisterContext().GetWatchpointHitAddress(wp_index);
1260b57cec5SDimitry Andric
127af732203SDimitry Andric SetStopped();
1280b57cec5SDimitry Andric m_stop_description = ostr.str();
1290b57cec5SDimitry Andric m_stop_info.reason = StopReason::eStopReasonWatchpoint;
1300b57cec5SDimitry Andric m_stop_info.details.signal.signo = SIGTRAP;
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric
SetStoppedByFork(lldb::pid_t child_pid,lldb::tid_t child_tid)133*5f7ddb14SDimitry Andric void NativeThreadNetBSD::SetStoppedByFork(lldb::pid_t child_pid,
134*5f7ddb14SDimitry Andric lldb::tid_t child_tid) {
135*5f7ddb14SDimitry Andric SetStopped();
136*5f7ddb14SDimitry Andric
137*5f7ddb14SDimitry Andric m_stop_info.reason = StopReason::eStopReasonFork;
138*5f7ddb14SDimitry Andric m_stop_info.details.fork.child_pid = child_pid;
139*5f7ddb14SDimitry Andric m_stop_info.details.fork.child_tid = child_tid;
140*5f7ddb14SDimitry Andric }
141*5f7ddb14SDimitry Andric
SetStoppedByVFork(lldb::pid_t child_pid,lldb::tid_t child_tid)142*5f7ddb14SDimitry Andric void NativeThreadNetBSD::SetStoppedByVFork(lldb::pid_t child_pid,
143*5f7ddb14SDimitry Andric lldb::tid_t child_tid) {
144*5f7ddb14SDimitry Andric SetStopped();
145*5f7ddb14SDimitry Andric
146*5f7ddb14SDimitry Andric m_stop_info.reason = StopReason::eStopReasonVFork;
147*5f7ddb14SDimitry Andric m_stop_info.details.fork.child_pid = child_pid;
148*5f7ddb14SDimitry Andric m_stop_info.details.fork.child_tid = child_tid;
149*5f7ddb14SDimitry Andric }
150*5f7ddb14SDimitry Andric
SetStoppedByVForkDone()151*5f7ddb14SDimitry Andric void NativeThreadNetBSD::SetStoppedByVForkDone() {
152*5f7ddb14SDimitry Andric SetStopped();
153*5f7ddb14SDimitry Andric
154*5f7ddb14SDimitry Andric m_stop_info.reason = StopReason::eStopReasonVForkDone;
155*5f7ddb14SDimitry Andric }
156*5f7ddb14SDimitry Andric
SetStoppedWithNoReason()157480093f4SDimitry Andric void NativeThreadNetBSD::SetStoppedWithNoReason() {
158480093f4SDimitry Andric SetStopped();
159480093f4SDimitry Andric
160480093f4SDimitry Andric m_stop_info.reason = StopReason::eStopReasonNone;
161480093f4SDimitry Andric m_stop_info.details.signal.signo = 0;
162480093f4SDimitry Andric }
163480093f4SDimitry Andric
SetStopped()1640b57cec5SDimitry Andric void NativeThreadNetBSD::SetStopped() {
1650b57cec5SDimitry Andric const StateType new_state = StateType::eStateStopped;
1660b57cec5SDimitry Andric m_state = new_state;
1670b57cec5SDimitry Andric m_stop_description.clear();
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric
SetRunning()1700b57cec5SDimitry Andric void NativeThreadNetBSD::SetRunning() {
1710b57cec5SDimitry Andric m_state = StateType::eStateRunning;
1720b57cec5SDimitry Andric m_stop_info.reason = StopReason::eStopReasonNone;
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric
SetStepping()1750b57cec5SDimitry Andric void NativeThreadNetBSD::SetStepping() {
1760b57cec5SDimitry Andric m_state = StateType::eStateStepping;
1770b57cec5SDimitry Andric m_stop_info.reason = StopReason::eStopReasonNone;
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric
GetName()180480093f4SDimitry Andric std::string NativeThreadNetBSD::GetName() {
181480093f4SDimitry Andric Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
182480093f4SDimitry Andric
183480093f4SDimitry Andric #ifdef PT_LWPSTATUS
184480093f4SDimitry Andric struct ptrace_lwpstatus info = {};
185480093f4SDimitry Andric info.pl_lwpid = m_tid;
186480093f4SDimitry Andric Status error = NativeProcessNetBSD::PtraceWrapper(
187480093f4SDimitry Andric PT_LWPSTATUS, static_cast<int>(m_process.GetID()), &info, sizeof(info));
188480093f4SDimitry Andric if (error.Fail()) {
189480093f4SDimitry Andric return "";
190480093f4SDimitry Andric }
191480093f4SDimitry Andric return info.pl_name;
192480093f4SDimitry Andric #else
193480093f4SDimitry Andric std::vector<struct kinfo_lwp> infos;
194480093f4SDimitry Andric int mib[5] = {CTL_KERN, KERN_LWP, static_cast<int>(m_process.GetID()),
195480093f4SDimitry Andric sizeof(struct kinfo_lwp), 0};
196480093f4SDimitry Andric size_t size;
197480093f4SDimitry Andric
198480093f4SDimitry Andric if (::sysctl(mib, 5, nullptr, &size, nullptr, 0) == -1 || size == 0) {
199480093f4SDimitry Andric LLDB_LOG(log, "sysctl() for LWP info size failed: {0}",
200480093f4SDimitry Andric llvm::sys::StrError());
201480093f4SDimitry Andric return "";
202480093f4SDimitry Andric }
203480093f4SDimitry Andric
204480093f4SDimitry Andric mib[4] = size / sizeof(size_t);
205480093f4SDimitry Andric infos.resize(size / sizeof(struct kinfo_lwp));
206480093f4SDimitry Andric
207480093f4SDimitry Andric if (sysctl(mib, 5, infos.data(), &size, NULL, 0) == -1 || size == 0) {
208480093f4SDimitry Andric LLDB_LOG(log, "sysctl() for LWP info failed: {0}", llvm::sys::StrError());
209480093f4SDimitry Andric return "";
210480093f4SDimitry Andric }
211480093f4SDimitry Andric
212480093f4SDimitry Andric size_t nlwps = size / sizeof(struct kinfo_lwp);
213480093f4SDimitry Andric for (size_t i = 0; i < nlwps; i++) {
214480093f4SDimitry Andric if (static_cast<lldb::tid_t>(infos[i].l_lid) == m_tid) {
215480093f4SDimitry Andric return infos[i].l_name;
216480093f4SDimitry Andric }
217480093f4SDimitry Andric }
218480093f4SDimitry Andric
219480093f4SDimitry Andric LLDB_LOG(log, "unable to find lwp {0} in LWP infos", m_tid);
220480093f4SDimitry Andric return "";
221480093f4SDimitry Andric #endif
222480093f4SDimitry Andric }
2230b57cec5SDimitry Andric
GetState()2240b57cec5SDimitry Andric lldb::StateType NativeThreadNetBSD::GetState() { return m_state; }
2250b57cec5SDimitry Andric
GetStopReason(ThreadStopInfo & stop_info,std::string & description)2260b57cec5SDimitry Andric bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info,
2270b57cec5SDimitry Andric std::string &description) {
2280b57cec5SDimitry Andric Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
2290b57cec5SDimitry Andric description.clear();
2300b57cec5SDimitry Andric
2310b57cec5SDimitry Andric switch (m_state) {
2320b57cec5SDimitry Andric case eStateStopped:
2330b57cec5SDimitry Andric case eStateCrashed:
2340b57cec5SDimitry Andric case eStateExited:
2350b57cec5SDimitry Andric case eStateSuspended:
2360b57cec5SDimitry Andric case eStateUnloaded:
2370b57cec5SDimitry Andric stop_info = m_stop_info;
2380b57cec5SDimitry Andric description = m_stop_description;
2390b57cec5SDimitry Andric
2400b57cec5SDimitry Andric return true;
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric case eStateInvalid:
2430b57cec5SDimitry Andric case eStateConnected:
2440b57cec5SDimitry Andric case eStateAttaching:
2450b57cec5SDimitry Andric case eStateLaunching:
2460b57cec5SDimitry Andric case eStateRunning:
2470b57cec5SDimitry Andric case eStateStepping:
2480b57cec5SDimitry Andric case eStateDetached:
2490b57cec5SDimitry Andric LLDB_LOG(log, "tid = {0} in state {1} cannot answer stop reason", GetID(),
2500b57cec5SDimitry Andric StateAsCString(m_state));
2510b57cec5SDimitry Andric return false;
2520b57cec5SDimitry Andric }
2530b57cec5SDimitry Andric llvm_unreachable("unhandled StateType!");
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric
GetRegisterContext()256480093f4SDimitry Andric NativeRegisterContextNetBSD &NativeThreadNetBSD::GetRegisterContext() {
2570b57cec5SDimitry Andric assert(m_reg_context_up);
2580b57cec5SDimitry Andric return *m_reg_context_up;
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric
SetWatchpoint(lldb::addr_t addr,size_t size,uint32_t watch_flags,bool hardware)2610b57cec5SDimitry Andric Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size,
2620b57cec5SDimitry Andric uint32_t watch_flags, bool hardware) {
263af732203SDimitry Andric assert(m_state == eStateStopped);
2640b57cec5SDimitry Andric if (!hardware)
2650b57cec5SDimitry Andric return Status("not implemented");
2660b57cec5SDimitry Andric Status error = RemoveWatchpoint(addr);
2670b57cec5SDimitry Andric if (error.Fail())
2680b57cec5SDimitry Andric return error;
269af732203SDimitry Andric uint32_t wp_index =
270af732203SDimitry Andric GetRegisterContext().SetHardwareWatchpoint(addr, size, watch_flags);
2710b57cec5SDimitry Andric if (wp_index == LLDB_INVALID_INDEX32)
2720b57cec5SDimitry Andric return Status("Setting hardware watchpoint failed.");
2730b57cec5SDimitry Andric m_watchpoint_index_map.insert({addr, wp_index});
2740b57cec5SDimitry Andric return Status();
2750b57cec5SDimitry Andric }
2760b57cec5SDimitry Andric
RemoveWatchpoint(lldb::addr_t addr)2770b57cec5SDimitry Andric Status NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) {
2780b57cec5SDimitry Andric auto wp = m_watchpoint_index_map.find(addr);
2790b57cec5SDimitry Andric if (wp == m_watchpoint_index_map.end())
2800b57cec5SDimitry Andric return Status();
2810b57cec5SDimitry Andric uint32_t wp_index = wp->second;
2820b57cec5SDimitry Andric m_watchpoint_index_map.erase(wp);
2830b57cec5SDimitry Andric if (GetRegisterContext().ClearHardwareWatchpoint(wp_index))
2840b57cec5SDimitry Andric return Status();
2850b57cec5SDimitry Andric return Status("Clearing hardware watchpoint failed.");
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric
SetHardwareBreakpoint(lldb::addr_t addr,size_t size)2880b57cec5SDimitry Andric Status NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr,
2890b57cec5SDimitry Andric size_t size) {
290af732203SDimitry Andric assert(m_state == eStateStopped);
2910b57cec5SDimitry Andric Status error = RemoveHardwareBreakpoint(addr);
2920b57cec5SDimitry Andric if (error.Fail())
2930b57cec5SDimitry Andric return error;
2940b57cec5SDimitry Andric
2950b57cec5SDimitry Andric uint32_t bp_index = GetRegisterContext().SetHardwareBreakpoint(addr, size);
2960b57cec5SDimitry Andric
2970b57cec5SDimitry Andric if (bp_index == LLDB_INVALID_INDEX32)
2980b57cec5SDimitry Andric return Status("Setting hardware breakpoint failed.");
2990b57cec5SDimitry Andric
3000b57cec5SDimitry Andric m_hw_break_index_map.insert({addr, bp_index});
3010b57cec5SDimitry Andric return Status();
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric
RemoveHardwareBreakpoint(lldb::addr_t addr)3040b57cec5SDimitry Andric Status NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) {
3050b57cec5SDimitry Andric auto bp = m_hw_break_index_map.find(addr);
3060b57cec5SDimitry Andric if (bp == m_hw_break_index_map.end())
3070b57cec5SDimitry Andric return Status();
3080b57cec5SDimitry Andric
3090b57cec5SDimitry Andric uint32_t bp_index = bp->second;
3100b57cec5SDimitry Andric if (GetRegisterContext().ClearHardwareBreakpoint(bp_index)) {
3110b57cec5SDimitry Andric m_hw_break_index_map.erase(bp);
3120b57cec5SDimitry Andric return Status();
3130b57cec5SDimitry Andric }
3140b57cec5SDimitry Andric
3150b57cec5SDimitry Andric return Status("Clearing hardware breakpoint failed.");
3160b57cec5SDimitry Andric }
317480093f4SDimitry Andric
318af732203SDimitry Andric llvm::Error
CopyWatchpointsFrom(NativeThreadNetBSD & source)319af732203SDimitry Andric NativeThreadNetBSD::CopyWatchpointsFrom(NativeThreadNetBSD &source) {
320af732203SDimitry Andric llvm::Error s = GetRegisterContext().CopyHardwareWatchpointsFrom(
321480093f4SDimitry Andric source.GetRegisterContext());
322af732203SDimitry Andric if (!s) {
323480093f4SDimitry Andric m_watchpoint_index_map = source.m_watchpoint_index_map;
324480093f4SDimitry Andric m_hw_break_index_map = source.m_hw_break_index_map;
325480093f4SDimitry Andric }
326480093f4SDimitry Andric return s;
327480093f4SDimitry Andric }
328