brintos

brintos / llvm-project-archived public Read only

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