blob: 2ab1c75727020f300ca95b3ffc7e45577569dfd9 [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))
42 log->Printf ("POSIXThread::%s (tid = %i)", __FUNCTION__, tid);
43}
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
149 ClearStackFrames();
150 if (m_unwinder_ap.get())
151 m_unwinder_ap->Clear();
152
153 return Thread::WillResume(resume_state);
154}
155
156bool
157POSIXThread::Resume()
158{
159 lldb::StateType resume_state = GetResumeState();
160 ProcessMonitor &monitor = GetMonitor();
161 bool status;
162
163 LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
164 if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
165 log->Printf ("POSIXThread::%s ()", __FUNCTION__);
166
167 switch (resume_state)
168 {
169 default:
170 assert(false && "Unexpected state for resume!");
171 status = false;
172 break;
173
174 case lldb::eStateRunning:
175 SetState(resume_state);
176 status = monitor.Resume(GetID(), GetResumeSignal());
177 break;
178
179 case lldb::eStateStepping:
180 SetState(resume_state);
181 status = monitor.SingleStep(GetID(), GetResumeSignal());
182 break;
183 }
184
185 return status;
186}
187
188void
189POSIXThread::Notify(const ProcessMessage &message)
190{
191 LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
192 if (log)
193 log->Printf ("POSIXThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind());
194
195 switch (message.GetKind())
196 {
197 default:
198 assert(false && "Unexpected message kind!");
199 break;
200
201 case ProcessMessage::eLimboMessage:
202 LimboNotify(message);
203 break;
204
205 case ProcessMessage::eSignalMessage:
206 SignalNotify(message);
207 break;
208
209 case ProcessMessage::eSignalDeliveredMessage:
210 SignalDeliveredNotify(message);
211 break;
212
213 case ProcessMessage::eTraceMessage:
214 TraceNotify(message);
215 break;
216
217 case ProcessMessage::eBreakpointMessage:
218 BreakNotify(message);
219 break;
220
221 case ProcessMessage::eCrashMessage:
222 CrashNotify(message);
223 break;
224 }
225}
226
227void
228POSIXThread::BreakNotify(const ProcessMessage &message)
229{
230 bool status;
231 LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
232
233 assert(GetRegisterContext());
234 status = GetRegisterContextPOSIX()->UpdateAfterBreakpoint();
235 assert(status && "Breakpoint update failed!");
236
237 // With our register state restored, resolve the breakpoint object
238 // corresponding to our current PC.
239 assert(GetRegisterContext());
240 lldb::addr_t pc = GetRegisterContext()->GetPC();
241 if (log)
242 log->Printf ("POSIXThread::%s () PC=0x%8.8llx", __FUNCTION__, pc);
Greg Claytone5eaa302012-02-21 18:40:07 +0000243 lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
Johnny Chen2341d352012-01-05 21:48:15 +0000244 assert(bp_site);
245 lldb::break_id_t bp_id = bp_site->GetID();
246 assert(bp_site && bp_site->ValidForThisThread(this));
247
248
249 m_breakpoint = bp_site;
250 m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id);
251}
252
253void
254POSIXThread::TraceNotify(const ProcessMessage &message)
255{
256 m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
257}
258
259void
260POSIXThread::LimboNotify(const ProcessMessage &message)
261{
262 m_stop_info = lldb::StopInfoSP(new POSIXLimboStopInfo(*this));
263}
264
265void
266POSIXThread::SignalNotify(const ProcessMessage &message)
267{
268 int signo = message.GetSignal();
269
270 m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo);
271 SetResumeSignal(signo);
272}
273
274void
275POSIXThread::SignalDeliveredNotify(const ProcessMessage &message)
276{
277 int signo = message.GetSignal();
278
279 // Just treat debugger generated signal events like breakpoints for now.
280 m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
281 SetResumeSignal(signo);
282}
283
284void
285POSIXThread::CrashNotify(const ProcessMessage &message)
286{
287 int signo = message.GetSignal();
288
289 assert(message.GetKind() == ProcessMessage::eCrashMessage);
290
291 LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
292 if (log)
293 log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason());
294
295 m_stop_info = lldb::StopInfoSP(new POSIXCrashStopInfo(
296 *this, signo, message.GetCrashReason()));
297 SetResumeSignal(signo);
298}
299
300unsigned
301POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
302{
303 unsigned reg;
304 ArchSpec arch = Host::GetArchitecture();
305
306 switch (arch.GetCore())
307 {
308 default:
309 assert(false && "CPU type not supported!");
310 break;
311
312 case ArchSpec::eCore_x86_32_i386:
313 case ArchSpec::eCore_x86_32_i486:
314 case ArchSpec::eCore_x86_32_i486sx:
315 reg = RegisterContext_i386::GetRegisterIndexFromOffset(offset);
316 break;
317
318 case ArchSpec::eCore_x86_64_x86_64:
319 reg = RegisterContext_x86_64::GetRegisterIndexFromOffset(offset);
320 break;
321 }
322 return reg;
323}
324
325const char *
326POSIXThread::GetRegisterName(unsigned reg)
327{
328 const char * name;
329 ArchSpec arch = Host::GetArchitecture();
330
331 switch (arch.GetCore())
332 {
333 default:
334 assert(false && "CPU type not supported!");
335 break;
336
337 case ArchSpec::eCore_x86_32_i386:
338 case ArchSpec::eCore_x86_32_i486:
339 case ArchSpec::eCore_x86_32_i486sx:
340 name = RegisterContext_i386::GetRegisterName(reg);
341 break;
342
343 case ArchSpec::eCore_x86_64_x86_64:
344 name = RegisterContext_x86_64::GetRegisterName(reg);
345 break;
346 }
347 return name;
348}
349
350const char *
351POSIXThread::GetRegisterNameFromOffset(unsigned offset)
352{
353 return GetRegisterName(GetRegisterIndexFromOffset(offset));
354}
355