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