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     lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
80     if (log)
81         log->Printf ("Resuming thread: %4.4llx 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     GetRegisterContext()->InvalidateIfNeeded (force);
99 }
100 
101 void
102 ThreadKDP::ClearStackFrames ()
103 {
104     Unwind *unwinder = GetUnwinder ();
105     if (unwinder)
106         unwinder->Clear();
107     Thread::ClearStackFrames();
108 }
109 
110 
111 bool
112 ThreadKDP::ThreadIDIsValid (lldb::tid_t thread)
113 {
114     return thread != 0;
115 }
116 
117 void
118 ThreadKDP::Dump(Log *log, uint32_t index)
119 {
120 }
121 
122 
123 bool
124 ThreadKDP::ShouldStop (bool &step_more)
125 {
126     return true;
127 }
128 lldb::RegisterContextSP
129 ThreadKDP::GetRegisterContext ()
130 {
131     if (m_reg_context_sp.get() == NULL)
132         m_reg_context_sp = CreateRegisterContextForFrame (NULL);
133     return m_reg_context_sp;
134 }
135 
136 lldb::RegisterContextSP
137 ThreadKDP::CreateRegisterContextForFrame (StackFrame *frame)
138 {
139     lldb::RegisterContextSP reg_ctx_sp;
140     uint32_t concrete_frame_idx = 0;
141 
142     if (frame)
143         concrete_frame_idx = frame->GetConcreteFrameIndex ();
144 
145     if (concrete_frame_idx == 0)
146     {
147         ProcessSP process_sp (CalculateProcess());
148         if (process_sp)
149         {
150             switch (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().GetCPUType())
151             {
152                 case llvm::MachO::CPUTypeARM:
153                     reg_ctx_sp.reset (new RegisterContextKDP_arm (*this, concrete_frame_idx));
154                     break;
155                 case llvm::MachO::CPUTypeI386:
156                     reg_ctx_sp.reset (new RegisterContextKDP_i386 (*this, concrete_frame_idx));
157                     break;
158                 case llvm::MachO::CPUTypeX86_64:
159                     reg_ctx_sp.reset (new RegisterContextKDP_x86_64 (*this, concrete_frame_idx));
160                     break;
161                 default:
162                     assert (!"Add CPU type support in KDP");
163                     break;
164             }
165         }
166     }
167     else if (m_unwinder_ap.get())
168         reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
169     return reg_ctx_sp;
170 }
171 
172 lldb::StopInfoSP
173 ThreadKDP::GetPrivateStopReason ()
174 {
175     ProcessSP process_sp (GetProcess());
176     if (process_sp)
177     {
178         const uint32_t process_stop_id = process_sp->GetStopID();
179         if (m_thread_stop_reason_stop_id != process_stop_id ||
180             (m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid()))
181         {
182             if (IsStillAtLastBreakpointHit())
183                 return m_actual_stop_info_sp;
184 
185             if (m_cached_stop_info_sp)
186                 SetStopInfo (m_cached_stop_info_sp);
187             else
188                 SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP));
189         }
190     }
191     return m_actual_stop_info_sp;
192 }
193 
194 void
195 ThreadKDP::SetStopInfoFrom_KDP_EXCEPTION (const DataExtractor &exc_reply_packet)
196 {
197     uint32_t offset = 0;
198     uint8_t reply_command = exc_reply_packet.GetU8(&offset);
199     if (reply_command == CommunicationKDP::KDP_EXCEPTION)
200     {
201         offset = 8;
202         const uint32_t count = exc_reply_packet.GetU32 (&offset);
203         if (count >= 1)
204         {
205             //const uint32_t cpu = exc_reply_packet.GetU32 (&offset);
206             offset += 4; // Skip the useless CPU field
207             const uint32_t exc_type = exc_reply_packet.GetU32 (&offset);
208             const uint32_t exc_code = exc_reply_packet.GetU32 (&offset);
209             const uint32_t exc_subcode = exc_reply_packet.GetU32 (&offset);
210             // We have to make a copy of the stop info because the thread list
211             // will iterate through the threads and clear all stop infos..
212 
213             // Let the StopInfoMachException::CreateStopReasonWithMachException()
214             // function update the PC if needed as we might hit a software breakpoint
215             // and need to decrement the PC (i386 and x86_64 need this) and KDP
216             // doesn't do this for us.
217             const bool pc_already_adjusted = false;
218             const bool adjust_pc_if_needed = true;
219 
220             m_cached_stop_info_sp = StopInfoMachException::CreateStopReasonWithMachException (*this,
221                                                                                               exc_type,
222                                                                                               2,
223                                                                                               exc_code,
224                                                                                               exc_subcode,
225                                                                                               0,
226                                                                                               pc_already_adjusted,
227                                                                                               adjust_pc_if_needed);
228         }
229     }
230 }
231 
232