LinuxThread.cpp revision f6f40333e91c97cc3b3ad5fb9fc0549079a96788
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#include <errno.h>
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15#include "lldb/Target/Process.h"
16#include "lldb/Target/Target.h"
17
18#include "LinuxThread.h"
19#include "ProcessLinux.h"
20#include "ProcessMonitor.h"
21#include "RegisterContextLinux_x86_64.h"
22
23using namespace lldb_private;
24
25LinuxThread::LinuxThread(Process &process, lldb::tid_t tid)
26    : Thread(process, tid),
27      m_frame_ap(0),
28      m_register_ap(0),
29      m_note(eNone)
30{
31    ArchSpec arch = process.GetTarget().GetArchitecture();
32
33    switch (arch.GetGenericCPUType())
34    {
35    default:
36        assert(false && "CPU type not supported!");
37        break;
38
39    case ArchSpec::eCPU_x86_64:
40        m_register_ap.reset(new RegisterContextLinux_x86_64(*this, NULL));
41        break;
42    }
43}
44
45ProcessMonitor &
46LinuxThread::GetMonitor()
47{
48    ProcessLinux *process = static_cast<ProcessLinux*>(CalculateProcess());
49    return process->GetMonitor();
50}
51
52void
53LinuxThread::RefreshStateAfterStop()
54{
55}
56
57const char *
58LinuxThread::GetInfo()
59{
60    return NULL;
61}
62
63uint32_t
64LinuxThread::GetStackFrameCount()
65{
66    return 0;
67}
68
69lldb::StackFrameSP
70LinuxThread::GetStackFrameAtIndex(uint32_t idx)
71{
72    if (idx == 0)
73    {
74        RegisterContextLinux *regs = GetRegisterContext();
75        StackFrame *frame = new StackFrame(
76            idx, *this, regs->GetFP(), regs->GetPC());
77        return lldb::StackFrameSP(frame);
78    }
79    else
80        return lldb::StackFrameSP();
81}
82
83RegisterContextLinux *
84LinuxThread::GetRegisterContext()
85{
86    return m_register_ap.get();
87}
88
89bool
90LinuxThread::SaveFrameZeroState(RegisterCheckpoint &checkpoint)
91{
92    return false;
93}
94
95bool
96LinuxThread::RestoreSaveFrameZero(const RegisterCheckpoint &checkpoint)
97{
98    return false;
99}
100
101RegisterContextLinux *
102LinuxThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
103{
104    return new RegisterContextLinux_x86_64(*this, frame);
105}
106
107bool
108LinuxThread::GetRawStopReason(StopInfo *stop_info)
109{
110    stop_info->Clear();
111
112    switch (m_note)
113    {
114    default:
115        stop_info->SetStopReasonToNone();
116        break;
117
118    case eBreak:
119        stop_info->SetStopReasonWithBreakpointSiteID(m_breakpoint->GetID());
120        break;
121
122    case eTrace:
123        stop_info->SetStopReasonToTrace();
124    }
125
126    return true;
127}
128
129bool
130LinuxThread::WillResume(lldb::StateType resume_state)
131{
132    SetResumeState(resume_state);
133    return Thread::WillResume(resume_state);
134}
135
136bool
137LinuxThread::Resume()
138{
139    lldb::StateType resume_state = GetResumeState();
140    ProcessMonitor &monitor = GetMonitor();
141    bool status;
142
143    switch (GetResumeState())
144    {
145    default:
146        assert(false && "Unexpected state for resume!");
147        status = false;
148        break;
149
150    case lldb::eStateSuspended:
151        // FIXME: Implement process suspension.
152        status = false;
153
154    case lldb::eStateRunning:
155        SetState(resume_state);
156        status = monitor.Resume(GetID());
157        break;
158
159    case lldb::eStateStepping:
160        SetState(resume_state);
161        status = GetRegisterContext()->HardwareSingleStep(true);
162        break;
163    }
164
165    m_note = eNone;
166    return status;
167}
168
169void
170LinuxThread::BreakNotify()
171{
172    bool status;
173
174    status = GetRegisterContext()->UpdateAfterBreakpoint();
175    assert(status && "Breakpoint update failed!");
176
177    // With our register state restored, resolve the breakpoint object
178    // corresponding to our current PC.
179    lldb::addr_t pc = GetRegisterContext()->GetPC();
180    lldb::BreakpointSiteSP bp_site =
181        GetProcess().GetBreakpointSiteList().FindByAddress(pc);
182    assert(bp_site && bp_site->ValidForThisThread(this));
183
184    m_note = eBreak;
185    m_breakpoint = bp_site;
186}
187
188void
189LinuxThread::TraceNotify()
190{
191    m_note = eTrace;
192}
193
194void
195LinuxThread::ExitNotify()
196{
197    m_note = eExit;
198}
199