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