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