LinuxThread.cpp revision a1f0b72a3ea94b48ea803de8ff2d9a56053e8a39
1//===-- 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// C Includes
11#include <errno.h>
12
13// C++ Includes
14// Other libraries and framework includes
15#include "lldb/Target/Process.h"
16#include "lldb/Target/StopInfo.h"
17#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#include "UnwindLLDB.h"
24
25using namespace lldb_private;
26
27LinuxThread::LinuxThread(Process &process, lldb::tid_t tid)
28    : Thread(process, tid),
29      m_frame_ap(0),
30      m_stop_info_id(0),
31      m_note(eNone)
32{
33}
34
35LinuxThread::~LinuxThread()
36{
37    DestroyThread();
38}
39
40ProcessMonitor &
41LinuxThread::GetMonitor()
42{
43    ProcessLinux &process = static_cast<ProcessLinux&>(GetProcess());
44    return process.GetMonitor();
45}
46
47void
48LinuxThread::RefreshStateAfterStop()
49{
50    RefreshPrivateStopReason();
51}
52
53const char *
54LinuxThread::GetInfo()
55{
56    return NULL;
57}
58
59lldb::RegisterContextSP
60LinuxThread::GetRegisterContext()
61{
62    ProcessLinux &process = static_cast<ProcessLinux&>(GetProcess());
63
64    if (!m_reg_context_sp)
65    {
66        ArchSpec arch = process.GetTarget().GetArchitecture();
67
68        switch (arch.GetCore())
69        {
70        default:
71            assert(false && "CPU type not supported!");
72            break;
73
74        case ArchSpec::eCore_x86_64_x86_64:
75            m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0));
76            break;
77        }
78    }
79    return m_reg_context_sp;
80}
81
82bool
83LinuxThread::SaveFrameZeroState(RegisterCheckpoint &checkpoint)
84{
85    return false;
86}
87
88bool
89LinuxThread::RestoreSaveFrameZero(const RegisterCheckpoint &checkpoint)
90{
91    return false;
92}
93
94lldb::RegisterContextSP
95LinuxThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
96{
97    lldb::RegisterContextSP reg_ctx_sp;
98    uint32_t concrete_frame_idx = 0;
99
100    if (frame)
101        concrete_frame_idx = frame->GetConcreteFrameIndex();
102
103    if (concrete_frame_idx == 0)
104        reg_ctx_sp = GetRegisterContext();
105    else
106        reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);
107
108    return reg_ctx_sp;
109}
110
111lldb::StopInfoSP
112LinuxThread::GetPrivateStopReason()
113{
114    const uint32_t process_stop_id = GetProcess().GetStopID();
115
116    if (m_stop_info_id != process_stop_id || !m_stop_info || !m_stop_info->IsValid())
117        RefreshPrivateStopReason();
118    return m_stop_info;
119}
120
121Unwind *
122LinuxThread::GetUnwinder()
123{
124    if (m_unwinder_ap.get() == NULL)
125        m_unwinder_ap.reset(new UnwindLLDB(*this));
126
127    return m_unwinder_ap.get();
128}
129
130bool
131LinuxThread::WillResume(lldb::StateType resume_state)
132{
133    SetResumeState(resume_state);
134
135    ClearStackFrames();
136    if (m_unwinder_ap.get())
137        m_unwinder_ap->Clear();
138
139    return Thread::WillResume(resume_state);
140}
141
142bool
143LinuxThread::Resume()
144{
145    lldb::StateType resume_state = GetResumeState();
146    ProcessMonitor &monitor = GetMonitor();
147    bool status;
148
149    switch (GetResumeState())
150    {
151    default:
152        assert(false && "Unexpected state for resume!");
153        status = false;
154        break;
155
156    case lldb::eStateSuspended:
157        // FIXME: Implement process suspension.
158        status = false;
159
160    case lldb::eStateRunning:
161        SetState(resume_state);
162        status = monitor.Resume(GetID());
163        break;
164
165    case lldb::eStateStepping:
166        SetState(resume_state);
167        status = monitor.SingleStep(GetID());
168        break;
169    }
170
171    m_note = eNone;
172    return status;
173}
174
175void
176LinuxThread::BreakNotify()
177{
178    bool status;
179
180    status = GetRegisterContextLinux()->UpdateAfterBreakpoint();
181    assert(status && "Breakpoint update failed!");
182
183    // With our register state restored, resolve the breakpoint object
184    // corresponding to our current PC.
185    lldb::addr_t pc = GetRegisterContext()->GetPC();
186    lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc));
187    assert(bp_site && bp_site->ValidForThisThread(this));
188
189    m_note = eBreak;
190    m_breakpoint = bp_site;
191}
192
193void
194LinuxThread::TraceNotify()
195{
196    m_note = eTrace;
197}
198
199void
200LinuxThread::ExitNotify()
201{
202    m_note = eExit;
203}
204
205void
206LinuxThread::RefreshPrivateStopReason()
207{
208    m_stop_info_id = GetProcess().GetStopID();
209
210    switch (m_note) {
211
212    default:
213    case eNone:
214        m_stop_info.reset();
215        break;
216
217    case eBreak:
218        m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
219            *this, m_breakpoint->GetID());
220        break;
221
222    case eTrace:
223        m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
224        break;
225
226    case eExit:
227        m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, SIGCHLD);
228        break;
229    }
230}
231