blob: e7848c0c2a37a89bb38a8d70aa28e18c0aaee6e5 [file] [log] [blame]
Johnny Chen2341d352012-01-05 21:48:15 +00001//===-- POSIXThread.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
Daniel Malead891f9b2012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Johnny Chen2341d352012-01-05 21:48:15 +000012// C Includes
13#include <errno.h>
14
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
18#include "lldb/Core/Debugger.h"
19#include "lldb/Host/Host.h"
20#include "lldb/Target/Process.h"
21#include "lldb/Target/StopInfo.h"
22#include "lldb/Target/Target.h"
23#include "POSIXStopInfo.h"
24#include "POSIXThread.h"
25#include "ProcessPOSIX.h"
26#include "ProcessPOSIXLog.h"
27#include "ProcessMonitor.h"
28#include "RegisterContext_i386.h"
29#include "RegisterContext_x86_64.h"
30#include "RegisterContextPOSIX.h"
31
32#include "UnwindLLDB.h"
33
Greg Claytone5eaa302012-02-21 18:40:07 +000034using namespace lldb;
Johnny Chen2341d352012-01-05 21:48:15 +000035using namespace lldb_private;
36
37
Greg Clayton5e91e372012-10-12 16:23:23 +000038POSIXThread::POSIXThread(Process &process, lldb::tid_t tid)
Johnny Chen2341d352012-01-05 21:48:15 +000039 : Thread(process, tid),
40 m_frame_ap(0)
41{
42 LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
43 if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
Daniel Malea5f35a4b2012-11-29 21:49:15 +000044 log->Printf ("POSIXThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid);
Johnny Chen2341d352012-01-05 21:48:15 +000045}
46
47POSIXThread::~POSIXThread()
48{
49 DestroyThread();
50}
51
52ProcessMonitor &
53POSIXThread::GetMonitor()
54{
Greg Claytone5eaa302012-02-21 18:40:07 +000055 ProcessSP base = GetProcess();
56 ProcessPOSIX &process = static_cast<ProcessPOSIX&>(*base);
Johnny Chen2341d352012-01-05 21:48:15 +000057 return process.GetMonitor();
58}
59
60void
61POSIXThread::RefreshStateAfterStop()
62{
63 LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
64 if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
65 log->Printf ("POSIXThread::%s ()", __FUNCTION__);
66
67 // Let all threads recover from stopping and do any clean up based
68 // on the previous thread state (if any).
Greg Claytone5eaa302012-02-21 18:40:07 +000069 ProcessSP base = GetProcess();
70 ProcessPOSIX &process = static_cast<ProcessPOSIX&>(*base);
Johnny Chen2341d352012-01-05 21:48:15 +000071 process.GetThreadList().RefreshStateAfterStop();
72}
73
74const char *
75POSIXThread::GetInfo()
76{
77 return NULL;
78}
79
80lldb::RegisterContextSP
81POSIXThread::GetRegisterContext()
82{
83 if (!m_reg_context_sp)
84 {
85 ArchSpec arch = Host::GetArchitecture();
86
87 switch (arch.GetCore())
88 {
89 default:
90 assert(false && "CPU type not supported!");
91 break;
92
93 case ArchSpec::eCore_x86_32_i386:
94 case ArchSpec::eCore_x86_32_i486:
95 case ArchSpec::eCore_x86_32_i486sx:
96 m_reg_context_sp.reset(new RegisterContext_i386(*this, 0));
97 break;
98
99 case ArchSpec::eCore_x86_64_x86_64:
100 m_reg_context_sp.reset(new RegisterContext_x86_64(*this, 0));
101 break;
102 }
103 }
104 return m_reg_context_sp;
105}
106
107lldb::RegisterContextSP
108POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
109{
110 lldb::RegisterContextSP reg_ctx_sp;
111 uint32_t concrete_frame_idx = 0;
112
113 LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
114 if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
115 log->Printf ("POSIXThread::%s ()", __FUNCTION__);
116
117 if (frame)
118 concrete_frame_idx = frame->GetConcreteFrameIndex();
119
120 if (concrete_frame_idx == 0)
121 reg_ctx_sp = GetRegisterContext();
122 else
123 {
124 assert(GetUnwinder());
125 reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);
126 }
127
128 return reg_ctx_sp;
129}
130
131lldb::StopInfoSP
132POSIXThread::GetPrivateStopReason()
133{
134 return m_stop_info;
135}
136
137Unwind *
138POSIXThread::GetUnwinder()
139{
140 if (m_unwinder_ap.get() == NULL)
141 m_unwinder_ap.reset(new UnwindLLDB(*this));
142
143 return m_unwinder_ap.get();
144}
145
146bool
147POSIXThread::WillResume(lldb::StateType resume_state)
148{
149 SetResumeState(resume_state);
150
Jim Inghama3da5722012-10-30 17:44:49 +0000151 if (!Thread::WillResume(resume_state))
152 return false;
153
Johnny Chen2341d352012-01-05 21:48:15 +0000154 if (m_unwinder_ap.get())
155 m_unwinder_ap->Clear();
Jim Inghama3da5722012-10-30 17:44:49 +0000156 Thread::ClearStackFrames();
Johnny Chen2341d352012-01-05 21:48:15 +0000157
Jim Inghama3da5722012-10-30 17:44:49 +0000158 return true;
Johnny Chen2341d352012-01-05 21:48:15 +0000159}
160
161bool
162POSIXThread::Resume()
163{
164 lldb::StateType resume_state = GetResumeState();
165 ProcessMonitor &monitor = GetMonitor();
166 bool status;
167
168 LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
169 if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
170 log->Printf ("POSIXThread::%s ()", __FUNCTION__);
171
172 switch (resume_state)
173 {
174 default:
175 assert(false && "Unexpected state for resume!");
176 status = false;
177 break;
178
179 case lldb::eStateRunning:
180 SetState(resume_state);
181 status = monitor.Resume(GetID(), GetResumeSignal());
182 break;
183
184 case lldb::eStateStepping:
185 SetState(resume_state);
186 status = monitor.SingleStep(GetID(), GetResumeSignal());
187 break;
188 }
189
190 return status;
191}
192
193void
194POSIXThread::Notify(const ProcessMessage &message)
195{
196 LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
197 if (log)
198 log->Printf ("POSIXThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind());
199
200 switch (message.GetKind())
201 {
202 default:
203 assert(false && "Unexpected message kind!");
204 break;
205
206 case ProcessMessage::eLimboMessage:
207 LimboNotify(message);
208 break;
209
210 case ProcessMessage::eSignalMessage:
211 SignalNotify(message);
212 break;
213
214 case ProcessMessage::eSignalDeliveredMessage:
215 SignalDeliveredNotify(message);
216 break;
217
218 case ProcessMessage::eTraceMessage:
219 TraceNotify(message);
220 break;
221
222 case ProcessMessage::eBreakpointMessage:
223 BreakNotify(message);
224 break;
225
226 case ProcessMessage::eCrashMessage:
227 CrashNotify(message);
228 break;
229 }
230}
231
232void
233POSIXThread::BreakNotify(const ProcessMessage &message)
234{
235 bool status;
236 LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
237
238 assert(GetRegisterContext());
239 status = GetRegisterContextPOSIX()->UpdateAfterBreakpoint();
240 assert(status && "Breakpoint update failed!");
241
242 // With our register state restored, resolve the breakpoint object
243 // corresponding to our current PC.
244 assert(GetRegisterContext());
245 lldb::addr_t pc = GetRegisterContext()->GetPC();
246 if (log)
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000247 log->Printf ("POSIXThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc);
Greg Claytone5eaa302012-02-21 18:40:07 +0000248 lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
Johnny Chen2341d352012-01-05 21:48:15 +0000249 assert(bp_site);
250 lldb::break_id_t bp_id = bp_site->GetID();
251 assert(bp_site && bp_site->ValidForThisThread(this));
252
253
254 m_breakpoint = bp_site;
255 m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id);
256}
257
258void
259POSIXThread::TraceNotify(const ProcessMessage &message)
260{
261 m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
262}
263
264void
265POSIXThread::LimboNotify(const ProcessMessage &message)
266{
267 m_stop_info = lldb::StopInfoSP(new POSIXLimboStopInfo(*this));
268}
269
270void
271POSIXThread::SignalNotify(const ProcessMessage &message)
272{
273 int signo = message.GetSignal();
274
275 m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo);
276 SetResumeSignal(signo);
277}
278
279void
280POSIXThread::SignalDeliveredNotify(const ProcessMessage &message)
281{
282 int signo = message.GetSignal();
283
Matt Kopec3a5ac5a2013-01-08 00:13:33 +0000284 m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo);
Johnny Chen2341d352012-01-05 21:48:15 +0000285 SetResumeSignal(signo);
286}
287
288void
289POSIXThread::CrashNotify(const ProcessMessage &message)
290{
291 int signo = message.GetSignal();
292
293 assert(message.GetKind() == ProcessMessage::eCrashMessage);
294
295 LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
296 if (log)
297 log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason());
298
299 m_stop_info = lldb::StopInfoSP(new POSIXCrashStopInfo(
300 *this, signo, message.GetCrashReason()));
301 SetResumeSignal(signo);
302}
303
304unsigned
305POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
306{
307 unsigned reg;
308 ArchSpec arch = Host::GetArchitecture();
309
310 switch (arch.GetCore())
311 {
312 default:
313 assert(false && "CPU type not supported!");
314 break;
315
316 case ArchSpec::eCore_x86_32_i386:
317 case ArchSpec::eCore_x86_32_i486:
318 case ArchSpec::eCore_x86_32_i486sx:
319 reg = RegisterContext_i386::GetRegisterIndexFromOffset(offset);
320 break;
321
322 case ArchSpec::eCore_x86_64_x86_64:
323 reg = RegisterContext_x86_64::GetRegisterIndexFromOffset(offset);
324 break;
325 }
326 return reg;
327}
328
329const char *
330POSIXThread::GetRegisterName(unsigned reg)
331{
332 const char * name;
333 ArchSpec arch = Host::GetArchitecture();
334
335 switch (arch.GetCore())
336 {
337 default:
338 assert(false && "CPU type not supported!");
339 break;
340
341 case ArchSpec::eCore_x86_32_i386:
342 case ArchSpec::eCore_x86_32_i486:
343 case ArchSpec::eCore_x86_32_i486sx:
344 name = RegisterContext_i386::GetRegisterName(reg);
345 break;
346
347 case ArchSpec::eCore_x86_64_x86_64:
348 name = RegisterContext_x86_64::GetRegisterName(reg);
349 break;
350 }
351 return name;
352}
353
354const char *
355POSIXThread::GetRegisterNameFromOffset(unsigned offset)
356{
357 return GetRegisterName(GetRegisterIndexFromOffset(offset));
358}
359