180814287SRaphael Isemann //===-- ThreadKDP.cpp -----------------------------------------------------===//
2a63d08c9SGreg Clayton //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a63d08c9SGreg Clayton //
7a63d08c9SGreg Clayton //===----------------------------------------------------------------------===//
8a63d08c9SGreg Clayton
9a63d08c9SGreg Clayton #include "ThreadKDP.h"
10a63d08c9SGreg Clayton
1177044731SPavel Labath #include "lldb/Host/SafeMachO.h"
12a63d08c9SGreg Clayton
13b9c1b51eSKate Stone #include "lldb/Breakpoint/Watchpoint.h"
14a63d08c9SGreg Clayton #include "lldb/Target/Process.h"
15a63d08c9SGreg Clayton #include "lldb/Target/RegisterContext.h"
16a63d08c9SGreg Clayton #include "lldb/Target/StopInfo.h"
17a63d08c9SGreg Clayton #include "lldb/Target/Target.h"
18a63d08c9SGreg Clayton #include "lldb/Target/Unwind.h"
192da1b597SPavel Labath #include "lldb/Utility/ArchSpec.h"
20666cc0b2SZachary Turner #include "lldb/Utility/DataExtractor.h"
21d821c997SPavel Labath #include "lldb/Utility/State.h"
22bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
23a63d08c9SGreg Clayton
24b9c1b51eSKate Stone #include "Plugins/Process/Utility/StopInfoMachException.h"
25a63d08c9SGreg Clayton #include "ProcessKDP.h"
26a63d08c9SGreg Clayton #include "ProcessKDPLog.h"
27a63d08c9SGreg Clayton #include "RegisterContextKDP_arm.h"
28a332978bSJason Molenda #include "RegisterContextKDP_arm64.h"
29a63d08c9SGreg Clayton #include "RegisterContextKDP_i386.h"
30a63d08c9SGreg Clayton #include "RegisterContextKDP_x86_64.h"
31a63d08c9SGreg Clayton
32796ac80bSJonas Devlieghere #include <memory>
33796ac80bSJonas Devlieghere
34a63d08c9SGreg Clayton using namespace lldb;
35a63d08c9SGreg Clayton using namespace lldb_private;
36a63d08c9SGreg Clayton
37a63d08c9SGreg Clayton // Thread Registers
38a63d08c9SGreg Clayton
ThreadKDP(Process & process,lldb::tid_t tid)39b9c1b51eSKate Stone ThreadKDP::ThreadKDP(Process &process, lldb::tid_t tid)
40b9c1b51eSKate Stone : Thread(process, tid), m_thread_name(), m_dispatch_queue_name(),
41b9c1b51eSKate Stone m_thread_dispatch_qaddr(LLDB_INVALID_ADDRESS) {
42*c8fbf803SPavel Labath Log *log = GetLog(KDPLog::Thread);
437b35b781SPavel Labath LLDB_LOG(log, "this = {0}, tid = {1:x}", this, GetID());
44a63d08c9SGreg Clayton }
45a63d08c9SGreg Clayton
~ThreadKDP()46b9c1b51eSKate Stone ThreadKDP::~ThreadKDP() {
47*c8fbf803SPavel Labath Log *log = GetLog(KDPLog::Thread);
487b35b781SPavel Labath LLDB_LOG(log, "this = {0}, tid = {1:x}", this, GetID());
49a63d08c9SGreg Clayton DestroyThread();
50a63d08c9SGreg Clayton }
51a63d08c9SGreg Clayton
GetName()52b9c1b51eSKate Stone const char *ThreadKDP::GetName() {
53a63d08c9SGreg Clayton if (m_thread_name.empty())
5445d8134cSStella Stamenova return nullptr;
55a63d08c9SGreg Clayton return m_thread_name.c_str();
56a63d08c9SGreg Clayton }
57a63d08c9SGreg Clayton
GetQueueName()5845d8134cSStella Stamenova const char *ThreadKDP::GetQueueName() { return nullptr; }
59a63d08c9SGreg Clayton
RefreshStateAfterStop()60b9c1b51eSKate Stone void ThreadKDP::RefreshStateAfterStop() {
61a63d08c9SGreg Clayton // Invalidate all registers in our register context. We don't set "force" to
62a63d08c9SGreg Clayton // true because the stop reply packet might have had some register values
63a63d08c9SGreg Clayton // that were expedited and these will already be copied into the register
64a63d08c9SGreg Clayton // context by the time this function gets called. The KDPRegisterContext
65a63d08c9SGreg Clayton // class has been made smart enough to detect when it needs to invalidate
66a63d08c9SGreg Clayton // which registers are valid by putting hooks in the register read and
6705097246SAdrian Prantl // register supply functions where they check the process stop ID and do the
6805097246SAdrian Prantl // right thing.
69a63d08c9SGreg Clayton const bool force = false;
701afa68edSGreg Clayton lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext());
711afa68edSGreg Clayton if (reg_ctx_sp)
721afa68edSGreg Clayton reg_ctx_sp->InvalidateIfNeeded(force);
73a63d08c9SGreg Clayton }
74a63d08c9SGreg Clayton
ThreadIDIsValid(lldb::tid_t thread)75b9c1b51eSKate Stone bool ThreadKDP::ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; }
76a63d08c9SGreg Clayton
Dump(Log * log,uint32_t index)77b9c1b51eSKate Stone void ThreadKDP::Dump(Log *log, uint32_t index) {}
78a63d08c9SGreg Clayton
ShouldStop(bool & step_more)79b9c1b51eSKate Stone bool ThreadKDP::ShouldStop(bool &step_more) { return true; }
GetRegisterContext()80b9c1b51eSKate Stone lldb::RegisterContextSP ThreadKDP::GetRegisterContext() {
8145d8134cSStella Stamenova if (!m_reg_context_sp)
8245d8134cSStella Stamenova m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
83a63d08c9SGreg Clayton return m_reg_context_sp;
84a63d08c9SGreg Clayton }
85a63d08c9SGreg Clayton
86a63d08c9SGreg Clayton lldb::RegisterContextSP
CreateRegisterContextForFrame(StackFrame * frame)87b9c1b51eSKate Stone ThreadKDP::CreateRegisterContextForFrame(StackFrame *frame) {
88a63d08c9SGreg Clayton lldb::RegisterContextSP reg_ctx_sp;
89a63d08c9SGreg Clayton uint32_t concrete_frame_idx = 0;
90a63d08c9SGreg Clayton
91a63d08c9SGreg Clayton if (frame)
92a63d08c9SGreg Clayton concrete_frame_idx = frame->GetConcreteFrameIndex();
93a63d08c9SGreg Clayton
94b9c1b51eSKate Stone if (concrete_frame_idx == 0) {
951ac04c30SGreg Clayton ProcessSP process_sp(CalculateProcess());
96b9c1b51eSKate Stone if (process_sp) {
97b9c1b51eSKate Stone switch (static_cast<ProcessKDP *>(process_sp.get())
98b9c1b51eSKate Stone ->GetCommunication()
99b9c1b51eSKate Stone .GetCPUType()) {
100510938e5SCharles Davis case llvm::MachO::CPU_TYPE_ARM:
101796ac80bSJonas Devlieghere reg_ctx_sp =
102796ac80bSJonas Devlieghere std::make_shared<RegisterContextKDP_arm>(*this, concrete_frame_idx);
103a63d08c9SGreg Clayton break;
104a332978bSJason Molenda case llvm::MachO::CPU_TYPE_ARM64:
105796ac80bSJonas Devlieghere reg_ctx_sp = std::make_shared<RegisterContextKDP_arm64>(
106796ac80bSJonas Devlieghere *this, concrete_frame_idx);
107a332978bSJason Molenda break;
108510938e5SCharles Davis case llvm::MachO::CPU_TYPE_I386:
109796ac80bSJonas Devlieghere reg_ctx_sp = std::make_shared<RegisterContextKDP_i386>(
110796ac80bSJonas Devlieghere *this, concrete_frame_idx);
111a63d08c9SGreg Clayton break;
112510938e5SCharles Davis case llvm::MachO::CPU_TYPE_X86_64:
113796ac80bSJonas Devlieghere reg_ctx_sp = std::make_shared<RegisterContextKDP_x86_64>(
114796ac80bSJonas Devlieghere *this, concrete_frame_idx);
115a63d08c9SGreg Clayton break;
116a63d08c9SGreg Clayton default:
117a322f36cSDavid Blaikie llvm_unreachable("Add CPU type support in KDP");
118a63d08c9SGreg Clayton }
119a63d08c9SGreg Clayton }
120b9c1b51eSKate Stone } else {
12112ba989eSJonas Devlieghere reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
122b3ae8761SGreg Clayton }
123a63d08c9SGreg Clayton return reg_ctx_sp;
124a63d08c9SGreg Clayton }
125a63d08c9SGreg Clayton
CalculateStopInfo()126b9c1b51eSKate Stone bool ThreadKDP::CalculateStopInfo() {
1271ac04c30SGreg Clayton ProcessSP process_sp(GetProcess());
128b9c1b51eSKate Stone if (process_sp) {
129b9c1b51eSKate Stone if (m_cached_stop_info_sp) {
13097d5cf05SGreg Clayton SetStopInfo(m_cached_stop_info_sp);
131b9c1b51eSKate Stone } else {
132a63d08c9SGreg Clayton SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, SIGSTOP));
133a63d08c9SGreg Clayton }
1346e0ff1a3SGreg Clayton return true;
1351ac04c30SGreg Clayton }
1366e0ff1a3SGreg Clayton return false;
137a63d08c9SGreg Clayton }
138a63d08c9SGreg Clayton
SetStopInfoFrom_KDP_EXCEPTION(const DataExtractor & exc_reply_packet)139b9c1b51eSKate Stone void ThreadKDP::SetStopInfoFrom_KDP_EXCEPTION(
140b9c1b51eSKate Stone const DataExtractor &exc_reply_packet) {
141c7bece56SGreg Clayton lldb::offset_t offset = 0;
14297d5cf05SGreg Clayton uint8_t reply_command = exc_reply_packet.GetU8(&offset);
143b9c1b51eSKate Stone if (reply_command == CommunicationKDP::KDP_EXCEPTION) {
14497d5cf05SGreg Clayton offset = 8;
14597d5cf05SGreg Clayton const uint32_t count = exc_reply_packet.GetU32(&offset);
146b9c1b51eSKate Stone if (count >= 1) {
14797d5cf05SGreg Clayton // const uint32_t cpu = exc_reply_packet.GetU32 (&offset);
14897d5cf05SGreg Clayton offset += 4; // Skip the useless CPU field
14997d5cf05SGreg Clayton const uint32_t exc_type = exc_reply_packet.GetU32(&offset);
15097d5cf05SGreg Clayton const uint32_t exc_code = exc_reply_packet.GetU32(&offset);
15197d5cf05SGreg Clayton const uint32_t exc_subcode = exc_reply_packet.GetU32(&offset);
15205097246SAdrian Prantl // We have to make a copy of the stop info because the thread list will
15305097246SAdrian Prantl // iterate through the threads and clear all stop infos..
15497d5cf05SGreg Clayton
15597d5cf05SGreg Clayton // Let the StopInfoMachException::CreateStopReasonWithMachException()
15697d5cf05SGreg Clayton // function update the PC if needed as we might hit a software breakpoint
15797d5cf05SGreg Clayton // and need to decrement the PC (i386 and x86_64 need this) and KDP
15897d5cf05SGreg Clayton // doesn't do this for us.
15997d5cf05SGreg Clayton const bool pc_already_adjusted = false;
16097d5cf05SGreg Clayton const bool adjust_pc_if_needed = true;
16197d5cf05SGreg Clayton
162b9c1b51eSKate Stone m_cached_stop_info_sp =
163b9c1b51eSKate Stone StopInfoMachException::CreateStopReasonWithMachException(
164b9c1b51eSKate Stone *this, exc_type, 2, exc_code, exc_subcode, 0, pc_already_adjusted,
16597d5cf05SGreg Clayton adjust_pc_if_needed);
16697d5cf05SGreg Clayton }
16797d5cf05SGreg Clayton }
16897d5cf05SGreg Clayton }
169