brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.1 KiB · f6aaff2 Raw
557 lines · cpp
1//===-- NativeThreadLinux.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 "NativeThreadLinux.h"10 11#include <csignal>12#include <sstream>13 14#include "NativeProcessLinux.h"15#include "NativeRegisterContextLinux.h"16#include "SingleStepCheck.h"17 18#include "lldb/Host/HostNativeThread.h"19#include "lldb/Host/linux/Ptrace.h"20#include "lldb/Host/linux/Support.h"21#include "lldb/Utility/LLDBAssert.h"22#include "lldb/Utility/LLDBLog.h"23#include "lldb/Utility/Log.h"24#include "lldb/Utility/State.h"25#include "lldb/lldb-enumerations.h"26 27#include "llvm/ADT/SmallString.h"28 29#include "Plugins/Process/POSIX/CrashReason.h"30#include "Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h"31 32#include <sys/syscall.h>33// Try to define a macro to encapsulate the tgkill syscall34#define tgkill(pid, tid, sig)                                                  \35  syscall(__NR_tgkill, static_cast<::pid_t>(pid), static_cast<::pid_t>(tid),   \36          sig)37 38using namespace lldb;39using namespace lldb_private;40using namespace lldb_private::process_linux;41 42namespace {43void LogThreadStopInfo(Log &log, const ThreadStopInfo &stop_info,44                       const char *const header) {45  switch (stop_info.reason) {46  case eStopReasonNone:47    log.Printf("%s: %s no stop reason", __FUNCTION__, header);48    return;49  case eStopReasonTrace:50    log.Printf("%s: %s trace, stopping signal 0x%" PRIx32, __FUNCTION__, header,51               stop_info.signo);52    return;53  case eStopReasonBreakpoint:54    log.Printf("%s: %s breakpoint, stopping signal 0x%" PRIx32, __FUNCTION__,55               header, stop_info.signo);56    return;57  case eStopReasonWatchpoint:58    log.Printf("%s: %s watchpoint, stopping signal 0x%" PRIx32, __FUNCTION__,59               header, stop_info.signo);60    return;61  case eStopReasonSignal:62    log.Printf("%s: %s signal 0x%02" PRIx32, __FUNCTION__, header,63               stop_info.signo);64    return;65  case eStopReasonException:66    log.Printf("%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header,67               stop_info.details.exception.type);68    return;69  case eStopReasonExec:70    log.Printf("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header,71               stop_info.signo);72    return;73  case eStopReasonPlanComplete:74    log.Printf("%s: %s plan complete", __FUNCTION__, header);75    return;76  case eStopReasonThreadExiting:77    log.Printf("%s: %s thread exiting", __FUNCTION__, header);78    return;79  case eStopReasonInstrumentation:80    log.Printf("%s: %s instrumentation", __FUNCTION__, header);81    return;82  case eStopReasonProcessorTrace:83    log.Printf("%s: %s processor trace", __FUNCTION__, header);84    return;85  case eStopReasonHistoryBoundary:86    log.Printf("%s: %s history boundary", __FUNCTION__, header);87    return;88  default:89    log.Printf("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header,90               static_cast<uint32_t>(stop_info.reason));91  }92}93}94 95NativeThreadLinux::NativeThreadLinux(NativeProcessLinux &process,96                                     lldb::tid_t tid)97    : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid),98      m_stop_info(),99      m_reg_context_up(100          NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(101              process.GetArchitecture(), *this)),102      m_stop_description() {}103 104std::string NativeThreadLinux::GetName() {105  NativeProcessLinux &process = GetProcess();106 107  auto BufferOrError = getProcFile(process.GetID(), GetID(), "comm");108  if (!BufferOrError)109    return "";110  return std::string(BufferOrError.get()->getBuffer().rtrim('\n'));111}112 113lldb::StateType NativeThreadLinux::GetState() { return m_state; }114 115bool NativeThreadLinux::GetStopReason(ThreadStopInfo &stop_info,116                                      std::string &description) {117  Log *log = GetLog(LLDBLog::Thread);118 119  description.clear();120 121  switch (m_state) {122  case eStateStopped:123  case eStateCrashed:124  case eStateExited:125  case eStateSuspended:126  case eStateUnloaded:127    if (log)128      LogThreadStopInfo(*log, m_stop_info, "m_stop_info in thread:");129    stop_info = m_stop_info;130    description = m_stop_description;131    if (log)132      LogThreadStopInfo(*log, stop_info, "returned stop_info:");133 134    return true;135 136  case eStateInvalid:137  case eStateConnected:138  case eStateAttaching:139  case eStateLaunching:140  case eStateRunning:141  case eStateStepping:142  case eStateDetached:143    if (log) {144      LLDB_LOGF(log,145                "NativeThreadLinux::%s tid %" PRIu64146                " in state %s cannot answer stop reason",147                __FUNCTION__, GetID(), StateAsCString(m_state));148    }149    return false;150  }151  llvm_unreachable("unhandled StateType!");152}153 154Status NativeThreadLinux::SetWatchpoint(lldb::addr_t addr, size_t size,155                                        uint32_t watch_flags, bool hardware) {156  if (!hardware)157    return Status::FromErrorString("not implemented");158  if (m_state == eStateLaunching)159    return Status();160  Status error = RemoveWatchpoint(addr);161  if (error.Fail())162    return error;163  uint32_t wp_index =164      m_reg_context_up->SetHardwareWatchpoint(addr, size, watch_flags);165  if (wp_index == LLDB_INVALID_INDEX32)166    return Status::FromErrorString("Setting hardware watchpoint failed.");167  m_watchpoint_index_map.insert({addr, wp_index});168  return Status();169}170 171Status NativeThreadLinux::RemoveWatchpoint(lldb::addr_t addr) {172  auto wp = m_watchpoint_index_map.find(addr);173  if (wp == m_watchpoint_index_map.end())174    return Status();175  uint32_t wp_index = wp->second;176  m_watchpoint_index_map.erase(wp);177  if (m_reg_context_up->ClearHardwareWatchpoint(wp_index))178    return Status();179  return Status::FromErrorString("Clearing hardware watchpoint failed.");180}181 182Status NativeThreadLinux::SetHardwareBreakpoint(lldb::addr_t addr,183                                                size_t size) {184  if (m_state == eStateLaunching)185    return Status();186 187  Status error = RemoveHardwareBreakpoint(addr);188  if (error.Fail())189    return error;190 191  uint32_t bp_index = m_reg_context_up->SetHardwareBreakpoint(addr, size);192 193  if (bp_index == LLDB_INVALID_INDEX32)194    return Status::FromErrorString("Setting hardware breakpoint failed.");195 196  m_hw_break_index_map.insert({addr, bp_index});197  return Status();198}199 200Status NativeThreadLinux::RemoveHardwareBreakpoint(lldb::addr_t addr) {201  auto bp = m_hw_break_index_map.find(addr);202  if (bp == m_hw_break_index_map.end())203    return Status();204 205  uint32_t bp_index = bp->second;206  if (m_reg_context_up->ClearHardwareBreakpoint(bp_index)) {207    m_hw_break_index_map.erase(bp);208    return Status();209  }210 211  return Status::FromErrorString("Clearing hardware breakpoint failed.");212}213 214Status NativeThreadLinux::Resume(uint32_t signo) {215  const StateType new_state = StateType::eStateRunning;216  MaybeLogStateChange(new_state);217  m_state = new_state;218 219  m_stop_info.reason = StopReason::eStopReasonNone;220  m_stop_description.clear();221 222  // If watchpoints have been set, but none on this thread, then this is a new223  // thread. So set all existing watchpoints.224  if (m_watchpoint_index_map.empty()) {225    NativeProcessLinux &process = GetProcess();226 227    const auto &watchpoint_map = process.GetWatchpointMap();228    m_reg_context_up->ClearAllHardwareWatchpoints();229    for (const auto &pair : watchpoint_map) {230      const auto &wp = pair.second;231      SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware);232    }233  }234 235  // Set all active hardware breakpoint on all threads.236  if (m_hw_break_index_map.empty()) {237    NativeProcessLinux &process = GetProcess();238 239    const auto &hw_breakpoint_map = process.GetHardwareBreakpointMap();240    m_reg_context_up->ClearAllHardwareBreakpoints();241    for (const auto &pair : hw_breakpoint_map) {242      const auto &bp = pair.second;243      SetHardwareBreakpoint(bp.m_addr, bp.m_size);244    }245  }246 247  intptr_t data = 0;248 249  if (signo != LLDB_INVALID_SIGNAL_NUMBER)250    data = signo;251 252  return NativeProcessLinux::PtraceWrapper(PTRACE_CONT, GetID(), nullptr,253                                           reinterpret_cast<void *>(data));254}255 256Status NativeThreadLinux::SingleStep(uint32_t signo) {257  const StateType new_state = StateType::eStateStepping;258  MaybeLogStateChange(new_state);259  m_state = new_state;260  m_stop_info.reason = StopReason::eStopReasonNone;261 262  if(!m_step_workaround) {263    // If we already hava a workaround inplace, don't reset it. Otherwise, the264    // destructor of the existing instance will run after the new instance has265    // fetched the cpu mask, and the thread will end up with the wrong mask.266    m_step_workaround = SingleStepWorkaround::Get(m_tid);267  }268 269  intptr_t data = 0;270  if (signo != LLDB_INVALID_SIGNAL_NUMBER)271    data = signo;272 273  // If hardware single-stepping is not supported, we just do a continue. The274  // breakpoint on the next instruction has been setup in275  // NativeProcessLinux::Resume.276  return NativeProcessLinux::PtraceWrapper(277      GetProcess().SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP278                                                   : PTRACE_CONT,279      m_tid, nullptr, reinterpret_cast<void *>(data));280}281 282void NativeThreadLinux::SetStoppedBySignal(uint32_t signo,283                                           const siginfo_t *info) {284  Log *log = GetLog(LLDBLog::Thread);285  LLDB_LOGF(log, "NativeThreadLinux::%s called with signal 0x%02" PRIx32,286            __FUNCTION__, signo);287 288  SetStopped();289 290  m_stop_info.reason = StopReason::eStopReasonSignal;291  m_stop_info.signo = signo;292 293  m_stop_description.clear();294  if (info) {295    switch (signo) {296    case SIGSEGV:297    case SIGBUS:298    case SIGFPE:299    case SIGILL:300      m_stop_description = GetCrashReasonString(*info);301#ifndef SEGV_MTESERR302#define SEGV_MTESERR 9303#endif304      if (info->si_signo == SIGSEGV && info->si_code == SEGV_MTESERR)305        AnnotateSyncTagCheckFault(306            reinterpret_cast<lldb::addr_t>(info->si_addr));307      break;308    }309  }310}311 312void NativeThreadLinux::AnnotateSyncTagCheckFault(lldb::addr_t fault_addr) {313  int32_t allocation_tag_type = 0;314  switch (GetProcess().GetArchitecture().GetMachine()) {315  // aarch64_32 deliberately not here because there's no 32 bit MTE316  case llvm::Triple::aarch64:317  case llvm::Triple::aarch64_be:318    allocation_tag_type = MemoryTagManagerAArch64MTE::eMTE_allocation;319    break;320  default:321    return;322  }323 324  auto details =325      GetRegisterContext().GetMemoryTaggingDetails(allocation_tag_type);326  if (!details) {327    llvm::consumeError(details.takeError());328    return;329  }330 331  // We assume that the stop description is currently:332  // signal SIGSEGV: sync tag check fault (fault address=<addr>)333  // Remove the closing )334  m_stop_description.pop_back();335 336  std::stringstream ss;337  std::unique_ptr<MemoryTagManager> manager(std::move(details->manager));338 339  ss << " logical tag=0x" << std::hex << manager->GetLogicalTag(fault_addr);340 341  std::vector<uint8_t> allocation_tag_data;342  // The fault address may not be granule aligned. ReadMemoryTags will granule343  // align any range you give it, potentially making it larger.344  // To prevent this set len to 1. This always results in a range that is at345  // most 1 granule in size and includes fault_addr.346  Status status = GetProcess().ReadMemoryTags(allocation_tag_type, fault_addr,347                                              1, allocation_tag_data);348 349  if (status.Success()) {350    llvm::Expected<std::vector<lldb::addr_t>> allocation_tag =351        manager->UnpackTagsData(allocation_tag_data, 1);352    if (allocation_tag) {353      ss << " allocation tag=0x" << std::hex << allocation_tag->front() << ")";354    } else {355      llvm::consumeError(allocation_tag.takeError());356      ss << ")";357    }358  } else359    ss << ")";360 361  m_stop_description += ss.str();362}363 364bool NativeThreadLinux::IsStopped(int *signo) {365  if (!StateIsStoppedState(m_state, false))366    return false;367 368  // If we are stopped by a signal, return the signo.369  if (signo && m_state == StateType::eStateStopped &&370      m_stop_info.reason == StopReason::eStopReasonSignal) {371    *signo = m_stop_info.signo;372  }373 374  // Regardless, we are stopped.375  return true;376}377 378void NativeThreadLinux::SetStopped() {379  if (m_state == StateType::eStateStepping)380    m_step_workaround.reset();381 382  // On every stop, clear any cached register data structures383  GetRegisterContext().InvalidateAllRegisters();384 385  const StateType new_state = StateType::eStateStopped;386  MaybeLogStateChange(new_state);387  m_state = new_state;388  m_stop_description.clear();389}390 391void NativeThreadLinux::SetStoppedByExec() {392  Log *log = GetLog(LLDBLog::Thread);393  LLDB_LOGF(log, "NativeThreadLinux::%s()", __FUNCTION__);394 395  SetStopped();396 397  m_stop_info.reason = StopReason::eStopReasonExec;398  m_stop_info.signo = SIGSTOP;399}400 401void NativeThreadLinux::SetStoppedByBreakpoint() {402  SetStopped();403 404  m_stop_info.reason = StopReason::eStopReasonBreakpoint;405  m_stop_info.signo = SIGTRAP;406  m_stop_description.clear();407}408 409void NativeThreadLinux::SetStoppedByWatchpoint(uint32_t wp_index) {410  SetStopped();411 412  lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid");413 414  std::ostringstream ostr;415  ostr << m_reg_context_up->GetWatchpointAddress(wp_index) << " ";416  ostr << wp_index;417 418  /*419   * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For420   * example:421   * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at422   * 'm', then423   * watch exception is generated even when 'n' is read/written. To handle this424   * case,425   * find the base address of the load/store instruction and append it in the426   * stop-info427   * packet.428  */429  ostr << " " << m_reg_context_up->GetWatchpointHitAddress(wp_index);430 431  m_stop_description = ostr.str();432 433  m_stop_info.reason = StopReason::eStopReasonWatchpoint;434  m_stop_info.signo = SIGTRAP;435}436 437bool NativeThreadLinux::IsStoppedAtBreakpoint() {438  return GetState() == StateType::eStateStopped &&439         m_stop_info.reason == StopReason::eStopReasonBreakpoint;440}441 442bool NativeThreadLinux::IsStoppedAtWatchpoint() {443  return GetState() == StateType::eStateStopped &&444         m_stop_info.reason == StopReason::eStopReasonWatchpoint;445}446 447void NativeThreadLinux::SetStoppedByTrace() {448  SetStopped();449 450  m_stop_info.reason = StopReason::eStopReasonTrace;451  m_stop_info.signo = SIGTRAP;452}453 454void NativeThreadLinux::SetStoppedByFork(bool is_vfork, lldb::pid_t child_pid) {455  SetStopped();456 457  m_stop_info.reason =458      is_vfork ? StopReason::eStopReasonVFork : StopReason::eStopReasonFork;459  m_stop_info.signo = SIGTRAP;460  m_stop_info.details.fork.child_pid = child_pid;461  m_stop_info.details.fork.child_tid = child_pid;462  m_stop_description = std::to_string(child_pid);463  m_stop_description += " ";464  m_stop_description += std::to_string(child_pid);465}466 467void NativeThreadLinux::SetStoppedByVForkDone() {468  SetStopped();469 470  m_stop_info.reason = StopReason::eStopReasonVForkDone;471  m_stop_info.signo = SIGTRAP;472}473 474void NativeThreadLinux::SetStoppedWithNoReason() {475  SetStopped();476 477  m_stop_info.reason = StopReason::eStopReasonNone;478  m_stop_info.signo = 0;479}480 481void NativeThreadLinux::SetStoppedByProcessorTrace(482    llvm::StringRef description) {483  SetStopped();484 485  m_stop_info.reason = StopReason::eStopReasonProcessorTrace;486  m_stop_info.signo = 0;487  m_stop_description = description.str();488}489 490void NativeThreadLinux::SetExited() {491  const StateType new_state = StateType::eStateExited;492  MaybeLogStateChange(new_state);493  m_state = new_state;494 495  m_stop_info.reason = StopReason::eStopReasonThreadExiting;496}497 498Status NativeThreadLinux::RequestStop() {499  Log *log = GetLog(LLDBLog::Thread);500 501  NativeProcessLinux &process = GetProcess();502 503  lldb::pid_t pid = process.GetID();504  lldb::tid_t tid = GetID();505 506  LLDB_LOGF(log,507            "NativeThreadLinux::%s requesting thread stop(pid: %" PRIu64508            ", tid: %" PRIu64 ")",509            __FUNCTION__, pid, tid);510 511  Status err;512  errno = 0;513  if (::tgkill(pid, tid, SIGSTOP) != 0) {514    err = Status::FromErrno();515    LLDB_LOGF(log,516              "NativeThreadLinux::%s tgkill(%" PRIu64 ", %" PRIu64517              ", SIGSTOP) failed: %s",518              __FUNCTION__, pid, tid, err.AsCString());519  }520 521  return err;522}523 524void NativeThreadLinux::MaybeLogStateChange(lldb::StateType new_state) {525  Log *log = GetLog(LLDBLog::Thread);526  // If we're not logging, we're done.527  if (!log)528    return;529 530  // If this is a state change to the same state, we're done.531  lldb::StateType old_state = m_state;532  if (new_state == old_state)533    return;534 535  LLDB_LOG(log, "pid={0}, tid={1}: changing from state {2} to {3}",536           m_process.GetID(), GetID(), old_state, new_state);537}538 539NativeProcessLinux &NativeThreadLinux::GetProcess() {540  return static_cast<NativeProcessLinux &>(m_process);541}542 543const NativeProcessLinux &NativeThreadLinux::GetProcess() const {544  return static_cast<const NativeProcessLinux &>(m_process);545}546 547llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>548NativeThreadLinux::GetSiginfo() const {549  auto siginfo_buf =550      llvm::WritableMemoryBuffer::getNewUninitMemBuffer(sizeof(siginfo_t));551  Status error =552      GetProcess().GetSignalInfo(GetID(), siginfo_buf->getBufferStart());553  if (!error.Success())554    return error.ToError();555  return std::move(siginfo_buf);556}557