xref: /llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp (revision b3ae87617437c5850003cd7ab35e0b3581d2b7da)
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 
11 #include "ThreadKDP.h"
12 
13 #include "llvm/Support/MachO.h"
14 
15 #include "lldb/Core/ArchSpec.h"
16 #include "lldb/Core/DataExtractor.h"
17 #include "lldb/Core/StreamString.h"
18 #include "lldb/Core/State.h"
19 #include "lldb/Target/Process.h"
20 #include "lldb/Target/RegisterContext.h"
21 #include "lldb/Target/StopInfo.h"
22 #include "lldb/Target/Target.h"
23 #include "lldb/Target/Unwind.h"
24 #include "lldb/Breakpoint/Watchpoint.h"
25 
26 #include "ProcessKDP.h"
27 #include "ProcessKDPLog.h"
28 #include "RegisterContextKDP_arm.h"
29 #include "RegisterContextKDP_i386.h"
30 #include "RegisterContextKDP_x86_64.h"
31 #include "Plugins/Process/Utility/StopInfoMachException.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),
42     m_thread_name (),
43     m_dispatch_queue_name (),
44     m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS)
45 {
46     ProcessKDPLog::LogIf(KDP_LOG_THREAD, "%p: ThreadKDP::ThreadKDP (tid = 0x%4.4x)", this, GetID());
47 }
48 
49 ThreadKDP::~ThreadKDP ()
50 {
51     ProcessKDPLog::LogIf(KDP_LOG_THREAD, "%p: ThreadKDP::~ThreadKDP (tid = 0x%4.4x)", this, GetID());
52     DestroyThread();
53 }
54 
55 const char *
56 ThreadKDP::GetName ()
57 {
58     if (m_thread_name.empty())
59         return NULL;
60     return m_thread_name.c_str();
61 }
62 
63 const char *
64 ThreadKDP::GetQueueName ()
65 {
66     return NULL;
67 }
68 
69 bool
70 ThreadKDP::WillResume (StateType resume_state)
71 {
72     // Call the Thread::WillResume first. If we stop at a signal, the stop info
73     // class for signal will set the resume signal that we need below. The signal
74     // stuff obeys the Process::UnixSignal defaults.
75     Thread::WillResume(resume_state);
76 
77     ClearStackFrames();
78 
79     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
80     if (log)
81         log->Printf ("Resuming thread: %4.4" PRIx64 " with state: %s.", GetID(), StateAsCString(resume_state));
82 
83     return true;
84 }
85 
86 void
87 ThreadKDP::RefreshStateAfterStop()
88 {
89     // Invalidate all registers in our register context. We don't set "force" to
90     // true because the stop reply packet might have had some register values
91     // that were expedited and these will already be copied into the register
92     // context by the time this function gets called. The KDPRegisterContext
93     // class has been made smart enough to detect when it needs to invalidate
94     // which registers are valid by putting hooks in the register read and
95     // register supply functions where they check the process stop ID and do
96     // the right thing.
97     const bool force = false;
98     lldb::RegisterContextSP reg_ctx_sp (GetRegisterContext());
99     if (reg_ctx_sp)
100         reg_ctx_sp->InvalidateIfNeeded (force);
101 }
102 
103 void
104 ThreadKDP::ClearStackFrames ()
105 {
106     Unwind *unwinder = GetUnwinder ();
107     if (unwinder)
108         unwinder->Clear();
109     Thread::ClearStackFrames();
110 }
111 
112 
113 bool
114 ThreadKDP::ThreadIDIsValid (lldb::tid_t thread)
115 {
116     return thread != 0;
117 }
118 
119 void
120 ThreadKDP::Dump(Log *log, uint32_t index)
121 {
122 }
123 
124 
125 bool
126 ThreadKDP::ShouldStop (bool &step_more)
127 {
128     return true;
129 }
130 lldb::RegisterContextSP
131 ThreadKDP::GetRegisterContext ()
132 {
133     if (m_reg_context_sp.get() == NULL)
134         m_reg_context_sp = CreateRegisterContextForFrame (NULL);
135     return m_reg_context_sp;
136 }
137 
138 lldb::RegisterContextSP
139 ThreadKDP::CreateRegisterContextForFrame (StackFrame *frame)
140 {
141     lldb::RegisterContextSP reg_ctx_sp;
142     uint32_t concrete_frame_idx = 0;
143 
144     if (frame)
145         concrete_frame_idx = frame->GetConcreteFrameIndex ();
146 
147     if (concrete_frame_idx == 0)
148     {
149         ProcessSP process_sp (CalculateProcess());
150         if (process_sp)
151         {
152             switch (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().GetCPUType())
153             {
154                 case llvm::MachO::CPUTypeARM:
155                     reg_ctx_sp.reset (new RegisterContextKDP_arm (*this, concrete_frame_idx));
156                     break;
157                 case llvm::MachO::CPUTypeI386:
158                     reg_ctx_sp.reset (new RegisterContextKDP_i386 (*this, concrete_frame_idx));
159                     break;
160                 case llvm::MachO::CPUTypeX86_64:
161                     reg_ctx_sp.reset (new RegisterContextKDP_x86_64 (*this, concrete_frame_idx));
162                     break;
163                 default:
164                     assert (!"Add CPU type support in KDP");
165                     break;
166             }
167         }
168     }
169     else
170     {
171         Unwind *unwinder = GetUnwinder ();
172         if (unwinder)
173             reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame);
174     }
175     return reg_ctx_sp;
176 }
177 
178 lldb::StopInfoSP
179 ThreadKDP::GetPrivateStopReason ()
180 {
181     ProcessSP process_sp (GetProcess());
182     if (process_sp)
183     {
184         const uint32_t process_stop_id = process_sp->GetStopID();
185         if (m_thread_stop_reason_stop_id != process_stop_id ||
186             (m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid()))
187         {
188             if (IsStillAtLastBreakpointHit())
189                 return m_actual_stop_info_sp;
190 
191             if (m_cached_stop_info_sp)
192                 SetStopInfo (m_cached_stop_info_sp);
193             else
194                 SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP));
195         }
196     }
197     return m_actual_stop_info_sp;
198 }
199 
200 void
201 ThreadKDP::SetStopInfoFrom_KDP_EXCEPTION (const DataExtractor &exc_reply_packet)
202 {
203     lldb::offset_t offset = 0;
204     uint8_t reply_command = exc_reply_packet.GetU8(&offset);
205     if (reply_command == CommunicationKDP::KDP_EXCEPTION)
206     {
207         offset = 8;
208         const uint32_t count = exc_reply_packet.GetU32 (&offset);
209         if (count >= 1)
210         {
211             //const uint32_t cpu = exc_reply_packet.GetU32 (&offset);
212             offset += 4; // Skip the useless CPU field
213             const uint32_t exc_type = exc_reply_packet.GetU32 (&offset);
214             const uint32_t exc_code = exc_reply_packet.GetU32 (&offset);
215             const uint32_t exc_subcode = exc_reply_packet.GetU32 (&offset);
216             // We have to make a copy of the stop info because the thread list
217             // will iterate through the threads and clear all stop infos..
218 
219             // Let the StopInfoMachException::CreateStopReasonWithMachException()
220             // function update the PC if needed as we might hit a software breakpoint
221             // and need to decrement the PC (i386 and x86_64 need this) and KDP
222             // doesn't do this for us.
223             const bool pc_already_adjusted = false;
224             const bool adjust_pc_if_needed = true;
225 
226             m_cached_stop_info_sp = StopInfoMachException::CreateStopReasonWithMachException (*this,
227                                                                                               exc_type,
228                                                                                               2,
229                                                                                               exc_code,
230                                                                                               exc_subcode,
231                                                                                               0,
232                                                                                               pc_already_adjusted,
233                                                                                               adjust_pc_if_needed);
234         }
235     }
236 }
237 
238