blob: caed8e1d544339afbf59c4a8a6474af809053894 [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
10#include <errno.h>
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15#include "lldb/Target/Process.h"
Stephen Wilsonc8c74e02011-01-04 21:43:19 +000016#include "lldb/Target/StopInfo.h"
Stephen Wilsonf6f40332010-07-24 02:19:04 +000017#include "lldb/Target/Target.h"
18
19#include "LinuxThread.h"
20#include "ProcessLinux.h"
21#include "ProcessMonitor.h"
22#include "RegisterContextLinux_x86_64.h"
23
24using namespace lldb_private;
25
26LinuxThread::LinuxThread(Process &process, lldb::tid_t tid)
27 : Thread(process, tid),
28 m_frame_ap(0),
Stephen Wilson140f69a2011-01-15 00:07:36 +000029 m_stop_info_id(0),
Stephen Wilsonf6f40332010-07-24 02:19:04 +000030 m_note(eNone)
31{
Stephen Wilsonf6f40332010-07-24 02:19:04 +000032}
33
34ProcessMonitor &
35LinuxThread::GetMonitor()
36{
Stephen Wilsonbc1418b2011-01-07 00:10:43 +000037 ProcessLinux &process = static_cast<ProcessLinux&>(GetProcess());
38 return process.GetMonitor();
Stephen Wilsonf6f40332010-07-24 02:19:04 +000039}
40
41void
42LinuxThread::RefreshStateAfterStop()
43{
Stephen Wilson140f69a2011-01-15 00:07:36 +000044 RefreshPrivateStopReason();
Stephen Wilsonf6f40332010-07-24 02:19:04 +000045}
46
47const char *
48LinuxThread::GetInfo()
49{
50 return NULL;
51}
52
Greg Clayton90ccf882011-01-06 22:35:55 +000053lldb::RegisterContextSP
Stephen Wilsonf6f40332010-07-24 02:19:04 +000054LinuxThread::GetRegisterContext()
55{
Stephen Wilsonbc1418b2011-01-07 00:10:43 +000056 ProcessLinux &process = static_cast<ProcessLinux&>(GetProcess());
57
Greg Clayton90ccf882011-01-06 22:35:55 +000058 if (!m_reg_context_sp)
59 {
60 ArchSpec arch = process.GetTarget().GetArchitecture();
61
62 switch (arch.GetGenericCPUType())
63 {
64 default:
65 assert(false && "CPU type not supported!");
66 break;
67
68 case ArchSpec::eCPU_x86_64:
69 m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0));
70 break;
71 }
72 }
Stephen Wilsonbc1418b2011-01-07 00:10:43 +000073 return m_reg_context_sp;
Stephen Wilsonf6f40332010-07-24 02:19:04 +000074}
75
76bool
77LinuxThread::SaveFrameZeroState(RegisterCheckpoint &checkpoint)
78{
79 return false;
80}
81
82bool
83LinuxThread::RestoreSaveFrameZero(const RegisterCheckpoint &checkpoint)
84{
85 return false;
86}
87
Greg Clayton90ccf882011-01-06 22:35:55 +000088lldb::RegisterContextSP
89LinuxThread::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;
93 if (frame)
94 concrete_frame_idx = frame->GetConcreteFrameIndex();
95
96 if (concrete_frame_idx == 0)
97 reg_ctx_sp = GetRegisterContext();
98 else
99 reg_ctx_sp.reset (new RegisterContextLinux_x86_64(*this, frame->GetConcreteFrameIndex()));
100 return reg_ctx_sp;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000101}
102
Stephen Wilsoned560022011-01-04 21:45:02 +0000103lldb::StopInfoSP
104LinuxThread::GetPrivateStopReason()
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000105{
Stephen Wilson140f69a2011-01-15 00:07:36 +0000106 const uint32_t process_stop_id = GetProcess().GetStopID();
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000107
Stephen Wilson140f69a2011-01-15 00:07:36 +0000108 if (m_stop_info_id != process_stop_id || !m_stop_info || !m_stop_info->IsValid())
109 RefreshPrivateStopReason();
110 return m_stop_info;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000111}
112
Stephen Wilsond61182d2011-01-04 21:45:57 +0000113Unwind *
114LinuxThread::GetUnwinder()
115{
116 return m_unwinder_ap.get();
117}
118
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000119bool
120LinuxThread::WillResume(lldb::StateType resume_state)
121{
122 SetResumeState(resume_state);
123 return Thread::WillResume(resume_state);
124}
125
126bool
127LinuxThread::Resume()
128{
129 lldb::StateType resume_state = GetResumeState();
130 ProcessMonitor &monitor = GetMonitor();
131 bool status;
132
133 switch (GetResumeState())
134 {
135 default:
136 assert(false && "Unexpected state for resume!");
137 status = false;
138 break;
139
140 case lldb::eStateSuspended:
141 // FIXME: Implement process suspension.
142 status = false;
143
144 case lldb::eStateRunning:
145 SetState(resume_state);
146 status = monitor.Resume(GetID());
147 break;
148
149 case lldb::eStateStepping:
150 SetState(resume_state);
151 status = GetRegisterContext()->HardwareSingleStep(true);
152 break;
153 }
154
155 m_note = eNone;
156 return status;
157}
158
159void
160LinuxThread::BreakNotify()
161{
162 bool status;
163
Greg Clayton90ccf882011-01-06 22:35:55 +0000164 status = GetRegisterContextLinux()->UpdateAfterBreakpoint();
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000165 assert(status && "Breakpoint update failed!");
166
167 // With our register state restored, resolve the breakpoint object
168 // corresponding to our current PC.
169 lldb::addr_t pc = GetRegisterContext()->GetPC();
Greg Clayton90ccf882011-01-06 22:35:55 +0000170 lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc));
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000171 assert(bp_site && bp_site->ValidForThisThread(this));
172
173 m_note = eBreak;
174 m_breakpoint = bp_site;
175}
176
177void
178LinuxThread::TraceNotify()
179{
180 m_note = eTrace;
181}
182
183void
184LinuxThread::ExitNotify()
185{
186 m_note = eExit;
187}
Stephen Wilson140f69a2011-01-15 00:07:36 +0000188
189void
190LinuxThread::RefreshPrivateStopReason()
191{
192 m_stop_info_id = GetProcess().GetStopID();
193
194 switch (m_note) {
195
196 default:
197 case eNone:
198 m_stop_info.reset();
199 break;
200
201 case eBreak:
202 m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
203 *this, m_breakpoint->GetID());
204 break;
205
206 case eTrace:
207 m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
208 break;
209
210 case eExit:
211 m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, SIGCHLD);
212 break;
213 }
214}