Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
39648 views
//===-- NativeThreadNetBSD.cpp --------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "NativeThreadNetBSD.h"9#include "NativeRegisterContextNetBSD.h"1011#include "NativeProcessNetBSD.h"1213#include "Plugins/Process/POSIX/CrashReason.h"14#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"15#include "lldb/Utility/LLDBAssert.h"16#include "lldb/Utility/RegisterValue.h"17#include "lldb/Utility/State.h"18#include "llvm/Support/Errno.h"1920// clang-format off21#include <sys/types.h>22#include <sys/ptrace.h>23// clang-format on2425#include <sstream>2627// clang-format off28#include <sys/types.h>29#include <sys/sysctl.h>30// clang-format on3132using namespace lldb;33using namespace lldb_private;34using namespace lldb_private::process_netbsd;3536NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD &process,37lldb::tid_t tid)38: NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid),39m_stop_info(), m_reg_context_up(40NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(process.GetArchitecture(), *this)41), m_stop_description() {}4243Status NativeThreadNetBSD::Resume() {44Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(),45nullptr, GetID());46if (!ret.Success())47return ret;48ret = NativeProcessNetBSD::PtraceWrapper(PT_CLEARSTEP, m_process.GetID(),49nullptr, GetID());50if (ret.Success())51SetRunning();52return ret;53}5455Status NativeThreadNetBSD::SingleStep() {56Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(),57nullptr, GetID());58if (!ret.Success())59return ret;60ret = NativeProcessNetBSD::PtraceWrapper(PT_SETSTEP, m_process.GetID(),61nullptr, GetID());62if (ret.Success())63SetStepping();64return ret;65}6667Status NativeThreadNetBSD::Suspend() {68Status ret = NativeProcessNetBSD::PtraceWrapper(PT_SUSPEND, m_process.GetID(),69nullptr, GetID());70if (ret.Success())71SetStopped();72return ret;73}7475void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo,76const siginfo_t *info) {77Log *log = GetLog(POSIXLog::Thread);78LLDB_LOG(log, "tid = {0} in called with signal {1}", GetID(), signo);7980SetStopped();8182m_stop_info.reason = StopReason::eStopReasonSignal;83m_stop_info.signo = signo;8485m_stop_description.clear();86if (info) {87switch (signo) {88case SIGSEGV:89case SIGBUS:90case SIGFPE:91case SIGILL:92m_stop_description = GetCrashReasonString(*info);93break;94}95}96}9798void NativeThreadNetBSD::SetStoppedByBreakpoint() {99SetStopped();100m_stop_info.reason = StopReason::eStopReasonBreakpoint;101m_stop_info.signo = SIGTRAP;102}103104void NativeThreadNetBSD::SetStoppedByTrace() {105SetStopped();106m_stop_info.reason = StopReason::eStopReasonTrace;107m_stop_info.signo = SIGTRAP;108}109110void NativeThreadNetBSD::SetStoppedByExec() {111SetStopped();112m_stop_info.reason = StopReason::eStopReasonExec;113m_stop_info.signo = SIGTRAP;114}115116void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) {117lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid");118119std::ostringstream ostr;120ostr << GetRegisterContext().GetWatchpointAddress(wp_index) << " ";121ostr << wp_index;122123ostr << " " << GetRegisterContext().GetWatchpointHitAddress(wp_index);124125SetStopped();126m_stop_description = ostr.str();127m_stop_info.reason = StopReason::eStopReasonWatchpoint;128m_stop_info.signo = SIGTRAP;129}130131void NativeThreadNetBSD::SetStoppedByFork(lldb::pid_t child_pid,132lldb::tid_t child_tid) {133SetStopped();134135m_stop_info.reason = StopReason::eStopReasonFork;136m_stop_info.signo = SIGTRAP;137m_stop_info.details.fork.child_pid = child_pid;138m_stop_info.details.fork.child_tid = child_tid;139}140141void NativeThreadNetBSD::SetStoppedByVFork(lldb::pid_t child_pid,142lldb::tid_t child_tid) {143SetStopped();144145m_stop_info.reason = StopReason::eStopReasonVFork;146m_stop_info.signo = SIGTRAP;147m_stop_info.details.fork.child_pid = child_pid;148m_stop_info.details.fork.child_tid = child_tid;149}150151void NativeThreadNetBSD::SetStoppedByVForkDone() {152SetStopped();153154m_stop_info.reason = StopReason::eStopReasonVForkDone;155m_stop_info.signo = SIGTRAP;156}157158void NativeThreadNetBSD::SetStoppedWithNoReason() {159SetStopped();160161m_stop_info.reason = StopReason::eStopReasonNone;162m_stop_info.signo = 0;163}164165void NativeThreadNetBSD::SetStopped() {166const StateType new_state = StateType::eStateStopped;167m_state = new_state;168m_stop_description.clear();169}170171void NativeThreadNetBSD::SetRunning() {172m_state = StateType::eStateRunning;173m_stop_info.reason = StopReason::eStopReasonNone;174}175176void NativeThreadNetBSD::SetStepping() {177m_state = StateType::eStateStepping;178m_stop_info.reason = StopReason::eStopReasonNone;179}180181std::string NativeThreadNetBSD::GetName() {182#ifdef PT_LWPSTATUS183struct ptrace_lwpstatus info = {};184info.pl_lwpid = m_tid;185Status error = NativeProcessNetBSD::PtraceWrapper(186PT_LWPSTATUS, static_cast<int>(m_process.GetID()), &info, sizeof(info));187if (error.Fail()) {188return "";189}190return info.pl_name;191#else192std::vector<struct kinfo_lwp> infos;193Log *log = GetLog(POSIXLog::Thread);194195int mib[5] = {CTL_KERN, KERN_LWP, static_cast<int>(m_process.GetID()),196sizeof(struct kinfo_lwp), 0};197size_t size;198199if (::sysctl(mib, 5, nullptr, &size, nullptr, 0) == -1 || size == 0) {200LLDB_LOG(log, "sysctl() for LWP info size failed: {0}",201llvm::sys::StrError());202return "";203}204205mib[4] = size / sizeof(size_t);206infos.resize(size / sizeof(struct kinfo_lwp));207208if (sysctl(mib, 5, infos.data(), &size, NULL, 0) == -1 || size == 0) {209LLDB_LOG(log, "sysctl() for LWP info failed: {0}", llvm::sys::StrError());210return "";211}212213size_t nlwps = size / sizeof(struct kinfo_lwp);214for (size_t i = 0; i < nlwps; i++) {215if (static_cast<lldb::tid_t>(infos[i].l_lid) == m_tid) {216return infos[i].l_name;217}218}219220LLDB_LOG(log, "unable to find lwp {0} in LWP infos", m_tid);221return "";222#endif223}224225lldb::StateType NativeThreadNetBSD::GetState() { return m_state; }226227bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info,228std::string &description) {229Log *log = GetLog(POSIXLog::Thread);230description.clear();231232switch (m_state) {233case eStateStopped:234case eStateCrashed:235case eStateExited:236case eStateSuspended:237case eStateUnloaded:238stop_info = m_stop_info;239description = m_stop_description;240241return true;242243case eStateInvalid:244case eStateConnected:245case eStateAttaching:246case eStateLaunching:247case eStateRunning:248case eStateStepping:249case eStateDetached:250LLDB_LOG(log, "tid = {0} in state {1} cannot answer stop reason", GetID(),251StateAsCString(m_state));252return false;253}254llvm_unreachable("unhandled StateType!");255}256257NativeRegisterContextNetBSD &NativeThreadNetBSD::GetRegisterContext() {258assert(m_reg_context_up);259return *m_reg_context_up;260}261262Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size,263uint32_t watch_flags, bool hardware) {264assert(m_state == eStateStopped);265if (!hardware)266return Status("not implemented");267Status error = RemoveWatchpoint(addr);268if (error.Fail())269return error;270uint32_t wp_index =271GetRegisterContext().SetHardwareWatchpoint(addr, size, watch_flags);272if (wp_index == LLDB_INVALID_INDEX32)273return Status("Setting hardware watchpoint failed.");274m_watchpoint_index_map.insert({addr, wp_index});275return Status();276}277278Status NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) {279auto wp = m_watchpoint_index_map.find(addr);280if (wp == m_watchpoint_index_map.end())281return Status();282uint32_t wp_index = wp->second;283m_watchpoint_index_map.erase(wp);284if (GetRegisterContext().ClearHardwareWatchpoint(wp_index))285return Status();286return Status("Clearing hardware watchpoint failed.");287}288289Status NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr,290size_t size) {291assert(m_state == eStateStopped);292Status error = RemoveHardwareBreakpoint(addr);293if (error.Fail())294return error;295296uint32_t bp_index = GetRegisterContext().SetHardwareBreakpoint(addr, size);297298if (bp_index == LLDB_INVALID_INDEX32)299return Status("Setting hardware breakpoint failed.");300301m_hw_break_index_map.insert({addr, bp_index});302return Status();303}304305Status NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) {306auto bp = m_hw_break_index_map.find(addr);307if (bp == m_hw_break_index_map.end())308return Status();309310uint32_t bp_index = bp->second;311if (GetRegisterContext().ClearHardwareBreakpoint(bp_index)) {312m_hw_break_index_map.erase(bp);313return Status();314}315316return Status("Clearing hardware breakpoint failed.");317}318319llvm::Error320NativeThreadNetBSD::CopyWatchpointsFrom(NativeThreadNetBSD &source) {321llvm::Error s = GetRegisterContext().CopyHardwareWatchpointsFrom(322source.GetRegisterContext());323if (!s) {324m_watchpoint_index_map = source.m_watchpoint_index_map;325m_hw_break_index_map = source.m_hw_break_index_map;326}327return s;328}329330331