blob: 725cc5a9485350a491de0eebc81d65598bfd3f03 [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 Wilsonf6f40332010-07-24 02:19:04 +000029 m_note(eNone)
30{
Stephen Wilsonf6f40332010-07-24 02:19:04 +000031}
32
33ProcessMonitor &
34LinuxThread::GetMonitor()
35{
36 ProcessLinux *process = static_cast<ProcessLinux*>(CalculateProcess());
37 return process->GetMonitor();
38}
39
40void
41LinuxThread::RefreshStateAfterStop()
42{
43}
44
45const char *
46LinuxThread::GetInfo()
47{
48 return NULL;
49}
50
Greg Clayton90ccf882011-01-06 22:35:55 +000051lldb::RegisterContextSP
Stephen Wilsonf6f40332010-07-24 02:19:04 +000052LinuxThread::GetRegisterContext()
53{
Greg Clayton90ccf882011-01-06 22:35:55 +000054 if (!m_reg_context_sp)
55 {
56 ArchSpec arch = process.GetTarget().GetArchitecture();
57
58 switch (arch.GetGenericCPUType())
59 {
60 default:
61 assert(false && "CPU type not supported!");
62 break;
63
64 case ArchSpec::eCPU_x86_64:
65 m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0));
66 break;
67 }
68 }
69 return m_reg_context_sp
Stephen Wilsonf6f40332010-07-24 02:19:04 +000070}
71
72bool
73LinuxThread::SaveFrameZeroState(RegisterCheckpoint &checkpoint)
74{
75 return false;
76}
77
78bool
79LinuxThread::RestoreSaveFrameZero(const RegisterCheckpoint &checkpoint)
80{
81 return false;
82}
83
Greg Clayton90ccf882011-01-06 22:35:55 +000084lldb::RegisterContextSP
85LinuxThread::CreateRegisterContextForFrame (lldb_private::StackFrame *frame)
Stephen Wilsonf6f40332010-07-24 02:19:04 +000086{
Greg Clayton90ccf882011-01-06 22:35:55 +000087 lldb::RegisterContextSP reg_ctx_sp;
88 uint32_t concrete_frame_idx = 0;
89 if (frame)
90 concrete_frame_idx = frame->GetConcreteFrameIndex();
91
92 if (concrete_frame_idx == 0)
93 reg_ctx_sp = GetRegisterContext();
94 else
95 reg_ctx_sp.reset (new RegisterContextLinux_x86_64(*this, frame->GetConcreteFrameIndex()));
96 return reg_ctx_sp;
Stephen Wilsonf6f40332010-07-24 02:19:04 +000097}
98
Stephen Wilsoned560022011-01-04 21:45:02 +000099lldb::StopInfoSP
100LinuxThread::GetPrivateStopReason()
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000101{
Stephen Wilsoned560022011-01-04 21:45:02 +0000102 lldb::StopInfoSP stop_info;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000103
104 switch (m_note)
105 {
106 default:
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000107 break;
108
109 case eBreak:
Stephen Wilsoned560022011-01-04 21:45:02 +0000110 stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
111 *this, m_breakpoint->GetID());
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000112 break;
113
114 case eTrace:
Stephen Wilsoned560022011-01-04 21:45:02 +0000115 stop_info = StopInfo::CreateStopReasonToTrace(*this);
116 break;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000117 }
118
Stephen Wilsoned560022011-01-04 21:45:02 +0000119 return stop_info;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000120}
121
Stephen Wilsond61182d2011-01-04 21:45:57 +0000122Unwind *
123LinuxThread::GetUnwinder()
124{
125 return m_unwinder_ap.get();
126}
127
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000128bool
129LinuxThread::WillResume(lldb::StateType resume_state)
130{
131 SetResumeState(resume_state);
132 return Thread::WillResume(resume_state);
133}
134
135bool
136LinuxThread::Resume()
137{
138 lldb::StateType resume_state = GetResumeState();
139 ProcessMonitor &monitor = GetMonitor();
140 bool status;
141
142 switch (GetResumeState())
143 {
144 default:
145 assert(false && "Unexpected state for resume!");
146 status = false;
147 break;
148
149 case lldb::eStateSuspended:
150 // FIXME: Implement process suspension.
151 status = false;
152
153 case lldb::eStateRunning:
154 SetState(resume_state);
155 status = monitor.Resume(GetID());
156 break;
157
158 case lldb::eStateStepping:
159 SetState(resume_state);
160 status = GetRegisterContext()->HardwareSingleStep(true);
161 break;
162 }
163
164 m_note = eNone;
165 return status;
166}
167
168void
169LinuxThread::BreakNotify()
170{
171 bool status;
172
Greg Clayton90ccf882011-01-06 22:35:55 +0000173 status = GetRegisterContextLinux()->UpdateAfterBreakpoint();
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000174 assert(status && "Breakpoint update failed!");
175
176 // With our register state restored, resolve the breakpoint object
177 // corresponding to our current PC.
178 lldb::addr_t pc = GetRegisterContext()->GetPC();
Greg Clayton90ccf882011-01-06 22:35:55 +0000179 lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc));
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000180 assert(bp_site && bp_site->ValidForThisThread(this));
181
182 m_note = eBreak;
183 m_breakpoint = bp_site;
184}
185
186void
187LinuxThread::TraceNotify()
188{
189 m_note = eTrace;
190}
191
192void
193LinuxThread::ExitNotify()
194{
195 m_note = eExit;
196}