xref: /llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp (revision 46d005dbc4f4a55d3cf830abcd7bd10c6a3803f8)
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 "lldb/Utility/SafeMachO.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_arm64.h"
30 #include "RegisterContextKDP_i386.h"
31 #include "RegisterContextKDP_x86_64.h"
32 #include "Plugins/Process/Utility/StopInfoMachException.h"
33 
34 using namespace lldb;
35 using namespace lldb_private;
36 
37 //----------------------------------------------------------------------
38 // Thread Registers
39 //----------------------------------------------------------------------
40 
41 ThreadKDP::ThreadKDP (Process &process, lldb::tid_t tid) :
42     Thread(process, tid),
43     m_thread_name (),
44     m_dispatch_queue_name (),
45     m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS)
46 {
47     ProcessKDPLog::LogIf(KDP_LOG_THREAD, "%p: ThreadKDP::ThreadKDP (tid = 0x%4.4x)", this, GetID());
48 }
49 
50 ThreadKDP::~ThreadKDP ()
51 {
52     ProcessKDPLog::LogIf(KDP_LOG_THREAD, "%p: ThreadKDP::~ThreadKDP (tid = 0x%4.4x)", this, GetID());
53     DestroyThread();
54 }
55 
56 const char *
57 ThreadKDP::GetName ()
58 {
59     if (m_thread_name.empty())
60         return NULL;
61     return m_thread_name.c_str();
62 }
63 
64 const char *
65 ThreadKDP::GetQueueName ()
66 {
67     return NULL;
68 }
69 
70 void
71 ThreadKDP::RefreshStateAfterStop()
72 {
73     // Invalidate all registers in our register context. We don't set "force" to
74     // true because the stop reply packet might have had some register values
75     // that were expedited and these will already be copied into the register
76     // context by the time this function gets called. The KDPRegisterContext
77     // class has been made smart enough to detect when it needs to invalidate
78     // which registers are valid by putting hooks in the register read and
79     // register supply functions where they check the process stop ID and do
80     // the right thing.
81     const bool force = false;
82     lldb::RegisterContextSP reg_ctx_sp (GetRegisterContext());
83     if (reg_ctx_sp)
84         reg_ctx_sp->InvalidateIfNeeded (force);
85 }
86 
87 bool
88 ThreadKDP::ThreadIDIsValid (lldb::tid_t thread)
89 {
90     return thread != 0;
91 }
92 
93 void
94 ThreadKDP::Dump(Log *log, uint32_t index)
95 {
96 }
97 
98 
99 bool
100 ThreadKDP::ShouldStop (bool &step_more)
101 {
102     return true;
103 }
104 lldb::RegisterContextSP
105 ThreadKDP::GetRegisterContext ()
106 {
107     if (m_reg_context_sp.get() == NULL)
108         m_reg_context_sp = CreateRegisterContextForFrame (NULL);
109     return m_reg_context_sp;
110 }
111 
112 lldb::RegisterContextSP
113 ThreadKDP::CreateRegisterContextForFrame (StackFrame *frame)
114 {
115     lldb::RegisterContextSP reg_ctx_sp;
116     uint32_t concrete_frame_idx = 0;
117 
118     if (frame)
119         concrete_frame_idx = frame->GetConcreteFrameIndex ();
120 
121     if (concrete_frame_idx == 0)
122     {
123         ProcessSP process_sp (CalculateProcess());
124         if (process_sp)
125         {
126             switch (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().GetCPUType())
127             {
128                 case llvm::MachO::CPU_TYPE_ARM:
129                     reg_ctx_sp.reset (new RegisterContextKDP_arm (*this, concrete_frame_idx));
130                     break;
131                 case llvm::MachO::CPU_TYPE_ARM64:
132                     reg_ctx_sp.reset (new RegisterContextKDP_arm64 (*this, concrete_frame_idx));
133                     break;
134                 case llvm::MachO::CPU_TYPE_I386:
135                     reg_ctx_sp.reset (new RegisterContextKDP_i386 (*this, concrete_frame_idx));
136                     break;
137                 case llvm::MachO::CPU_TYPE_X86_64:
138                     reg_ctx_sp.reset (new RegisterContextKDP_x86_64 (*this, concrete_frame_idx));
139                     break;
140                 default:
141                     assert (!"Add CPU type support in KDP");
142                     break;
143             }
144         }
145     }
146     else
147     {
148         Unwind *unwinder = GetUnwinder ();
149         if (unwinder)
150             reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame);
151     }
152     return reg_ctx_sp;
153 }
154 
155 bool
156 ThreadKDP::CalculateStopInfo ()
157 {
158     ProcessSP process_sp (GetProcess());
159     if (process_sp)
160     {
161         if (m_cached_stop_info_sp)
162         {
163             SetStopInfo (m_cached_stop_info_sp);
164         }
165         else
166         {
167             SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP));
168         }
169         return true;
170     }
171     return false;
172 }
173 
174 void
175 ThreadKDP::SetStopInfoFrom_KDP_EXCEPTION (const DataExtractor &exc_reply_packet)
176 {
177     lldb::offset_t offset = 0;
178     uint8_t reply_command = exc_reply_packet.GetU8(&offset);
179     if (reply_command == CommunicationKDP::KDP_EXCEPTION)
180     {
181         offset = 8;
182         const uint32_t count = exc_reply_packet.GetU32 (&offset);
183         if (count >= 1)
184         {
185             //const uint32_t cpu = exc_reply_packet.GetU32 (&offset);
186             offset += 4; // Skip the useless CPU field
187             const uint32_t exc_type = exc_reply_packet.GetU32 (&offset);
188             const uint32_t exc_code = exc_reply_packet.GetU32 (&offset);
189             const uint32_t exc_subcode = exc_reply_packet.GetU32 (&offset);
190             // We have to make a copy of the stop info because the thread list
191             // will iterate through the threads and clear all stop infos..
192 
193             // Let the StopInfoMachException::CreateStopReasonWithMachException()
194             // function update the PC if needed as we might hit a software breakpoint
195             // and need to decrement the PC (i386 and x86_64 need this) and KDP
196             // doesn't do this for us.
197             const bool pc_already_adjusted = false;
198             const bool adjust_pc_if_needed = true;
199 
200             m_cached_stop_info_sp = StopInfoMachException::CreateStopReasonWithMachException (*this,
201                                                                                               exc_type,
202                                                                                               2,
203                                                                                               exc_code,
204                                                                                               exc_subcode,
205                                                                                               0,
206                                                                                               pc_already_adjusted,
207                                                                                               adjust_pc_if_needed);
208         }
209     }
210 }
211 
212