164 lines · cpp
1//===-- ThreadKDP.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 "ThreadKDP.h"10 11#include "lldb/Host/SafeMachO.h"12 13#include "lldb/Breakpoint/Watchpoint.h"14#include "lldb/Target/Process.h"15#include "lldb/Target/RegisterContext.h"16#include "lldb/Target/StopInfo.h"17#include "lldb/Target/Target.h"18#include "lldb/Target/Unwind.h"19#include "lldb/Utility/ArchSpec.h"20#include "lldb/Utility/DataExtractor.h"21#include "lldb/Utility/State.h"22#include "lldb/Utility/StreamString.h"23 24#include "Plugins/Process/Utility/StopInfoMachException.h"25#include "ProcessKDP.h"26#include "ProcessKDPLog.h"27#include "RegisterContextKDP_arm.h"28#include "RegisterContextKDP_arm64.h"29#include "RegisterContextKDP_x86_64.h"30 31#include <memory>32 33using namespace lldb;34using namespace lldb_private;35 36// Thread Registers37 38ThreadKDP::ThreadKDP(Process &process, lldb::tid_t tid)39 : Thread(process, tid), m_thread_name(), m_dispatch_queue_name(),40 m_thread_dispatch_qaddr(LLDB_INVALID_ADDRESS) {41 Log *log = GetLog(KDPLog::Thread);42 LLDB_LOG(log, "this = {0}, tid = {1:x}", this, GetID());43}44 45ThreadKDP::~ThreadKDP() {46 Log *log = GetLog(KDPLog::Thread);47 LLDB_LOG(log, "this = {0}, tid = {1:x}", this, GetID());48 DestroyThread();49}50 51const char *ThreadKDP::GetName() {52 if (m_thread_name.empty())53 return nullptr;54 return m_thread_name.c_str();55}56 57const char *ThreadKDP::GetQueueName() { return nullptr; }58 59void ThreadKDP::RefreshStateAfterStop() {60 // Invalidate all registers in our register context. We don't set "force" to61 // true because the stop reply packet might have had some register values62 // that were expedited and these will already be copied into the register63 // context by the time this function gets called. The KDPRegisterContext64 // class has been made smart enough to detect when it needs to invalidate65 // which registers are valid by putting hooks in the register read and66 // register supply functions where they check the process stop ID and do the67 // right thing.68 const bool force = false;69 lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext());70 if (reg_ctx_sp)71 reg_ctx_sp->InvalidateIfNeeded(force);72}73 74bool ThreadKDP::ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; }75 76void ThreadKDP::Dump(Log *log, uint32_t index) {}77 78bool ThreadKDP::ShouldStop(bool &step_more) { return true; }79lldb::RegisterContextSP ThreadKDP::GetRegisterContext() {80 if (!m_reg_context_sp)81 m_reg_context_sp = CreateRegisterContextForFrame(nullptr);82 return m_reg_context_sp;83}84 85lldb::RegisterContextSP86ThreadKDP::CreateRegisterContextForFrame(StackFrame *frame) {87 lldb::RegisterContextSP reg_ctx_sp;88 uint32_t concrete_frame_idx = 0;89 90 if (frame)91 concrete_frame_idx = frame->GetConcreteFrameIndex();92 93 if (concrete_frame_idx == 0) {94 ProcessSP process_sp(CalculateProcess());95 if (process_sp) {96 switch (static_cast<ProcessKDP *>(process_sp.get())97 ->GetCommunication()98 .GetCPUType()) {99 case llvm::MachO::CPU_TYPE_ARM:100 reg_ctx_sp =101 std::make_shared<RegisterContextKDP_arm>(*this, concrete_frame_idx);102 break;103 case llvm::MachO::CPU_TYPE_ARM64:104 reg_ctx_sp = std::make_shared<RegisterContextKDP_arm64>(105 *this, concrete_frame_idx);106 break;107 case llvm::MachO::CPU_TYPE_X86_64:108 reg_ctx_sp = std::make_shared<RegisterContextKDP_x86_64>(109 *this, concrete_frame_idx);110 break;111 default:112 llvm_unreachable("Add CPU type support in KDP");113 }114 }115 } else {116 reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);117 }118 return reg_ctx_sp;119}120 121bool ThreadKDP::CalculateStopInfo() {122 ProcessSP process_sp(GetProcess());123 if (process_sp) {124 if (m_cached_stop_info_sp) {125 SetStopInfo(m_cached_stop_info_sp);126 } else {127 SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, SIGSTOP));128 }129 return true;130 }131 return false;132}133 134void ThreadKDP::SetStopInfoFrom_KDP_EXCEPTION(135 const DataExtractor &exc_reply_packet) {136 lldb::offset_t offset = 0;137 uint8_t reply_command = exc_reply_packet.GetU8(&offset);138 if (reply_command == CommunicationKDP::KDP_EXCEPTION) {139 offset = 8;140 const uint32_t count = exc_reply_packet.GetU32(&offset);141 if (count >= 1) {142 // const uint32_t cpu = exc_reply_packet.GetU32 (&offset);143 offset += 4; // Skip the useless CPU field144 const uint32_t exc_type = exc_reply_packet.GetU32(&offset);145 const uint32_t exc_code = exc_reply_packet.GetU32(&offset);146 const uint32_t exc_subcode = exc_reply_packet.GetU32(&offset);147 // We have to make a copy of the stop info because the thread list will148 // iterate through the threads and clear all stop infos..149 150 // Let the StopInfoMachException::CreateStopReasonWithMachException()151 // function update the PC if needed as we might hit a software breakpoint152 // and need to decrement the PC (i386 and x86_64 need this) and KDP153 // doesn't do this for us.154 const bool pc_already_adjusted = false;155 const bool adjust_pc_if_needed = true;156 157 m_cached_stop_info_sp =158 StopInfoMachException::CreateStopReasonWithMachException(159 *this, exc_type, 2, exc_code, exc_subcode, 0, pc_already_adjusted,160 adjust_pc_if_needed);161 }162 }163}164