blob: bac9d48c3cee6f51d3b40cc6452627c4b40620b3 [file] [log] [blame]
Stephen Wilsonf6f40332010-07-24 02:19:04 +00001//===-- LinuxThread.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
Stephen Wilsone0c20da2011-01-19 01:36:10 +000010// C Includes
Stephen Wilsonf6f40332010-07-24 02:19:04 +000011#include <errno.h>
12
Stephen Wilsonf6f40332010-07-24 02:19:04 +000013// C++ Includes
14// Other libraries and framework includes
Stephen Wilson67d9f7e2011-03-30 15:55:52 +000015// Project includes
Stephen Wilson708b4472011-02-28 22:52:38 +000016#include "lldb/Host/Host.h"
Stephen Wilsonf6f40332010-07-24 02:19:04 +000017#include "lldb/Target/Process.h"
Stephen Wilsonc8c74e02011-01-04 21:43:19 +000018#include "lldb/Target/StopInfo.h"
Stephen Wilsonf6f40332010-07-24 02:19:04 +000019#include "lldb/Target/Target.h"
20
Stephen Wilson67d9f7e2011-03-30 15:55:52 +000021#include "LinuxStopInfo.h"
Stephen Wilsonf6f40332010-07-24 02:19:04 +000022#include "LinuxThread.h"
23#include "ProcessLinux.h"
24#include "ProcessMonitor.h"
Stephen Wilson708b4472011-02-28 22:52:38 +000025#include "RegisterContextLinux_i386.h"
Stephen Wilsonf6f40332010-07-24 02:19:04 +000026#include "RegisterContextLinux_x86_64.h"
Stephen Wilsone0c20da2011-01-19 01:36:10 +000027#include "UnwindLLDB.h"
Stephen Wilsonf6f40332010-07-24 02:19:04 +000028
29using namespace lldb_private;
30
Stephen Wilson67d9f7e2011-03-30 15:55:52 +000031
Stephen Wilsonf6f40332010-07-24 02:19:04 +000032LinuxThread::LinuxThread(Process &process, lldb::tid_t tid)
33 : Thread(process, tid),
Stephen Wilson67d9f7e2011-03-30 15:55:52 +000034 m_frame_ap(0)
Stephen Wilsonf6f40332010-07-24 02:19:04 +000035{
Stephen Wilsonf6f40332010-07-24 02:19:04 +000036}
37
Stephen Wilsonb47794a2011-01-16 16:56:16 +000038LinuxThread::~LinuxThread()
39{
40 DestroyThread();
41}
42
Stephen Wilsonf6f40332010-07-24 02:19:04 +000043ProcessMonitor &
44LinuxThread::GetMonitor()
45{
Stephen Wilsonbc1418b2011-01-07 00:10:43 +000046 ProcessLinux &process = static_cast<ProcessLinux&>(GetProcess());
47 return process.GetMonitor();
Stephen Wilsonf6f40332010-07-24 02:19:04 +000048}
49
50void
51LinuxThread::RefreshStateAfterStop()
52{
53}
54
55const char *
56LinuxThread::GetInfo()
57{
58 return NULL;
59}
60
Greg Clayton90ccf882011-01-06 22:35:55 +000061lldb::RegisterContextSP
Stephen Wilsonf6f40332010-07-24 02:19:04 +000062LinuxThread::GetRegisterContext()
63{
Greg Clayton90ccf882011-01-06 22:35:55 +000064 if (!m_reg_context_sp)
65 {
Stephen Wilson708b4472011-02-28 22:52:38 +000066 ArchSpec arch = Host::GetArchitecture();
Greg Clayton90ccf882011-01-06 22:35:55 +000067
Stephen Wilsona1f0b722011-02-24 19:17:09 +000068 switch (arch.GetCore())
Greg Clayton90ccf882011-01-06 22:35:55 +000069 {
70 default:
71 assert(false && "CPU type not supported!");
72 break;
73
Stephen Wilson708b4472011-02-28 22:52:38 +000074 case ArchSpec::eCore_x86_32_i386:
75 case ArchSpec::eCore_x86_32_i486:
76 case ArchSpec::eCore_x86_32_i486sx:
77 m_reg_context_sp.reset(new RegisterContextLinux_i386(*this, 0));
78 break;
79
Stephen Wilsona1f0b722011-02-24 19:17:09 +000080 case ArchSpec::eCore_x86_64_x86_64:
Greg Clayton90ccf882011-01-06 22:35:55 +000081 m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0));
82 break;
83 }
84 }
Stephen Wilsonbc1418b2011-01-07 00:10:43 +000085 return m_reg_context_sp;
Stephen Wilsonf6f40332010-07-24 02:19:04 +000086}
87
88bool
89LinuxThread::SaveFrameZeroState(RegisterCheckpoint &checkpoint)
90{
91 return false;
92}
93
94bool
95LinuxThread::RestoreSaveFrameZero(const RegisterCheckpoint &checkpoint)
96{
97 return false;
98}
99
Greg Clayton90ccf882011-01-06 22:35:55 +0000100lldb::RegisterContextSP
Stephen Wilsone0c20da2011-01-19 01:36:10 +0000101LinuxThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000102{
Greg Clayton90ccf882011-01-06 22:35:55 +0000103 lldb::RegisterContextSP reg_ctx_sp;
104 uint32_t concrete_frame_idx = 0;
Stephen Wilsone0c20da2011-01-19 01:36:10 +0000105
Greg Clayton90ccf882011-01-06 22:35:55 +0000106 if (frame)
107 concrete_frame_idx = frame->GetConcreteFrameIndex();
Stephen Wilson708b4472011-02-28 22:52:38 +0000108
Greg Clayton90ccf882011-01-06 22:35:55 +0000109 if (concrete_frame_idx == 0)
110 reg_ctx_sp = GetRegisterContext();
111 else
Stephen Wilsone0c20da2011-01-19 01:36:10 +0000112 reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);
113
Greg Clayton90ccf882011-01-06 22:35:55 +0000114 return reg_ctx_sp;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000115}
116
Stephen Wilsoned560022011-01-04 21:45:02 +0000117lldb::StopInfoSP
118LinuxThread::GetPrivateStopReason()
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000119{
Stephen Wilson140f69a2011-01-15 00:07:36 +0000120 return m_stop_info;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000121}
122
Stephen Wilsond61182d2011-01-04 21:45:57 +0000123Unwind *
124LinuxThread::GetUnwinder()
125{
Stephen Wilsone0c20da2011-01-19 01:36:10 +0000126 if (m_unwinder_ap.get() == NULL)
127 m_unwinder_ap.reset(new UnwindLLDB(*this));
128
Stephen Wilsond61182d2011-01-04 21:45:57 +0000129 return m_unwinder_ap.get();
130}
131
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000132bool
133LinuxThread::WillResume(lldb::StateType resume_state)
134{
135 SetResumeState(resume_state);
Stephen Wilsone0c20da2011-01-19 01:36:10 +0000136
137 ClearStackFrames();
138 if (m_unwinder_ap.get())
139 m_unwinder_ap->Clear();
140
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000141 return Thread::WillResume(resume_state);
142}
143
144bool
145LinuxThread::Resume()
146{
147 lldb::StateType resume_state = GetResumeState();
148 ProcessMonitor &monitor = GetMonitor();
149 bool status;
150
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000151 switch (resume_state)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000152 {
153 default:
154 assert(false && "Unexpected state for resume!");
155 status = false;
156 break;
157
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000158 case lldb::eStateRunning:
159 SetState(resume_state);
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000160 status = monitor.Resume(GetID(), GetResumeSignal());
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000161 break;
162
163 case lldb::eStateStepping:
164 SetState(resume_state);
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000165 status = monitor.SingleStep(GetID(), GetResumeSignal());
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000166 break;
167 }
168
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000169 return status;
170}
171
172void
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000173LinuxThread::Notify(const ProcessMessage &message)
174{
175 switch (message.GetKind())
176 {
177 default:
178 assert(false && "Unexpected message kind!");
179 break;
180
181 case ProcessMessage::eLimboMessage:
182 LimboNotify(message);
183 break;
184
185 case ProcessMessage::eSignalMessage:
186 SignalNotify(message);
187 break;
188
189 case ProcessMessage::eSignalDeliveredMessage:
190 SignalDeliveredNotify(message);
191 break;
192
193 case ProcessMessage::eTraceMessage:
194 TraceNotify(message);
195 break;
196
197 case ProcessMessage::eBreakpointMessage:
198 BreakNotify(message);
199 break;
200
201 case ProcessMessage::eCrashMessage:
202 CrashNotify(message);
203 break;
204 }
205}
206
207void
208LinuxThread::BreakNotify(const ProcessMessage &message)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000209{
210 bool status;
211
Greg Clayton90ccf882011-01-06 22:35:55 +0000212 status = GetRegisterContextLinux()->UpdateAfterBreakpoint();
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000213 assert(status && "Breakpoint update failed!");
214
215 // With our register state restored, resolve the breakpoint object
216 // corresponding to our current PC.
217 lldb::addr_t pc = GetRegisterContext()->GetPC();
Greg Clayton90ccf882011-01-06 22:35:55 +0000218 lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc));
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000219 lldb::break_id_t bp_id = bp_site->GetID();
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000220 assert(bp_site && bp_site->ValidForThisThread(this));
221
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000222
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000223 m_breakpoint = bp_site;
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000224 m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000225}
226
227void
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000228LinuxThread::TraceNotify(const ProcessMessage &message)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000229{
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000230 m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000231}
232
233void
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000234LinuxThread::LimboNotify(const ProcessMessage &message)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000235{
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000236 m_stop_info = lldb::StopInfoSP(new LinuxLimboStopInfo(*this));
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000237}
Stephen Wilson140f69a2011-01-15 00:07:36 +0000238
239void
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000240LinuxThread::SignalNotify(const ProcessMessage &message)
Stephen Wilson140f69a2011-01-15 00:07:36 +0000241{
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000242 int signo = message.GetSignal();
Stephen Wilson140f69a2011-01-15 00:07:36 +0000243
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000244 m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo);
245 SetResumeSignal(signo);
246}
Stephen Wilson140f69a2011-01-15 00:07:36 +0000247
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000248void
249LinuxThread::SignalDeliveredNotify(const ProcessMessage &message)
250{
251 int signo = message.GetSignal();
Stephen Wilson140f69a2011-01-15 00:07:36 +0000252
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000253 // Just treat debugger generated signal events like breakpoints for now.
254 m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
255 SetResumeSignal(signo);
256}
Stephen Wilson140f69a2011-01-15 00:07:36 +0000257
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000258void
259LinuxThread::CrashNotify(const ProcessMessage &message)
260{
261 int signo = message.GetSignal();
Stephen Wilson140f69a2011-01-15 00:07:36 +0000262
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000263 assert(message.GetKind() == ProcessMessage::eCrashMessage);
264
265 m_stop_info = lldb::StopInfoSP(new LinuxCrashStopInfo(
266 *this, signo, message.GetCrashReason()));
267 SetResumeSignal(signo);
Stephen Wilson140f69a2011-01-15 00:07:36 +0000268}