LinuxThread.cpp revision bc1418b89ec30b6ffdda3acb9217871ee38754a3
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/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
24using namespace lldb_private;
25
26LinuxThread::LinuxThread(Process &process, lldb::tid_t tid)
27    : Thread(process, tid),
28      m_frame_ap(0),
29      m_note(eNone)
30{
31}
32
33ProcessMonitor &
34LinuxThread::GetMonitor()
35{
36    ProcessLinux &process = static_cast<ProcessLinux&>(GetProcess());
37    return process.GetMonitor();
38}
39
40void
41LinuxThread::RefreshStateAfterStop()
42{
43}
44
45const char *
46LinuxThread::GetInfo()
47{
48    return NULL;
49}
50
51lldb::RegisterContextSP
52LinuxThread::GetRegisterContext()
53{
54    ProcessLinux &process = static_cast<ProcessLinux&>(GetProcess());
55
56    if (!m_reg_context_sp)
57    {
58        ArchSpec arch = process.GetTarget().GetArchitecture();
59
60        switch (arch.GetGenericCPUType())
61        {
62        default:
63            assert(false && "CPU type not supported!");
64            break;
65
66        case ArchSpec::eCPU_x86_64:
67            m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0));
68            break;
69        }
70    }
71    return m_reg_context_sp;
72}
73
74bool
75LinuxThread::SaveFrameZeroState(RegisterCheckpoint &checkpoint)
76{
77    return false;
78}
79
80bool
81LinuxThread::RestoreSaveFrameZero(const RegisterCheckpoint &checkpoint)
82{
83    return false;
84}
85
86lldb::RegisterContextSP
87LinuxThread::CreateRegisterContextForFrame (lldb_private::StackFrame *frame)
88{
89    lldb::RegisterContextSP reg_ctx_sp;
90    uint32_t concrete_frame_idx = 0;
91    if (frame)
92        concrete_frame_idx = frame->GetConcreteFrameIndex();
93
94    if (concrete_frame_idx == 0)
95        reg_ctx_sp = GetRegisterContext();
96    else
97        reg_ctx_sp.reset (new RegisterContextLinux_x86_64(*this, frame->GetConcreteFrameIndex()));
98    return reg_ctx_sp;
99}
100
101lldb::StopInfoSP
102LinuxThread::GetPrivateStopReason()
103{
104    lldb::StopInfoSP stop_info;
105
106    switch (m_note)
107    {
108    default:
109        break;
110
111    case eBreak:
112        stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
113            *this, m_breakpoint->GetID());
114        break;
115
116    case eTrace:
117        stop_info = StopInfo::CreateStopReasonToTrace(*this);
118        break;
119    }
120
121    return stop_info;
122}
123
124Unwind *
125LinuxThread::GetUnwinder()
126{
127    return m_unwinder_ap.get();
128}
129
130bool
131LinuxThread::WillResume(lldb::StateType resume_state)
132{
133    SetResumeState(resume_state);
134    return Thread::WillResume(resume_state);
135}
136
137bool
138LinuxThread::Resume()
139{
140    lldb::StateType resume_state = GetResumeState();
141    ProcessMonitor &monitor = GetMonitor();
142    bool status;
143
144    switch (GetResumeState())
145    {
146    default:
147        assert(false && "Unexpected state for resume!");
148        status = false;
149        break;
150
151    case lldb::eStateSuspended:
152        // FIXME: Implement process suspension.
153        status = false;
154
155    case lldb::eStateRunning:
156        SetState(resume_state);
157        status = monitor.Resume(GetID());
158        break;
159
160    case lldb::eStateStepping:
161        SetState(resume_state);
162        status = GetRegisterContext()->HardwareSingleStep(true);
163        break;
164    }
165
166    m_note = eNone;
167    return status;
168}
169
170void
171LinuxThread::BreakNotify()
172{
173    bool status;
174
175    status = GetRegisterContextLinux()->UpdateAfterBreakpoint();
176    assert(status && "Breakpoint update failed!");
177
178    // With our register state restored, resolve the breakpoint object
179    // corresponding to our current PC.
180    lldb::addr_t pc = GetRegisterContext()->GetPC();
181    lldb::BreakpointSiteSP bp_site(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