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