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