blob: c6e0e553e44c3d6cf2f718d982ab96e8fb8ebde4 [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
Greg Clayton90ccf882011-01-06 22:35:55 +000088lldb::RegisterContextSP
Stephen Wilsone0c20da2011-01-19 01:36:10 +000089LinuxThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
Stephen Wilsonf6f40332010-07-24 02:19:04 +000090{
Greg Clayton90ccf882011-01-06 22:35:55 +000091 lldb::RegisterContextSP reg_ctx_sp;
92 uint32_t concrete_frame_idx = 0;
Stephen Wilsone0c20da2011-01-19 01:36:10 +000093
Greg Clayton90ccf882011-01-06 22:35:55 +000094 if (frame)
95 concrete_frame_idx = frame->GetConcreteFrameIndex();
Stephen Wilson708b4472011-02-28 22:52:38 +000096
Greg Clayton90ccf882011-01-06 22:35:55 +000097 if (concrete_frame_idx == 0)
98 reg_ctx_sp = GetRegisterContext();
99 else
Stephen Wilsone0c20da2011-01-19 01:36:10 +0000100 reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);
101
Greg Clayton90ccf882011-01-06 22:35:55 +0000102 return reg_ctx_sp;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000103}
104
Stephen Wilsoned560022011-01-04 21:45:02 +0000105lldb::StopInfoSP
106LinuxThread::GetPrivateStopReason()
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000107{
Stephen Wilson140f69a2011-01-15 00:07:36 +0000108 return m_stop_info;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000109}
110
Stephen Wilsond61182d2011-01-04 21:45:57 +0000111Unwind *
112LinuxThread::GetUnwinder()
113{
Stephen Wilsone0c20da2011-01-19 01:36:10 +0000114 if (m_unwinder_ap.get() == NULL)
115 m_unwinder_ap.reset(new UnwindLLDB(*this));
116
Stephen Wilsond61182d2011-01-04 21:45:57 +0000117 return m_unwinder_ap.get();
118}
119
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000120bool
121LinuxThread::WillResume(lldb::StateType resume_state)
122{
123 SetResumeState(resume_state);
Stephen Wilsone0c20da2011-01-19 01:36:10 +0000124
125 ClearStackFrames();
126 if (m_unwinder_ap.get())
127 m_unwinder_ap->Clear();
128
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000129 return Thread::WillResume(resume_state);
130}
131
132bool
133LinuxThread::Resume()
134{
135 lldb::StateType resume_state = GetResumeState();
136 ProcessMonitor &monitor = GetMonitor();
137 bool status;
138
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000139 switch (resume_state)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000140 {
141 default:
142 assert(false && "Unexpected state for resume!");
143 status = false;
144 break;
145
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000146 case lldb::eStateRunning:
147 SetState(resume_state);
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000148 status = monitor.Resume(GetID(), GetResumeSignal());
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000149 break;
150
151 case lldb::eStateStepping:
152 SetState(resume_state);
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000153 status = monitor.SingleStep(GetID(), GetResumeSignal());
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000154 break;
155 }
156
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000157 return status;
158}
159
160void
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000161LinuxThread::Notify(const ProcessMessage &message)
162{
163 switch (message.GetKind())
164 {
165 default:
166 assert(false && "Unexpected message kind!");
167 break;
168
169 case ProcessMessage::eLimboMessage:
170 LimboNotify(message);
171 break;
172
173 case ProcessMessage::eSignalMessage:
174 SignalNotify(message);
175 break;
176
177 case ProcessMessage::eSignalDeliveredMessage:
178 SignalDeliveredNotify(message);
179 break;
180
181 case ProcessMessage::eTraceMessage:
182 TraceNotify(message);
183 break;
184
185 case ProcessMessage::eBreakpointMessage:
186 BreakNotify(message);
187 break;
188
189 case ProcessMessage::eCrashMessage:
190 CrashNotify(message);
191 break;
192 }
193}
194
195void
196LinuxThread::BreakNotify(const ProcessMessage &message)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000197{
198 bool status;
199
Greg Clayton90ccf882011-01-06 22:35:55 +0000200 status = GetRegisterContextLinux()->UpdateAfterBreakpoint();
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000201 assert(status && "Breakpoint update failed!");
202
203 // With our register state restored, resolve the breakpoint object
204 // corresponding to our current PC.
205 lldb::addr_t pc = GetRegisterContext()->GetPC();
Greg Clayton90ccf882011-01-06 22:35:55 +0000206 lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc));
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000207 lldb::break_id_t bp_id = bp_site->GetID();
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000208 assert(bp_site && bp_site->ValidForThisThread(this));
209
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000210
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000211 m_breakpoint = bp_site;
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000212 m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000213}
214
215void
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000216LinuxThread::TraceNotify(const ProcessMessage &message)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000217{
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000218 m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000219}
220
221void
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000222LinuxThread::LimboNotify(const ProcessMessage &message)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000223{
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000224 m_stop_info = lldb::StopInfoSP(new LinuxLimboStopInfo(*this));
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000225}
Stephen Wilson140f69a2011-01-15 00:07:36 +0000226
227void
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000228LinuxThread::SignalNotify(const ProcessMessage &message)
Stephen Wilson140f69a2011-01-15 00:07:36 +0000229{
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000230 int signo = message.GetSignal();
Stephen Wilson140f69a2011-01-15 00:07:36 +0000231
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000232 m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo);
233 SetResumeSignal(signo);
234}
Stephen Wilson140f69a2011-01-15 00:07:36 +0000235
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000236void
237LinuxThread::SignalDeliveredNotify(const ProcessMessage &message)
238{
239 int signo = message.GetSignal();
Stephen Wilson140f69a2011-01-15 00:07:36 +0000240
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000241 // Just treat debugger generated signal events like breakpoints for now.
242 m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
243 SetResumeSignal(signo);
244}
Stephen Wilson140f69a2011-01-15 00:07:36 +0000245
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000246void
247LinuxThread::CrashNotify(const ProcessMessage &message)
248{
249 int signo = message.GetSignal();
Stephen Wilson140f69a2011-01-15 00:07:36 +0000250
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000251 assert(message.GetKind() == ProcessMessage::eCrashMessage);
252
253 m_stop_info = lldb::StopInfoSP(new LinuxCrashStopInfo(
254 *this, signo, message.GetCrashReason()));
255 SetResumeSignal(signo);
Stephen Wilson140f69a2011-01-15 00:07:36 +0000256}